diff mbox series

vhost: handle zero regions in vhost_set_memory

Message ID 20220221072852.31820-1-mail@anirudhrb.com (mailing list archive)
State Not Applicable
Delegated to: Netdev Maintainers
Headers show
Series vhost: handle zero regions in vhost_set_memory | expand

Checks

Context Check Description
netdev/tree_selection success Not a local patch

Commit Message

Anirudh Rayabharam Feb. 21, 2022, 7:28 a.m. UTC
Return early when userspace sends zero regions in the VHOST_SET_MEM_TABLE
ioctl.

Otherwise, this causes an erroneous entry to be added to the iotlb. This
entry has a range size of 0 (due to u64 overflow). This then causes
iotlb_access_ok() to loop indefinitely resulting in a hung thread.
Syzbot has reported this here:

https://syzkaller.appspot.com/bug?extid=0abd373e2e50d704db87

Reported-and-tested-by: syzbot+0abd373e2e50d704db87@syzkaller.appspotmail.com
Signed-off-by: Anirudh Rayabharam <mail@anirudhrb.com>
---
 drivers/vhost/vhost.c | 2 ++
 1 file changed, 2 insertions(+)

Comments

Jason Wang Feb. 21, 2022, 7:56 a.m. UTC | #1
On Mon, Feb 21, 2022 at 3:45 PM Anirudh Rayabharam <mail@anirudhrb.com> wrote:
>
> Return early when userspace sends zero regions in the VHOST_SET_MEM_TABLE
> ioctl.
>
> Otherwise, this causes an erroneous entry to be added to the iotlb. This
> entry has a range size of 0 (due to u64 overflow). This then causes
> iotlb_access_ok() to loop indefinitely resulting in a hung thread.
> Syzbot has reported this here:

Interesting, I think iotlb_access_ok() won't be called for memory
table entries, or anything I missed?

(If this is not true, we need a kernel patch as well).

Thanks

