@@ -332,6 +332,133 @@ TEST_F(hidraw, ioctl_gfeature_invalid)
332332 ASSERT_EQ (errno , EIO ) TH_LOG ("expected EIO, got errno %d" , errno );
333333}
334334
335+ /*
336+ * Test ioctl with incorrect nr bits
337+ */
338+ TEST_F (hidraw , ioctl_invalid_nr )
339+ {
340+ char buf [256 ] = {0 };
341+ int err ;
342+ unsigned int bad_cmd ;
343+
344+ /*
345+ * craft an ioctl command with wrong _IOC_NR bits
346+ */
347+ bad_cmd = _IOC (_IOC_WRITE |_IOC_READ , 'H' , 0x00 , sizeof (buf )); /* 0 is not valid */
348+
349+ /* test the ioctl */
350+ err = ioctl (self -> hidraw_fd , bad_cmd , buf );
351+ ASSERT_LT (err , 0 ) TH_LOG ("ioctl read-write with wrong _IOC_NR (0) should have failed" );
352+ ASSERT_EQ (errno , ENOTTY )
353+ TH_LOG ("expected ENOTTY for wrong read-write _IOC_NR (0), got errno %d" , errno );
354+
355+ /*
356+ * craft an ioctl command with wrong _IOC_NR bits
357+ */
358+ bad_cmd = _IOC (_IOC_READ , 'H' , 0x00 , sizeof (buf )); /* 0 is not valid */
359+
360+ /* test the ioctl */
361+ err = ioctl (self -> hidraw_fd , bad_cmd , buf );
362+ ASSERT_LT (err , 0 ) TH_LOG ("ioctl read-only with wrong _IOC_NR (0) should have failed" );
363+ ASSERT_EQ (errno , ENOTTY )
364+ TH_LOG ("expected ENOTTY for wrong read-only _IOC_NR (0), got errno %d" , errno );
365+
366+ /* also test with bigger number */
367+ bad_cmd = _IOC (_IOC_READ , 'H' , 0x42 , sizeof (buf )); /* 0x42 is not valid as well */
368+
369+ err = ioctl (self -> hidraw_fd , bad_cmd , buf );
370+ ASSERT_LT (err , 0 ) TH_LOG ("ioctl read-only with wrong _IOC_NR (0x42) should have failed" );
371+ ASSERT_EQ (errno , ENOTTY )
372+ TH_LOG ("expected ENOTTY for wrong read-only _IOC_NR (0x42), got errno %d" , errno );
373+
374+ /* also test with bigger number: 0x42 is not valid as well */
375+ bad_cmd = _IOC (_IOC_WRITE |_IOC_READ , 'H' , 0x42 , sizeof (buf ));
376+
377+ err = ioctl (self -> hidraw_fd , bad_cmd , buf );
378+ ASSERT_LT (err , 0 ) TH_LOG ("ioctl read-write with wrong _IOC_NR (0x42) should have failed" );
379+ ASSERT_EQ (errno , ENOTTY )
380+ TH_LOG ("expected ENOTTY for wrong read-write _IOC_NR (0x42), got errno %d" , errno );
381+ }
382+
383+ /*
384+ * Test ioctl with incorrect type bits
385+ */
386+ TEST_F (hidraw , ioctl_invalid_type )
387+ {
388+ char buf [256 ] = {0 };
389+ int err ;
390+ unsigned int bad_cmd ;
391+
392+ /*
393+ * craft an ioctl command with wrong _IOC_TYPE bits
394+ */
395+ bad_cmd = _IOC (_IOC_WRITE |_IOC_READ , 'I' , 0x01 , sizeof (buf )); /* 'I' should be 'H' */
396+
397+ /* test the ioctl */
398+ err = ioctl (self -> hidraw_fd , bad_cmd , buf );
399+ ASSERT_LT (err , 0 ) TH_LOG ("ioctl with wrong _IOC_TYPE (I) should have failed" );
400+ ASSERT_EQ (errno , EINVAL ) TH_LOG ("expected EINVAL for wrong _IOC_NR, got errno %d" , errno );
401+ }
402+
403+ /*
404+ * Test HIDIOCGFEATURE ioctl with incorrect _IOC_DIR bits
405+ */
406+ TEST_F (hidraw , ioctl_gfeature_invalid_dir )
407+ {
408+ __u8 buf [10 ] = {0 };
409+ int err ;
410+ unsigned int bad_cmd ;
411+
412+ /* set report ID 1 in first byte */
413+ buf [0 ] = 1 ;
414+
415+ /*
416+ * craft an ioctl command with wrong _IOC_DIR bits
417+ * HIDIOCGFEATURE should have _IOC_WRITE|_IOC_READ, let's use only _IOC_WRITE
418+ */
419+ bad_cmd = _IOC (_IOC_WRITE , 'H' , 0x07 , sizeof (buf )); /* should be _IOC_WRITE|_IOC_READ */
420+
421+ /* try to get feature report with wrong direction bits */
422+ err = ioctl (self -> hidraw_fd , bad_cmd , buf );
423+ ASSERT_LT (err , 0 ) TH_LOG ("HIDIOCGFEATURE with wrong _IOC_DIR should have failed" );
424+ ASSERT_EQ (errno , EINVAL ) TH_LOG ("expected EINVAL for wrong _IOC_DIR, got errno %d" , errno );
425+
426+ /* also test with only _IOC_READ */
427+ bad_cmd = _IOC (_IOC_READ , 'H' , 0x07 , sizeof (buf )); /* should be _IOC_WRITE|_IOC_READ */
428+
429+ err = ioctl (self -> hidraw_fd , bad_cmd , buf );
430+ ASSERT_LT (err , 0 ) TH_LOG ("HIDIOCGFEATURE with wrong _IOC_DIR should have failed" );
431+ ASSERT_EQ (errno , EINVAL ) TH_LOG ("expected EINVAL for wrong _IOC_DIR, got errno %d" , errno );
432+ }
433+
434+ /*
435+ * Test read-only ioctl with incorrect _IOC_DIR bits
436+ */
437+ TEST_F (hidraw , ioctl_readonly_invalid_dir )
438+ {
439+ char buf [256 ] = {0 };
440+ int err ;
441+ unsigned int bad_cmd ;
442+
443+ /*
444+ * craft an ioctl command with wrong _IOC_DIR bits
445+ * HIDIOCGRAWNAME should have _IOC_READ, let's use _IOC_WRITE
446+ */
447+ bad_cmd = _IOC (_IOC_WRITE , 'H' , 0x04 , sizeof (buf )); /* should be _IOC_READ */
448+
449+ /* try to get device name with wrong direction bits */
450+ err = ioctl (self -> hidraw_fd , bad_cmd , buf );
451+ ASSERT_LT (err , 0 ) TH_LOG ("HIDIOCGRAWNAME with wrong _IOC_DIR should have failed" );
452+ ASSERT_EQ (errno , EINVAL ) TH_LOG ("expected EINVAL for wrong _IOC_DIR, got errno %d" , errno );
453+
454+ /* also test with _IOC_WRITE|_IOC_READ */
455+ bad_cmd = _IOC (_IOC_WRITE |_IOC_READ , 'H' , 0x04 , sizeof (buf )); /* should be only _IOC_READ */
456+
457+ err = ioctl (self -> hidraw_fd , bad_cmd , buf );
458+ ASSERT_LT (err , 0 ) TH_LOG ("HIDIOCGRAWNAME with wrong _IOC_DIR should have failed" );
459+ ASSERT_EQ (errno , EINVAL ) TH_LOG ("expected EINVAL for wrong _IOC_DIR, got errno %d" , errno );
460+ }
461+
335462/*
336463 * Test HIDIOCSFEATURE ioctl to set feature report
337464 */
0 commit comments