diff options
| author | Chuck Tuffli <chuck@FreeBSD.org> | 2026-06-08 21:19:34 +0000 |
|---|---|---|
| committer | Chuck Tuffli <chuck@FreeBSD.org> | 2026-06-08 21:20:14 +0000 |
| commit | 471fdd91d9156aeab026dc420fb97d97be872d65 (patch) | |
| tree | fae2dea2718224034e1a0fb558ecf1962ba903e6 | |
| parent | ea3426bc80aad58e689c144ec6ddee0cda7861cb (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.c | 17 |
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); } |
