Skip to contentSkip to conversation

Bluetooth: SCO: require CAP_NET_BIND_SERVICE to bind

PATCH In review Luiz Augusto von Dentz 3 participants 8 messages Aug 27 – Aug 29

Subsystems (2)
lore
Share & tools
lore

Luiz Augusto von Dentz

author maintainer
#0 lore raw

PATCH 1/2 Bluetooth: SCO: require CAP_NET_BIND_SERVICE to bind

From: Luiz Augusto von Dentz <[email protected]>

SCO sockets have no PSM or port namespace: binding one simply reserves the ability to accept any incoming eSCO/SCO connection on the adapter. That is equivalent to listening on a well-known service, which L2CAP already restricts to CAP_NET_BIND_SERVICE in l2cap_validate_bredr_psm()/l2cap_validate_le_psm().

Apply the same restriction to sco_sock_bind() so unprivileged processes can no longer hijack incoming SCO links.

Fixes 1da177e4c3f4 ("Linux-2.6.12-rc2")
---
 net/bluetooth/sco.c | 7 +++++++
 1 file changed, 7 insertions(+)
net/bluetooth/sco.c +7 -0
index 3d4362a09df4..e4c26551e513 100644
@@ -667,6 +667,13 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr_unsized *addr,
 
 	BT_DBG("sk %p %pMR", sk, &sa->sco_bdaddr);
 
