aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2010-03-15 17:12:58 -0400
committerMarcel Holtmann <marcel@holtmann.org>2010-03-21 00:49:32 -0400
commit101545f6fef4a0a3ea8daf0b5b880df2c6a92a69 (patch)
tree5b4254a64db65f1958a36ec6955dbba1b71031a7 /net
parentaf98441397227a5a4f212cd48710eea72a14dbdb (diff)
Bluetooth: Fix potential bad memory access with sysfs files
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>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/l2cap.c10
-rw-r--r--net/bluetooth/rfcomm/core.c13
-rw-r--r--net/bluetooth/rfcomm/sock.c11
-rw-r--r--net/bluetooth/sco.c11
4 files changed, 41 insertions, 4 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 4db7ae2fe07d..27551820741e 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3944,16 +3944,24 @@ static ssize_t l2cap_sysfs_show(struct class *dev,
3944 struct sock *sk; 3944 struct sock *sk;
3945 struct hlist_node *node; 3945 struct hlist_node *node;
3946 char *str = buf; 3946 char *str = buf;
3947 int size = PAGE_SIZE;
3947 3948
3948 read_lock_bh(&l2cap_sk_list.lock); 3949 read_lock_bh(&l2cap_sk_list.lock);
3949 3950
3950 sk_for_each(sk, node, &l2cap_sk_list.head) { 3951 sk_for_each(sk, node, &l2cap_sk_list.head) {
3951 struct l2cap_pinfo *pi = l2cap_pi(sk); 3952 struct l2cap_pinfo *pi = l2cap_pi(sk);
3953 int len;
3952 3954
3953 str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n", 3955 len = snprintf(str, size, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
3954 batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), 3956 batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
3955 sk->sk_state, __le16_to_cpu(pi->psm), pi->scid, 3957 sk->sk_state, __le16_to_cpu(pi->psm), pi->scid,
3956 pi->dcid, pi->imtu, pi->omtu, pi->sec_level); 3958 pi->dcid, pi->imtu, pi->omtu, pi->sec_level);
3959
3960 size -= len;
3961 if (size <= 0)
3962 break;
3963
3964 str += len;
3957 } 3965 }
3958 3966
3959 read_unlock_bh(&l2cap_sk_list.lock); 3967 read_unlock_bh(&l2cap_sk_list.lock);
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index db8a68e1a5ba..cf164073269d 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -2105,6 +2105,7 @@ static ssize_t rfcomm_dlc_sysfs_show(struct class *dev,
2105 struct rfcomm_session *s; 2105 struct rfcomm_session *s;
2106 struct list_head *pp, *p; 2106 struct list_head *pp, *p;
2107 char *str = buf; 2107 char *str = buf;
2108 int size = PAGE_SIZE;
2108 2109
2109 rfcomm_lock(); 2110 rfcomm_lock();
2110 2111
@@ -2113,11 +2114,21 @@ static ssize_t rfcomm_dlc_sysfs_show(struct class *dev,
2113 list_for_each(pp, &s->dlcs) { 2114 list_for_each(pp, &s->dlcs) {
2114 struct sock *sk = s->sock->sk; 2115 struct sock *sk = s->sock->sk;
2115 struct rfcomm_dlc *d = list_entry(pp, struct rfcomm_dlc, list); 2116 struct rfcomm_dlc *d = list_entry(pp, struct rfcomm_dlc, list);
2117 int len;
2116 2118
2117 str += sprintf(str, "%s %s %ld %d %d %d %d\n", 2119 len = snprintf(str, size, "%s %s %ld %d %d %d %d\n",
2118 batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), 2120 batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
2119 d->state, d->dlci, d->mtu, d->rx_credits, d->tx_credits); 2121 d->state, d->dlci, d->mtu, d->rx_credits, d->tx_credits);
2122
2123 size -= len;
2124 if (size <= 0)
2125 break;
2126
2127 str += len;
2120 } 2128 }
2129
2130 if (size <= 0)
2131 break;
2121 } 2132 }
2122 2133
2123 rfcomm_unlock(); 2134 rfcomm_unlock();
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index ca87d6ac6a20..8d0ee0b8a6b6 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -1068,13 +1068,22 @@ static ssize_t rfcomm_sock_sysfs_show(struct class *dev,
1068 struct sock *sk; 1068 struct sock *sk;
1069 struct hlist_node *node; 1069 struct hlist_node *node;
1070 char *str = buf; 1070 char *str = buf;
1071 int size = PAGE_SIZE;
1071 1072
1072 read_lock_bh(&rfcomm_sk_list.lock); 1073 read_lock_bh(&rfcomm_sk_list.lock);
1073 1074
1074 sk_for_each(sk, node, &rfcomm_sk_list.head) { 1075 sk_for_each(sk, node, &rfcomm_sk_list.head) {
1075 str += sprintf(str, "%s %s %d %d\n", 1076 int len;
1077
1078 len = snprintf(str, size, "%s %s %d %d\n",
1076 batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), 1079 batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
1077 sk->sk_state, rfcomm_pi(sk)->channel); 1080 sk->sk_state, rfcomm_pi(sk)->channel);
1081
1082 size -= len;
1083 if (size <= 0)
1084 break;
1085
1086 str += len;
1078 } 1087 }
1079 1088
1080 read_unlock_bh(&rfcomm_sk_list.lock); 1089 read_unlock_bh(&rfcomm_sk_list.lock);
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index f93b939539bc..967a75175c66 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -960,13 +960,22 @@ static ssize_t sco_sysfs_show(struct class *dev,
960 struct sock *sk; 960 struct sock *sk;
961 struct hlist_node *node; 961 struct hlist_node *node;
962 char *str = buf; 962 char *str = buf;
963 int size = PAGE_SIZE;
963 964
964 read_lock_bh(&sco_sk_list.lock); 965 read_lock_bh(&sco_sk_list.lock);
965 966
966 sk_for_each(sk, node, &sco_sk_list.head) { 967 sk_for_each(sk, node, &sco_sk_list.head) {
967 str += sprintf(str, "%s %s %d\n", 968 int len;
969
970 len = snprintf(str, size, "%s %s %d\n",
968 batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), 971 batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
969 sk->sk_state); 972 sk->sk_state);
973
974 size -= len;
975 if (size <= 0)
976 break;
977
978 str += len;
970 } 979 }
971 980
972 read_unlock_bh(&sco_sk_list.lock); 981 read_unlock_bh(&sco_sk_list.lock);