linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] HID: uhid: fix a missing-check bug
@ 2018-05-05  4:17 Wenwen Wang
  2018-05-07  6:27 ` David Herrmann
  0 siblings, 1 reply; 2+ messages in thread
From: Wenwen Wang @ 2018-05-05  4:17 UTC (permalink / raw)
  To: Wenwen Wang
  Cc: Kangjie Lu, David Herrmann, Jiri Kosina, Benjamin Tissoires,
	open list:UHID USERSPACE HID IO DRIVER:,
	open list

In uhid_event_from_user(), if it is in_compat_syscall(), the 'type' of the
event is first fetched from the 'buffer' in userspace and checked. If the
'type' is UHID_CREATE, it is a messed up request with compat pointer, which
could be more than 256 bytes, so it is better allocated from the heap, as
mentioned in the comment. Its fields are then prepared one by one instead
of using a whole copy. For all other cases, the event object is copied
directly from user space. In other words, based on the 'type', the memory
size and structure of the event object vary.

Given that the 'buffer' resides in userspace, a malicious userspace process
can race to change the 'type' between the two copies, which will cause
inconsistency issues, potentially security issues. Plus, various operations
such as uhid_dev_destroy() and uhid_dev_input() are performed based on
'type' in function uhid_char_write(). If 'type' is modified by user, there
could be some issues such as uninitialized uses.

To fix this problem, we need to recheck the type after the second fetch to
make sure it is not UHID_CREATE.

Signed-off-by: Wenwen Wang <wang6495@umn.edu>
---
 drivers/hid/uhid.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
index 3c55073..0220385 100644
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -447,11 +447,17 @@ static int uhid_event_from_user(const char __user *buffer, size_t len,
 			event->u.create.country = compat->country;
 
 			kfree(compat);
-			return 0;
+		} else {
+			if (copy_from_user(event, buffer,
+					min(len, sizeof(*event))))
+				return -EFAULT;
+			if (event->type == UHID_CREATE)
+				return -EINVAL;
 		}
-		/* All others can be copied directly */
+		return 0;
 	}
 
+	/* Others can be copied directly */
 	if (copy_from_user(event, buffer, min(len, sizeof(*event))))
 		return -EFAULT;
 
-- 
2.7.4

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

* Re: [PATCH] HID: uhid: fix a missing-check bug
  2018-05-05  4:17 [PATCH] HID: uhid: fix a missing-check bug Wenwen Wang
@ 2018-05-07  6:27 ` David Herrmann
  0 siblings, 0 replies; 2+ messages in thread
From: David Herrmann @ 2018-05-07  6:27 UTC (permalink / raw)
  To: Wenwen Wang
  Cc: Kangjie Lu, David Herrmann, Jiri Kosina, Benjamin Tissoires,
	open list:UHID USERSPACE HID IO DRIVER:,
	open list, Dmitry Torokhov

Hey

On Sat, May 5, 2018 at 6:17 AM, Wenwen Wang <wang6495@umn.edu> wrote:
> In uhid_event_from_user(), if it is in_compat_syscall(), the 'type' of the
> event is first fetched from the 'buffer' in userspace and checked. If the
> 'type' is UHID_CREATE, it is a messed up request with compat pointer, which
> could be more than 256 bytes, so it is better allocated from the heap, as
> mentioned in the comment. Its fields are then prepared one by one instead
> of using a whole copy. For all other cases, the event object is copied
> directly from user space. In other words, based on the 'type', the memory
> size and structure of the event object vary.
>
> Given that the 'buffer' resides in userspace, a malicious userspace process
> can race to change the 'type' between the two copies, which will cause
> inconsistency issues, potentially security issues. Plus, various operations
> such as uhid_dev_destroy() and uhid_dev_input() are performed based on
> 'type' in function uhid_char_write(). If 'type' is modified by user, there
> could be some issues such as uninitialized uses.
>
> To fix this problem, we need to recheck the type after the second fetch to
> make sure it is not UHID_CREATE.
>
> Signed-off-by: Wenwen Wang <wang6495@umn.edu>
> ---
>  drivers/hid/uhid.c | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
> index 3c55073..0220385 100644
> --- a/drivers/hid/uhid.c
> +++ b/drivers/hid/uhid.c
> @@ -447,11 +447,17 @@ static int uhid_event_from_user(const char __user *buffer, size_t len,
>                         event->u.create.country = compat->country;
>
>                         kfree(compat);
> -                       return 0;
> +               } else {
> +                       if (copy_from_user(event, buffer,
> +                                       min(len, sizeof(*event))))
> +                               return -EFAULT;
> +                       if (event->type == UHID_CREATE)
> +                               return -EINVAL;

You are correct, the race against malicious/buggy user-space exists.
However, it is harmless. Lets assume user-space rewrites the input,
all that happens is that we end up with garbage in the kernel.
However, input-validation is done *after* this function, hence
everything will work just fine. If user-space rewrites input-buffers,
they better be aware that this might mean random garbage is pushed
into the kernel.

IOW, this race simply allows user-space to circumvent the "compat
conversion". But if user-space wants that... let them. No point in
protecting them from doing something stupid.

Thanks
David

>                 }
> -               /* All others can be copied directly */
> +               return 0;
>         }
>
> +       /* Others can be copied directly */
>         if (copy_from_user(event, buffer, min(len, sizeof(*event))))
>                 return -EFAULT;
>
> --
> 2.7.4
>

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

end of thread, other threads:[~2018-05-07  6:27 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-05  4:17 [PATCH] HID: uhid: fix a missing-check bug Wenwen Wang
2018-05-07  6:27 ` David Herrmann

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).