[PATCH net-next v2 1/7] ipv6: treat a negative optlen as 4 in do_ipv6_getsockopt()
From: Breno Leitao
Date: Fri Oct 09 2026 - 05:13:15 EST
do_ipv6_getsockopt() reads optlen into an int and never checks its
sign. Most of what consumes len compares it as unsigned, so a negative
optlen reads as a huge buffer, and the reply depends on the option.
The int options clamp it to their own size:
len = min_t(unsigned int, sizeof(int), len);
so getsockopt(fd, SOL_IPV6, IPV6_TCLASS, buf, &len) with len set to -1
answers 4 bytes and reports 4, rather than failing.
The other options see a huge buffer. The sticky options reply with
their whole header, IPV6_2292PKTOPTIONS writes every pending control
message without a limit, and IPV6_PATHMTU and IPV6_FLOWLABEL_MGR pass
their length check.
do_ip_getsockopt() rejects a negative optlen, but doing that here would
turn a call that works today into an error for a caller that passes an
uninitialized length. Answer it as 4, as the int options do, for every
option.
That leaves the int options as they are. The sticky headers are cut to
4 bytes, IPV6_2292PKTOPTIONS gets a 4 byte control buffer, and
IPV6_PATHMTU and IPV6_FLOWLABEL_MGR fail with -EINVAL, as they do for
any other undersized buffer.
The conversion of this function to sockopt_t builds its buffers from
optlen, which the standard helpers reject when negative, so the answer
has to be settled before that.
Suggested-by: David Laight <david.laight.linux@xxxxxxxxx>
Signed-off-by: Breno Leitao <leitao@xxxxxxxxxx>
---
net/ipv6/ipv6_sockglue.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 4b3536571c9804..4091d1521cc09f 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -1002,6 +1002,11 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
if (copy_from_sockptr(&len, optlen, sizeof(int)))
return -EFAULT;
+ /* Historic bug compatibility: the int options have always taken a
+ * negative optlen as 4, so take it as 4 everywhere.
+ */
+ if (len < 0)
+ len = 4;
switch (optname) {
case MCAST_MSFILTER:
if (in_compat_syscall())
--
2.53.0-Meta