Skip to content

Commit

Permalink
Bluetooth: Send control open and close messages for HCI raw sockets
Browse files Browse the repository at this point in the history
When opening and closing HCI raw sockets their main usage is for legacy
userspace. To track interaction with the modern mgmt interface, send
open and close monitoring messages for these action.

The HCI raw sockets is special since it supports unbound ioctl operation
and for that special case delay the notification message until at least
one ioctl has been executed. The difference between a bound and unbound
socket will be detailed by the fact the HCI index is present or not.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
  • Loading branch information
Marcel Holtmann committed Sep 19, 2016
1 parent d0bef1d commit f81f5b2
Showing 1 changed file with 48 additions and 0 deletions.
48 changes: 48 additions & 0 deletions net/bluetooth/hci_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,11 @@ static struct sk_buff *create_monitor_ctrl_open(struct sock *sk)
return NULL;

switch (hci_pi(sk)->channel) {
case HCI_CHANNEL_RAW:
format = 0x0000;
ver[0] = BT_SUBSYS_VERSION;
put_unaligned_le16(BT_SUBSYS_REVISION, ver + 1);
break;
case HCI_CHANNEL_CONTROL:
format = 0x0002;
mgmt_fill_version_info(ver);
Expand Down Expand Up @@ -533,6 +538,7 @@ static struct sk_buff *create_monitor_ctrl_close(struct sock *sk)
return NULL;

switch (hci_pi(sk)->channel) {
case HCI_CHANNEL_RAW:
case HCI_CHANNEL_CONTROL:
break;
default:
Expand Down Expand Up @@ -820,6 +826,7 @@ static int hci_sock_release(struct socket *sock)
case HCI_CHANNEL_MONITOR:
atomic_dec(&monitor_promisc);
break;
case HCI_CHANNEL_RAW:
case HCI_CHANNEL_CONTROL:
/* Send event to monitor */
skb = create_monitor_ctrl_close(sk);
Expand Down Expand Up @@ -958,6 +965,27 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd,
goto done;
}

/* When calling an ioctl on an unbound raw socket, then ensure
* that the monitor gets informed. Ensure that the resulting event
* is only send once by checking if the cookie exists or not. The
* socket cookie will be only ever generated once for the lifetime
* of a given socket.
*/
if (hci_sock_gen_cookie(sk)) {
struct sk_buff *skb;

if (capable(CAP_NET_ADMIN))
hci_sock_set_flag(sk, HCI_SOCK_TRUSTED);

/* Send event to monitor */
skb = create_monitor_ctrl_open(sk);
if (skb) {
hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
HCI_SOCK_TRUSTED, NULL);
kfree_skb(skb);
}
}

release_sock(sk);

switch (cmd) {
Expand Down Expand Up @@ -1061,6 +1089,26 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,

hci_pi(sk)->channel = haddr.hci_channel;
hci_pi(sk)->hdev = hdev;

/* Only send the event to monitor when a new cookie has
* been generated. An existing cookie means that an unbound
* socket has seen an ioctl and that triggered the cookie
* generation and sending of the monitor event.
*/
if (hci_sock_gen_cookie(sk)) {
struct sk_buff *skb;

if (capable(CAP_NET_ADMIN))
hci_sock_set_flag(sk, HCI_SOCK_TRUSTED);

/* Send event to monitor */
skb = create_monitor_ctrl_open(sk);
if (skb) {
hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
HCI_SOCK_TRUSTED, NULL);
kfree_skb(skb);
}
}
break;

case HCI_CHANNEL_USER:
Expand Down

0 comments on commit f81f5b2

Please sign in to comment.