Syzbot found an issue in usbmon where it can corrupt monitor internal memory causing the usbmon to crash with segfault, UAF, etc. The reproducer mmaps the /dev/usbmon memory to userspace and overwrites it with arbitrary data, which causes the issues. To prevent that explicitly clear the VM_WRITE flag in mon_bin_mmap().
Cc: linux-usb@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: stable@vger.kernel.org Fixes: 6f23ee1fefdc ("USB: add binary API to usbmon") Link: https://syzkaller.appspot.com/bug?id=2eb1f35d6525fa4a74d75b4244971e5b1411c95... Signed-off-by: Tadeusz Struk tadeusz.struk@linaro.org --- drivers/usb/mon/mon_bin.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index f48a23adbc35..f452fc03093c 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -1268,6 +1268,7 @@ static int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma) { /* don't do anything here: "fault" will set up page table entries */ vma->vm_ops = &mon_bin_vm_ops; + vma->vm_flags &= ~VM_WRITE; vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; vma->vm_private_data = filp->private_data; mon_bin_vma_open(vma);
On 9/16/22 15:47, Tadeusz Struk wrote:
Syzbot found an issue in usbmon where it can corrupt monitor internal memory causing the usbmon to crash with segfault, UAF, etc. The reproducer mmaps the /dev/usbmon memory to userspace and overwrites it with arbitrary data, which causes the issues. To prevent that explicitly clear the VM_WRITE flag in mon_bin_mmap().
Cc:linux-usb@vger.kernel.org Cc:linux-kernel@vger.kernel.org Cc:stable@vger.kernel.org Fixes: 6f23ee1fefdc ("USB: add binary API to usbmon") Link:https://syzkaller.appspot.com/bug?id=2eb1f35d6525fa4a74d75b4244971e5b1411c95... Signed-off-by: Tadeusz Struktadeusz.struk@linaro.org
I forgot to add: Reported-by: syzbot+23f57c5ae902429285d7@syzkaller.appspotmail.com
Hi Tadeusz,
Looking at places like these: https://elixir.bootlin.com/linux/v6.0-rc5/source/drivers/infiniband/hw/qib/q... https://elixir.bootlin.com/linux/v6.0-rc5/source/drivers/infiniband/hw/mlx5/... I think we also need to remove VM_MAYWRITE, otherwise it's still possible to turn it into a writable mapping with mprotect.
It's also probably better to return an error if VM_WRITE (or VM_EXEC?) is set rather than silently fix it up.
On Mon, 19 Sept 2022 at 06:25, Dmitry Vyukov dvyukov@google.com wrote:
Hi Tadeusz,
Looking at places like these: https://elixir.bootlin.com/linux/v6.0-rc5/source/drivers/infiniband/hw/qib/q... https://elixir.bootlin.com/linux/v6.0-rc5/source/drivers/infiniband/hw/mlx5/... I think we also need to remove VM_MAYWRITE, otherwise it's still possible to turn it into a writable mapping with mprotect.
It's also probably better to return an error if VM_WRITE (or VM_EXEC?) is set rather than silently fix it up.
The credit for the VM_MAYWRITE suggestion goes to the PaX Team.
Suggested-by: PaX Team pageexec@freemail.hu
Hi Dmitry, On 9/18/22 21:25, Dmitry Vyukov wrote:
Hi Tadeusz,
Looking at places like these: https://elixir.bootlin.com/linux/v6.0-rc5/source/drivers/infiniband/hw/qib/q... https://elixir.bootlin.com/linux/v6.0-rc5/source/drivers/infiniband/hw/mlx5/... I think we also need to remove VM_MAYWRITE, otherwise it's still possible to turn it into a writable mapping with mprotect.
It's also probably better to return an error if VM_WRITE (or VM_EXEC?) is set rather than silently fix it up.
Yes, I think that returning an error will make more sense here. I don't think we need to worry about VM_EXEC. Even if userspace will try to execute from the mmaped location it won't work. It will probably crash the application without causing any harm to the kernel. I will update the patch and send a v2 soon.
Syzbot found an issue in usbmon module, where the user space client can corrupt the monitor's internal memory, causing the usbmon module to crash the kernel with segfault, UAF, etc. The reproducer mmaps the /dev/usbmon memory to user space, and overwrites it with arbitrary data, which causes all kinds of issues. Return an -EPERM error from mon_bin_mmap() if the flag VM_WRTIE is set. Also clear VM_MAYWRITE to make it impossible to change it to writable later.
Cc: "Dmitry Vyukov" dvyukov@google.com Cc: linux-usb@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: stable@vger.kernel.org Fixes: 6f23ee1fefdc ("USB: add binary API to usbmon")
For the VM_MAYWRITE part: Suggested-by: PaX Team pageexec@freemail.hu
Link: https://syzkaller.appspot.com/bug?id=2eb1f35d6525fa4a74d75b4244971e5b1411c95... Reported-by: syzbot+23f57c5ae902429285d7@syzkaller.appspotmail.com Signed-off-by: Tadeusz Struk tadeusz.struk@linaro.org --- v2: Return an error instead of quietly clearing the flag, when VM_WRTIE is set. Also clear VM_MAYWRITE. --- drivers/usb/mon/mon_bin.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index f48a23adbc35..094e812e9e69 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -1268,6 +1268,11 @@ static int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma) { /* don't do anything here: "fault" will set up page table entries */ vma->vm_ops = &mon_bin_vm_ops; + + if (vma->vm_flags & VM_WRITE) + return -EPERM; + + vma->vm_flags &= ~VM_MAYWRITE; vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; vma->vm_private_data = filp->private_data; mon_bin_vma_open(vma);
linux-stable-mirror@lists.linaro.org