Thomas Bogendoerfer 18d9ec
From: Jakub Kicinski <kuba@kernel.org>
Thomas Bogendoerfer 18d9ec
Date: Mon, 13 Feb 2023 22:53:55 -0800
Thomas Bogendoerfer 18d9ec
Subject: net: mpls: fix stale pointer if allocation fails during device rename
Thomas Bogendoerfer 18d9ec
Patch-mainline: v6.2
Thomas Bogendoerfer 18d9ec
Git-commit: fda6c89fe3d9aca073495a664e1d5aea28cd4377
Thomas Bogendoerfer 18d9ec
References: bsc#1208700 CVE-2023-26545
Thomas Bogendoerfer 18d9ec
Thomas Bogendoerfer 18d9ec
lianhui reports that when MPLS fails to register the sysctl table
Thomas Bogendoerfer 18d9ec
under new location (during device rename) the old pointers won't
Thomas Bogendoerfer 18d9ec
get overwritten and may be freed again (double free).
Thomas Bogendoerfer 18d9ec
Thomas Bogendoerfer 18d9ec
Handle this gracefully. The best option would be unregistering
Thomas Bogendoerfer 18d9ec
the MPLS from the device completely on failure, but unfortunately
Thomas Bogendoerfer 18d9ec
mpls_ifdown() can fail. So failing fully is also unreliable.
Thomas Bogendoerfer 18d9ec
Thomas Bogendoerfer 18d9ec
Another option is to register the new table first then only
Thomas Bogendoerfer 18d9ec
remove old one if the new one succeeds. That requires more
Thomas Bogendoerfer 18d9ec
code, changes order of notifications and two tables may be
Thomas Bogendoerfer 18d9ec
visible at the same time.
Thomas Bogendoerfer 18d9ec
Thomas Bogendoerfer 18d9ec
sysctl point is not used in the rest of the code - set to NULL
Thomas Bogendoerfer 18d9ec
on failures and skip unregister if already NULL.
Thomas Bogendoerfer 18d9ec
Thomas Bogendoerfer 18d9ec
Reported-by: lianhui tang <bluetlh@gmail.com>
Thomas Bogendoerfer 18d9ec
Fixes: 0fae3bf018d9 ("mpls: handle device renames for per-device sysctls")
Thomas Bogendoerfer 18d9ec
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Thomas Bogendoerfer 18d9ec
Signed-off-by: David S. Miller <davem@davemloft.net>
Thomas Bogendoerfer 18d9ec
Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
Thomas Bogendoerfer 18d9ec
---
Thomas Bogendoerfer 18d9ec
 net/mpls/af_mpls.c |    4 ++++
Thomas Bogendoerfer 18d9ec
 1 file changed, 4 insertions(+)
Thomas Bogendoerfer 18d9ec
Thomas Bogendoerfer 18d9ec
--- a/net/mpls/af_mpls.c
Thomas Bogendoerfer 18d9ec
+++ b/net/mpls/af_mpls.c
Thomas Bogendoerfer 18d9ec
@@ -1428,6 +1428,7 @@ static int mpls_dev_sysctl_register(stru
Thomas Bogendoerfer 18d9ec
 free:
Thomas Bogendoerfer 18d9ec
 	kfree(table);
Thomas Bogendoerfer 18d9ec
 out:
Thomas Bogendoerfer 18d9ec
+	mdev->sysctl = NULL;
Thomas Bogendoerfer 18d9ec
 	return -ENOBUFS;
Thomas Bogendoerfer 18d9ec
 }
Thomas Bogendoerfer 18d9ec
 
Thomas Bogendoerfer 18d9ec
@@ -1437,6 +1438,9 @@ static void mpls_dev_sysctl_unregister(s
Thomas Bogendoerfer 18d9ec
 	struct net *net = dev_net(dev);
Thomas Bogendoerfer 18d9ec
 	struct ctl_table *table;
Thomas Bogendoerfer 18d9ec
 
Thomas Bogendoerfer 18d9ec
+	if (!mdev->sysctl)
Thomas Bogendoerfer 18d9ec
+		return;
Thomas Bogendoerfer 18d9ec
+
Thomas Bogendoerfer 18d9ec
 	table = mdev->sysctl->ctl_table_arg;
Thomas Bogendoerfer 18d9ec
 	unregister_net_sysctl_table(mdev->sysctl);
Thomas Bogendoerfer 18d9ec
 	kfree(table);