aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChuck Tuffli <chuck@FreeBSD.org>2026-06-08 21:19:34 +0000
committerChuck Tuffli <chuck@FreeBSD.org>2026-06-08 21:20:14 +0000
commit471fdd91d9156aeab026dc420fb97d97be872d65 (patch)
treefae2dea2718224034e1a0fb558ecf1962ba903e6
parentea3426bc80aad58e689c144ec6ddee0cda7861cb (diff)
linux: Fix sockopt copyout
The Linux getsockopt did not check the size of the provided buffer when copying out the value, leading to buffer overflows (e.g., for TCP_INFO). Fix is to use the smaller of the option value size and the provided buffer. MFC after: 1 month Relnotes: yes Reviewed by: kib, markj Differential Revision: https://reviews.freebsd.org/D55881
-rw-r--r--sys/compat/linux/linux_socket.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index 29b55ef60357..12ba6a3adfce 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -2316,10 +2316,21 @@ linux_sockopt_copyout(struct thread *td, void *val, socklen_t len,
struct linux_getsockopt_args *args)
{
int error;
+ l_int loptlen;
+ socklen_t optlen;
- error = copyout(val, PTRIN(args->optval), len);
- if (error == 0)
- error = copyout(&len, PTRIN(args->optlen), sizeof(len));
+ error = copyin(PTRIN(args->optlen), &loptlen, sizeof(loptlen));
+ if (error != 0)
+ return (error);
+ if (loptlen < 0)
+ return (EINVAL);
+
+ optlen = (socklen_t)loptlen;
+ error = copyout(val, PTRIN(args->optval), min(len, optlen));
+ if (error == 0) {
+ loptlen = (l_int)len;
+ error = copyout(&loptlen, PTRIN(args->optlen), sizeof(loptlen));
+ }
return (error);
}