When in_compat_syscall(), a user could make type != UHID_CREATE when
get_user(type, buffer) [first fetch] and later make event->type ==
UHID_CREATE in copy_from_user(event, buffer, ...) [second fetch].

By doing so, an attacker might circumvent the specific logic to handle
the type == UHID_CREATE case and later cause undefined behaviors.

This patch enforces that event->type is overriden to the type value
copied in the first fetch and thus, mitigate this race condition attack.

Signed-off-by: Meng Xu <mengxu.gat...@gmail.com>
---
 drivers/hid/uhid.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
index 7f8ff39..4bbfd8a 100644
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -448,11 +448,20 @@ static int uhid_event_from_user(const char __user 
*buffer, size_t len,
                        kfree(compat);
                        return 0;
                }
+
                /* All others can be copied directly */
-       }
+               if (copy_from_user(event, buffer, min(len, sizeof(*event))))
+                       return -EFAULT;
 
-       if (copy_from_user(event, buffer, min(len, sizeof(*event))))
-               return -EFAULT;
+               /* 
+                * Override type in case the user process rushes to change it 
+                * between two fetches 
+                * */
+               event->type = type;
+       } else {
+               if (copy_from_user(event, buffer, min(len, sizeof(*event))))
+                       return -EFAULT;
+       }
 
        return 0;
 }
-- 
2.7.4

Reply via email to