diff options
Diffstat (limited to 'drivers/hid/uhid.c')
| -rw-r--r-- | drivers/hid/uhid.c | 25 | 
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 @@  #include <linux/atomic.h>  #include <linux/compat.h> +#include <linux/cred.h>  #include <linux/device.h>  #include <linux/fs.h>  #include <linux/hid.h> @@ -496,12 +497,13 @@ static int uhid_dev_create2(struct uhid_device *uhid,  		goto err_free;  	} -	len = min(sizeof(hid->name), sizeof(ev->u.create2.name)); -	strlcpy(hid->name, ev->u.create2.name, len); -	len = min(sizeof(hid->phys), sizeof(ev->u.create2.phys)); -	strlcpy(hid->phys, ev->u.create2.phys, len); -	len = min(sizeof(hid->uniq), sizeof(ev->u.create2.uniq)); -	strlcpy(hid->uniq, ev->u.create2.uniq, len); +	/* @hid is zero-initialized, strncpy() is correct, strlcpy() not */ +	len = min(sizeof(hid->name), sizeof(ev->u.create2.name)) - 1; +	strncpy(hid->name, ev->u.create2.name, len); +	len = min(sizeof(hid->phys), sizeof(ev->u.create2.phys)) - 1; +	strncpy(hid->phys, ev->u.create2.phys, len); +	len = min(sizeof(hid->uniq), sizeof(ev->u.create2.uniq)) - 1; +	strncpy(hid->uniq, ev->u.create2.uniq, len);  	hid->ll_driver = &uhid_hid_driver;  	hid->bus = ev->u.create2.bus; @@ -722,6 +724,17 @@ static ssize_t uhid_char_write(struct file *file, const char __user *buffer,  	switch (uhid->input_buf.type) {  	case UHID_CREATE: +		/* +		 * 'struct uhid_create_req' contains a __user pointer which is +		 * copied from, so it's unsafe to allow this with elevated +		 * privileges (e.g. from a setuid binary) or via kernel_write(). +		 */ +		if (file->f_cred != current_cred() || uaccess_kernel()) { +			pr_err_once("UHID_CREATE from different security context by process %d (%s), this is not allowed.\n", +				    task_tgid_vnr(current), current->comm); +			ret = -EACCES; +			goto unlock; +		}  		ret = uhid_dev_create(uhid, &uhid->input_buf);  		break;  	case UHID_CREATE2: | 
