| .. | .. |
|---|
| 23 | 23 | */ |
|---|
| 24 | 24 | |
|---|
| 25 | 25 | /* Bluetooth HCI sockets. */ |
|---|
| 26 | | - |
|---|
| 26 | +#include <linux/compat.h> |
|---|
| 27 | 27 | #include <linux/export.h> |
|---|
| 28 | 28 | #include <linux/utsname.h> |
|---|
| 29 | 29 | #include <linux/sched.h> |
|---|
| .. | .. |
|---|
| 52 | 52 | struct bt_sock bt; |
|---|
| 53 | 53 | struct hci_dev *hdev; |
|---|
| 54 | 54 | struct hci_filter filter; |
|---|
| 55 | | - __u32 cmsg_mask; |
|---|
| 55 | + __u8 cmsg_mask; |
|---|
| 56 | 56 | unsigned short channel; |
|---|
| 57 | 57 | unsigned long flags; |
|---|
| 58 | 58 | __u32 cookie; |
|---|
| .. | .. |
|---|
| 222 | 222 | if (hci_skb_pkt_type(skb) != HCI_COMMAND_PKT && |
|---|
| 223 | 223 | hci_skb_pkt_type(skb) != HCI_EVENT_PKT && |
|---|
| 224 | 224 | hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && |
|---|
| 225 | | - hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) |
|---|
| 225 | + hci_skb_pkt_type(skb) != HCI_SCODATA_PKT && |
|---|
| 226 | + hci_skb_pkt_type(skb) != HCI_ISODATA_PKT) |
|---|
| 226 | 227 | continue; |
|---|
| 227 | 228 | if (is_filtered_packet(sk, skb)) |
|---|
| 228 | 229 | continue; |
|---|
| .. | .. |
|---|
| 231 | 232 | continue; |
|---|
| 232 | 233 | if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT && |
|---|
| 233 | 234 | hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && |
|---|
| 234 | | - hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) |
|---|
| 235 | + hci_skb_pkt_type(skb) != HCI_SCODATA_PKT && |
|---|
| 236 | + hci_skb_pkt_type(skb) != HCI_ISODATA_PKT) |
|---|
| 235 | 237 | continue; |
|---|
| 236 | 238 | } else { |
|---|
| 237 | 239 | /* Don't send frame to other channel types */ |
|---|
| .. | .. |
|---|
| 334 | 336 | opcode = cpu_to_le16(HCI_MON_SCO_RX_PKT); |
|---|
| 335 | 337 | else |
|---|
| 336 | 338 | opcode = cpu_to_le16(HCI_MON_SCO_TX_PKT); |
|---|
| 339 | + break; |
|---|
| 340 | + case HCI_ISODATA_PKT: |
|---|
| 341 | + if (bt_cb(skb)->incoming) |
|---|
| 342 | + opcode = cpu_to_le16(HCI_MON_ISO_RX_PKT); |
|---|
| 343 | + else |
|---|
| 344 | + opcode = cpu_to_le16(HCI_MON_ISO_TX_PKT); |
|---|
| 337 | 345 | break; |
|---|
| 338 | 346 | case HCI_DIAG_PKT: |
|---|
| 339 | 347 | opcode = cpu_to_le16(HCI_MON_VENDOR_DIAG); |
|---|
| .. | .. |
|---|
| 446 | 454 | case HCI_DEV_SETUP: |
|---|
| 447 | 455 | if (hdev->manufacturer == 0xffff) |
|---|
| 448 | 456 | return NULL; |
|---|
| 449 | | - |
|---|
| 450 | | - /* fall through */ |
|---|
| 457 | + fallthrough; |
|---|
| 451 | 458 | |
|---|
| 452 | 459 | case HCI_DEV_UP: |
|---|
| 453 | 460 | skb = bt_skb_alloc(HCI_MON_INDEX_INFO_SIZE, GFP_ATOMIC); |
|---|
| .. | .. |
|---|
| 881 | 888 | } |
|---|
| 882 | 889 | |
|---|
| 883 | 890 | sock_orphan(sk); |
|---|
| 884 | | - |
|---|
| 885 | | - skb_queue_purge(&sk->sk_receive_queue); |
|---|
| 886 | | - skb_queue_purge(&sk->sk_write_queue); |
|---|
| 887 | | - |
|---|
| 888 | 891 | release_sock(sk); |
|---|
| 889 | 892 | sock_put(sk); |
|---|
| 890 | 893 | return 0; |
|---|
| .. | .. |
|---|
| 977 | 980 | |
|---|
| 978 | 981 | BT_DBG("cmd %x arg %lx", cmd, arg); |
|---|
| 979 | 982 | |
|---|
| 983 | + /* Make sure the cmd is valid before doing anything */ |
|---|
| 984 | + switch (cmd) { |
|---|
| 985 | + case HCIGETDEVLIST: |
|---|
| 986 | + case HCIGETDEVINFO: |
|---|
| 987 | + case HCIGETCONNLIST: |
|---|
| 988 | + case HCIDEVUP: |
|---|
| 989 | + case HCIDEVDOWN: |
|---|
| 990 | + case HCIDEVRESET: |
|---|
| 991 | + case HCIDEVRESTAT: |
|---|
| 992 | + case HCISETSCAN: |
|---|
| 993 | + case HCISETAUTH: |
|---|
| 994 | + case HCISETENCRYPT: |
|---|
| 995 | + case HCISETPTYPE: |
|---|
| 996 | + case HCISETLINKPOL: |
|---|
| 997 | + case HCISETLINKMODE: |
|---|
| 998 | + case HCISETACLMTU: |
|---|
| 999 | + case HCISETSCOMTU: |
|---|
| 1000 | + case HCIINQUIRY: |
|---|
| 1001 | + case HCISETRAW: |
|---|
| 1002 | + case HCIGETCONNINFO: |
|---|
| 1003 | + case HCIGETAUTHINFO: |
|---|
| 1004 | + case HCIBLOCKADDR: |
|---|
| 1005 | + case HCIUNBLOCKADDR: |
|---|
| 1006 | + break; |
|---|
| 1007 | + default: |
|---|
| 1008 | + return -ENOIOCTLCMD; |
|---|
| 1009 | + } |
|---|
| 1010 | + |
|---|
| 980 | 1011 | lock_sock(sk); |
|---|
| 981 | 1012 | |
|---|
| 982 | 1013 | if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { |
|---|
| .. | .. |
|---|
| 993 | 1024 | if (hci_sock_gen_cookie(sk)) { |
|---|
| 994 | 1025 | struct sk_buff *skb; |
|---|
| 995 | 1026 | |
|---|
| 996 | | - if (capable(CAP_NET_ADMIN)) |
|---|
| 1027 | + /* Perform careful checks before setting the HCI_SOCK_TRUSTED |
|---|
| 1028 | + * flag. Make sure that not only the current task but also |
|---|
| 1029 | + * the socket opener has the required capability, since |
|---|
| 1030 | + * privileged programs can be tricked into making ioctl calls |
|---|
| 1031 | + * on HCI sockets, and the socket should not be marked as |
|---|
| 1032 | + * trusted simply because the ioctl caller is privileged. |
|---|
| 1033 | + */ |
|---|
| 1034 | + if (sk_capable(sk, CAP_NET_ADMIN)) |
|---|
| 997 | 1035 | hci_sock_set_flag(sk, HCI_SOCK_TRUSTED); |
|---|
| 998 | 1036 | |
|---|
| 999 | 1037 | /* Send event to monitor */ |
|---|
| .. | .. |
|---|
| 1061 | 1099 | release_sock(sk); |
|---|
| 1062 | 1100 | return err; |
|---|
| 1063 | 1101 | } |
|---|
| 1102 | + |
|---|
| 1103 | +#ifdef CONFIG_COMPAT |
|---|
| 1104 | +static int hci_sock_compat_ioctl(struct socket *sock, unsigned int cmd, |
|---|
| 1105 | + unsigned long arg) |
|---|
| 1106 | +{ |
|---|
| 1107 | + switch (cmd) { |
|---|
| 1108 | + case HCIDEVUP: |
|---|
| 1109 | + case HCIDEVDOWN: |
|---|
| 1110 | + case HCIDEVRESET: |
|---|
| 1111 | + case HCIDEVRESTAT: |
|---|
| 1112 | + return hci_sock_ioctl(sock, cmd, arg); |
|---|
| 1113 | + } |
|---|
| 1114 | + |
|---|
| 1115 | + return hci_sock_ioctl(sock, cmd, (unsigned long)compat_ptr(arg)); |
|---|
| 1116 | +} |
|---|
| 1117 | +#endif |
|---|
| 1064 | 1118 | |
|---|
| 1065 | 1119 | static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, |
|---|
| 1066 | 1120 | int addr_len) |
|---|
| .. | .. |
|---|
| 1392 | 1446 | static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, |
|---|
| 1393 | 1447 | struct sk_buff *skb) |
|---|
| 1394 | 1448 | { |
|---|
| 1395 | | - __u32 mask = hci_pi(sk)->cmsg_mask; |
|---|
| 1449 | + __u8 mask = hci_pi(sk)->cmsg_mask; |
|---|
| 1396 | 1450 | |
|---|
| 1397 | 1451 | if (mask & HCI_CMSG_DIR) { |
|---|
| 1398 | 1452 | int incoming = bt_cb(skb)->incoming; |
|---|
| .. | .. |
|---|
| 1402 | 1456 | |
|---|
| 1403 | 1457 | if (mask & HCI_CMSG_TSTAMP) { |
|---|
| 1404 | 1458 | #ifdef CONFIG_COMPAT |
|---|
| 1405 | | - struct compat_timeval ctv; |
|---|
| 1459 | + struct old_timeval32 ctv; |
|---|
| 1406 | 1460 | #endif |
|---|
| 1407 | | - struct timeval tv; |
|---|
| 1461 | + struct __kernel_old_timeval tv; |
|---|
| 1408 | 1462 | void *data; |
|---|
| 1409 | 1463 | int len; |
|---|
| 1410 | 1464 | |
|---|
| .. | .. |
|---|
| 1572 | 1626 | } |
|---|
| 1573 | 1627 | } |
|---|
| 1574 | 1628 | |
|---|
| 1575 | | - no_hdev = (handler->flags & HCI_MGMT_NO_HDEV); |
|---|
| 1576 | | - if (no_hdev != !hdev) { |
|---|
| 1577 | | - err = mgmt_cmd_status(sk, index, opcode, |
|---|
| 1578 | | - MGMT_STATUS_INVALID_INDEX); |
|---|
| 1579 | | - goto done; |
|---|
| 1629 | + if (!(handler->flags & HCI_MGMT_HDEV_OPTIONAL)) { |
|---|
| 1630 | + no_hdev = (handler->flags & HCI_MGMT_NO_HDEV); |
|---|
| 1631 | + if (no_hdev != !hdev) { |
|---|
| 1632 | + err = mgmt_cmd_status(sk, index, opcode, |
|---|
| 1633 | + MGMT_STATUS_INVALID_INDEX); |
|---|
| 1634 | + goto done; |
|---|
| 1635 | + } |
|---|
| 1580 | 1636 | } |
|---|
| 1581 | 1637 | |
|---|
| 1582 | 1638 | var_len = (handler->flags & HCI_MGMT_VAR_LEN); |
|---|
| .. | .. |
|---|
| 1766 | 1822 | */ |
|---|
| 1767 | 1823 | if (hci_skb_pkt_type(skb) != HCI_COMMAND_PKT && |
|---|
| 1768 | 1824 | hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && |
|---|
| 1769 | | - hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) { |
|---|
| 1825 | + hci_skb_pkt_type(skb) != HCI_SCODATA_PKT && |
|---|
| 1826 | + hci_skb_pkt_type(skb) != HCI_ISODATA_PKT) { |
|---|
| 1770 | 1827 | err = -EINVAL; |
|---|
| 1771 | 1828 | goto drop; |
|---|
| 1772 | 1829 | } |
|---|
| .. | .. |
|---|
| 1810 | 1867 | } |
|---|
| 1811 | 1868 | |
|---|
| 1812 | 1869 | if (hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && |
|---|
| 1813 | | - hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) { |
|---|
| 1870 | + hci_skb_pkt_type(skb) != HCI_SCODATA_PKT && |
|---|
| 1871 | + hci_skb_pkt_type(skb) != HCI_ISODATA_PKT) { |
|---|
| 1814 | 1872 | err = -EINVAL; |
|---|
| 1815 | 1873 | goto drop; |
|---|
| 1816 | 1874 | } |
|---|
| .. | .. |
|---|
| 1831 | 1889 | } |
|---|
| 1832 | 1890 | |
|---|
| 1833 | 1891 | static int hci_sock_setsockopt(struct socket *sock, int level, int optname, |
|---|
| 1834 | | - char __user *optval, unsigned int len) |
|---|
| 1892 | + sockptr_t optval, unsigned int len) |
|---|
| 1835 | 1893 | { |
|---|
| 1836 | 1894 | struct hci_ufilter uf = { .opcode = 0 }; |
|---|
| 1837 | 1895 | struct sock *sk = sock->sk; |
|---|
| .. | .. |
|---|
| 1851 | 1909 | |
|---|
| 1852 | 1910 | switch (optname) { |
|---|
| 1853 | 1911 | case HCI_DATA_DIR: |
|---|
| 1854 | | - if (get_user(opt, (int __user *)optval)) { |
|---|
| 1912 | + if (copy_from_sockptr(&opt, optval, sizeof(opt))) { |
|---|
| 1855 | 1913 | err = -EFAULT; |
|---|
| 1856 | 1914 | break; |
|---|
| 1857 | 1915 | } |
|---|
| .. | .. |
|---|
| 1863 | 1921 | break; |
|---|
| 1864 | 1922 | |
|---|
| 1865 | 1923 | case HCI_TIME_STAMP: |
|---|
| 1866 | | - if (get_user(opt, (int __user *)optval)) { |
|---|
| 1924 | + if (copy_from_sockptr(&opt, optval, sizeof(opt))) { |
|---|
| 1867 | 1925 | err = -EFAULT; |
|---|
| 1868 | 1926 | break; |
|---|
| 1869 | 1927 | } |
|---|
| .. | .. |
|---|
| 1885 | 1943 | } |
|---|
| 1886 | 1944 | |
|---|
| 1887 | 1945 | len = min_t(unsigned int, len, sizeof(uf)); |
|---|
| 1888 | | - if (copy_from_user(&uf, optval, len)) { |
|---|
| 1946 | + if (copy_from_sockptr(&uf, optval, len)) { |
|---|
| 1889 | 1947 | err = -EFAULT; |
|---|
| 1890 | 1948 | break; |
|---|
| 1891 | 1949 | } |
|---|
| .. | .. |
|---|
| 1985 | 2043 | return err; |
|---|
| 1986 | 2044 | } |
|---|
| 1987 | 2045 | |
|---|
| 2046 | +static void hci_sock_destruct(struct sock *sk) |
|---|
| 2047 | +{ |
|---|
| 2048 | + skb_queue_purge(&sk->sk_receive_queue); |
|---|
| 2049 | + skb_queue_purge(&sk->sk_write_queue); |
|---|
| 2050 | +} |
|---|
| 2051 | + |
|---|
| 1988 | 2052 | static const struct proto_ops hci_sock_ops = { |
|---|
| 1989 | 2053 | .family = PF_BLUETOOTH, |
|---|
| 1990 | 2054 | .owner = THIS_MODULE, |
|---|
| .. | .. |
|---|
| 1994 | 2058 | .sendmsg = hci_sock_sendmsg, |
|---|
| 1995 | 2059 | .recvmsg = hci_sock_recvmsg, |
|---|
| 1996 | 2060 | .ioctl = hci_sock_ioctl, |
|---|
| 2061 | +#ifdef CONFIG_COMPAT |
|---|
| 2062 | + .compat_ioctl = hci_sock_compat_ioctl, |
|---|
| 2063 | +#endif |
|---|
| 1997 | 2064 | .poll = datagram_poll, |
|---|
| 1998 | 2065 | .listen = sock_no_listen, |
|---|
| 1999 | 2066 | .shutdown = sock_no_shutdown, |
|---|
| .. | .. |
|---|
| 2035 | 2102 | |
|---|
| 2036 | 2103 | sock->state = SS_UNCONNECTED; |
|---|
| 2037 | 2104 | sk->sk_state = BT_OPEN; |
|---|
| 2105 | + sk->sk_destruct = hci_sock_destruct; |
|---|
| 2038 | 2106 | |
|---|
| 2039 | 2107 | bt_sock_link(&hci_sk_list, sk); |
|---|
| 2040 | 2108 | return 0; |
|---|