Bluetooth: Restrict application of socket options
authorMarcel Holtmann <marcel@holtmann.org>
Fri, 16 Jan 2009 09:06:13 +0000 (10:06 +0100)
committerMarcel Holtmann <marcel@holtmann.org>
Fri, 27 Feb 2009 05:14:33 +0000 (06:14 +0100)
The new socket options should only be evaluated for SOL_BLUETOOTH level
and not for every other level. Previously this causes some minor issues
when detecting if a kernel with certain features is available.

Also restrict BT_SECURITY to SOCK_SEQPACKET for L2CAP and SOCK_STREAM for
the RFCOMM protocol.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
net/bluetooth/l2cap.c
net/bluetooth/rfcomm/sock.c

index b2d279c..82a9e69 100644 (file)
@@ -1248,10 +1248,18 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
        if (level == SOL_L2CAP)
                return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
 
        if (level == SOL_L2CAP)
                return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
 
+       if (level != SOL_BLUETOOTH)
+               return -ENOPROTOOPT;
+
        lock_sock(sk);
 
        switch (optname) {
        case BT_SECURITY:
        lock_sock(sk);
 
        switch (optname) {
        case BT_SECURITY:
+               if (sk->sk_type != SOCK_SEQPACKET) {
+                       err = -EINVAL;
+                       break;
+               }
+
                sec.level = BT_SECURITY_LOW;
 
                len = min_t(unsigned int, sizeof(sec), optlen);
                sec.level = BT_SECURITY_LOW;
 
                len = min_t(unsigned int, sizeof(sec), optlen);
@@ -1384,6 +1392,9 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
        if (level == SOL_L2CAP)
                return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
 
        if (level == SOL_L2CAP)
                return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
 
+       if (level != SOL_BLUETOOTH)
+               return -ENOPROTOOPT;
+
        if (get_user(len, optlen))
                return -EFAULT;
 
        if (get_user(len, optlen))
                return -EFAULT;
 
@@ -1391,6 +1402,11 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
 
        switch (optname) {
        case BT_SECURITY:
 
        switch (optname) {
        case BT_SECURITY:
+               if (sk->sk_type != SOCK_SEQPACKET) {
+                       err = -EINVAL;
+                       break;
+               }
+
                sec.level = l2cap_pi(sk)->sec_level;
 
                len = min_t(unsigned int, len, sizeof(sec));
                sec.level = l2cap_pi(sk)->sec_level;
 
                len = min_t(unsigned int, len, sizeof(sec));
index 9986ef3..7f48278 100644 (file)
@@ -778,10 +778,18 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
        if (level == SOL_RFCOMM)
                return rfcomm_sock_setsockopt_old(sock, optname, optval, optlen);
 
        if (level == SOL_RFCOMM)
                return rfcomm_sock_setsockopt_old(sock, optname, optval, optlen);
 
+       if (level != SOL_BLUETOOTH)
+               return -ENOPROTOOPT;
+
        lock_sock(sk);
 
        switch (optname) {
        case BT_SECURITY:
        lock_sock(sk);
 
        switch (optname) {
        case BT_SECURITY:
+               if (sk->sk_type != SOCK_STREAM) {
+                       err = -EINVAL;
+                       break;
+               }
+
                sec.level = BT_SECURITY_LOW;
 
                len = min_t(unsigned int, sizeof(sec), optlen);
                sec.level = BT_SECURITY_LOW;
 
                len = min_t(unsigned int, sizeof(sec), optlen);
@@ -899,6 +907,9 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c
        if (level == SOL_RFCOMM)
                return rfcomm_sock_getsockopt_old(sock, optname, optval, optlen);
 
        if (level == SOL_RFCOMM)
                return rfcomm_sock_getsockopt_old(sock, optname, optval, optlen);
 
+       if (level != SOL_BLUETOOTH)
+               return -ENOPROTOOPT;
+
        if (get_user(len, optlen))
                return -EFAULT;
 
        if (get_user(len, optlen))
                return -EFAULT;
 
@@ -906,6 +917,11 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c
 
        switch (optname) {
        case BT_SECURITY:
 
        switch (optname) {
        case BT_SECURITY:
+               if (sk->sk_type != SOCK_STREAM) {
+                       err = -EINVAL;
+                       break;
+               }
+
                sec.level = rfcomm_pi(sk)->sec_level;
 
                len = min_t(unsigned int, len, sizeof(sec));
                sec.level = rfcomm_pi(sk)->sec_level;
 
                len = min_t(unsigned int, len, sizeof(sec));