Skip to content

Commit 6937a82

Browse files
author
Benjamin Tissoires
committed
Merge branch 'for-6.12/hidraw' into for-linus
- introduction of HIDIOCREVOKE ioctl to revoke a hidraw fd opened by a regular (non-root) application (Peter Hutterer)
2 parents 054e0bd + 321f779 commit 6937a82

File tree

8 files changed

+714
-440
lines changed

8 files changed

+714
-440
lines changed

drivers/hid/hidraw.c

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,20 @@ static const struct class hidraw_class = {
3838
static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];
3939
static DECLARE_RWSEM(minors_rwsem);
4040

41+
static inline bool hidraw_is_revoked(struct hidraw_list *list)
42+
{
43+
return list->revoked;
44+
}
45+
4146
static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
4247
{
4348
struct hidraw_list *list = file->private_data;
4449
int ret = 0, len;
4550
DECLARE_WAITQUEUE(wait, current);
4651

52+
if (hidraw_is_revoked(list))
53+
return -ENODEV;
54+
4755
mutex_lock(&list->read_mutex);
4856

4957
while (ret == 0) {
@@ -161,9 +169,13 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,
161169

162170
static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
163171
{
172+
struct hidraw_list *list = file->private_data;
164173
ssize_t ret;
165174
down_read(&minors_rwsem);
166-
ret = hidraw_send_report(file, buffer, count, HID_OUTPUT_REPORT);
175+
if (hidraw_is_revoked(list))
176+
ret = -ENODEV;
177+
else
178+
ret = hidraw_send_report(file, buffer, count, HID_OUTPUT_REPORT);
167179
up_read(&minors_rwsem);
168180
return ret;
169181
}
@@ -256,7 +268,7 @@ static __poll_t hidraw_poll(struct file *file, poll_table *wait)
256268
poll_wait(file, &list->hidraw->wait, wait);
257269
if (list->head != list->tail)
258270
mask |= EPOLLIN | EPOLLRDNORM;
259-
if (!list->hidraw->exist)
271+
if (!list->hidraw->exist || hidraw_is_revoked(list))
260272
mask |= EPOLLERR | EPOLLHUP;
261273
return mask;
262274
}
@@ -320,6 +332,9 @@ static int hidraw_fasync(int fd, struct file *file, int on)
320332
{
321333
struct hidraw_list *list = file->private_data;
322334

335+
if (hidraw_is_revoked(list))
336+
return -ENODEV;
337+
323338
return fasync_helper(fd, file, on, &list->fasync);
324339
}
325340

@@ -372,18 +387,26 @@ static int hidraw_release(struct inode * inode, struct file * file)
372387
return 0;
373388
}
374389

390+
static int hidraw_revoke(struct hidraw_list *list)
391+
{
392+
list->revoked = true;
393+
394+
return 0;
395+
}
396+
375397
static long hidraw_ioctl(struct file *file, unsigned int cmd,
376398
unsigned long arg)
377399
{
378400
struct inode *inode = file_inode(file);
379401
unsigned int minor = iminor(inode);
380402
long ret = 0;
381403
struct hidraw *dev;
404+
struct hidraw_list *list = file->private_data;
382405
void __user *user_arg = (void __user*) arg;
383406

384407
down_read(&minors_rwsem);
385408
dev = hidraw_table[minor];
386-
if (!dev || !dev->exist) {
409+
if (!dev || !dev->exist || hidraw_is_revoked(list)) {
387410
ret = -ENODEV;
388411
goto out;
389412
}
@@ -421,6 +444,14 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
421444
ret = -EFAULT;
422445
break;
423446
}
447+
case HIDIOCREVOKE:
448+
{
449+
if (user_arg)
450+
ret = -EINVAL;
451+
else
452+
ret = hidraw_revoke(list);
453+
break;
454+
}
424455
default:
425456
{
426457
struct hid_device *hid = dev->hid;
@@ -527,7 +558,7 @@ int hidraw_report_event(struct hid_device *hid, u8 *data, int len)
527558
list_for_each_entry(list, &dev->list, node) {
528559
int new_head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1);
529560

530-
if (new_head == list->tail)
561+
if (hidraw_is_revoked(list) || new_head == list->tail)
531562
continue;
532563

533564
if (!(list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC))) {

include/linux/hidraw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ struct hidraw_list {
3232
struct hidraw *hidraw;
3333
struct list_head node;
3434
struct mutex read_mutex;
35+
bool revoked;
3536
};
3637

3738
#ifdef CONFIG_HIDRAW

include/uapi/linux/hidraw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ struct hidraw_devinfo {
4646
/* The first byte of SOUTPUT and GOUTPUT is the report number */
4747
#define HIDIOCSOUTPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0B, len)
4848
#define HIDIOCGOUTPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0C, len)
49+
#define HIDIOCREVOKE _IOW('H', 0x0D, int) /* Revoke device access */
4950

5051
#define HIDRAW_FIRST_MINOR 0
5152
#define HIDRAW_MAX_DEVICES 64

tools/testing/selftests/hid/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ bpftool
22
*.skel.h
33
/tools
44
hid_bpf
5+
hidraw
56
results

tools/testing/selftests/hid/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ CFLAGS += -Wno-unused-command-line-argument
3232
endif
3333

3434
# Order correspond to 'make run_tests' order
35-
TEST_GEN_PROGS = hid_bpf
35+
TEST_GEN_PROGS = hid_bpf hidraw
3636

3737
# Emit succinct information message describing current building step
3838
# $1 - generic step name (e.g., CC, LINK, etc);

0 commit comments

Comments
 (0)