aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/uhid.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/uhid.c')
-rw-r--r--drivers/hid/uhid.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
index 3c5507313606..840634e0f1e3 100644
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -12,6 +12,7 @@
12 12
13#include <linux/atomic.h> 13#include <linux/atomic.h>
14#include <linux/compat.h> 14#include <linux/compat.h>
15#include <linux/cred.h>
15#include <linux/device.h> 16#include <linux/device.h>
16#include <linux/fs.h> 17#include <linux/fs.h>
17#include <linux/hid.h> 18#include <linux/hid.h>
@@ -496,12 +497,13 @@ static int uhid_dev_create2(struct uhid_device *uhid,
496 goto err_free; 497 goto err_free;
497 } 498 }
498 499
499 len = min(sizeof(hid->name), sizeof(ev->u.create2.name)); 500 /* @hid is zero-initialized, strncpy() is correct, strlcpy() not */
500 strlcpy(hid->name, ev->u.create2.name, len); 501 len = min(sizeof(hid->name), sizeof(ev->u.create2.name)) - 1;
501 len = min(sizeof(hid->phys), sizeof(ev->u.create2.phys)); 502 strncpy(hid->name, ev->u.create2.name, len);
502 strlcpy(hid->phys, ev->u.create2.phys, len); 503 len = min(sizeof(hid->phys), sizeof(ev->u.create2.phys)) - 1;
503 len = min(sizeof(hid->uniq), sizeof(ev->u.create2.uniq)); 504 strncpy(hid->phys, ev->u.create2.phys, len);
504 strlcpy(hid->uniq, ev->u.create2.uniq, len); 505 len = min(sizeof(hid->uniq), sizeof(ev->u.create2.uniq)) - 1;
506 strncpy(hid->uniq, ev->u.create2.uniq, len);
505 507
506 hid->ll_driver = &uhid_hid_driver; 508 hid->ll_driver = &uhid_hid_driver;
507 hid->bus = ev->u.create2.bus; 509 hid->bus = ev->u.create2.bus;
@@ -722,6 +724,17 @@ static ssize_t uhid_char_write(struct file *file, const char __user *buffer,
722 724
723 switch (uhid->input_buf.type) { 725 switch (uhid->input_buf.type) {
724 case UHID_CREATE: 726 case UHID_CREATE:
727 /*
728 * 'struct uhid_create_req' contains a __user pointer which is
729 * copied from, so it's unsafe to allow this with elevated
730 * privileges (e.g. from a setuid binary) or via kernel_write().
731 */
732 if (file->f_cred != current_cred() || uaccess_kernel()) {
733 pr_err_once("UHID_CREATE from different security context by process %d (%s), this is not allowed.\n",
734 task_tgid_vnr(current), current->comm);
735 ret = -EACCES;
736 goto unlock;
737 }
725 ret = uhid_dev_create(uhid, &uhid->input_buf); 738 ret = uhid_dev_create(uhid, &uhid->input_buf);
726 break; 739 break;
727 case UHID_CREATE2: 740 case UHID_CREATE2: