@@ -492,13 +492,15 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p)
492492}
493493
494494#define OLD_KEY_MAX 0x1ff
495- static int handle_eviocgbit (struct input_dev * dev , unsigned int cmd , void __user * p , int compat_mode )
495+ static int handle_eviocgbit (struct input_dev * dev ,
496+ unsigned int type , unsigned int size ,
497+ void __user * p , int compat_mode )
496498{
497499 static unsigned long keymax_warn_time ;
498500 unsigned long * bits ;
499501 int len ;
500502
501- switch (_IOC_NR ( cmd ) & EV_MAX ) {
503+ switch (type ) {
502504
503505 case 0 : bits = dev -> evbit ; len = EV_MAX ; break ;
504506 case EV_KEY : bits = dev -> keybit ; len = KEY_MAX ; break ;
@@ -517,7 +519,7 @@ static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user
517519 * EVIOCGBIT(EV_KEY, KEY_MAX) and not realize that 'len'
518520 * should be in bytes, not in bits.
519521 */
520- if (( _IOC_NR ( cmd ) & EV_MAX ) == EV_KEY && _IOC_SIZE ( cmd ) == OLD_KEY_MAX ) {
522+ if (type == EV_KEY && size == OLD_KEY_MAX ) {
521523 len = OLD_KEY_MAX ;
522524 if (printk_timed_ratelimit (& keymax_warn_time , 10 * 1000 ))
523525 printk (KERN_WARNING
@@ -528,7 +530,7 @@ static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user
528530 BITS_TO_LONGS (OLD_KEY_MAX ) * sizeof (long ));
529531 }
530532
531- return bits_to_user (bits , len , _IOC_SIZE ( cmd ) , p , compat_mode );
533+ return bits_to_user (bits , len , size , p , compat_mode );
532534}
533535#undef OLD_KEY_MAX
534536
@@ -542,8 +544,10 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
542544 struct ff_effect effect ;
543545 int __user * ip = (int __user * )p ;
544546 unsigned int i , t , u , v ;
547+ unsigned int size ;
545548 int error ;
546549
550+ /* First we check for fixed-length commands */
547551 switch (cmd ) {
548552
549553 case EVIOCGVERSION :
@@ -610,101 +614,102 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
610614 return evdev_grab (evdev , client );
611615 else
612616 return evdev_ungrab (evdev , client );
617+ }
613618
614- default :
619+ size = _IOC_SIZE ( cmd );
615620
616- if ( _IOC_TYPE ( cmd ) != 'E' )
617- return - EINVAL ;
621+ /* Now check variable-length commands */
622+ #define EVIOC_MASK_SIZE ( nr ) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
618623
619- if ( _IOC_DIR (cmd ) == _IOC_READ ) {
624+ switch ( EVIOC_MASK_SIZE (cmd )) {
620625
621- if (( _IOC_NR ( cmd ) & ~ EV_MAX ) == _IOC_NR ( EVIOCGBIT ( 0 , 0 )))
622- return handle_eviocgbit (dev , cmd , p , compat_mode );
626+ case EVIOCGKEY ( 0 ):
627+ return bits_to_user (dev -> key , KEY_MAX , size , p , compat_mode );
623628
624- if (_IOC_NR (cmd ) == _IOC_NR (EVIOCGKEY (0 )))
625- return bits_to_user (dev -> key , KEY_MAX , _IOC_SIZE (cmd ),
626- p , compat_mode );
629+ case EVIOCGLED (0 ):
630+ return bits_to_user (dev -> led , LED_MAX , size , p , compat_mode );
627631
628- if (_IOC_NR (cmd ) == _IOC_NR (EVIOCGLED (0 )))
629- return bits_to_user (dev -> led , LED_MAX , _IOC_SIZE (cmd ),
630- p , compat_mode );
632+ case EVIOCGSND (0 ):
633+ return bits_to_user (dev -> snd , SND_MAX , size , p , compat_mode );
631634
632- if (_IOC_NR (cmd ) == _IOC_NR (EVIOCGSND (0 )))
633- return bits_to_user (dev -> snd , SND_MAX , _IOC_SIZE (cmd ),
634- p , compat_mode );
635+ case EVIOCGSW (0 ):
636+ return bits_to_user (dev -> sw , SW_MAX , size , p , compat_mode );
635637
636- if (_IOC_NR (cmd ) == _IOC_NR (EVIOCGSW (0 )))
637- return bits_to_user (dev -> sw , SW_MAX , _IOC_SIZE (cmd ),
638- p , compat_mode );
638+ case EVIOCGNAME (0 ):
639+ return str_to_user (dev -> name , size , p );
639640
640- if ( _IOC_NR ( cmd ) == _IOC_NR ( EVIOCGNAME ( 0 )))
641- return str_to_user (dev -> name , _IOC_SIZE ( cmd ) , p );
641+ case EVIOCGPHYS ( 0 ):
642+ return str_to_user (dev -> phys , size , p );
642643
643- if ( _IOC_NR ( cmd ) == _IOC_NR ( EVIOCGPHYS ( 0 )))
644- return str_to_user (dev -> phys , _IOC_SIZE ( cmd ) , p );
644+ case EVIOCGUNIQ ( 0 ):
645+ return str_to_user (dev -> uniq , size , p );
645646
646- if (_IOC_NR (cmd ) == _IOC_NR (EVIOCGUNIQ (0 )))
647- return str_to_user (dev -> uniq , _IOC_SIZE (cmd ), p );
647+ case EVIOC_MASK_SIZE (EVIOCSFF ):
648+ if (input_ff_effect_from_user (p , size , & effect ))
649+ return - EFAULT ;
648650
649- if (( _IOC_NR ( cmd ) & ~ ABS_MAX ) == _IOC_NR ( EVIOCGABS ( 0 ))) {
651+ error = input_ff_upload ( dev , & effect , file );
650652
651- t = _IOC_NR ( cmd ) & ABS_MAX ;
652- abs = dev -> absinfo [ t ] ;
653+ if ( put_user ( effect . id , & ((( struct ff_effect __user * ) p ) -> id )))
654+ return - EFAULT ;
653655
654- if (copy_to_user (p , & abs , min_t (size_t ,
655- _IOC_SIZE (cmd ),
656- sizeof (struct input_absinfo ))))
657- return - EFAULT ;
656+ return error ;
657+ }
658658
659- return 0 ;
660- }
659+ /* Multi-number variable-length handlers */
660+ if (_IOC_TYPE (cmd ) != 'E' )
661+ return - EINVAL ;
661662
662- }
663+ if ( _IOC_DIR ( cmd ) == _IOC_READ ) {
663664
664- if (_IOC_DIR (cmd ) == _IOC_WRITE ) {
665+ if ((_IOC_NR (cmd ) & ~EV_MAX ) == _IOC_NR (EVIOCGBIT (0 , 0 )))
666+ return handle_eviocgbit (dev ,
667+ _IOC_NR (cmd ) & EV_MAX , size ,
668+ p , compat_mode );
665669
666- if (_IOC_NR (cmd ) == _IOC_NR (EVIOCSFF )) {
670+ if (( _IOC_NR (cmd ) & ~ ABS_MAX ) == _IOC_NR (EVIOCGABS ( 0 ) )) {
667671
668- if ( input_ff_effect_from_user ( p , _IOC_SIZE (cmd ), & effect ))
669- return - EFAULT ;
672+ t = _IOC_NR (cmd ) & ABS_MAX ;
673+ abs = dev -> absinfo [ t ] ;
670674
671- error = input_ff_upload (dev , & effect , file );
675+ if (copy_to_user (p , & abs , min_t (size_t ,
676+ size , sizeof (struct input_absinfo ))))
677+ return - EFAULT ;
672678
673- if (put_user (effect .id , & (((struct ff_effect __user * )p )-> id )))
674- return - EFAULT ;
679+ return 0 ;
680+ }
681+ }
675682
676- return error ;
677- }
683+ if (_IOC_DIR (cmd ) == _IOC_READ ) {
678684
679- if ((_IOC_NR (cmd ) & ~ABS_MAX ) == _IOC_NR (EVIOCSABS (0 ))) {
685+ if ((_IOC_NR (cmd ) & ~ABS_MAX ) == _IOC_NR (EVIOCSABS (0 ))) {
680686
681- t = _IOC_NR (cmd ) & ABS_MAX ;
687+ t = _IOC_NR (cmd ) & ABS_MAX ;
682688
683- if (copy_from_user (& abs , p , min_t (size_t ,
684- _IOC_SIZE (cmd ),
685- sizeof (struct input_absinfo ))))
686- return - EFAULT ;
689+ if (copy_from_user (& abs , p , min_t (size_t ,
690+ size , sizeof (struct input_absinfo ))))
691+ return - EFAULT ;
687692
688- if (_IOC_SIZE ( cmd ) < sizeof (struct input_absinfo ))
689- abs .resolution = 0 ;
693+ if (size < sizeof (struct input_absinfo ))
694+ abs .resolution = 0 ;
690695
691- /* We can't change number of reserved MT slots */
692- if (t == ABS_MT_SLOT )
693- return - EINVAL ;
696+ /* We can't change number of reserved MT slots */
697+ if (t == ABS_MT_SLOT )
698+ return - EINVAL ;
694699
695- /*
696- * Take event lock to ensure that we are not
697- * changing device parameters in the middle
698- * of event.
699- */
700- spin_lock_irq (& dev -> event_lock );
701- dev -> absinfo [t ] = abs ;
702- spin_unlock_irq (& dev -> event_lock );
700+ /*
701+ * Take event lock to ensure that we are not
702+ * changing device parameters in the middle
703+ * of event.
704+ */
705+ spin_lock_irq (& dev -> event_lock );
706+ dev -> absinfo [t ] = abs ;
707+ spin_unlock_irq (& dev -> event_lock );
703708
704- return 0 ;
705- }
709+ return 0 ;
706710 }
707711 }
712+
708713 return - EINVAL ;
709714}
710715
0 commit comments