@@ -38,12 +38,20 @@ static const struct class hidraw_class = {
3838static struct hidraw * hidraw_table [HIDRAW_MAX_DEVICES ];
3939static DECLARE_RWSEM (minors_rwsem );
4040
41+ static inline bool hidraw_is_revoked (struct hidraw_list * list )
42+ {
43+ return list -> revoked ;
44+ }
45+
4146static 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
162170static 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+
375397static 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 ))) {
0 commit comments