package: qca-nss: Replace patch 'qca-nss-ecm-fix-a-memcpy-overflow-in-ecm_db' with 'Validate dst_len before-calling-IP-addr-copy'
This change fixes the following issue... ``` <0>[ 3372.560724] fortify_panic from ecm_db_exit+0x384/0x388 [ecm] <0>[ 3372.568927] ecm_db_exit [ecm] from ecm_db_ipv6_route_table_update_event+0x3c/0x5c [ecm] <0>[ 3372.574608] ecm_db_ipv6_route_table_update_event [ecm] from atomic_notifier_call_chain+0x58/0x6c <0>[ 3372.582769] atomic_notifier_call_chain from ip6_route_add+0xac/0xdc <0>[ 3372.591533] ip6_route_add from inet6_rtm_newroute+0xb0/0xc0 ```
This commit is contained in:
		| @@ -912,70 +912,6 @@ | |||||||
|  }; |  }; | ||||||
|  #endif |  #endif | ||||||
|  #endif |  #endif | ||||||
| --- a/ecm_db/ecm_db.c |  | ||||||
| +++ b/ecm_db/ecm_db.c |  | ||||||
| @@ -242,11 +242,13 @@ static int ecm_db_ipv6_route_table_updat |  | ||||||
|  					       unsigned long event, |  | ||||||
|  					       void *ptr) |  | ||||||
|  { |  | ||||||
| +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0)) |  | ||||||
|  	struct fib6_config *cfg = (struct fib6_config *)ptr; |  | ||||||
|  	struct ecm_db_connection_instance *ci; |  | ||||||
| - |  | ||||||
| +#endif |  | ||||||
|  	DEBUG_TRACE("route table update event v6\n"); |  | ||||||
|   |  | ||||||
| +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0)) |  | ||||||
|  	if ((event != RTM_DELROUTE) && (event != RTM_NEWROUTE)) { |  | ||||||
|  		DEBUG_WARN("%px: Unhandled route table event: %lu\n", cfg, event); |  | ||||||
|  		return NOTIFY_DONE; |  | ||||||
| @@ -262,12 +264,13 @@ static int ecm_db_ipv6_route_table_updat |  | ||||||
|  		ecm_db_connection_defunct_ip_version(6); |  | ||||||
|  		return NOTIFY_DONE; |  | ||||||
|  	} |  | ||||||
| - |  | ||||||
| +#endif |  | ||||||
|  	/* |  | ||||||
|  	 * Disable IPv6 frontend processing until defunct function call is completed. |  | ||||||
|  	 */ |  | ||||||
|  	ecm_front_end_ipv6_stop(1); |  | ||||||
|   |  | ||||||
| +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0)) |  | ||||||
|  	/* |  | ||||||
|  	 * Iterate all connections |  | ||||||
|  	 */ |  | ||||||
| @@ -298,7 +301,7 @@ static int ecm_db_ipv6_route_table_updat |  | ||||||
|  		 * Compute ECM connection's prefix destination address by masking it with the |  | ||||||
|  		 * route config's destination address prefix length. |  | ||||||
|  		 */ |  | ||||||
| -		ipv6_addr_prefix(&prefix_addr, &ecm_in6, cfg->fc_dst_len); |  | ||||||
| +		ipv6_addr_prefix(&prefix_addr, &ecm_in6, min(128, cfg->fc_dst_len)); |  | ||||||
|   |  | ||||||
|  		DEBUG_TRACE("dest addr prefix: %pI6 prefix_len: %d ecm_in6: %pI6\n", &prefix_addr, cfg->fc_dst_len, &ecm_in6); |  | ||||||
|   |  | ||||||
| @@ -326,7 +329,7 @@ static int ecm_db_ipv6_route_table_updat |  | ||||||
|  			 * Compute ECM connection's prefix source address by masking it with the |  | ||||||
|  			 * route config's destination address prefix length. |  | ||||||
|  			 */ |  | ||||||
| -			ipv6_addr_prefix(&prefix_addr, &ecm_in6, cfg->fc_dst_len); |  | ||||||
| +			ipv6_addr_prefix(&prefix_addr, &ecm_in6, min(128, cfg->fc_dst_len)); |  | ||||||
|   |  | ||||||
|  			DEBUG_TRACE("src addr prefix: %pI6 prefix_len: %d ecm_in6: %pI6\n", &prefix_addr, cfg->fc_dst_len, &ecm_in6); |  | ||||||
|   |  | ||||||
| @@ -402,11 +405,12 @@ next: |  | ||||||
|  		ecm_db_connection_deref(ci); |  | ||||||
|  		ci = cin; |  | ||||||
|  	} |  | ||||||
| - |  | ||||||
| +#else |  | ||||||
|  	/* |  | ||||||
|  	 * Re-enable IPv6 frontend processing. |  | ||||||
|  	 */ |  | ||||||
|  	ecm_front_end_ipv6_stop(0); |  | ||||||
| +#endif |  | ||||||
|  	return NOTIFY_DONE; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| --- a/ecm_db/ecm_db_connection.c | --- a/ecm_db/ecm_db_connection.c | ||||||
| +++ b/ecm_db/ecm_db_connection.c | +++ b/ecm_db/ecm_db_connection.c | ||||||
| @@ -446,7 +446,9 @@ EXPORT_SYMBOL(ecm_db_connection_make_def | @@ -446,7 +446,9 @@ EXPORT_SYMBOL(ecm_db_connection_make_def | ||||||
|   | |||||||
| @@ -0,0 +1,91 @@ | |||||||
|  | From a7c2db4fbccb5199ea3f3e2ce17cbd8cbce43924 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Amitesh Anand <quic_amitesh@quicinc.com> | ||||||
|  | Date: Fri, 12 Apr 2024 17:07:38 +0530 | ||||||
|  | Subject: [PATCH] [qca-nss-ecm] Validate dst_len before calling IP addr copy | ||||||
|  |  | ||||||
|  | Incorrect lenght passed for as parameter ipv6_addr_prefix(), | ||||||
|  | which crashes during memcpy. Linux mandates the caller to | ||||||
|  | ensure len is between 0 to 128. | ||||||
|  |  | ||||||
|  | Crash signature: | ||||||
|  | PC points to "fortify_panic+0x18/0x1c" | ||||||
|  | LR points to "fortify_panic+0x18/0x1c". | ||||||
|  | The Backtrace obtained is as follows: | ||||||
|  | fortify_panic+0x18/0x1c | ||||||
|  | ecm_db_init+0x51c/0x948 [ecm] | ||||||
|  | notifier_call_chain+0x64/0x84 | ||||||
|  | atomic_notifier_call_chain+0x38/0x54 | ||||||
|  | ip6_route_add+0x6c/0xc0 | ||||||
|  | addrconf_prefix_route+0xd8/0x10c | ||||||
|  | inet6_rtm_newaddr+0x42c/0x5a4 | ||||||
|  | rtnetlink_rcv_msg+0x260/0x2ac | ||||||
|  | netlink_rcv_skb+0x9c/0x108 | ||||||
|  | rtnetlink_rcv+0x14/0x1c | ||||||
|  | netlink_unicast+0x168/0x244 | ||||||
|  | netlink_sendmsg+0x35c/0x3b8 | ||||||
|  | __sock_sendmsg+0x18/0x2c | ||||||
|  | ____sys_sendmsg+0x27c/0x31c | ||||||
|  | ___sys_sendmsg+0x74/0xbc | ||||||
|  | __sys_sendmsg+0x64/0xb0 | ||||||
|  | __arm64_sys_sendmsg+0x1c/0x24 | ||||||
|  | el0_svc_common.constprop.0+0xc8/0x128 | ||||||
|  | do_el0_svc+0x18/0x20 | ||||||
|  | el0_svc+0x18/0x40 | ||||||
|  | el0t_64_sync_handler+0x88/0x124 | ||||||
|  |  | ||||||
|  | Change-Id: I7547eedb1f2af70180ca22d373c5cd6426510776 | ||||||
|  | Signed-off-by: Amitesh Anand <quic_amitesh@quicinc.com> | ||||||
|  | --- | ||||||
|  |  ecm_db/ecm_db.c | 19 +++++++++++++++---- | ||||||
|  |  1 file changed, 15 insertions(+), 4 deletions(-) | ||||||
|  |  | ||||||
|  | diff --git a/ecm_db/ecm_db.c b/ecm_db/ecm_db.c | ||||||
|  | index 722d6d5e..201f2b91 100644 | ||||||
|  | --- a/ecm_db/ecm_db.c | ||||||
|  | +++ b/ecm_db/ecm_db.c | ||||||
|  | @@ -283,6 +283,7 @@ static int ecm_db_ipv6_route_table_update_event(struct notifier_block *nb, | ||||||
|  |  		struct net_device *fc_dev; | ||||||
|  |  		bool is_dest_ip_match = true; | ||||||
|  |  		ecm_db_obj_dir_t obj_dir = ECM_DB_OBJ_DIR_TO; | ||||||
|  | +		int fc_dst_len = cfg->fc_dst_len; | ||||||
|  |   | ||||||
|  |  		if (ci->ip_version != 6) { | ||||||
|  |  			goto next; | ||||||
|  | @@ -297,10 +298,19 @@ static int ecm_db_ipv6_route_table_update_event(struct notifier_block *nb, | ||||||
|  |  		/* | ||||||
|  |  		 * Compute ECM connection's prefix destination address by masking it with the | ||||||
|  |  		 * route config's destination address prefix length. | ||||||
|  | +		 * | ||||||
|  | +		 * Validate dst_len to be 0 <= len <= 128 | ||||||
|  |  		 */ | ||||||
|  | -		ipv6_addr_prefix(&prefix_addr, &ecm_in6, cfg->fc_dst_len); | ||||||
|  | +		if (cfg->fc_dst_len > 128) { | ||||||
|  | +			fc_dst_len = 128; | ||||||
|  | +		} else if (cfg->fc_dst_len < 0){ | ||||||
|  | +			fc_dst_len = 0; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		ipv6_addr_prefix(&prefix_addr, &ecm_in6, fc_dst_len); | ||||||
|  |   | ||||||
|  | -		DEBUG_TRACE("dest addr prefix: %pI6 prefix_len: %d ecm_in6: %pI6\n", &prefix_addr, cfg->fc_dst_len, &ecm_in6); | ||||||
|  | +		DEBUG_TRACE("dest addr prefix: %pI6 prefix_len: %d(cfg=%d) ecm_in6: %pI6\n", | ||||||
|  | +				&prefix_addr, fc_dst_len, cfg->fc_dst_len, &ecm_in6); | ||||||
|  |   | ||||||
|  |  		/* | ||||||
|  |  		 * Compare the ECM connection's destination address prefix with the route config's | ||||||
|  | @@ -326,9 +336,10 @@ static int ecm_db_ipv6_route_table_update_event(struct notifier_block *nb, | ||||||
|  |  			 * Compute ECM connection's prefix source address by masking it with the | ||||||
|  |  			 * route config's destination address prefix length. | ||||||
|  |  			 */ | ||||||
|  | -			ipv6_addr_prefix(&prefix_addr, &ecm_in6, cfg->fc_dst_len); | ||||||
|  | +			ipv6_addr_prefix(&prefix_addr, &ecm_in6, fc_dst_len); | ||||||
|  |   | ||||||
|  | -			DEBUG_TRACE("src addr prefix: %pI6 prefix_len: %d ecm_in6: %pI6\n", &prefix_addr, cfg->fc_dst_len, &ecm_in6); | ||||||
|  | +			DEBUG_TRACE("src addr prefix: %pI6 prefix_len: %d(cfg=%d) ecm_in6: %pI6\n", | ||||||
|  | +					&prefix_addr, fc_dst_len, cfg->fc_dst_len, &ecm_in6); | ||||||
|  |   | ||||||
|  |  			if (ipv6_addr_cmp(&prefix_addr, &cfg->fc_dst)) { | ||||||
|  |  				DEBUG_TRACE("src addr prefix: %pI6 not equal to cfg->fc_dst: %pI6, go to next connection\n", &prefix_addr, &cfg->fc_dst); | ||||||
|  | --  | ||||||
|  | GitLab | ||||||
|  |  | ||||||
		Reference in New Issue
	
	Block a user
	 SqTER-PL
					SqTER-PL