1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
---
drivers/input/misc/uinput.c | 48 +++++++++++++++++++++++++------------
include/uapi/linux/uinput.h | 5 ++++
2 files changed, 38 insertions(+), 15 deletions(-)
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 84051f20b18a..2c3180370a02 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -20,6 +20,7 @@
*/
#include <uapi/linux/uinput.h>
#include <linux/poll.h>
+#include <linux/printk.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/module.h>
@@ -280,7 +281,7 @@ static int uinput_dev_flush(struct input_dev *dev, struct file *file)
static void uinput_destroy_device(struct uinput_device *udev)
{
- const char *name, *phys;
+ const char *name, *phys, *uniq;
struct input_dev *dev = udev->dev;
enum uinput_state old_state = udev->state;
@@ -289,6 +290,7 @@ static void uinput_destroy_device(struct uinput_device *udev)
if (dev) {
name = dev->name;
phys = dev->phys;
+ uniq = dev->uniq;
if (old_state == UIST_CREATED) {
uinput_flush_requests(udev);
input_unregister_device(dev);
@@ -297,6 +299,7 @@ static void uinput_destroy_device(struct uinput_device *udev)
}
kfree(name);
kfree(phys);
+ kfree(uniq);
udev->dev = NULL;
}
}
@@ -831,6 +834,24 @@ static int uinput_str_to_user(void __user *dest, const char *str,
return ret ? -EFAULT : len;
}
+static int uinput_get_user_str(struct uinput_device *udev, const char **kptr,
+ const char *uptr, unsigned int size)
+{
+ char *tmp;
+
+ if (udev->state == UIST_CREATED)
+ return -EINVAL;
+
+ tmp = strndup_user(uptr, size);
+ if (IS_ERR(tmp))
+ return PTR_ERR(tmp);
+
+ kfree(*kptr);
+ *kptr = tmp;
+
+ return 0;
+}
+
static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
unsigned long arg, void __user *p)
{
@@ -839,7 +860,6 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
struct uinput_ff_upload ff_up;
struct uinput_ff_erase ff_erase;
struct uinput_request *req;
- char *phys;
const char *name;
unsigned int size;
@@ -916,19 +936,8 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
goto out;
case UI_SET_PHYS:
- if (udev->state == UIST_CREATED) {
- retval = -EINVAL;
- goto out;
- }
-
- phys = strndup_user(p, 1024);
- if (IS_ERR(phys)) {
- retval = PTR_ERR(phys);
- goto out;
- }
-
- kfree(udev->dev->phys);
- udev->dev->phys = phys;
+ pr_warn_once("uinput: UI_SET_PHYS is deprecated. Use UI_SET_PHYS_STR");
+ retval = uinput_get_user_str(udev, &udev->dev->phys, p, 1024);
goto out;
case UI_BEGIN_FF_UPLOAD:
@@ -1023,6 +1032,15 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
case UI_ABS_SETUP & ~IOCSIZE_MASK:
retval = uinput_abs_setup(udev, p, size);
goto out;
+
+ case UI_SET_PHYS_STR(0):
+ retval = uinput_get_user_str(udev, &udev->dev->phys, p, size);
+ goto out;
+
+ case UI_SET_UNIQ_STR(0):
+ retval = uinput_get_user_str(udev, &udev->dev->uniq, p, size);
+ goto out;
+
}
retval = -EINVAL;
diff --git a/include/uapi/linux/uinput.h b/include/uapi/linux/uinput.h
index c9e677e3af1d..84d4fa142830 100644
--- a/include/uapi/linux/uinput.h
+++ b/include/uapi/linux/uinput.h
@@ -142,9 +142,14 @@ struct uinput_abs_setup {
#define UI_SET_LEDBIT _IOW(UINPUT_IOCTL_BASE, 105, int)
#define UI_SET_SNDBIT _IOW(UINPUT_IOCTL_BASE, 106, int)
#define UI_SET_FFBIT _IOW(UINPUT_IOCTL_BASE, 107, int)
+
+/* DEPRECATED: Data size is ambiguous. Use UI_SET_PHYS_STR instead. */
#define UI_SET_PHYS _IOW(UINPUT_IOCTL_BASE, 108, char*)
+
#define UI_SET_SWBIT _IOW(UINPUT_IOCTL_BASE, 109, int)
#define UI_SET_PROPBIT _IOW(UINPUT_IOCTL_BASE, 110, int)
+#define UI_SET_PHYS_STR(len) _IOC(_IOC_WRITE, UINPUT_IOCTL_BASE, 111, len)
+#define UI_SET_UNIQ_STR(len) _IOC(_IOC_WRITE, UINPUT_IOCTL_BASE, 112, len)
#define UI_BEGIN_FF_UPLOAD _IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload)
#define UI_END_FF_UPLOAD _IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload)
|