netdev.vger.kernel.org archive mirror
 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

* [PATCH net v2 2/2] tun: always set skb->dev to tun->dev
  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 ` Stanislav Fomichev
  2019-01-07 22:30   ` Willem de Bruijn
  2019-01-10 14:26 ` [PATCH net v2 1/2] tun: publish tfile after it's fully initialized David Miller
  1 sibling, 1 reply; 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

While debugging previous issue I noticed that commit 90e33d459407 ("tun:
enable napi_gro_frags() for TUN/TAP driver") started conditionally
(!frags) calling eth_type_trans(skb, tun->dev) for IFF_TAP case. Since
eth_type_trans sets skb->dev, some skbs can now have NULL skb->dev.
Fix that by always setting skb->dev unconditionally.

The syzbot fails with the following trace:
WARNING: CPU: 0 PID: 11136 at net/core/flow_dissector.c:764
 skb_flow_dissect_flow_keys_basic include/linux/skbuff.h:1240 [inline]
 skb_probe_transport_header include/linux/skbuff.h:2403 [inline]
 tun_get_user+0x2d4a/0x4250 drivers/net/tun.c:1906
 tun_chr_write_iter+0xb9/0x160 drivers/net/tun.c:1993
 call_write_iter include/linux/fs.h:1808 [inline]
 new_sync_write fs/read_write.c:474 [inline]

But I don't think there is an actual issue since we exercise flow
dissector via eth_get_headlen which doesn't use skb (and hence BPF flow
dissector). But let's still properly set skb->dev so we don't have
any problems going forward.

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 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 18656c4094b3..2dea2fb88b62 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1890,6 +1890,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
 		return -EINVAL;
 	}
 
+	skb->dev = tun->dev;
 	switch (tun->flags & TUN_TYPE_MASK) {
 	case IFF_TUN:
 		if (tun->flags & IFF_NO_PI) {
@@ -1911,7 +1912,6 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
 
 		skb_reset_mac_header(skb);
 		skb->protocol = pi.proto;
-		skb->dev = tun->dev;
 		break;
 	case IFF_TAP:
 		if (!frags)
-- 
2.20.1.97.g81188d93c3-goog

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

* Re: [PATCH net v2 2/2] tun: always set skb->dev to tun->dev
  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
  0 siblings, 1 reply; 5+ messages in thread
From: Willem de Bruijn @ 2019-01-07 22:30 UTC (permalink / raw)
  To: Stanislav Fomichev
  Cc: Network Development, David Miller, Jason Wang,
	Jesper Dangaard Brouer, Michael S. Tsirkin, Eric Dumazet, syzbot

On Mon, Jan 7, 2019 at 4:41 PM Stanislav Fomichev <sdf@google.com> wrote:
>
> While debugging previous issue I noticed that commit 90e33d459407 ("tun:
> enable napi_gro_frags() for TUN/TAP driver") started conditionally
> (!frags) calling eth_type_trans(skb, tun->dev) for IFF_TAP case. Since
> eth_type_trans sets skb->dev, some skbs can now have NULL skb->dev.
> Fix that by always setting skb->dev unconditionally.
>
> The syzbot fails with the following trace:
> WARNING: CPU: 0 PID: 11136 at net/core/flow_dissector.c:764
>  skb_flow_dissect_flow_keys_basic include/linux/skbuff.h:1240 [inline]
>  skb_probe_transport_header include/linux/skbuff.h:2403 [inline]
>  tun_get_user+0x2d4a/0x4250 drivers/net/tun.c:1906
>  tun_chr_write_iter+0xb9/0x160 drivers/net/tun.c:1993
>  call_write_iter include/linux/fs.h:1808 [inline]
>  new_sync_write fs/read_write.c:474 [inline]
>
> But I don't think there is an actual issue since we exercise flow
> dissector via eth_get_headlen which doesn't use skb (and hence BPF flow
> dissector).

Do you mean skb_probe_transport_header?

if frags, tun_napi_alloc_frags will return napi->skb, which has
skb->dev set by napi_reuse_skb.

I don't think this is needed.

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

* Re: [PATCH net v2 2/2] tun: always set skb->dev to tun->dev
  2019-01-07 22:30   ` Willem de Bruijn
@ 2019-01-07 22:37     ` Stanislav Fomichev
  0 siblings, 0 replies; 5+ messages in thread
From: Stanislav Fomichev @ 2019-01-07 22:37 UTC (permalink / raw)
  To: Willem de Bruijn
  Cc: Stanislav Fomichev, Network Development, David Miller, Jason Wang,
	Jesper Dangaard Brouer, Michael S. Tsirkin, Eric Dumazet, syzbot

On 01/07, Willem de Bruijn wrote:
> On Mon, Jan 7, 2019 at 4:41 PM Stanislav Fomichev <sdf@google.com> wrote:
> >
> > While debugging previous issue I noticed that commit 90e33d459407 ("tun:
> > enable napi_gro_frags() for TUN/TAP driver") started conditionally
> > (!frags) calling eth_type_trans(skb, tun->dev) for IFF_TAP case. Since
> > eth_type_trans sets skb->dev, some skbs can now have NULL skb->dev.
> > Fix that by always setting skb->dev unconditionally.
> >
> > The syzbot fails with the following trace:
> > WARNING: CPU: 0 PID: 11136 at net/core/flow_dissector.c:764
> >  skb_flow_dissect_flow_keys_basic include/linux/skbuff.h:1240 [inline]
> >  skb_probe_transport_header include/linux/skbuff.h:2403 [inline]
> >  tun_get_user+0x2d4a/0x4250 drivers/net/tun.c:1906
> >  tun_chr_write_iter+0xb9/0x160 drivers/net/tun.c:1993
> >  call_write_iter include/linux/fs.h:1808 [inline]
> >  new_sync_write fs/read_write.c:474 [inline]
> >
> > But I don't think there is an actual issue since we exercise flow
> > dissector via eth_get_headlen which doesn't use skb (and hence BPF flow
> > dissector).
> 
> Do you mean skb_probe_transport_header?
I was actually thinking about possible future conversion of
eth_get_headlen to be able to run bpf flow dissector, I missed the fact
that we already call dissector via skb_probe_transport_header :-(
> 
> if frags, tun_napi_alloc_frags will return napi->skb, which has
> skb->dev set by napi_reuse_skb.
> 
> I don't think this is needed.
Ah, indeed, napi_alloc_skb sets proper skb->dev.

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

* Re: [PATCH net v2 1/2] tun: publish tfile after it's fully initialized
  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-10 14:26 ` David Miller
  1 sibling, 0 replies; 5+ messages in thread
From: David Miller @ 2019-01-10 14:26 UTC (permalink / raw)
  To: sdf; +Cc: netdev, jasowang, brouer, mst, edumazet, syzkaller

From: Stanislav Fomichev <sdf@google.com>
Date: Mon,  7 Jan 2019 13:38:38 -0800

> BUG: unable to handle kernel NULL pointer dereference at 00000000000000d1
> Call Trace:
 ...
> 
> I think there is a subtle race between sending a packet via tap and
> attaching it:
> 
> CPU0:                    CPU1:
> tun_chr_ioctl(TUNSETIFF)
 ...
> 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>

Applied and queued up for -stable.

Please, the next time you submit a patch series, provide a proper header
posting.

Thank you.

^ permalink raw reply	[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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).