Re: [PATCH v3] Input: uinput - Add UI_SET_PHYS_STR and UI_SET_UNIQ_STR

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Dec 04, 2019 at 01:55:35PM -0800, Abhishek Pandit-Subedi wrote:
> The ioctl definition for UI_SET_PHYS is ambiguous because it is defined
> with size = sizeof(char*) but is expected to be given a variable length
> string. Add a deprecation notice for UI_SET_PHYS and provide
> UI_SET_PHYS_STR(len) which expects a size from the user.
> 
> Also support setting the uniq attribute of the input device. The uniq
> attribute is used as a unique identifier for the connected device.
> 
> For example, uinput devices created by BlueZ will store the address of
> the connected device as the uniq property.
> 
> Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@xxxxxxxxxxxx>
> ---
> Hi input maintainers,
> 
> Here is an updated patch that refactors the ioctl handlers (properly
> allowing the size to be set from userspace). When calling the new
> ioctls, the call signature will look like this:
> 
> ```
> ioctl(fd, UI_SET_PHYS_STR(18), "00:11:22:33:44:55");
> ```
> 
> I've tested this on a Chromebook running kernel v4.19 with a sample
> program compiled for both 32-bit (i.e. gcc -m32 test.c) and 64-bit.
> 
> The final uinput device looks like this:
> 
> ```
> udevadm info -a -p /devices/virtual/input/input18
> 
> Udevadm info starts with the device specified by the devpath and then
> walks up the chain of parent devices. It prints for every device
> found, all possible attributes in the udev rules key format.
> A rule to match, can be composed by the attributes of the device
> and the attributes from one single parent device.
> 
>   looking at device '/devices/virtual/input/input18':
>     KERNEL=="input18"
>     SUBSYSTEM=="input"
>     DRIVER==""
>     ATTR{inhibited}=="0"
>     ATTR{name}=="Test"
>     ATTR{phys}=="00:00:00:33:44:55"
>     ATTR{properties}=="0"
>     ATTR{uniq}=="00:11:22:00:00:00"
> 
> ```
> 
> 
> Changes in v3:
> - Added UI_SET_PHYS_STR(len) and UI_SET_UNIQ_STR(len) and added
>   deprecation notice for UI_SET_PHYS
> 
> Changes in v2:
> - Added compat handling for UI_SET_UNIQ
> 
>  drivers/input/misc/uinput.c | 41 ++++++++++++++++++++++++++++++++++++-
>  include/uapi/linux/uinput.h |  5 +++++
>  2 files changed, 45 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
> index 84051f20b18a..27a750896c71 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;
>  	}
>  }
> @@ -840,6 +843,7 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
>  	struct uinput_ff_erase  ff_erase;
>  	struct uinput_request   *req;
>  	char			*phys;
> +	char			*uniq;
>  	const char		*name;
>  	unsigned int		size;
>  
> @@ -916,6 +920,8 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
>  		goto out;
>  
>  	case UI_SET_PHYS:
> +		pr_warn_once("uinput: UI_SET_PHYS is deprecated. Use UI_SET_PHYS_STR");
> +
>  		if (udev->state == UIST_CREATED) {
>  			retval = -EINVAL;
>  			goto out;
> @@ -1023,6 +1029,39 @@ 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):
> +		if (udev->state == UIST_CREATED) {
> +			retval = -EINVAL;
> +			goto out;
> +		}
> +
> +		phys = strndup_user(p, size);
> +		if (IS_ERR(phys)) {
> +			retval = PTR_ERR(phys);
> +			goto out;
> +		}
> +
> +		kfree(udev->dev->phys);
> +		udev->dev->phys = phys;

Could we maybe refactor this into uinput_get_user_str(udev,
&udev->dev->phys, p, size) ?

> +		goto out;
> +
> +	case UI_SET_UNIQ_STR(0):
> +		if (udev->state == UIST_CREATED) {
> +			retval = -EINVAL;
> +			goto out;
> +		}
> +
> +		uniq = strndup_user(p, size);
> +		if (IS_ERR(uniq)) {
> +			retval = PTR_ERR(uniq);
> +			goto out;
> +		}
> +
> +		kfree(udev->dev->uniq);
> +		udev->dev->uniq = uniq;
> +		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)
> -- 
> 2.24.0.393.g34dc348eaf-goog
> 

-- 
Dmitry



[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux