Re: [PATCH net 2/2] ipv6: mcast: do not write past optlen in the source filter getsockopt
David Laight <[email protected]>
| Newsgroups | gmane.linux.network,gmane.linux.kernel,gmane.linux.kernel.stable |
|---|---|
| Message-ID | <20260807174437.01bf2e33@pumpkin> |
On Thu, 06 Aug 2026 02:42:01 -0700 Breno Leitao <[email protected]> wrote: > getsockopt(MCAST_MSFILTER) on an IPv6 socket overruns the caller's buffer > the same way the IPv4 one does. ip6_mc_msfget() fills the source list from > the numsrc left in optval, and nothing compares that against optlen, which > ipv6_get_msfilter() has already reused for the length of the reply. > > Clamp numsrc to what optlen holds, as the IPv4 side now does. Nak, same as IPv4. David > > Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") > Cc: [email protected] > Signed-off-by: Breno Leitao <[email protected]> > --- > net/ipv6/ipv6_sockglue.c | 11 +++++++++++ > 1 file changed, 11 insertions(+) > > diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c > index b4c977434c2e0..2c3fbde7cb058 100644 > --- a/net/ipv6/ipv6_sockglue.c > +++ b/net/ipv6/ipv6_sockglue.c > @@ -1012,6 +1012,7 @@ static int ipv6_get_msfilter(struct sock *sk, sockptr_t optval, > { > const int size0 = offsetof(struct group_filter, gf_slist_flex); > struct group_filter gsf; > + unsigned int max_numsrc; > int num; > int err; > > @@ -1021,6 +1022,11 @@ static int ipv6_get_msfilter(struct sock *sk, sockptr_t optval, > return -EFAULT; > if (gsf.gf_group.ss_family != AF_INET6) > return -EADDRNOTAVAIL; > + > + /* Number of sources that would fit in the userspace buffer */ > + max_numsrc = (len - size0) / sizeof(gsf.gf_slist_flex[0]); > + gsf.gf_numsrc = min_t(u32, gsf.gf_numsrc, max_numsrc); > + > num = gsf.gf_numsrc; > sockopt_lock_sock(sk); > err = ip6_mc_msfget(sk, &gsf, optval, size0); > @@ -1041,6 +1047,7 @@ static int compat_ipv6_get_msfilter(struct sock *sk, sockptr_t optval, > { > const int size0 = offsetof(struct compat_group_filter, gf_slist_flex); > struct compat_group_filter gf32; > + unsigned int max_numsrc; > struct group_filter gf; > int err; > int num; > @@ -1050,6 +1057,10 @@ static int compat_ipv6_get_msfilter(struct sock *sk, sockptr_t optval, > > if (copy_from_sockptr(&gf32, optval, size0)) > return -EFAULT; > + > + max_numsrc = (len - size0) / sizeof(gf32.gf_slist_flex[0]); > + gf32.gf_numsrc = min_t(u32, gf32.gf_numsrc, max_numsrc); > + > gf.gf_interface = gf32.gf_interface; > gf.gf_fmode = gf32.gf_fmode; > num = gf.gf_numsrc = gf32.gf_numsrc; >