+	/* Binding a SCO socket reserves the ability to accept any incoming
+	 * eSCO/SCO connection on the adapter, so restrict it in the same way
+	 * L2CAP restricts well-known PSMs.
+	 */
+	if (!capable(CAP_NET_BIND_SERVICE))
+		return -EACCES;
+
 	lock_sock(sk);
 
 	if (sk->sk_state != BT_OPEN) {
Signature · 1 line
2.54.0
author maintainer
#1 lore raw

PATCH 2/2 Bluetooth: ISO: require CAP_NET_BIND_SERVICE to bind

From: Luiz Augusto von Dentz <[email protected]>

ISO sockets have no PSM or port namespace: binding one reserves the ability to accept any incoming CIS or to sync to broadcast streams on the adapter. That is equivalent to listening on a well-known service, which L2CAP already restricts to CAP_NET_BIND_SERVICE in l2cap_validate_bredr_psm()/l2cap_validate_le_psm().

Apply the same restriction to iso_sock_bind() so unprivileged processes can no longer hijack incoming ISO links.

Fixes ccf74f2390d6 ("Bluetooth: Add BTPROTO_ISO socket type")
---
 net/bluetooth/iso.c | 7 +++++++
 1 file changed, 7 insertions(+)
net/bluetooth/iso.c +7 -0
index 75bfd5938b2e..4e1e34ffc294 100644
@@ -1200,6 +1200,13 @@ static int iso_sock_bind(struct socket *sock, struct sockaddr_unsized *addr,
 	    addr->sa_family != AF_BLUETOOTH)
 		return -EINVAL;
 
+	/* Binding an ISO socket reserves the ability to accept any incoming
+	 * CIS/BIS on the adapter, so restrict it in the same way L2CAP
+	 * restricts well-known PSMs.
+	 */
+	if (!capable(CAP_NET_BIND_SERVICE))
+		return -EACCES;
+
 	lock_sock(sk);
 
 	if ((sk->sk_state == BT_CONNECT2 || sk->sk_state == BT_CONNECTED) &&
Signature · 1 line
2.54.0
#2 lore raw
In reply to Luiz Augusto von Dentz

Hi,

to, 2026-08-27 kello 14:01 -0400, Luiz Augusto von Dentz kirjoitti:

Quoted 7 lines

From: Luiz Augusto von Dentz <[email protected]>

SCO sockets have no PSM or port namespace: binding one simply reserves the ability to accept any incoming eSCO/SCO connection on the adapter. That is equivalent to listening on a well-known service, which L2CAP already restricts to CAP_NET_BIND_SERVICE in l2cap_validate_bredr_psm()/l2cap_validate_le_psm().

In current Linux userspace, sound servers that do HFP listen on SCO sockets, and I think often don't have CAP_NET_BIND_SERVICE.

Do they continue working with this change?

Quoted 27 lines

Apply the same restriction to sco_sock_bind() so unprivileged processes can no longer hijack incoming SCO links.

Fixes 1da177e4c3f4 ("Linux-2.6.12-rc2")
---
 net/bluetooth/sco.c | 7 +++++++
 1 file changed, 7 insertions(+)
net/bluetooth/sco.c +7 -0
index 3d4362a09df4..e4c26551e513 100644
@@ -667,6 +667,13 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr_unsized *addr,
 
 	BT_DBG("sk %p %pMR", sk, &sa->sco_bdaddr);
 
+	/* Binding a SCO socket reserves the ability to accept any incoming
+	 * eSCO/SCO connection on the adapter, so restrict it in the same way
+	 * L2CAP restricts well-known PSMs.
+	 */
+	if (!capable(CAP_NET_BIND_SERVICE))
+		return -EACCES;
+
 	lock_sock(sk);
 
 	if (sk->sk_state != BT_OPEN) {
Signature · 1 line
Pauli Virtanen
author maintainer
#3 lore raw

Hi Pauli,

Quoted 12 lines · Pauli Virtanen

Hi,

to, 2026-08-27 kello 14:01 -0400, Luiz Augusto von Dentz kirjoitti:

Quoted 7 lines

From: Luiz Augusto von Dentz <[email protected]>

SCO sockets have no PSM or port namespace: binding one simply reserves the ability to accept any incoming eSCO/SCO connection on the adapter. That is equivalent to listening on a well-known service, which L2CAP already restricts to CAP_NET_BIND_SERVICE in l2cap_validate_bredr_psm()/l2cap_validate_le_psm().

Quoted 4 lines

In current Linux userspace, sound servers that do HFP listen on SCO sockets, and I think often don't have CAP_NET_BIND_SERVICE.

Do they continue working with this change?

Good question, that said this is a part of security hardening otherwise any process could start listening to an SCO connection, and the sound server would stop working. Btw, does the sound server have any special capability to, let's say, open the sound card device so perhaps we can gate it on sound capability as well.

Quoted 30 lines
Quoted 17 lines

Apply the same restriction to sco_sock_bind() so unprivileged processes can no longer hijack incoming SCO links.

Fixes 1da177e4c3f4 ("Linux-2.6.12-rc2")
---
 net/bluetooth/sco.c | 7 +++++++
 1 file changed, 7 insertions(+)
net/bluetooth/sco.c +0 -0
index 3d4362a09df4..e4c26551e513 100644
@@ -667,6 +667,13 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr_unsized *addr,
 
      BT_DBG("sk %p %pMR", sk, &sa->sco_bdaddr);
 

net/bluetooth/sco.c static int sco_sock_bind(struct socket *sock, struct sockaddr_unsized *addr, · line 679

Quoted 10 lines
net/bluetooth/sco.c +7 -0
+     /* Binding a SCO socket reserves the ability to accept any incoming
+      * eSCO/SCO connection on the adapter, so restrict it in the same way
+      * L2CAP restricts well-known PSMs.
+      */
+     if (!capable(CAP_NET_BIND_SERVICE))
+             return -EACCES;
+
      lock_sock(sk);
 
      if (sk->sk_state != BT_OPEN) {

--
Pauli Virtanen

Signature · 1 line
Luiz Augusto von Dentz
#4 lore raw

Hi,

pe, 2026-08-28 kello 09:50 -0400, Luiz Augusto von Dentz kirjoitti:

Quoted 13 lines · Pauli Virtanen
Quoted 12 lines

to, 2026-08-27 kello 14:01 -0400, Luiz Augusto von Dentz kirjoitti:

Quoted 7 lines

From: Luiz Augusto von Dentz <[email protected]>

SCO sockets have no PSM or port namespace: binding one simply reserves the ability to accept any incoming eSCO/SCO connection on the adapter. That is equivalent to listening on a well-known service, which L2CAP already restricts to CAP_NET_BIND_SERVICE in l2cap_validate_bredr_psm()/l2cap_validate_le_psm().

In current Linux userspace, sound servers that do HFP listen on SCO sockets, and I think often don't have CAP_NET_BIND_SERVICE.

Quoted 7 lines
Quoted 1 line

Do they continue working with this change?

Good question, that said this is a part of security hardening otherwise any process could start listening to an SCO connection, and the sound server would stop working. Btw, does the sound server have any special capability to, let's say, open the sound card device so perhaps we can gate it on sound capability as well.

For ALSA, the sound hardware access is controlled by device file permissions in /dev/snd/* Not sure if that's usable here, or if there's some other per-user controlled solution that could be used.

In most current distros sound server runs with user permissions without special capabilities, and don't have CAP_NET_BIND_SERVICE, so I'd expect this patch breaks userspace.

Giving this capability to them allows binding to low network ports, so it probably makes the hardening issue worse and not better.

The next simplest is probably separate executable with setcap bit set, which gives a SCO listen socket for those who can run it based on file permissions.

For ISO bluetoothd manages this (so can be gated with DBus/selinux policies), and it could make sense for it to be made to work like that for SCO too.

Quoted 32 lines
Quoted 30 lines
Quoted 17 lines

Apply the same restriction to sco_sock_bind() so unprivileged processes can no longer hijack incoming SCO links.

Fixes 1da177e4c3f4 ("Linux-2.6.12-rc2")
---
 net/bluetooth/sco.c | 7 +++++++
 1 file changed, 7 insertions(+)
net/bluetooth/sco.c +0 -0
index 3d4362a09df4..e4c26551e513 100644
@@ -667,6 +667,13 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr_unsized *addr,
 
      BT_DBG("sk %p %pMR", sk, &sa->sco_bdaddr);
 

net/bluetooth/sco.c static int sco_sock_bind(struct socket *sock, struct sockaddr_unsized *addr, · line 679

Quoted 10 lines
net/bluetooth/sco.c +7 -0
+     /* Binding a SCO socket reserves the ability to accept any incoming
+      * eSCO/SCO connection on the adapter, so restrict it in the same way
+      * L2CAP restricts well-known PSMs.
+      */
+     if (!capable(CAP_NET_BIND_SERVICE))
+             return -EACCES;
+
      lock_sock(sk);
 
      if (sk->sk_state != BT_OPEN) {

--
Pauli Virtanen

author maintainer
#5 lore raw

Hi Pauli,

Quoted 25 lines · Pauli Virtanen

Hi,

pe, 2026-08-28 kello 09:50 -0400, Luiz Augusto von Dentz kirjoitti:

Quoted 13 lines · Pauli Virtanen
Quoted 12 lines

to, 2026-08-27 kello 14:01 -0400, Luiz Augusto von Dentz kirjoitti:

Quoted 7 lines

From: Luiz Augusto von Dentz <[email protected]>

SCO sockets have no PSM or port namespace: binding one simply reserves the ability to accept any incoming eSCO/SCO connection on the adapter. That is equivalent to listening on a well-known service, which L2CAP already restricts to CAP_NET_BIND_SERVICE in l2cap_validate_bredr_psm()/l2cap_validate_le_psm().

In current Linux userspace, sound servers that do HFP listen on SCO sockets, and I think often don't have CAP_NET_BIND_SERVICE.

Quoted 7 lines
Quoted 1 line

Do they continue working with this change?

Good question, that said this is a part of security hardening otherwise any process could start listening to an SCO connection, and the sound server would stop working. Btw, does the sound server have any special capability to, let's say, open the sound card device so perhaps we can gate it on sound capability as well.

Quoted 3 lines

For ALSA, the sound hardware access is controlled by device file permissions in /dev/snd/* Not sure if that's usable here, or if there's some other per-user controlled solution that could be used.

Ok, so you are saying anyone user with file access to /dev/snd/* can grab the hardware for itself, since pipewire is just a regular user it just works because it is the first one to open it?

Quoted 6 lines

In most current distros sound server runs with user permissions without special capabilities, and don't have CAP_NET_BIND_SERVICE, so I'd expect this patch breaks userspace.

Giving this capability to them allows binding to low network ports, so it probably makes the hardening issue worse and not better.

You would grant it to a specific set of binaries, probably via a systemd file. This would block other users, which currently might just be testing tools like isotest, where you just use sudo instead, or an AI agent trying to fabricate vulnerabilities.

Quoted 3 lines

The next simplest is probably separate executable with setcap bit set, which gives a SCO listen socket for those who can run it based on file permissions.

What file permission? Afaik a socket protocol doesn't have file permissions, or does it? The is no open just bind which is what we are trying to protect.

Quoted 3 lines

For ISO bluetoothd manages this (so can be gated with DBus/selinux policies), and it could make sense for it to be made to work like that for SCO too.

Yeah, bluetoothd manages this for ISO and I wish we did this for SCO too, maybe via Profle interface which I guess PipeWire registers, but it just for RFCOMM/AT commands, right? Anyway this is too late because we cannot break support of older versions of pipewire/bluetoothd + new kernel, so we need a way to determine if SCO usage is allowed or not.

Quoted 32 lines
Quoted 32 lines
Quoted 30 lines
Quoted 17 lines

Apply the same restriction to sco_sock_bind() so unprivileged processes can no longer hijack incoming SCO links.

Fixes 1da177e4c3f4 ("Linux-2.6.12-rc2")
---
 net/bluetooth/sco.c | 7 +++++++
 1 file changed, 7 insertions(+)
net/bluetooth/sco.c +0 -0
index 3d4362a09df4..e4c26551e513 100644
@@ -667,6 +667,13 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr_unsized *addr,
 
      BT_DBG("sk %p %pMR", sk, &sa->sco_bdaddr);
 

net/bluetooth/sco.c static int sco_sock_bind(struct socket *sock, struct sockaddr_unsized *addr, · line 679

Quoted 10 lines
net/bluetooth/sco.c +7 -0
+     /* Binding a SCO socket reserves the ability to accept any incoming
+      * eSCO/SCO connection on the adapter, so restrict it in the same way
+      * L2CAP restricts well-known PSMs.
+      */
+     if (!capable(CAP_NET_BIND_SERVICE))
+             return -EACCES;
+
      lock_sock(sk);
 
      if (sk->sk_state != BT_OPEN) {

--
Pauli Virtanen

Signature · 1 line
Luiz Augusto von Dentz
#6 lore raw

pe, 2026-08-28 kello 12:46 -0400, Luiz Augusto von Dentz kirjoitti:

Quoted 23 lines · Pauli Virtanen
Quoted 22 lines

pe, 2026-08-28 kello 09:50 -0400, Luiz Augusto von Dentz kirjoitti:

Quoted 20 lines · Pauli Virtanen
Quoted 9 lines

to, 2026-08-27 kello 14:01 -0400, Luiz Augusto von Dentz kirjoitti:

Quoted 7 lines

From: Luiz Augusto von Dentz <[email protected]>

SCO sockets have no PSM or port namespace: binding one simply reserves the ability to accept any incoming eSCO/SCO connection on the adapter. That is equivalent to listening on a well-known service, which L2CAP already restricts to CAP_NET_BIND_SERVICE in l2cap_validate_bredr_psm()/l2cap_validate_le_psm().

Quoted 4 lines

In current Linux userspace, sound servers that do HFP listen on SCO sockets, and I think often don't have CAP_NET_BIND_SERVICE.

Do they continue working with this change?

Good question, that said this is a part of security hardening otherwise any process could start listening to an SCO connection, and the sound server would stop working. Btw, does the sound server have any special capability to, let's say, open the sound card device so perhaps we can gate it on sound capability as well.

Quoted 7 lines
Quoted 3 lines

For ALSA, the sound hardware access is controlled by device file permissions in /dev/snd/* Not sure if that's usable here, or if there's some other per-user controlled solution that could be used.

Ok, so you are saying anyone user with file access to /dev/snd/* can grab the hardware for itself, since pipewire is just a regular user it just works because it is the first one to open it?

Normally udev adjusts the /dev/snd/* file permissions, so that only the user who has the current "active seat" ie virtual console, can access them.

So they are not system-wide accessible to all users in mainstream current distros.

If the user with active seat runs multiple applications that want exclusive access to /dev/snd/*, they need to coordinate with themselves who gets the access. There exists a DBus protocol for cooperatively doing this, but usually everything just passes through the sound server so it's not needed.

Quoted 11 lines
Quoted 6 lines

In most current distros sound server runs with user permissions without special capabilities, and don't have CAP_NET_BIND_SERVICE, so I'd expect this patch breaks userspace.

Giving this capability to them allows binding to low network ports, so it probably makes the hardening issue worse and not better.

You would grant it to a specific set of binaries, probably via a systemd file. This would block other users, which currently might just be testing tools like isotest, where you just use sudo instead, or an AI agent trying to fabricate vulnerabilities.

That requires these binaries are hardened like suid-executables to only use the capability for SCO ...

Granting capabilities with systemd AFAIK does not work for user services, so not sure there's other alternative than setcap.

Quoted 7 lines
Quoted 3 lines

The next simplest is probably separate executable with setcap bit set, which gives a SCO listen socket for those who can run it based on file permissions.

What file permission? Afaik a socket protocol doesn't have file permissions, or does it? The is no open just bind which is what we are trying to protect.

I mean the file permissions of the executable file.

... hardening like that is easier to do by moving it to separate "suid" executable, which has setcap cap_net_bind_service=p executable file bits set, and chmod/chown permissions to restrict it to specific users.

Quoted 9 lines
Quoted 3 lines

For ISO bluetoothd manages this (so can be gated with DBus/selinux policies), and it could make sense for it to be made to work like that for SCO too.

Yeah, bluetoothd manages this for ISO and I wish we did this for SCO too, maybe via Profle interface which I guess PipeWire registers, but it just for RFCOMM/AT commands, right? Anyway this is too late because we cannot break support of older versions of pipewire/bluetoothd + new kernel, so we need a way to determine if SCO usage is allowed or not.

If sound server developers have to start thinking about separate executable/services for hardening this, it would be simpler to just add new DBus API to bluetoothd that does just SCO bind.

So I'm not really seeing a way to add the hardening now, without this type of ground work first, or accepting that distros have to temporarily set cap_net_bind_service=p (or some other capability) on the executable files. Which then allows sound servers to do other things like bind to low network ports as a side effect.

Quoted 34 lines
Quoted 32 lines
Quoted 32 lines
Quoted 30 lines
Quoted 17 lines

Apply the same restriction to sco_sock_bind() so unprivileged processes can no longer hijack incoming SCO links.

Fixes 1da177e4c3f4 ("Linux-2.6.12-rc2")
---
 net/bluetooth/sco.c | 7 +++++++
 1 file changed, 7 insertions(+)
net/bluetooth/sco.c +0 -0
index 3d4362a09df4..e4c26551e513 100644
@@ -667,6 +667,13 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr_unsized *addr,
 
      BT_DBG("sk %p %pMR", sk, &sa->sco_bdaddr);
 

net/bluetooth/sco.c static int sco_sock_bind(struct socket *sock, struct sockaddr_unsized *addr, · line 679

Quoted 10 lines
net/bluetooth/sco.c +7 -0
+     /* Binding a SCO socket reserves the ability to accept any incoming
+      * eSCO/SCO connection on the adapter, so restrict it in the same way
+      * L2CAP restricts well-known PSMs.
+      */
+     if (!capable(CAP_NET_BIND_SERVICE))
+             return -EACCES;
+
      lock_sock(sk);
 
      if (sk->sk_state != BT_OPEN) {

--
Pauli Virtanen

Signature · 1 line
Pauli Virtanen
#7 lore raw
In reply to Luiz Augusto von Dentz

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list. This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1152789

---Test result---

Test Summary:

CheckPatch                    PASS      1.08 seconds
VerifyFixes                   PASS      0.07 seconds
VerifySignedoff               PASS      0.07 seconds
GitLint                       PASS      0.42 seconds
SubjectPrefix                 PASS      0.13 seconds
BuildKernel                   PASS      27.76 seconds
CheckAllWarning               PASS      30.59 seconds
CheckSparse                   PASS      29.04 seconds
BuildKernel32                 PASS      26.89 seconds
CheckKernelLLVM               SKIP      0.00 seconds
TestRunnerSetup               PASS      503.99 seconds
TestRunner_iso-tester         PASS      102.37 seconds
TestRunner_sco-tester         PASS      32.11 seconds
IncrementalBuild              PASS      29.64 seconds

Details
##############################
Test: CheckKernelLLVM - SKIP
Desc: Build kernel with LLVM + context analysis
Output:
Clang not found

https://github.com/bluez/bluetooth-next/pull/657

---
Regards,
Linux Bluetooth