diff options
| author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2008-05-26 05:25:26 -0400 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2008-07-23 09:21:55 -0400 |
| commit | 979c407e3b89b606e810fa494ef316896eadbfad (patch) | |
| tree | 87cd809c8ef5bcb7957a29354e2e7e17fec27e00 | |
| parent | 7961df16819085b8a357720d89d0239036e6af2a (diff) | |
HID: Push down BKL into ioctl handler in hidraw
In this case I simply wrapped it as code review suggests the locking
already terminally broken and I didn't want to make it first. See added
comment
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
| -rw-r--r-- | drivers/hid/hidraw.c | 46 |
1 files changed, 24 insertions, 22 deletions
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 0c6b4d4e7e27..1018f380de35 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
| @@ -105,6 +105,7 @@ out: | |||
| 105 | static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 105 | static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) |
| 106 | { | 106 | { |
| 107 | unsigned int minor = iminor(file->f_path.dentry->d_inode); | 107 | unsigned int minor = iminor(file->f_path.dentry->d_inode); |
| 108 | /* FIXME: What stops hidraw_table going NULL */ | ||
| 108 | struct hid_device *dev = hidraw_table[minor]->hid; | 109 | struct hid_device *dev = hidraw_table[minor]->hid; |
| 109 | __u8 *buf; | 110 | __u8 *buf; |
| 110 | int ret = 0; | 111 | int ret = 0; |
| @@ -214,35 +215,38 @@ static int hidraw_release(struct inode * inode, struct file * file) | |||
| 214 | return 0; | 215 | return 0; |
| 215 | } | 216 | } |
| 216 | 217 | ||
| 217 | static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 218 | static long hidraw_ioctl(struct file *file, unsigned int cmd, |
| 219 | unsigned long arg) | ||
| 218 | { | 220 | { |
| 221 | struct inode *inode = file->f_path.dentry->d_inode; | ||
| 219 | unsigned int minor = iminor(inode); | 222 | unsigned int minor = iminor(inode); |
| 223 | long ret = 0; | ||
| 224 | /* FIXME: What stops hidraw_table going NULL */ | ||
| 220 | struct hidraw *dev = hidraw_table[minor]; | 225 | struct hidraw *dev = hidraw_table[minor]; |
| 221 | void __user *user_arg = (void __user*) arg; | 226 | void __user *user_arg = (void __user*) arg; |
| 222 | 227 | ||
| 228 | lock_kernel(); | ||
| 223 | switch (cmd) { | 229 | switch (cmd) { |
| 224 | case HIDIOCGRDESCSIZE: | 230 | case HIDIOCGRDESCSIZE: |
| 225 | if (put_user(dev->hid->rsize, (int __user *)arg)) | 231 | if (put_user(dev->hid->rsize, (int __user *)arg)) |
| 226 | return -EFAULT; | 232 | ret = -EFAULT; |
| 227 | return 0; | 233 | break; |
| 228 | 234 | ||
| 229 | case HIDIOCGRDESC: | 235 | case HIDIOCGRDESC: |
| 230 | { | 236 | { |
| 231 | __u32 len; | 237 | __u32 len; |
| 232 | 238 | ||
| 233 | if (get_user(len, (int __user *)arg)) | 239 | if (get_user(len, (int __user *)arg)) |
| 234 | return -EFAULT; | 240 | ret = -EFAULT; |
| 235 | 241 | else if (len > HID_MAX_DESCRIPTOR_SIZE - 1) | |
| 236 | if (len > HID_MAX_DESCRIPTOR_SIZE - 1) | 242 | ret = -EINVAL; |
| 237 | return -EINVAL; | 243 | else if (copy_to_user(user_arg + offsetof( |
| 238 | 244 | struct hidraw_report_descriptor, | |
| 239 | if (copy_to_user(user_arg + offsetof( | 245 | value[0]), |
| 240 | struct hidraw_report_descriptor, | 246 | dev->hid->rdesc, |
| 241 | value[0]), | 247 | min(dev->hid->rsize, len))) |
| 242 | dev->hid->rdesc, | 248 | ret = -EFAULT; |
| 243 | min(dev->hid->rsize, len))) | 249 | break; |
| 244 | return -EFAULT; | ||
| 245 | return 0; | ||
| 246 | } | 250 | } |
| 247 | case HIDIOCGRAWINFO: | 251 | case HIDIOCGRAWINFO: |
| 248 | { | 252 | { |
| @@ -252,15 +256,13 @@ static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
| 252 | dinfo.vendor = dev->hid->vendor; | 256 | dinfo.vendor = dev->hid->vendor; |
| 253 | dinfo.product = dev->hid->product; | 257 | dinfo.product = dev->hid->product; |
| 254 | if (copy_to_user(user_arg, &dinfo, sizeof(dinfo))) | 258 | if (copy_to_user(user_arg, &dinfo, sizeof(dinfo))) |
| 255 | return -EFAULT; | 259 | ret = -EFAULT; |
| 256 | 260 | break; | |
| 257 | return 0; | ||
| 258 | } | 261 | } |
| 259 | default: | 262 | default: |
| 260 | printk(KERN_EMERG "hidraw: unsupported ioctl() %x\n", | 263 | ret = -ENOTTY; |
| 261 | cmd); | ||
| 262 | } | 264 | } |
| 263 | return -EINVAL; | 265 | return ret; |
| 264 | } | 266 | } |
| 265 | 267 | ||
| 266 | static const struct file_operations hidraw_ops = { | 268 | static const struct file_operations hidraw_ops = { |
| @@ -270,7 +272,7 @@ static const struct file_operations hidraw_ops = { | |||
| 270 | .poll = hidraw_poll, | 272 | .poll = hidraw_poll, |
| 271 | .open = hidraw_open, | 273 | .open = hidraw_open, |
| 272 | .release = hidraw_release, | 274 | .release = hidraw_release, |
| 273 | .ioctl = hidraw_ioctl, | 275 | .unlocked_ioctl = hidraw_ioctl, |
| 274 | }; | 276 | }; |
| 275 | 277 | ||
| 276 | void hidraw_report_event(struct hid_device *hid, u8 *data, int len) | 278 | void hidraw_report_event(struct hid_device *hid, u8 *data, int len) |
