Loading drivers/hid/hidraw.c +35 −4 Original line number Diff line number Diff line Loading @@ -38,12 +38,20 @@ static const struct class hidraw_class = { static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; static DECLARE_RWSEM(minors_rwsem); static inline bool hidraw_is_revoked(struct hidraw_list *list) { return list->revoked; } static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct hidraw_list *list = file->private_data; int ret = 0, len; DECLARE_WAITQUEUE(wait, current); if (hidraw_is_revoked(list)) return -ENODEV; mutex_lock(&list->read_mutex); while (ret == 0) { Loading Loading @@ -161,8 +169,12 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { struct hidraw_list *list = file->private_data; ssize_t ret; down_read(&minors_rwsem); if (hidraw_is_revoked(list)) ret = -ENODEV; else ret = hidraw_send_report(file, buffer, count, HID_OUTPUT_REPORT); up_read(&minors_rwsem); return ret; Loading Loading @@ -256,7 +268,7 @@ static __poll_t hidraw_poll(struct file *file, poll_table *wait) poll_wait(file, &list->hidraw->wait, wait); if (list->head != list->tail) mask |= EPOLLIN | EPOLLRDNORM; if (!list->hidraw->exist) if (!list->hidraw->exist || hidraw_is_revoked(list)) mask |= EPOLLERR | EPOLLHUP; return mask; } Loading Loading @@ -320,6 +332,9 @@ static int hidraw_fasync(int fd, struct file *file, int on) { struct hidraw_list *list = file->private_data; if (hidraw_is_revoked(list)) return -ENODEV; return fasync_helper(fd, file, on, &list->fasync); } Loading Loading @@ -372,6 +387,13 @@ static int hidraw_release(struct inode * inode, struct file * file) return 0; } static int hidraw_revoke(struct hidraw_list *list) { list->revoked = true; return 0; } static long hidraw_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { Loading @@ -379,11 +401,12 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, unsigned int minor = iminor(inode); long ret = 0; struct hidraw *dev; struct hidraw_list *list = file->private_data; void __user *user_arg = (void __user*) arg; down_read(&minors_rwsem); dev = hidraw_table[minor]; if (!dev || !dev->exist) { if (!dev || !dev->exist || hidraw_is_revoked(list)) { ret = -ENODEV; goto out; } Loading Loading @@ -421,6 +444,14 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, ret = -EFAULT; break; } case HIDIOCREVOKE: { if (user_arg) ret = -EINVAL; else ret = hidraw_revoke(list); break; } default: { struct hid_device *hid = dev->hid; Loading Loading @@ -527,7 +558,7 @@ int hidraw_report_event(struct hid_device *hid, u8 *data, int len) list_for_each_entry(list, &dev->list, node) { int new_head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1); if (new_head == list->tail) if (hidraw_is_revoked(list) || new_head == list->tail) continue; if (!(list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC))) { Loading include/linux/hidraw.h +1 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ struct hidraw_list { struct hidraw *hidraw; struct list_head node; struct mutex read_mutex; bool revoked; }; #ifdef CONFIG_HIDRAW Loading include/uapi/linux/hidraw.h +1 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ struct hidraw_devinfo { /* The first byte of SOUTPUT and GOUTPUT is the report number */ #define HIDIOCSOUTPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0B, len) #define HIDIOCGOUTPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0C, len) #define HIDIOCREVOKE _IOW('H', 0x0D, int) /* Revoke device access */ #define HIDRAW_FIRST_MINOR 0 #define HIDRAW_MAX_DEVICES 64 Loading tools/testing/selftests/hid/.gitignore +1 −0 Original line number Diff line number Diff line Loading @@ -2,4 +2,5 @@ bpftool *.skel.h /tools hid_bpf hidraw results tools/testing/selftests/hid/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ CFLAGS += -Wno-unused-command-line-argument endif # Order correspond to 'make run_tests' order TEST_GEN_PROGS = hid_bpf TEST_GEN_PROGS = hid_bpf hidraw # Emit succinct information message describing current building step # $1 - generic step name (e.g., CC, LINK, etc); Loading Loading
drivers/hid/hidraw.c +35 −4 Original line number Diff line number Diff line Loading @@ -38,12 +38,20 @@ static const struct class hidraw_class = { static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; static DECLARE_RWSEM(minors_rwsem); static inline bool hidraw_is_revoked(struct hidraw_list *list) { return list->revoked; } static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct hidraw_list *list = file->private_data; int ret = 0, len; DECLARE_WAITQUEUE(wait, current); if (hidraw_is_revoked(list)) return -ENODEV; mutex_lock(&list->read_mutex); while (ret == 0) { Loading Loading @@ -161,8 +169,12 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { struct hidraw_list *list = file->private_data; ssize_t ret; down_read(&minors_rwsem); if (hidraw_is_revoked(list)) ret = -ENODEV; else ret = hidraw_send_report(file, buffer, count, HID_OUTPUT_REPORT); up_read(&minors_rwsem); return ret; Loading Loading @@ -256,7 +268,7 @@ static __poll_t hidraw_poll(struct file *file, poll_table *wait) poll_wait(file, &list->hidraw->wait, wait); if (list->head != list->tail) mask |= EPOLLIN | EPOLLRDNORM; if (!list->hidraw->exist) if (!list->hidraw->exist || hidraw_is_revoked(list)) mask |= EPOLLERR | EPOLLHUP; return mask; } Loading Loading @@ -320,6 +332,9 @@ static int hidraw_fasync(int fd, struct file *file, int on) { struct hidraw_list *list = file->private_data; if (hidraw_is_revoked(list)) return -ENODEV; return fasync_helper(fd, file, on, &list->fasync); } Loading Loading @@ -372,6 +387,13 @@ static int hidraw_release(struct inode * inode, struct file * file) return 0; } static int hidraw_revoke(struct hidraw_list *list) { list->revoked = true; return 0; } static long hidraw_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { Loading @@ -379,11 +401,12 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, unsigned int minor = iminor(inode); long ret = 0; struct hidraw *dev; struct hidraw_list *list = file->private_data; void __user *user_arg = (void __user*) arg; down_read(&minors_rwsem); dev = hidraw_table[minor]; if (!dev || !dev->exist) { if (!dev || !dev->exist || hidraw_is_revoked(list)) { ret = -ENODEV; goto out; } Loading Loading @@ -421,6 +444,14 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, ret = -EFAULT; break; } case HIDIOCREVOKE: { if (user_arg) ret = -EINVAL; else ret = hidraw_revoke(list); break; } default: { struct hid_device *hid = dev->hid; Loading Loading @@ -527,7 +558,7 @@ int hidraw_report_event(struct hid_device *hid, u8 *data, int len) list_for_each_entry(list, &dev->list, node) { int new_head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1); if (new_head == list->tail) if (hidraw_is_revoked(list) || new_head == list->tail) continue; if (!(list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC))) { Loading
include/linux/hidraw.h +1 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ struct hidraw_list { struct hidraw *hidraw; struct list_head node; struct mutex read_mutex; bool revoked; }; #ifdef CONFIG_HIDRAW Loading
include/uapi/linux/hidraw.h +1 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ struct hidraw_devinfo { /* The first byte of SOUTPUT and GOUTPUT is the report number */ #define HIDIOCSOUTPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0B, len) #define HIDIOCGOUTPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0C, len) #define HIDIOCREVOKE _IOW('H', 0x0D, int) /* Revoke device access */ #define HIDRAW_FIRST_MINOR 0 #define HIDRAW_MAX_DEVICES 64 Loading
tools/testing/selftests/hid/.gitignore +1 −0 Original line number Diff line number Diff line Loading @@ -2,4 +2,5 @@ bpftool *.skel.h /tools hid_bpf hidraw results
tools/testing/selftests/hid/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ CFLAGS += -Wno-unused-command-line-argument endif # Order correspond to 'make run_tests' order TEST_GEN_PROGS = hid_bpf TEST_GEN_PROGS = hid_bpf hidraw # Emit succinct information message describing current building step # $1 - generic step name (e.g., CC, LINK, etc); Loading