[ Upstream commit 99253eb750fda6a644d5188fb26c43bad8d5a745 ]
Commit 5e1859fbcc3c ("ipv4: ipmr: various fixes and cleanups") fixed the issue for ipv4 ipmr:
ip_mroute_setsockopt() & ip_mroute_getsockopt() should not access/set raw_sk(sk)->ipmr_table before making sure the socket is a raw socket, and protocol is IGMP
The same fix should be done for ipv6 ipmr as well.
This patch can fix the panic caused by overwriting the same offset as ipmr_table as in raw_sk(sk) when accessing other type's socket by ip_mroute_setsockopt().
Signed-off-by: Xin Long lucien.xin@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/ipv6/ip6mr.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
--- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -1668,6 +1668,10 @@ int ip6_mroute_setsockopt(struct sock *s struct net *net = sock_net(sk); struct mr6_table *mrt;
+ if (sk->sk_type != SOCK_RAW || + inet_sk(sk)->inet_num != IPPROTO_ICMPV6) + return -EOPNOTSUPP; + mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); if (!mrt) return -ENOENT; @@ -1679,9 +1683,6 @@ int ip6_mroute_setsockopt(struct sock *s
switch (optname) { case MRT6_INIT: - if (sk->sk_type != SOCK_RAW || - inet_sk(sk)->inet_num != IPPROTO_ICMPV6) - return -EOPNOTSUPP; if (optlen < sizeof(int)) return -EINVAL;
@@ -1818,6 +1819,10 @@ int ip6_mroute_getsockopt(struct sock *s struct net *net = sock_net(sk); struct mr6_table *mrt;
+ if (sk->sk_type != SOCK_RAW || + inet_sk(sk)->inet_num != IPPROTO_ICMPV6) + return -EOPNOTSUPP; + mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); if (!mrt) return -ENOENT;