]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Bluetooth: hci_sock: write the full optval for getsockopt
authorBreno Leitao <leitao@debian.org>
Tue, 12 May 2026 11:12:16 +0000 (04:12 -0700)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Thu, 11 Jun 2026 18:24:38 +0000 (14:24 -0400)
In hci_sock_getsockopt_old(), HCI_DATA_DIR and HCI_TIME_STAMP both store
their value into a local int and then call put_user(opt, optval). Because
optval is the function parameter typed char __user *, put_user sizes the
write from sizeof(*optval), so only the low byte of the int is copied to
userspace.

The matching setsockopt path reads sizeof(int) via copy_safe_from_sockptr,
so userspace passes a 4-byte buffer in both directions but previously got
back only one initialized byte on the read side.

Not sending this through 'net' tree given this bug is mostly invisble,
given opt is 0/1, and the last byte is being properly copied.

With this change, the upcoming translation to .getsockopt_iter becomes
mechanical.

FWIW: This behavior appeared in commit 1da177e4c3f4 ("Linux-2.6.12-rc2").

Signed-off-by: Breno Leitao <leitao@debian.org>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
net/bluetooth/hci_sock.c

index 0290dea081f621782eb1a89512835430f1facf50..1823c06ba8940b0fb3ed8ddd0910f3aad2063cf3 100644 (file)
@@ -2088,7 +2088,7 @@ static int hci_sock_getsockopt_old(struct socket *sock, int level, int optname,
                else
                        opt = 0;
 
-               if (put_user(opt, optval))
+               if (put_user(opt, (int __user *)optval))
                        err = -EFAULT;
                break;
 
@@ -2098,7 +2098,7 @@ static int hci_sock_getsockopt_old(struct socket *sock, int level, int optname,
                else
                        opt = 0;
 
-               if (put_user(opt, optval))
+               if (put_user(opt, (int __user *)optval))
                        err = -EFAULT;
                break;