--- 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 #include +#include #include #include #include @@ -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)