Replace old implementation from patch 'qca-nss-ecm-fix-a-memcpy-overflow-in-ecm_db' with new one '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
|
||||
--- 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
|
||||
+++ b/ecm_db/ecm_db_connection.c
|
||||
@@ -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