>
> https://syzkaller.appspot.com/bug?extid=0abd373e2e50d704db87
>
> Reported-and-tested-by: syzbot+0abd373e2e50d704db87@syzkaller.appspotmail.com
> Signed-off-by: Anirudh Rayabharam <mail@anirudhrb.com>
> ---
>  drivers/vhost/vhost.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> index 59edb5a1ffe2..821aba60eac2 100644
> --- a/drivers/vhost/vhost.c
> +++ b/drivers/vhost/vhost.c
> @@ -1428,6 +1428,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
>                 return -EFAULT;
>         if (mem.padding)
>                 return -EOPNOTSUPP;
> +       if (mem.nregions == 0)
> +               return 0;
>         if (mem.nregions > max_mem_regions)
>                 return -E2BIG;
>         newmem = kvzalloc(struct_size(newmem, regions, mem.nregions),
> --
> 2.35.1
>
Anirudh Rayabharam Feb. 21, 2022, 8:11 a.m. UTC | #2
On Mon, Feb 21, 2022 at 03:56:29PM +0800, Jason Wang wrote:
> On Mon, Feb 21, 2022 at 3:45 PM Anirudh Rayabharam <mail@anirudhrb.com> wrote:
> >
> > Return early when userspace sends zero regions in the VHOST_SET_MEM_TABLE
> > ioctl.
> >
> > Otherwise, this causes an erroneous entry to be added to the iotlb. This
> > entry has a range size of 0 (due to u64 overflow). This then causes
> > iotlb_access_ok() to loop indefinitely resulting in a hung thread.
> > Syzbot has reported this here:
> 
> Interesting, I think iotlb_access_ok() won't be called for memory
> table entries, or anything I missed?

Yeah, vhost_set_memory() doesn't call iotlb_access_ok(). The issue
appears when it is called later in a different code path. Here's the
trace for iotlb_access_ok():

NMI backtrace for cpu 1
CPU: 1 PID: 3633 Comm: vhost-3632 Not tainted 5.17.0-rc3-syzkaller-00029-ge6251ab4551f #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
RIP: 0010:check_kcov_mode kernel/kcov.c:166 [inline]
RIP: 0010:__sanitizer_cov_trace_pc+0xd/0x60 kernel/kcov.c:200
Code: 00 00 e9 c6 41 66 02 66 0f 1f 44 00 00 48 8b be b0 01 00 00 e8 b4 ff ff ff 31 c0 c3 90 65 8b 05 29 f7 89 7e 89 c1 48 8b 34 24 <81> e1 00 01 00 00 65 48 8b 14 25 00 70 02 00 a9 00 01 ff 00 74 0e
RSP: 0018:ffffc90000cd7c78 EFLAGS: 00000246
RAX: 0000000080000000 RBX: ffff888079ca8a80 RCX: 0000000080000000
RDX: 0000000000000000 RSI: ffffffff86d3f8fb RDI: 0000000000000003
RBP: 0000000000000000 R08: 0000000000000000 R09: ffffc90000cd7c77
R10: ffffffff86d3f8ed R11: 0000000000000001 R12: 0000000000000000
R13: 0000000000000000 R14: 0000000000000001 R15: 0000000000000000
FS:  0000000000000000(0000) GS:ffff8880b9d00000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007ffdf716a3b8 CR3: 00000000235b6000 CR4: 00000000003506e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
 <TASK>
 iotlb_access_ok+0x21b/0x3e0 drivers/vhost/vhost.c:1340
 vq_meta_prefetch+0xbc/0x280 drivers/vhost/vhost.c:1366
 vhost_transport_do_send_pkt+0xe0/0xfd0 drivers/vhost/vsock.c:104
 vhost_worker+0x23d/0x3d0 drivers/vhost/vhost.c:372
 kthread+0x2e9/0x3a0 kernel/kthread.c:377
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:295
 </TASK>
----------------

Thanks,

	- Anirudh
> 
> (If this is not true, we need a kernel patch as well).
> 
> Thanks
> 
> >
> > https://syzkaller.appspot.com/bug?extid=0abd373e2e50d704db87
> >
> > Reported-and-tested-by: syzbot+0abd373e2e50d704db87@syzkaller.appspotmail.com
> > Signed-off-by: Anirudh Rayabharam <mail@anirudhrb.com>
> > ---
> >  drivers/vhost/vhost.c | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> > index 59edb5a1ffe2..821aba60eac2 100644
> > --- a/drivers/vhost/vhost.c
> > +++ b/drivers/vhost/vhost.c
> > @@ -1428,6 +1428,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
> >                 return -EFAULT;
> >         if (mem.padding)
> >                 return -EOPNOTSUPP;
> > +       if (mem.nregions == 0)
> > +               return 0;
> >         if (mem.nregions > max_mem_regions)
> >                 return -E2BIG;
> >         newmem = kvzalloc(struct_size(newmem, regions, mem.nregions),
> > --
> > 2.35.1
> >
>
Stefano Garzarella Feb. 21, 2022, 4:48 p.m. UTC | #3
On Mon, Feb 21, 2022 at 12:58:51PM +0530, Anirudh Rayabharam wrote:
>Return early when userspace sends zero regions in the VHOST_SET_MEM_TABLE
>ioctl.
>
>Otherwise, this causes an erroneous entry to be added to the iotlb. This
>entry has a range size of 0 (due to u64 overflow). This then causes
>iotlb_access_ok() to loop indefinitely resulting in a hung thread.
>Syzbot has reported this here:
>
>https://syzkaller.appspot.com/bug?extid=0abd373e2e50d704db87

IIUC vhost_iotlb_add_range() in the for loop is never called if 
mem.nregions is 0, so I'm not sure the problem reported by syzbot is 
related.

In any case maybe this patch is fine, but currently I think we're just 
registering an iotlb without any regions, which in theory shouldn't 
cause any problems.

Thanks,
Stefano

>
>Reported-and-tested-by: syzbot+0abd373e2e50d704db87@syzkaller.appspotmail.com
>Signed-off-by: Anirudh Rayabharam <mail@anirudhrb.com>
>---
> drivers/vhost/vhost.c | 2 ++
> 1 file changed, 2 insertions(+)
>
>diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
>index 59edb5a1ffe2..821aba60eac2 100644
>--- a/drivers/vhost/vhost.c
>+++ b/drivers/vhost/vhost.c
>@@ -1428,6 +1428,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
> 		return -EFAULT;
> 	if (mem.padding)
> 		return -EOPNOTSUPP;
>+	if (mem.nregions == 0)
>+		return 0;
> 	if (mem.nregions > max_mem_regions)
> 		return -E2BIG;
> 	newmem = kvzalloc(struct_size(newmem, regions, mem.nregions),
>-- 
>2.35.1
>
Anirudh Rayabharam Feb. 21, 2022, 5:59 p.m. UTC | #4
On Mon, Feb 21, 2022 at 05:48:17PM +0100, Stefano Garzarella wrote:
> On Mon, Feb 21, 2022 at 12:58:51PM +0530, Anirudh Rayabharam wrote:
> > Return early when userspace sends zero regions in the VHOST_SET_MEM_TABLE
> > ioctl.
> > 
> > Otherwise, this causes an erroneous entry to be added to the iotlb. This
> > entry has a range size of 0 (due to u64 overflow). This then causes
> > iotlb_access_ok() to loop indefinitely resulting in a hung thread.
> > Syzbot has reported this here:
> > 
> > https://syzkaller.appspot.com/bug?extid=0abd373e2e50d704db87
> 
> IIUC vhost_iotlb_add_range() in the for loop is never called if mem.nregions
> is 0, so I'm not sure the problem reported by syzbot is related.

Oh you're right. My bad! The problem is actually elsewhere.

> 
> In any case maybe this patch is fine, but currently I think we're just
> registering an iotlb without any regions, which in theory shouldn't cause
> any problems.

Yeah, there shouldn't be any problems here. The problem actually seems
to be in vhost_process_iotlb_msg() where we end up adding a zero sized
region to the iotlb. I will send a new patch...

Thanks!
	- Anirudh.

> 
> Thanks,
> Stefano
> 
> > 
> > Reported-and-tested-by: syzbot+0abd373e2e50d704db87@syzkaller.appspotmail.com
> > Signed-off-by: Anirudh Rayabharam <mail@anirudhrb.com>
> > ---
> > drivers/vhost/vhost.c | 2 ++
> > 1 file changed, 2 insertions(+)
> > 
> > diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> > index 59edb5a1ffe2..821aba60eac2 100644
> > --- a/drivers/vhost/vhost.c
> > +++ b/drivers/vhost/vhost.c
> > @@ -1428,6 +1428,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
> > 		return -EFAULT;
> > 	if (mem.padding)
> > 		return -EOPNOTSUPP;
> > +	if (mem.nregions == 0)
> > +		return 0;
> > 	if (mem.nregions > max_mem_regions)
> > 		return -E2BIG;
> > 	newmem = kvzalloc(struct_size(newmem, regions, mem.nregions),
> > -- 
> > 2.35.1
> > 
>
Anirudh Rayabharam Feb. 21, 2022, 7:57 p.m. UTC | #5
On Mon, Feb 21, 2022 at 05:48:17PM +0100, Stefano Garzarella wrote:
> On Mon, Feb 21, 2022 at 12:58:51PM +0530, Anirudh Rayabharam wrote:
> > Return early when userspace sends zero regions in the VHOST_SET_MEM_TABLE
> > ioctl.
> > 
> > Otherwise, this causes an erroneous entry to be added to the iotlb. This
> > entry has a range size of 0 (due to u64 overflow). This then causes
> > iotlb_access_ok() to loop indefinitely resulting in a hung thread.
> > Syzbot has reported this here:
> > 
> > https://syzkaller.appspot.com/bug?extid=0abd373e2e50d704db87
> 
> IIUC vhost_iotlb_add_range() in the for loop is never called if mem.nregions
> is 0, so I'm not sure the problem reported by syzbot is related.
> 
> In any case maybe this patch is fine, but currently I think we're just
> registering an iotlb without any regions, which in theory shouldn't cause
> any problems.

Sent a new patch: https://lore.kernel.org/lkml/20220221195303.13560-1-mail@anirudhrb.com/T/#u

> 
> Thanks,
> Stefano
> 
> > 
> > Reported-and-tested-by: syzbot+0abd373e2e50d704db87@syzkaller.appspotmail.com
> > Signed-off-by: Anirudh Rayabharam <mail@anirudhrb.com>
> > ---
> > drivers/vhost/vhost.c | 2 ++
> > 1 file changed, 2 insertions(+)
> > 
> > diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> > index 59edb5a1ffe2..821aba60eac2 100644
> > --- a/drivers/vhost/vhost.c
> > +++ b/drivers/vhost/vhost.c
> > @@ -1428,6 +1428,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
> > 		return -EFAULT;
> > 	if (mem.padding)
> > 		return -EOPNOTSUPP;
> > +	if (mem.nregions == 0)
> > +		return 0;
> > 	if (mem.nregions > max_mem_regions)
> > 		return -E2BIG;
> > 	newmem = kvzalloc(struct_size(newmem, regions, mem.nregions),
> > -- 
> > 2.35.1
> > 
>
diff mbox series

Patch

diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 59edb5a1ffe2..821aba60eac2 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1428,6 +1428,8 @@  static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
 		return -EFAULT;
 	if (mem.padding)
 		return -EOPNOTSUPP;
+	if (mem.nregions == 0)
+		return 0;
 	if (mem.nregions > max_mem_regions)
 		return -E2BIG;
 	newmem = kvzalloc(struct_size(newmem, regions, mem.nregions),