Procházet zdrojové kódy

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>
Marcel Holtmann před 13 roky
rodič
revize
cedc546977
1 změnil soubory, kde provedl 17 přidání a 6 odebrání
  1. 17 6
      net/bluetooth/hci_sock.c

+ 17 - 6
net/bluetooth/hci_sock.c

@@ -677,11 +677,20 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char
 {
 {
 	struct hci_ufilter uf;
 	struct hci_ufilter uf;
 	struct sock *sk = sock->sk;
 	struct sock *sk = sock->sk;
-	int len, opt;
+	int len, opt, err = 0;
+
+	BT_DBG("sk %p, opt %d", sk, optname);
 
 
 	if (get_user(len, optlen))
 	if (get_user(len, optlen))
 		return -EFAULT;
 		return -EFAULT;
 
 
+	lock_sock(sk);
+
+	if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {
+		err = -EINVAL;
+		goto done;
+	}
+
 	switch (optname) {
 	switch (optname) {
 	case HCI_DATA_DIR:
 	case HCI_DATA_DIR:
 		if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR)
 		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
 			opt = 0;
 			opt = 0;
 
 
 		if (put_user(opt, optval))
 		if (put_user(opt, optval))
-			return -EFAULT;
+			err = -EFAULT;
 		break;
 		break;
 
 
 	case HCI_TIME_STAMP:
 	case HCI_TIME_STAMP:
@@ -700,7 +709,7 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char
 			opt = 0;
 			opt = 0;
 
 
 		if (put_user(opt, optval))
 		if (put_user(opt, optval))
-			return -EFAULT;
+			err = -EFAULT;
 		break;
 		break;
 
 
 	case HCI_FILTER:
 	case HCI_FILTER:
@@ -715,15 +724,17 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char
 
 
 		len = min_t(unsigned int, len, sizeof(uf));
 		len = min_t(unsigned int, len, sizeof(uf));
 		if (copy_to_user(optval, &uf, len))
 		if (copy_to_user(optval, &uf, len))
-			return -EFAULT;
+			err = -EFAULT;
 		break;
 		break;
 
 
 	default:
 	default:
-		return -ENOPROTOOPT;
+		err = -ENOPROTOOPT;
 		break;
 		break;
 	}
 	}
 
 
-	return 0;
+done:
+	release_sock(sk);
+	return err;
 }
 }
 
 
 static const struct proto_ops hci_sock_ops = {
 static const struct proto_ops hci_sock_ops = {