All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, syzkaller <syzkaller@googlegroups.com>,
	George Kennedy <george.kennedy@oracle.com>,
	Jakub Kicinski <kuba@kernel.org>,
	Fedor Pchelkin <pchelkin@ispras.ru>
Subject: [PATCH 5.10 06/23] tun: avoid double free in tun_free_netdev
Date: Tue,  9 Aug 2022 20:00:24 +0200	[thread overview]
Message-ID: <20220809175513.106377185@linuxfoundation.org> (raw)
In-Reply-To: <20220809175512.853274191@linuxfoundation.org>

From: George Kennedy <george.kennedy@oracle.com>

commit 158b515f703e75e7d68289bf4d98c664e1d632df upstream.

Avoid double free in tun_free_netdev() by moving the
dev->tstats and tun->security allocs to a new ndo_init routine
(tun_net_init()) that will be called by register_netdevice().
ndo_init is paired with the desctructor (tun_free_netdev()),
so if there's an error in register_netdevice() the destructor
will handle the frees.

BUG: KASAN: double-free or invalid-free in selinux_tun_dev_free_security+0x1a/0x20 security/selinux/hooks.c:5605

CPU: 0 PID: 25750 Comm: syz-executor416 Not tainted 5.16.0-rc2-syzk #1
Hardware name: Red Hat KVM, BIOS
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0x89/0xb5 lib/dump_stack.c:106
print_address_description.constprop.9+0x28/0x160 mm/kasan/report.c:247
kasan_report_invalid_free+0x55/0x80 mm/kasan/report.c:372
____kasan_slab_free mm/kasan/common.c:346 [inline]
__kasan_slab_free+0x107/0x120 mm/kasan/common.c:374
kasan_slab_free include/linux/kasan.h:235 [inline]
slab_free_hook mm/slub.c:1723 [inline]
slab_free_freelist_hook mm/slub.c:1749 [inline]
slab_free mm/slub.c:3513 [inline]
kfree+0xac/0x2d0 mm/slub.c:4561
selinux_tun_dev_free_security+0x1a/0x20 security/selinux/hooks.c:5605
security_tun_dev_free_security+0x4f/0x90 security/security.c:2342
tun_free_netdev+0xe6/0x150 drivers/net/tun.c:2215
netdev_run_todo+0x4df/0x840 net/core/dev.c:10627
rtnl_unlock+0x13/0x20 net/core/rtnetlink.c:112
__tun_chr_ioctl+0x80c/0x2870 drivers/net/tun.c:3302
tun_chr_ioctl+0x2f/0x40 drivers/net/tun.c:3311
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:874 [inline]
__se_sys_ioctl fs/ioctl.c:860 [inline]
__x64_sys_ioctl+0x19d/0x220 fs/ioctl.c:860
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x3a/0x80 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x44/0xae

Reported-by: syzkaller <syzkaller@googlegroups.com>
Signed-off-by: George Kennedy <george.kennedy@oracle.com>
Suggested-by: Jakub Kicinski <kuba@kernel.org>
Link: https://lore.kernel.org/r/1639679132-19884-1-git-send-email-george.kennedy@oracle.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/net/tun.c |  114 +++++++++++++++++++++++++++---------------------------
 1 file changed, 59 insertions(+), 55 deletions(-)

