Re: [PATCH net-next v4 1/7] ipv6: treat a negative optlen as 4 in do_ipv6_getsockopt()

From: Jiayuan Chen

Date: Tue Nov 03 2026 - 23:15:47 EST



On 11/3/26 7:01 PM, Breno Leitao wrote:
> 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 this function handles itself.
>
> 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.
>
> MRT6_* is dispatched earlier and keeps rejecting a negative optlen, and
> the netfilter fallback still sees the caller's value.
>
> This changes what callers that pass a negative length see. It is a
> behaviour change, not a fix, so there is no Fixes: tag.
>
> 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>
> Acked-by: Stanislav Fomichev <sdf@xxxxxxxxxxx>
> Acked-by: Ido Schimmel <idosch@xxxxxxxxxx>
> Signed-off-by: Breno Leitao <leitao@xxxxxxxxxx>


Reviewed-by: Jiayuan Chen <jiayuan.chen@xxxxxxxxx>


> ---
> 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..700133e2fd11c2 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: take a negative optlen as 4, as the
> + * int options always did.
> + */
> + if (len < 0)
> + len = 4;
> switch (optname) {
> case MCAST_MSFILTER:
> if (in_compat_syscall())
>