diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2010-03-15 17:12:58 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2010-03-21 00:49:32 -0400 |
commit | 101545f6fef4a0a3ea8daf0b5b880df2c6a92a69 (patch) | |
tree | 5b4254a64db65f1958a36ec6955dbba1b71031a7 /net | |
parent | af98441397227a5a4f212cd48710eea72a14dbdb (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.c | 10 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/core.c | 13 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/sock.c | 11 | ||||
-rw-r--r-- | net/bluetooth/sco.c | 11 |
4 files changed, 41 insertions, 4 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 4db7ae2fe07..27551820741 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 db8a68e1a5b..cf164073269 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 ca87d6ac6a2..8d0ee0b8a6b 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 f93b939539b..967a75175c6 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); |