diff options
Diffstat (limited to 'Documentation')
-rw-r--r-- | Documentation/DocBook/usb.tmpl | 12 | ||||
-rw-r--r-- | Documentation/usb/usbdevfs-drop-permissions.c | 120 |
2 files changed, 132 insertions, 0 deletions
diff --git a/Documentation/DocBook/usb.tmpl b/Documentation/DocBook/usb.tmpl index 4cd5b2cd0f3d..bc776be0f19c 100644 --- a/Documentation/DocBook/usb.tmpl +++ b/Documentation/DocBook/usb.tmpl @@ -732,6 +732,18 @@ usbdev_ioctl (int fd, int ifno, unsigned request, void *param) or SET_INTERFACE. </para></warning></listitem></varlistentry> + <varlistentry><term>USBDEVFS_DROP_PRIVILEGES</term> + <listitem><para>This is used to relinquish the ability + to do certain operations which are considered to be + privileged on a usbfs file descriptor. + This includes claiming arbitrary interfaces, resetting + a device on which there are currently claimed interfaces + from other users, and issuing USBDEVFS_IOCTL calls. + The ioctl parameter is a 32 bit mask of interfaces + the user is allowed to claim on this file descriptor. + You may issue this ioctl more than one time to narrow + said mask. + </para></listitem></varlistentry> </variablelist> </sect2> diff --git a/Documentation/usb/usbdevfs-drop-permissions.c b/Documentation/usb/usbdevfs-drop-permissions.c new file mode 100644 index 000000000000..6b8da6ef0c9a --- /dev/null +++ b/Documentation/usb/usbdevfs-drop-permissions.c @@ -0,0 +1,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; +} |