Input: joydev - validate axis/button maps before clobbering current ones
Up to now axis and button map validation was done after the user-supplied values were copied over the driver's map. This patch copies the user-supplied values into temporary buffers and validated them before overwriting the driver's permanent maps. Also change JSIOCGBTNMAP and JSIOCGAXMAP to return number of bytes returned to userspace instead of 0. Signed-off-by: Stephen Kitt <steve@sk2.org> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
This commit is contained in:
parent
4b61bb575b
commit
999b874f4a
1 changed files with 74 additions and 32 deletions
|
@ -452,6 +452,76 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait)
|
|||
(joydev->exist ? 0 : (POLLHUP | POLLERR));
|
||||
}
|
||||
|
||||
static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev,
|
||||
void __user *argp, size_t len)
|
||||
{
|
||||
__u8 *abspam;
|
||||
int i;
|
||||
int retval = 0;
|
||||
|
||||
len = min(len, sizeof(joydev->abspam));
|
||||
|
||||
/* Validate the map. */
|
||||
abspam = kmalloc(len, GFP_KERNEL);
|
||||
if (!abspam)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(abspam, argp, len)) {
|
||||
retval = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < joydev->nabs; i++) {
|
||||
if (abspam[i] > ABS_MAX) {
|
||||
retval = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(joydev->abspam, abspam, len);
|
||||
|
||||
out:
|
||||
kfree(abspam);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev,
|
||||
void __user *argp, size_t len)
|
||||
{
|
||||
__u16 *keypam;
|
||||
int i;
|
||||
int retval = 0;
|
||||
|
||||
len = min(len, sizeof(joydev->keypam));
|
||||
|
||||
/* Validate the map. */
|
||||
keypam = kmalloc(len, GFP_KERNEL);
|
||||
if (!keypam)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(keypam, argp, len)) {
|
||||
retval = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < joydev->nkey; i++) {
|
||||
if (keypam[i] > KEY_MAX || keypam[i] < BTN_MISC) {
|
||||
retval = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(joydev->keypam, keypam, len);
|
||||
|
||||
for (i = 0; i < joydev->nkey; i++)
|
||||
joydev->keymap[keypam[i] - BTN_MISC] = i;
|
||||
|
||||
out:
|
||||
kfree(keypam);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static int joydev_ioctl_common(struct joydev *joydev,
|
||||
unsigned int cmd, void __user *argp)
|
||||
{
|
||||
|
@ -512,46 +582,18 @@ static int joydev_ioctl_common(struct joydev *joydev,
|
|||
switch (cmd & ~IOCSIZE_MASK) {
|
||||
|
||||
case (JSIOCSAXMAP & ~IOCSIZE_MASK):
|
||||
len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam));
|
||||
/*
|
||||
* FIXME: we should not copy into our axis map before
|
||||
* validating the data.
|
||||
*/
|
||||
if (copy_from_user(joydev->abspam, argp, len))
|
||||
return -EFAULT;
|
||||
|
||||
for (i = 0; i < joydev->nabs; i++) {
|
||||
if (joydev->abspam[i] > ABS_MAX)
|
||||
return -EINVAL;
|
||||
joydev->absmap[joydev->abspam[i]] = i;
|
||||
}
|
||||
return 0;
|
||||
return joydev_handle_JSIOCSAXMAP(joydev, argp, _IOC_SIZE(cmd));
|
||||
|
||||
case (JSIOCGAXMAP & ~IOCSIZE_MASK):
|
||||
len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam));
|
||||
return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : 0;
|
||||
return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : len;
|
||||
|
||||
case (JSIOCSBTNMAP & ~IOCSIZE_MASK):
|
||||
len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam));
|
||||
/*
|
||||
* FIXME: we should not copy into our keymap before
|
||||
* validating the data.
|
||||
*/
|
||||
if (copy_from_user(joydev->keypam, argp, len))
|
||||
return -EFAULT;
|
||||
|
||||
for (i = 0; i < joydev->nkey; i++) {
|
||||
if (joydev->keypam[i] > KEY_MAX ||
|
||||
joydev->keypam[i] < BTN_MISC)
|
||||
return -EINVAL;
|
||||
joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return joydev_handle_JSIOCSBTNMAP(joydev, argp, _IOC_SIZE(cmd));
|
||||
|
||||
case (JSIOCGBTNMAP & ~IOCSIZE_MASK):
|
||||
len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam));
|
||||
return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : 0;
|
||||
return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : len;
|
||||
|
||||
case JSIOCGNAME(0):
|
||||
name = dev->name;
|
||||
|
|
Loading…
Reference in a new issue