aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_sock.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2012-02-20 08:50:33 -0500
committerJohan Hedberg <johan.hedberg@intel.com>2012-02-20 08:56:05 -0500
commitcedc5469778846ee18c653aaa6d70681961eed93 (patch)
tree62474c68745e8c63f35ba8af4fe8ad31e0e2fa8c /net/bluetooth/hci_sock.c
parent2f39cdb7a270da24532734dfdfd10c490be981c4 (diff)
Bluetooth: Lock socket when reading HCI socket options
When reading the HCI raw socket option, the socket was never locked. So lock the socket and in addition return EINVAL on non raw sockets. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net/bluetooth/hci_sock.c')
-rw-r--r--net/bluetooth/hci_sock.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 612bc2af05a9..27ec9088508f 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -677,11 +677,20 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char
677{ 677{
678 struct hci_ufilter uf; 678 struct hci_ufilter uf;
679 struct sock *sk = sock->sk; 679 struct sock *sk = sock->sk;
680 int len, opt; 680 int len, opt, err = 0;
681
682 BT_DBG("sk %p, opt %d", sk, optname);
681 683
682 if (get_user(len, optlen)) 684 if (get_user(len, optlen))
683 return -EFAULT; 685 return -EFAULT;
684 686
687 lock_sock(sk);
688
689 if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {
690 err = -EINVAL;
691 goto done;
692 }
693
685 switch (optname) { 694 switch (optname) {
686 case HCI_DATA_DIR: 695 case HCI_DATA_DIR:
687 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR) 696 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR)
@@ -690,7 +699,7 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char
690 opt = 0; 699 opt = 0;
691 700
692 if (put_user(opt, optval)) 701 if (put_user(opt, optval))
693 return -EFAULT; 702 err = -EFAULT;
694 break; 703 break;
695 704
696 case HCI_TIME_STAMP: 705 case HCI_TIME_STAMP:
@@ -700,7 +709,7 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char
700 opt = 0; 709 opt = 0;
701 710
702 if (put_user(opt, optval)) 711 if (put_user(opt, optval))
703 return -EFAULT; 712 err = -EFAULT;
704 break; 713 break;
705 714
706 case HCI_FILTER: 715 case HCI_FILTER:
@@ -715,15 +724,17 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char
715 724
716 len = min_t(unsigned int, len, sizeof(uf)); 725 len = min_t(unsigned int, len, sizeof(uf));
717 if (copy_to_user(optval, &uf, len)) 726 if (copy_to_user(optval, &uf, len))
718 return -EFAULT; 727 err = -EFAULT;
719 break; 728 break;
720 729
721 default: 730 default:
722 return -ENOPROTOOPT; 731 err = -ENOPROTOOPT;
723 break; 732 break;
724 } 733 }
725 734
726 return 0; 735done:
736 release_sock(sk);
737 return err;
727} 738}
728 739
729static const struct proto_ops hci_sock_ops = { 740static const struct proto_ops hci_sock_ops = {