diff options
-rw-r--r-- | net/bluetooth/hci_sock.c | 23 |
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; | 735 | done: |
736 | release_sock(sk); | ||
737 | return err; | ||
727 | } | 738 | } |
728 | 739 | ||
729 | static const struct proto_ops hci_sock_ops = { | 740 | static const struct proto_ops hci_sock_ops = { |