Bluetooth: Fix HCI User Channel permission check in hci_sock_sendmsg
The HCI User Channel is an admin operation which enforces CAP_NET_ADMIN when binding the socket. Problem now is that it then requires also CAP_NET_RAW when calling into hci_sock_sendmsg. This is not intended and just an oversight since general HCI sockets (which do not require special permission to bind) and HCI User Channel share the same code path here. Remove the extra CAP_NET_RAW check for HCI User Channel write operation since the permission check has already been enforced when binding the socket. This also makes it possible to open HCI User Channel from a privileged process and then hand the file descriptor to an unprivilged process. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Tested-by: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
parent
bd0976dd33
commit
1bc5ad168f
|
@ -942,8 +942,22 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
|
|||
bt_cb(skb)->pkt_type = *((unsigned char *) skb->data);
|
||||
skb_pull(skb, 1);
|
||||
|
||||
if (hci_pi(sk)->channel == HCI_CHANNEL_RAW &&
|
||||
bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
|
||||
if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
|
||||
/* No permission check is needed for user channel
|
||||
* since that gets enforced when binding the socket.
|
||||
*
|
||||
* However check that the packet type is valid.
|
||||
*/
|
||||
if (bt_cb(skb)->pkt_type != HCI_COMMAND_PKT &&
|
||||
bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
|
||||
bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) {
|
||||
err = -EINVAL;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
skb_queue_tail(&hdev->raw_q, skb);
|
||||
queue_work(hdev->workqueue, &hdev->tx_work);
|
||||
} else if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
|
||||
u16 opcode = get_unaligned_le16(skb->data);
|
||||
u16 ogf = hci_opcode_ogf(opcode);
|
||||
u16 ocf = hci_opcode_ocf(opcode);
|
||||
|
@ -974,14 +988,6 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
|
|||
goto drop;
|
||||
}
|
||||
|
||||
if (hci_pi(sk)->channel == HCI_CHANNEL_USER &&
|
||||
bt_cb(skb)->pkt_type != HCI_COMMAND_PKT &&
|
||||
bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
|
||||
bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) {
|
||||
err = -EINVAL;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
skb_queue_tail(&hdev->raw_q, skb);
|
||||
queue_work(hdev->workqueue, &hdev->tx_work);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue