Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 101545f6 authored by Marcel Holtmann's avatar Marcel Holtmann
Browse files

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: default avatarNeil Brown <neilb@suse.de>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent af984413
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -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);
+12 −1
Original line number Diff line number Diff line
@@ -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();
+10 −1
Original line number Diff line number Diff line
@@ -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);
+10 −1
Original line number Diff line number Diff line
@@ -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);