Bluetooth: Fix potential bad memory access with sysfs files
authorMarcel Holtmann <marcel@holtmann.org>
Mon, 15 Mar 2010 21:12:58 +0000 (14:12 -0700)
committerMarcel Holtmann <marcel@holtmann.org>
Sun, 21 Mar 2010 04:49:32 +0000 (05:49 +0100)
When creating a high number of Bluetooth sockets (L2CAP, SCO
and RFCOMM) it is possible to scribble repeatedly on arbitrary
pages of memory. Ensure that the content of these sysfs files is
always less than one page. Even if this means truncating. The
files in question are scheduled to be moved over to debugfs in
the future anyway.

Based on initial patches from Neil Brown and Linus Torvalds

Reported-by: Neil Brown <neilb@suse.de>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
net/bluetooth/l2cap.c
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/sock.c
net/bluetooth/sco.c

index 4db7ae2fe07dea0fcc12d142f072b8ebef5c6a58..27551820741e5b696746865793d2dd1301742aab 100644 (file)
@@ -3944,16 +3944,24 @@ static ssize_t l2cap_sysfs_show(struct class *dev,
        struct sock *sk;
        struct hlist_node *node;
        char *str = buf;
+       int size = PAGE_SIZE;
 
        read_lock_bh(&l2cap_sk_list.lock);
 
        sk_for_each(sk, node, &l2cap_sk_list.head) {
                struct l2cap_pinfo *pi = l2cap_pi(sk);
+               int len;
 
-               str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
+               len = snprintf(str, size, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
                                batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
                                sk->sk_state, __le16_to_cpu(pi->psm), pi->scid,
                                pi->dcid, pi->imtu, pi->omtu, pi->sec_level);
+
+               size -= len;
+               if (size <= 0)
+                       break;
+
+               str += len;
        }
 
        read_unlock_bh(&l2cap_sk_list.lock);
index db8a68e1a5ba835c11eff1f4d1f0525642e9ab41..cf164073269dd2b2fa5aa2a98f1ed17693244233 100644 (file)
@@ -2105,6 +2105,7 @@ static ssize_t rfcomm_dlc_sysfs_show(struct class *dev,
        struct rfcomm_session *s;
        struct list_head *pp, *p;
        char *str = buf;
+       int size = PAGE_SIZE;
 
        rfcomm_lock();
 
@@ -2113,11 +2114,21 @@ static ssize_t rfcomm_dlc_sysfs_show(struct class *dev,
                list_for_each(pp, &s->dlcs) {
                        struct sock *sk = s->sock->sk;
                        struct rfcomm_dlc *d = list_entry(pp, struct rfcomm_dlc, list);
+                       int len;
 
-                       str += sprintf(str, "%s %s %ld %d %d %d %d\n",
+                       len = snprintf(str, size, "%s %s %ld %d %d %d %d\n",
                                        batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
                                        d->state, d->dlci, d->mtu, d->rx_credits, d->tx_credits);
+
+                       size -= len;
+                       if (size <= 0)
+                               break;
+
+                       str += len;
                }
+
+               if (size <= 0)
+                       break;
        }
 
        rfcomm_unlock();
index ca87d6ac6a2036dd7030c334c133e4326edcda62..8d0ee0b8a6b680e8f3eaa15d323c0e999dc65e5e 100644 (file)
@@ -1068,13 +1068,22 @@ static ssize_t rfcomm_sock_sysfs_show(struct class *dev,
        struct sock *sk;
        struct hlist_node *node;
        char *str = buf;
+       int size = PAGE_SIZE;
 
        read_lock_bh(&rfcomm_sk_list.lock);
 
        sk_for_each(sk, node, &rfcomm_sk_list.head) {
-               str += sprintf(str, "%s %s %d %d\n",
+               int len;
+
+               len = snprintf(str, size, "%s %s %d %d\n",
                                batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
                                sk->sk_state, rfcomm_pi(sk)->channel);
+
+               size -= len;
+               if (size <= 0)
+                       break;
+
+               str += len;
        }
 
        read_unlock_bh(&rfcomm_sk_list.lock);
index f93b939539bc121da4448ce68e0e785b55b08416..967a75175c663728874a7dfc7a4d15c7636882f4 100644 (file)
@@ -960,13 +960,22 @@ static ssize_t sco_sysfs_show(struct class *dev,
        struct sock *sk;
        struct hlist_node *node;
        char *str = buf;
+       int size = PAGE_SIZE;
 
        read_lock_bh(&sco_sk_list.lock);
 
        sk_for_each(sk, node, &sco_sk_list.head) {
-               str += sprintf(str, "%s %s %d\n",
+               int len;
+
+               len = snprintf(str, size, "%s %s %d\n",
                                batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
                                sk->sk_state);
+
+               size -= len;
+               if (size <= 0)
+                       break;
+
+               str += len;
        }
 
        read_unlock_bh(&sco_sk_list.lock);