summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorXin Long <lucien.xin@gmail.com>2017-02-24 16:29:06 +0800
committerBen Hutchings <ben@decadent.org.uk>2019-08-13 12:38:38 +0100
commit2b8d63b97d78835d3cd75b0ee344d21489df4edc (patch)
tree587d2e2ebbaf514e407f90f999814dae8026add4 /net
parent8eb43aebcde79ccadf76d80f20d8b3e60663e940 (diff)
ipv6: check sk sk_type and protocol early in ip_mroute_set/getsockopt
commit 99253eb750fda6a644d5188fb26c43bad8d5a745 upstream. 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: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/ip6mr.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 42978998534c..5733b05558a5 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1662,6 +1662,10 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
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 == NULL)
return -ENOENT;
@@ -1673,9 +1677,6 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
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;
@@ -1812,6 +1813,10 @@ int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval,
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 == NULL)
return -ENOENT;