1 #include <sys/ioctl.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <stdio.h>
6 #include <errno.h>
7 #include <string.h>
8 #include <inttypes.h>
9 #include <unistd.h>
10 
11 #include <linux/usbdevice_fs.h>
12 
13 /* For building without an updated set of headers */
14 #ifndef USBDEVFS_DROP_PRIVILEGES
15 #define USBDEVFS_DROP_PRIVILEGES		_IOW('U', 30, __u32)
16 #define USBDEVFS_CAP_DROP_PRIVILEGES		0x40
17 #endif
18 
19 void drop_privileges(int fd, uint32_t mask)
20 {
21 	int res;
22 
23 	res = ioctl(fd, USBDEVFS_DROP_PRIVILEGES, &mask);
24 	if (res)
25 		printf("ERROR: USBDEVFS_DROP_PRIVILEGES returned %d\n", res);
26 	else
27 		printf("OK: privileges dropped!\n");
28 }
29 
30 void reset_device(int fd)
31 {
32 	int res;
33 
34 	res = ioctl(fd, USBDEVFS_RESET);
35 	if (!res)
36 		printf("OK: USBDEVFS_RESET succeeded\n");
37 	else
38 		printf("ERROR: reset failed! (%d - %s)\n",
39 		       -res, strerror(-res));
40 }
41 
42 void claim_some_intf(int fd)
43 {
44 	int i, res;
45 
46 	for (i = 0; i < 4; i++) {
47 		res = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &i);
48 		if (!res)
49 			printf("OK: claimed if %d\n", i);
50 		else
51 			printf("ERROR claiming if %d (%d - %s)\n",
52 			       i, -res, strerror(-res));
53 	}
54 }
55 
56 int main(int argc, char *argv[])
57 {
58 	uint32_t mask, caps;
59 	int c, fd;
60 
61 	fd = open(argv[1], O_RDWR);
62 	if (fd < 0) {
63 		printf("Failed to open file\n");
64 		goto err_fd;
65 	}
66 
67 	/*
68 	 * check if dropping privileges is supported,
69 	 * bail on systems where the capability is not present
70 	 */
71 	ioctl(fd, USBDEVFS_GET_CAPABILITIES, &caps);
72 	if (!(caps & USBDEVFS_CAP_DROP_PRIVILEGES)) {
73 		printf("DROP_PRIVILEGES not supported\n");
74 		goto err;
75 	}
76 
77 	/*
78 	 * Drop privileges but keep the ability to claim all
79 	 * free interfaces (i.e., those not used by kernel drivers)
80 	 */
81 	drop_privileges(fd, -1U);
82 
83 	printf("Available options:\n"
84 		"[0] Exit now\n"
85 		"[1] Reset device. Should fail if device is in use\n"
86 		"[2] Claim 4 interfaces. Should succeed where not in use\n"
87 		"[3] Narrow interface permission mask\n"
88 		"Which option shall I run?: ");
89 
90 	while (scanf("%d", &c) == 1) {
91 		switch (c) {
92 		case 0:
93 			goto exit;
94 		case 1:
95 			reset_device(fd);
96 			break;
97 		case 2:
98 			claim_some_intf(fd);
99 			break;
100 		case 3:
101 			printf("Insert new mask: ");
102 			scanf("%x", &mask);
103 			drop_privileges(fd, mask);
104 			break;
105 		default:
106 			printf("I don't recognize that\n");
107 		}
108 
109 		printf("Which test shall I run next?: ");
110 	}
111 
112 exit:
113 	close(fd);
114 	return 0;
115 
116 err:
117 	close(fd);
118 err_fd:
119 	return 1;
120 }
121