From 40008e921133f95685ca4dfd7233b3df96af2bd6 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 17 Jun 2019 16:02:27 +0200 Subject: [PATCH 1/2] net: ipv4: remove erroneous advancement of list pointer Causes crash when lifetime expires on an adress as garbage is dereferenced soon after. This used to look like this: for (ifap = &ifa->ifa_dev->ifa_list; *ifap != NULL; ifap = &(*ifap)->ifa_next) { if (*ifap == ifa) ... but this was changed to: struct in_ifaddr *tmp; ifap = &ifa->ifa_dev->ifa_list; tmp = rtnl_dereference(*ifap); while (tmp) { tmp = rtnl_dereference(tmp->ifa_next); // Bogus if (rtnl_dereference(*ifap) == ifa) { ... ifap = &tmp->ifa_next; // Can be NULL tmp = rtnl_dereference(*ifap); // Dereference } } Remove the bogus assigment/list entry skip. Fixes: 2638eb8b50cf ("net: ipv4: provide __rcu annotation for ifa_list") Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- net/ipv4/devinet.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 925dffa915cb..914ccc7f192a 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -745,8 +745,7 @@ static void check_lifetime(struct work_struct *work) ifap = &ifa->ifa_dev->ifa_list; tmp = rtnl_dereference(*ifap); while (tmp) { - tmp = rtnl_dereference(tmp->ifa_next); - if (rtnl_dereference(*ifap) == ifa) { + if (tmp == ifa) { inet_del_ifa(ifa->ifa_dev, ifap, 1); break; From 3cfa148826e3c666da1cc2a43fbe8689e2650636 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 17 Jun 2019 16:02:28 +0200 Subject: [PATCH 2/2] selftests: rtnetlink: add addresses with fixed life time This exercises kernel code path that deal with addresses that have a limited lifetime. Without previous fix, this triggers following crash on net-next: BUG: KASAN: null-ptr-deref in check_lifetime+0x403/0x670 Read of size 8 at addr 0000000000000010 by task kworker [..] Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- tools/testing/selftests/net/rtnetlink.sh | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tools/testing/selftests/net/rtnetlink.sh b/tools/testing/selftests/net/rtnetlink.sh index b25c9fe019d2..ed606a2e3865 100755 --- a/tools/testing/selftests/net/rtnetlink.sh +++ b/tools/testing/selftests/net/rtnetlink.sh @@ -249,6 +249,26 @@ kci_test_route_get() echo "PASS: route get" } +kci_test_addrlft() +{ + for i in $(seq 10 100) ;do + lft=$(((RANDOM%3) + 1)) + ip addr add 10.23.11.$i/32 dev "$devdummy" preferred_lft $lft valid_lft $((lft+1)) + check_err $? + done + + sleep 5 + + ip addr show dev "$devdummy" | grep "10.23.11." + if [ $? -eq 0 ]; then + echo "FAIL: preferred_lft addresses remaining" + check_err 1 + return + fi + + echo "PASS: preferred_lft addresses have expired" +} + kci_test_addrlabel() { ret=0 @@ -1140,6 +1160,7 @@ kci_test_rtnl() kci_test_polrouting kci_test_route_get + kci_test_addrlft kci_test_tc kci_test_gre kci_test_gretap