GNU Linux-libre 4.19.211-gnu1
[releases.git] / Documentation / usb / usbdevfs-drop-permissions.c
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 }