Documentation / usb / usbdevfs-drop-permissions.c


Based on kernel version 6.8. Page generated on 2024-03-11 21:26 EST.

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