18c2ecf20Sopenharmony_ci#include <sys/ioctl.h> 28c2ecf20Sopenharmony_ci#include <sys/types.h> 38c2ecf20Sopenharmony_ci#include <sys/stat.h> 48c2ecf20Sopenharmony_ci#include <fcntl.h> 58c2ecf20Sopenharmony_ci#include <stdio.h> 68c2ecf20Sopenharmony_ci#include <errno.h> 78c2ecf20Sopenharmony_ci#include <string.h> 88c2ecf20Sopenharmony_ci#include <inttypes.h> 98c2ecf20Sopenharmony_ci#include <unistd.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/usbdevice_fs.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* For building without an updated set of headers */ 148c2ecf20Sopenharmony_ci#ifndef USBDEVFS_DROP_PRIVILEGES 158c2ecf20Sopenharmony_ci#define USBDEVFS_DROP_PRIVILEGES _IOW('U', 30, __u32) 168c2ecf20Sopenharmony_ci#define USBDEVFS_CAP_DROP_PRIVILEGES 0x40 178c2ecf20Sopenharmony_ci#endif 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_civoid drop_privileges(int fd, uint32_t mask) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci int res; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci res = ioctl(fd, USBDEVFS_DROP_PRIVILEGES, &mask); 248c2ecf20Sopenharmony_ci if (res) 258c2ecf20Sopenharmony_ci printf("ERROR: USBDEVFS_DROP_PRIVILEGES returned %d\n", res); 268c2ecf20Sopenharmony_ci else 278c2ecf20Sopenharmony_ci printf("OK: privileges dropped!\n"); 288c2ecf20Sopenharmony_ci} 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_civoid reset_device(int fd) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci int res; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci res = ioctl(fd, USBDEVFS_RESET); 358c2ecf20Sopenharmony_ci if (!res) 368c2ecf20Sopenharmony_ci printf("OK: USBDEVFS_RESET succeeded\n"); 378c2ecf20Sopenharmony_ci else 388c2ecf20Sopenharmony_ci printf("ERROR: reset failed! (%d - %s)\n", 398c2ecf20Sopenharmony_ci -res, strerror(-res)); 408c2ecf20Sopenharmony_ci} 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_civoid claim_some_intf(int fd) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci int i, res; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 478c2ecf20Sopenharmony_ci res = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &i); 488c2ecf20Sopenharmony_ci if (!res) 498c2ecf20Sopenharmony_ci printf("OK: claimed if %d\n", i); 508c2ecf20Sopenharmony_ci else 518c2ecf20Sopenharmony_ci printf("ERROR claiming if %d (%d - %s)\n", 528c2ecf20Sopenharmony_ci i, -res, strerror(-res)); 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci} 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ciint main(int argc, char *argv[]) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci uint32_t mask, caps; 598c2ecf20Sopenharmony_ci int c, fd; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci fd = open(argv[1], O_RDWR); 628c2ecf20Sopenharmony_ci if (fd < 0) { 638c2ecf20Sopenharmony_ci printf("Failed to open file\n"); 648c2ecf20Sopenharmony_ci goto err_fd; 658c2ecf20Sopenharmony_ci } 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci /* 688c2ecf20Sopenharmony_ci * check if dropping privileges is supported, 698c2ecf20Sopenharmony_ci * bail on systems where the capability is not present 708c2ecf20Sopenharmony_ci */ 718c2ecf20Sopenharmony_ci ioctl(fd, USBDEVFS_GET_CAPABILITIES, &caps); 728c2ecf20Sopenharmony_ci if (!(caps & USBDEVFS_CAP_DROP_PRIVILEGES)) { 738c2ecf20Sopenharmony_ci printf("DROP_PRIVILEGES not supported\n"); 748c2ecf20Sopenharmony_ci goto err; 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci /* 788c2ecf20Sopenharmony_ci * Drop privileges but keep the ability to claim all 798c2ecf20Sopenharmony_ci * free interfaces (i.e., those not used by kernel drivers) 808c2ecf20Sopenharmony_ci */ 818c2ecf20Sopenharmony_ci drop_privileges(fd, -1U); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci printf("Available options:\n" 848c2ecf20Sopenharmony_ci "[0] Exit now\n" 858c2ecf20Sopenharmony_ci "[1] Reset device. Should fail if device is in use\n" 868c2ecf20Sopenharmony_ci "[2] Claim 4 interfaces. Should succeed where not in use\n" 878c2ecf20Sopenharmony_ci "[3] Narrow interface permission mask\n" 888c2ecf20Sopenharmony_ci "Which option shall I run?: "); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci while (scanf("%d", &c) == 1) { 918c2ecf20Sopenharmony_ci switch (c) { 928c2ecf20Sopenharmony_ci case 0: 938c2ecf20Sopenharmony_ci goto exit; 948c2ecf20Sopenharmony_ci case 1: 958c2ecf20Sopenharmony_ci reset_device(fd); 968c2ecf20Sopenharmony_ci break; 978c2ecf20Sopenharmony_ci case 2: 988c2ecf20Sopenharmony_ci claim_some_intf(fd); 998c2ecf20Sopenharmony_ci break; 1008c2ecf20Sopenharmony_ci case 3: 1018c2ecf20Sopenharmony_ci printf("Insert new mask: "); 1028c2ecf20Sopenharmony_ci scanf("%x", &mask); 1038c2ecf20Sopenharmony_ci drop_privileges(fd, mask); 1048c2ecf20Sopenharmony_ci break; 1058c2ecf20Sopenharmony_ci default: 1068c2ecf20Sopenharmony_ci printf("I don't recognize that\n"); 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci printf("Which test shall I run next?: "); 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ciexit: 1138c2ecf20Sopenharmony_ci close(fd); 1148c2ecf20Sopenharmony_ci return 0; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cierr: 1178c2ecf20Sopenharmony_ci close(fd); 1188c2ecf20Sopenharmony_cierr_fd: 1198c2ecf20Sopenharmony_ci return 1; 1208c2ecf20Sopenharmony_ci} 121