--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -220,6 +220,9 @@ struct tun_struct {
 	struct tun_prog __rcu *steering_prog;
 	struct tun_prog __rcu *filter_prog;
 	struct ethtool_link_ksettings link_ksettings;
+	/* init args */
+	struct file *file;
+	struct ifreq *ifr;
 };
 
 struct veth {
@@ -227,6 +230,9 @@ struct veth {
 	__be16 h_vlan_TCI;
 };
 
+static void tun_flow_init(struct tun_struct *tun);
+static void tun_flow_uninit(struct tun_struct *tun);
+
 static int tun_napi_receive(struct napi_struct *napi, int budget)
 {
 	struct tun_file *tfile = container_of(napi, struct tun_file, napi);
@@ -975,6 +981,49 @@ static int check_filter(struct tap_filte
 
 static const struct ethtool_ops tun_ethtool_ops;
 
+static int tun_net_init(struct net_device *dev)
+{
+	struct tun_struct *tun = netdev_priv(dev);
+	struct ifreq *ifr = tun->ifr;
+	int err;
+
+	tun->pcpu_stats = netdev_alloc_pcpu_stats(struct tun_pcpu_stats);
+	if (!tun->pcpu_stats)
+		return -ENOMEM;
+
+	spin_lock_init(&tun->lock);
+
+	err = security_tun_dev_alloc_security(&tun->security);
+	if (err < 0) {
+		free_percpu(tun->pcpu_stats);
+		return err;
+	}
+
+	tun_flow_init(tun);
+
+	dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST |
+			   TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX |
+			   NETIF_F_HW_VLAN_STAG_TX;
+	dev->features = dev->hw_features | NETIF_F_LLTX;
+	dev->vlan_features = dev->features &
+			     ~(NETIF_F_HW_VLAN_CTAG_TX |
+			       NETIF_F_HW_VLAN_STAG_TX);
+
+	tun->flags = (tun->flags & ~TUN_FEATURES) |
+		      (ifr->ifr_flags & TUN_FEATURES);
+
+	INIT_LIST_HEAD(&tun->disabled);
+	err = tun_attach(tun, tun->file, false, ifr->ifr_flags & IFF_NAPI,
+			 ifr->ifr_flags & IFF_NAPI_FRAGS, false);
+	if (err < 0) {
+		tun_flow_uninit(tun);
+		security_tun_dev_free_security(tun->security);
+		free_percpu(tun->pcpu_stats);
+		return err;
+	}
+	return 0;
+}
+
 /* Net device detach from fd. */
 static void tun_net_uninit(struct net_device *dev)
 {
@@ -1216,6 +1265,7 @@ static int tun_net_change_carrier(struct
 }
 
 static const struct net_device_ops tun_netdev_ops = {
+	.ndo_init		= tun_net_init,
 	.ndo_uninit		= tun_net_uninit,
 	.ndo_open		= tun_net_open,
 	.ndo_stop		= tun_net_close,
@@ -1296,6 +1346,7 @@ static int tun_xdp_tx(struct net_device
 }
 
 static const struct net_device_ops tap_netdev_ops = {
+	.ndo_init		= tun_net_init,
 	.ndo_uninit		= tun_net_uninit,
 	.ndo_open		= tun_net_open,
 	.ndo_stop		= tun_net_close,
@@ -1336,7 +1387,7 @@ static void tun_flow_uninit(struct tun_s
 #define MAX_MTU 65535
 
 /* Initialize net device. */
-static void tun_net_init(struct net_device *dev)
+static void tun_net_initialize(struct net_device *dev)
 {
 	struct tun_struct *tun = netdev_priv(dev);
 
@@ -2268,10 +2319,6 @@ static void tun_free_netdev(struct net_d
 	BUG_ON(!(list_empty(&tun->disabled)));
 
 	free_percpu(tun->pcpu_stats);
-	/* We clear pcpu_stats so that tun_set_iff() can tell if
-	 * tun_free_netdev() has been called from register_netdevice().
-	 */
-	tun->pcpu_stats = NULL;
 
 	tun_flow_uninit(tun);
 	security_tun_dev_free_security(tun->security);
@@ -2784,41 +2831,16 @@ static int tun_set_iff(struct net *net,
 		tun->rx_batched = 0;
 		RCU_INIT_POINTER(tun->steering_prog, NULL);
 
-		tun->pcpu_stats = netdev_alloc_pcpu_stats(struct tun_pcpu_stats);
-		if (!tun->pcpu_stats) {
-			err = -ENOMEM;
-			goto err_free_dev;
-		}
-
-		spin_lock_init(&tun->lock);
-
-		err = security_tun_dev_alloc_security(&tun->security);
-		if (err < 0)
-			goto err_free_stat;
-
-		tun_net_init(dev);
-		tun_flow_init(tun);
+		tun->ifr = ifr;
+		tun->file = file;
 
-		dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST |
-				   TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX |
-				   NETIF_F_HW_VLAN_STAG_TX;
-		dev->features = dev->hw_features | NETIF_F_LLTX;
-		dev->vlan_features = dev->features &
-				     ~(NETIF_F_HW_VLAN_CTAG_TX |
-				       NETIF_F_HW_VLAN_STAG_TX);
-
-		tun->flags = (tun->flags & ~TUN_FEATURES) |
-			      (ifr->ifr_flags & TUN_FEATURES);
-
-		INIT_LIST_HEAD(&tun->disabled);
-		err = tun_attach(tun, file, false, ifr->ifr_flags & IFF_NAPI,
-				 ifr->ifr_flags & IFF_NAPI_FRAGS, false);
-		if (err < 0)
-			goto err_free_flow;
+		tun_net_initialize(dev);
 
 		err = register_netdevice(tun->dev);
-		if (err < 0)
-			goto err_detach;
+		if (err < 0) {
+			free_netdev(dev);
+			return err;
+		}
 		/* free_netdev() won't check refcnt, to aovid race
 		 * with dev_put() we need publish tun after registration.
 		 */
@@ -2835,24 +2857,6 @@ static int tun_set_iff(struct net *net,
 
 	strcpy(ifr->ifr_name, tun->dev->name);
 	return 0;
-
-err_detach:
-	tun_detach_all(dev);
-	/* We are here because register_netdevice() has failed.
-	 * If register_netdevice() already called tun_free_netdev()
-	 * while dealing with the error, tun->pcpu_stats has been cleared.
-	 */
-	if (!tun->pcpu_stats)
-		goto err_free_dev;
-
-err_free_flow:
-	tun_flow_uninit(tun);
-	security_tun_dev_free_security(tun->security);
-err_free_stat:
-	free_percpu(tun->pcpu_stats);
-err_free_dev:
-	free_netdev(dev);
-	return err;
 }
 
 static void tun_get_iff(struct tun_struct *tun, struct ifreq *ifr)



  parent reply	other threads:[~2022-08-09 18:10 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-09 18:00 [PATCH 5.10 00/23] 5.10.136-rc1 review Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 01/23] x86/speculation: Make all RETbleed mitigations 64-bit only Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 02/23] ath9k_htc: fix NULL pointer dereference at ath9k_htc_rxep() Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 03/23] ath9k_htc: fix NULL pointer dereference at ath9k_htc_tx_get_packet() Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 04/23] selftests/bpf: Extend verifier and bpf_sock tests for dst_port loads Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 05/23] selftests/bpf: Check dst_port only on the client socket Greg Kroah-Hartman
2022-08-09 18:00 ` Greg Kroah-Hartman [this message]
2022-08-09 18:00 ` [PATCH 5.10 07/23] ACPI: video: Force backlight native for some TongFang devices Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 08/23] ACPI: video: Shortening quirk list by identifying Clevo by board_name only Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 09/23] ACPI: APEI: Better fix to avoid spamming the console with old error logs Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 10/23] crypto: arm64/poly1305 - fix a read out-of-bound Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 11/23] tools/kvm_stat: fix display of error when multiple processes are found Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 12/23] selftests: KVM: Handle compiler optimizations in ucall Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 13/23] Bluetooth: hci_bcm: Add BCM4349B1 variant Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 14/23] Bluetooth: hci_bcm: Add DT compatible for CYW55572 Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 15/23] Bluetooth: btusb: Add support of IMC Networks PID 0x3568 Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 16/23] Bluetooth: btusb: Add Realtek RTL8852C support ID 0x04CA:0x4007 Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 17/23] Bluetooth: btusb: Add Realtek RTL8852C support ID 0x04C5:0x1675 Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 18/23] Bluetooth: btusb: Add Realtek RTL8852C support ID 0x0CB8:0xC558 Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 19/23] Bluetooth: btusb: Add Realtek RTL8852C support ID 0x13D3:0x3587 Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 20/23] Bluetooth: btusb: Add Realtek RTL8852C support ID 0x13D3:0x3586 Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 21/23] macintosh/adb: fix oob read in do_adb_query() function Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 22/23] x86/speculation: Add RSB VM Exit protections Greg Kroah-Hartman
2022-08-09 18:00 ` [PATCH 5.10 23/23] x86/speculation: Add LFENCE to RSB fill sequence Greg Kroah-Hartman
2022-08-09 20:30 ` [PATCH 5.10 00/23] 5.10.136-rc1 review Florian Fainelli
2022-08-10  8:25 ` Naresh Kamboju
2022-08-10  9:21 ` Pavel Machek
2022-08-10  9:49 ` Rudi Heitbaum
2022-08-10 13:22 ` Sudip Mukherjee (Codethink)
2022-08-10 13:32 ` Guenter Roeck
2022-08-10 14:25 ` Jon Hunter
2022-08-10 14:42 ` Shuah Khan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220809175513.106377185@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=george.kennedy@oracle.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pchelkin@ispras.ru \
    --cc=stable@vger.kernel.org \
    --cc=syzkaller@googlegroups.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.