|
@@ -12,6 +12,7 @@
|
|
|
|
|
|
|
|
#include <linux/atomic.h>
|
|
#include <linux/atomic.h>
|
|
|
#include <linux/compat.h>
|
|
#include <linux/compat.h>
|
|
|
|
|
+#include <linux/cred.h>
|
|
|
#include <linux/device.h>
|
|
#include <linux/device.h>
|
|
|
#include <linux/fs.h>
|
|
#include <linux/fs.h>
|
|
|
#include <linux/hid.h>
|
|
#include <linux/hid.h>
|
|
@@ -722,6 +723,17 @@ static ssize_t uhid_char_write(struct file *file, const char __user *buffer,
|
|
|
|
|
|
|
|
switch (uhid->input_buf.type) {
|
|
switch (uhid->input_buf.type) {
|
|
|
case UHID_CREATE:
|
|
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);
|
|
ret = uhid_dev_create(uhid, &uhid->input_buf);
|
|
|
break;
|
|
break;
|
|
|
case UHID_CREATE2:
|
|
case UHID_CREATE2:
|