162306a36Sopenharmony_ci#include <sys/ioctl.h> 262306a36Sopenharmony_ci#include <sys/types.h> 362306a36Sopenharmony_ci#include <sys/stat.h> 462306a36Sopenharmony_ci#include <fcntl.h> 562306a36Sopenharmony_ci#include <stdio.h> 662306a36Sopenharmony_ci#include <errno.h> 762306a36Sopenharmony_ci#include <string.h> 862306a36Sopenharmony_ci#include <inttypes.h> 962306a36Sopenharmony_ci#include <unistd.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/usbdevice_fs.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci/* For building without an updated set of headers */ 1462306a36Sopenharmony_ci#ifndef USBDEVFS_DROP_PRIVILEGES 1562306a36Sopenharmony_ci#define USBDEVFS_DROP_PRIVILEGES _IOW('U', 30, __u32) 1662306a36Sopenharmony_ci#define USBDEVFS_CAP_DROP_PRIVILEGES 0x40 1762306a36Sopenharmony_ci#endif 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_civoid drop_privileges(int fd, uint32_t mask) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci int res; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci res = ioctl(fd, USBDEVFS_DROP_PRIVILEGES, &mask); 2462306a36Sopenharmony_ci if (res) 2562306a36Sopenharmony_ci printf("ERROR: USBDEVFS_DROP_PRIVILEGES returned %d\n", res); 2662306a36Sopenharmony_ci else 2762306a36Sopenharmony_ci printf("OK: privileges dropped!\n"); 2862306a36Sopenharmony_ci} 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_civoid reset_device(int fd) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci int res; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci res = ioctl(fd, USBDEVFS_RESET); 3562306a36Sopenharmony_ci if (!res) 3662306a36Sopenharmony_ci printf("OK: USBDEVFS_RESET succeeded\n"); 3762306a36Sopenharmony_ci else 3862306a36Sopenharmony_ci printf("ERROR: reset failed! (%d - %s)\n", 3962306a36Sopenharmony_ci -res, strerror(-res)); 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_civoid claim_some_intf(int fd) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci int i, res; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 4762306a36Sopenharmony_ci res = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &i); 4862306a36Sopenharmony_ci if (!res) 4962306a36Sopenharmony_ci printf("OK: claimed if %d\n", i); 5062306a36Sopenharmony_ci else 5162306a36Sopenharmony_ci printf("ERROR claiming if %d (%d - %s)\n", 5262306a36Sopenharmony_ci i, -res, strerror(-res)); 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ciint main(int argc, char *argv[]) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci uint32_t mask, caps; 5962306a36Sopenharmony_ci int c, fd; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci fd = open(argv[1], O_RDWR); 6262306a36Sopenharmony_ci if (fd < 0) { 6362306a36Sopenharmony_ci printf("Failed to open file\n"); 6462306a36Sopenharmony_ci goto err_fd; 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci /* 6862306a36Sopenharmony_ci * check if dropping privileges is supported, 6962306a36Sopenharmony_ci * bail on systems where the capability is not present 7062306a36Sopenharmony_ci */ 7162306a36Sopenharmony_ci ioctl(fd, USBDEVFS_GET_CAPABILITIES, &caps); 7262306a36Sopenharmony_ci if (!(caps & USBDEVFS_CAP_DROP_PRIVILEGES)) { 7362306a36Sopenharmony_ci printf("DROP_PRIVILEGES not supported\n"); 7462306a36Sopenharmony_ci goto err; 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci /* 7862306a36Sopenharmony_ci * Drop privileges but keep the ability to claim all 7962306a36Sopenharmony_ci * free interfaces (i.e., those not used by kernel drivers) 8062306a36Sopenharmony_ci */ 8162306a36Sopenharmony_ci drop_privileges(fd, -1U); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci printf("Available options:\n" 8462306a36Sopenharmony_ci "[0] Exit now\n" 8562306a36Sopenharmony_ci "[1] Reset device. Should fail if device is in use\n" 8662306a36Sopenharmony_ci "[2] Claim 4 interfaces. Should succeed where not in use\n" 8762306a36Sopenharmony_ci "[3] Narrow interface permission mask\n" 8862306a36Sopenharmony_ci "Which option shall I run?: "); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci while (scanf("%d", &c) == 1) { 9162306a36Sopenharmony_ci switch (c) { 9262306a36Sopenharmony_ci case 0: 9362306a36Sopenharmony_ci goto exit; 9462306a36Sopenharmony_ci case 1: 9562306a36Sopenharmony_ci reset_device(fd); 9662306a36Sopenharmony_ci break; 9762306a36Sopenharmony_ci case 2: 9862306a36Sopenharmony_ci claim_some_intf(fd); 9962306a36Sopenharmony_ci break; 10062306a36Sopenharmony_ci case 3: 10162306a36Sopenharmony_ci printf("Insert new mask: "); 10262306a36Sopenharmony_ci scanf("%x", &mask); 10362306a36Sopenharmony_ci drop_privileges(fd, mask); 10462306a36Sopenharmony_ci break; 10562306a36Sopenharmony_ci default: 10662306a36Sopenharmony_ci printf("I don't recognize that\n"); 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci printf("Which test shall I run next?: "); 11062306a36Sopenharmony_ci } 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ciexit: 11362306a36Sopenharmony_ci close(fd); 11462306a36Sopenharmony_ci return 0; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cierr: 11762306a36Sopenharmony_ci close(fd); 11862306a36Sopenharmony_cierr_fd: 11962306a36Sopenharmony_ci return 1; 12062306a36Sopenharmony_ci} 121