All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net v2 1/2] tun: publish tfile after it's fully initialized
@ 2019-01-07 21:38 Stanislav Fomichev
  2019-01-07 21:38 ` [PATCH net v2 2/2] tun: always set skb->dev to tun->dev Stanislav Fomichev
  2019-01-10 14:26 ` [PATCH net v2 1/2] tun: publish tfile after it's fully initialized David Miller
  0 siblings, 2 replies; 5+ messages in thread
From: Stanislav Fomichev @ 2019-01-07 21:38 UTC (permalink / raw)
  To: netdev; +Cc: davem, jasowang, brouer, mst, edumazet, Stanislav Fomichev,
	syzbot

BUG: unable to handle kernel NULL pointer dereference at 00000000000000d1
Call Trace:
 ? napi_gro_frags+0xa7/0x2c0
 tun_get_user+0xb50/0xf20
 tun_chr_write_iter+0x53/0x70
 new_sync_write+0xff/0x160
 vfs_write+0x191/0x1e0
 __x64_sys_write+0x5e/0xd0
 do_syscall_64+0x47/0xf0
 entry_SYSCALL_64_after_hwframe+0x44/0xa9

I think there is a subtle race between sending a packet via tap and
attaching it:

CPU0:                    CPU1:
tun_chr_ioctl(TUNSETIFF)
  tun_set_iff
    tun_attach
      rcu_assign_pointer(tfile->tun, tun);
                         tun_fops->write_iter()
                           tun_chr_write_iter
                             tun_napi_alloc_frags
                               napi_get_frags
                                 napi->skb = napi_alloc_skb
      tun_napi_init
        netif_napi_add
          napi->skb = NULL
                              napi->skb is NULL here
                              napi_gro_frags
                                napi_frags_skb
				  skb = napi->skb
				  skb_reset_mac_header(skb)
				  panic()

Move rcu_assign_pointer(tfile->tun) and rcu_assign_pointer(tun->tfiles) to
be the last thing we do in tun_attach(); this should guarantee that when we
call tun_get() we always get an initialized object.

v2 changes:
* remove extra napi_mutex locks/unlocks for napi operations

Reported-by: syzbot <syzkaller@googlegroups.com>
Fixes: 90e33d459407 ("tun: enable napi_gro_frags() for TUN/TAP driver")

Signed-off-by: Stanislav Fomichev <sdf@google.com>
---
 drivers/net/tun.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index a4fdad475594..18656c4094b3 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -856,10 +856,6 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
 		err = 0;
 	}
 
-	rcu_assign_pointer(tfile->tun, tun);
-	rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
-	tun->numqueues++;
-
 	if (tfile->detached) {
 		tun_enable_queue(tfile);
 	} else {
@@ -876,6 +872,13 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
 	 * refcnt.
 	 */
 
+	/* Publish tfile->tun and tun->tfiles only after we've fully
+	 * initialized tfile; otherwise we risk using half-initialized
+	 * object.
+	 */
+	rcu_assign_pointer(tfile->tun, tun);
+	rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
+	tun->numqueues++;
 out:
 	return err;
 }
-- 
2.20.1.97.g81188d93c3-goog

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-01-10 14:26 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-01-07 21:38 [PATCH net v2 1/2] tun: publish tfile after it's fully initialized Stanislav Fomichev
2019-01-07 21:38 ` [PATCH net v2 2/2] tun: always set skb->dev to tun->dev Stanislav Fomichev
2019-01-07 22:30   ` Willem de Bruijn
2019-01-07 22:37     ` Stanislav Fomichev
2019-01-10 14:26 ` [PATCH net v2 1/2] tun: publish tfile after it's fully initialized David Miller

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.