netns: Add network namespace argument in rt6_fill_node() and ipv6_dev_get_saddr()
Subsystems (5)
PATCH 2/2 netns: Add network namespace argument in rt6_fill_node() and ipv6_dev_get_saddr()
Add network namespace argument to rt6_fill_node() and ipv6_dev_get_saddr(). This required adding a namespace pointer in the IPv6 fib dump callback routine.
-Brian
---
include/net/addrconf.h +2 -1
@@ -80,7 +80,8 @@ extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,struct net_device *dev, int strict); -extern int ipv6_dev_get_saddr (struct net_device *dev, +extern int ipv6_dev_get_saddr (struct net *net, +struct net_device *dev,const struct in6_addr *daddr,unsigned int srcprefs,struct in6_addr *saddr);
include/net/ip6_route.h +1 -0
@@ -107,6 +107,7 @@ struct rt6_rtnl_dump_arg {struct sk_buff *skb;struct netlink_callback *cb; +struct net *net; };extern int rt6_dump_route (struct rt6_info *rt,void *p_arg);
net/ipv6/addrconf.c +4 -2
@@ -1106,17 +1106,19 @@ out:return ret; } -int ipv6_dev_get_saddr (struct net_device *dst_dev, +int ipv6_dev_get_saddr (struct net *net,struct net_device *dst_dev,const struct in6_addr *daddr,unsigned int prefs,struct in6_addr *saddr) {struct ipv6_saddr_score scores[2 ], *score = &scores[0 ], *hiscore = &scores[1 ]; -struct net *net =dev_net (dst_dev);struct ipv6_saddr_dst dst;struct net_device *dev;int dst_type; +if (!net) + net =dev_net (dst_dev); + dst_type =__ipv6_addr_type (daddr); dst.addr = daddr; dst.ifindex = dst_dev ? dst_dev->ifindex :0 ;
net/ipv6/fib6_rules.c +2 -1
@@ -93,7 +93,8 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,if (flags &RT6_LOOKUP_F_SRCPREF_COA ) srcprefs |=IPV6_PREFER_SRC_COA ; -if (ipv6_dev_get_saddr (ip6_dst_idev (&rt->u.dst)->dev, +if (ipv6_dev_get_saddr (net, +ip6_dst_idev (&rt->u.dst)->dev, &flp->fl6_dst, srcprefs, &saddr)) goto again;
net/ipv6/ip6_fib.c +1 -0
@@ -378,6 +378,7 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) arg.skb = skb; arg.cb = cb; + arg.net = net; w->args = &arg;for (h = s_h; h <FIB_TABLE_HASHSZ ; h++, s_e =0 ) {
net/ipv6/ip6_output.c +1 -1
@@ -934,7 +934,7 @@ static int ip6_dst_lookup_tail(struct sock *sk, goto out_err_release;if (ipv6_addr_any (&fl->fl6_src)) { - err =ipv6_dev_get_saddr (ip6_dst_idev (*dst)->dev, + err =ipv6_dev_get_saddr (net,ip6_dst_idev (*dst)->dev, &fl->fl6_dst, sk ?inet6_sk (sk)->srcprefs :0 , &fl->fl6_src);
net/ipv6/ndisc.c +1 -1
@@ -549,7 +549,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, override =0 ;in6_ifa_put (ifp); }else { -if (ipv6_dev_get_saddr (dev, daddr, +if (ipv6_dev_get_saddr (dev_net (dev), dev, daddr,inet6_sk (dev_net (dev)->ipv6.ndisc_sk)->srcprefs, &tmpaddr))return ;
net/ipv6/route.c +7 -5
@@ -2106,7 +2106,8 @@ static inline size_t rt6_nlmsg_size(void) +nla_total_size (sizeof (struct rta_cacheinfo )); } -static int rt6_fill_node (struct sk_buff *skb,struct rt6_info *rt, +static int rt6_fill_node (struct net *net, +struct sk_buff *skb,struct rt6_info *rt,struct in6_addr *dst,struct in6_addr *src,int iif,int type,u32 pid,u32 seq,int prefix,int nowait,unsigned int flags)
@@ -2189,7 +2190,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, }else if (dst) {struct inet6_dev *idev =ip6_dst_idev (&rt->u.dst);struct in6_addr saddr_buf; -if (ipv6_dev_get_saddr (idev ? idev->dev :NULL , +if (ipv6_dev_get_saddr (net, idev ? idev->dev :NULL , dst,0 , &saddr_buf) ==0 )NLA_PUT (skb,RTA_PREFSRC ,16 , &saddr_buf); }
@@ -2234,7 +2235,8 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg) }else prefix =0 ; -return rt6_fill_node (arg->skb, rt,NULL ,NULL ,0 ,RTM_NEWROUTE , +return rt6_fill_node (arg->net, + arg->skb, rt,NULL ,NULL ,0 ,RTM_NEWROUTE ,NETLINK_CB (arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq, prefix,0 ,NLM_F_MULTI ); }
@@ -2300,7 +2302,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void rt = (struct rt6_info *)ip6_route_output (net,NULL , &fl); skb->dst = &rt->u.dst; - err =rt6_fill_node (skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, + err =rt6_fill_node (net, skb, rt, &fl.fl6_dst, &fl.fl6_src, iif,RTM_NEWROUTE ,NETLINK_CB (in_skb).pid, nlh->nlmsg_seq,0 ,0 ,0 );if (err <0 ) {
@@ -2327,7 +2329,7 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)if (skb ==NULL ) goto errout; - err =rt6_fill_node (skb, rt,NULL ,NULL ,0 , + err =rt6_fill_node (net, skb, rt,NULL ,NULL ,0 , event, info->pid, seq,0 ,0 ,0 );if (err <0 ) {/* -EMSGSIZE implies BUG in rt6_nlmsg_size() */
net/ipv6/xfrm6_policy.c +1 -1
@@ -57,7 +57,7 @@ static int xfrm6_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr)if (IS_ERR (dst))return -EHOSTUNREACH ; -ipv6_dev_get_saddr (ip6_dst_idev (dst)->dev, +ipv6_dev_get_saddr (NULL ,ip6_dst_idev (dst)->dev, (struct in6_addr *)&daddr->a6,0 , (struct in6_addr *)&saddr->a6);dst_release (dst);
net/sctp/ipv6.c +2 -1
@@ -319,7 +319,8 @@ static void sctp_v6_get_saddr(struct sctp_sock *sk, __func__, asoc, dst, NIP6(daddr->v6.sin6_addr));if (!asoc) { -ipv6_dev_get_saddr (dst ?ip6_dst_idev (dst)->dev :NULL , +ipv6_dev_get_saddr (NULL , + dst ?ip6_dst_idev (dst)->dev :NULL , &daddr->v6.sin6_addr,inet6_sk (&sk->inet.sk)->srcprefs, &saddr->v6.sin6_addr);
Hi Brian
Quoted 7 lines · Brian Haley
---
net/sctp/ipv6.c +0
-0
net/sctp/ipv6.c static void sctp_v6_get_saddr(struct sctp_sock *sk, · line 326
Quoted 9 lines
net/sctp/ipv6.c +2
-1@@ -319,7 +319,8 @@ static void sctp_v6_get_saddr(struct sctp_sock *sk, __func__, asoc, dst, NIP6(daddr->v6.sin6_addr));if (!asoc) { -ipv6_dev_get_saddr (dst ?ip6_dst_idev (dst)->dev :NULL , +ipv6_dev_get_saddr (NULL , + dst ?ip6_dst_idev (dst)->dev :NULL , &daddr->v6.sin6_addr,inet6_sk (&sk->inet.sk)->srcprefs, &saddr->v6.sin6_addr);
I think this needs to use sock_net(sctp_opt2s(sk)) instead of NULL.
-vlad
Hi Vlad,
Quoted 12 lines · Vlad Yasevich
Hi Brian
Quoted 9 lines · Brian Haley
---
net/sctp/ipv6.c +0
-0@@ -319,7 +319,8 @@ static void sctp_v6_get_saddr(struct sctp_sock *sk, __func__, asoc, dst, NIP6(daddr->v6.sin6_addr));
Quoted 10 lines
net/sctp/ipv6.c static void sctp_v6_get_saddr(struct sctp_sock *sk, · line 326
Quoted 7 lines
net/sctp/ipv6.c +2
-1if (!asoc) { -ipv6_dev_get_saddr (dst ?ip6_dst_idev (dst)->dev :NULL , +ipv6_dev_get_saddr (NULL , + dst ?ip6_dst_idev (dst)->dev :NULL , &daddr->v6.sin6_addr,inet6_sk (&sk->inet.sk)->srcprefs, &saddr->v6.sin6_addr);I think this needs to use sock_net(sctp_opt2s(sk)) instead of NULL.
Thanks Vlad, I didn't see that. I noticed the xfrm code could pass non-NULL has well, I'll respin.
-Brian
Quoted 25 lines · Brian Haley
Hi Vlad,
Quoted 22 lines · Vlad Yasevich
Hi Brian
Quoted 7 lines · Brian Haley
---
net/sctp/ipv6.c +0
-0net/sctp/ipv6.c static void sctp_v6_get_saddr(struct sctp_sock *sk, · line 326
Quoted 9 lines
net/sctp/ipv6.c +2
-1@@ -319,7 +319,8 @@ static void sctp_v6_get_saddr(struct sctp_sock *sk, __func__, asoc, dst, NIP6(daddr->v6.sin6_addr));if (!asoc) { -ipv6_dev_get_saddr (dst ?ip6_dst_idev (dst)->dev :NULL , +ipv6_dev_get_saddr (NULL , + dst ?ip6_dst_idev (dst)->dev :NULL , &daddr->v6.sin6_addr,inet6_sk (&sk->inet.sk)->srcprefs, &saddr->v6.sin6_addr);I think this needs to use sock_net(sctp_opt2s(sk)) instead of NULL.
that was supposed to read: sock_net(sctp_opt2sk(sk)
-vlad
Quoted 12 lines · Vlad Yasevich
Hi Brian
Quoted 9 lines · Brian Haley
---
net/sctp/ipv6.c +0
-0@@ -319,7 +319,8 @@ static void sctp_v6_get_saddr(struct sctp_sock *sk, __func__, asoc, dst, NIP6(daddr->v6.sin6_addr));
Quoted 10 lines
net/sctp/ipv6.c static void sctp_v6_get_saddr(struct sctp_sock *sk, · line 326
Quoted 7 lines
net/sctp/ipv6.c +2
-1if (!asoc) { -ipv6_dev_get_saddr (dst ?ip6_dst_idev (dst)->dev :NULL , +ipv6_dev_get_saddr (NULL , + dst ?ip6_dst_idev (dst)->dev :NULL , &daddr->v6.sin6_addr,inet6_sk (&sk->inet.sk)->srcprefs, &saddr->v6.sin6_addr);I think this needs to use sock_net(sctp_opt2s(sk)) instead of NULL.
this looks safe to me
Quoted 8 lines · Brian Haley
Add network namespace argument to
rt6_fill_node()andipv6_dev_get_saddr(). This required adding a namespace pointer in the IPv6 fib dump callback routine.-Brian
Signed-off-by Brian Haley <[email protected]>---
This patch is to fix a kernel panic in ipv6_dev_get_saddr.
That happens because the dev parameter can be null and we try to dereference dev->nd_net, right ?
The approach looks correct except with the network namespace passed as parameter, it must never be NULL.
Quoted 38 lines
include/net/addrconf.h +2
-1@@ -80,7 +80,8 @@ extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,struct net_device *dev, int strict); -extern int ipv6_dev_get_saddr (struct net_device *dev, +extern int ipv6_dev_get_saddr (struct net *net, +struct net_device *dev,const struct in6_addr *daddr,unsigned int srcprefs,struct in6_addr *saddr);include/net/ip6_route.h +1
-0@@ -107,6 +107,7 @@ struct rt6_rtnl_dump_arg {struct sk_buff *skb;struct netlink_callback *cb; +struct net *net; };extern int rt6_dump_route (struct rt6_info *rt,void *p_arg);net/ipv6/addrconf.c +1
-1@@ -1106,17 +1106,19 @@ out:return ret; } -int ipv6_dev_get_saddr (struct net_device *dst_dev, +int ipv6_dev_get_saddr (struct net *net,struct net_device *dst_dev,const struct in6_addr *daddr,unsigned int prefs,struct in6_addr *saddr)
net/ipv6/addrconf.c out: · line 1120
Quoted 10 lines
net/ipv6/addrconf.c +2
-1{struct ipv6_saddr_score scores[2 ], *score = &scores[0 ], *hiscore = &scores[1 ]; -struct net *net =dev_net (dst_dev);struct ipv6_saddr_dst dst;struct net_device *dev;int dst_type; +if (!net) + net =dev_net (dst_dev);
These lines are not needed, because the net parameter will be never NULL, see below.
Quoted 111 lines
net/ipv6/addrconf.c +0
-0dst_type =__ipv6_addr_type (daddr); dst.addr = daddr; dst.ifindex = dst_dev ? dst_dev->ifindex :0 ;net/ipv6/fib6_rules.c +2
-1@@ -93,7 +93,8 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,if (flags &RT6_LOOKUP_F_SRCPREF_COA ) srcprefs |=IPV6_PREFER_SRC_COA ; -if (ipv6_dev_get_saddr (ip6_dst_idev (&rt->u.dst)->dev, +if (ipv6_dev_get_saddr (net, +ip6_dst_idev (&rt->u.dst)->dev, &flp->fl6_dst, srcprefs, &saddr)) goto again;net/ipv6/ip6_fib.c +1
-0@@ -378,6 +378,7 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) arg.skb = skb; arg.cb = cb; + arg.net = net; w->args = &arg;for (h = s_h; h <FIB_TABLE_HASHSZ ; h++, s_e =0 ) {net/ipv6/ip6_output.c +1
-1@@ -934,7 +934,7 @@ static int ip6_dst_lookup_tail(struct sock *sk, goto out_err_release;if (ipv6_addr_any (&fl->fl6_src)) { - err =ipv6_dev_get_saddr (ip6_dst_idev (*dst)->dev, + err =ipv6_dev_get_saddr (net,ip6_dst_idev (*dst)->dev, &fl->fl6_dst, sk ?inet6_sk (sk)->srcprefs :0 , &fl->fl6_src);net/ipv6/ndisc.c +1
-1@@ -549,7 +549,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, override =0 ;in6_ifa_put (ifp); }else { -if (ipv6_dev_get_saddr (dev, daddr, +if (ipv6_dev_get_saddr (dev_net (dev), dev, daddr,inet6_sk (dev_net (dev)->ipv6.ndisc_sk)->srcprefs, &tmpaddr))return ;net/ipv6/route.c +7
-5@@ -2106,7 +2106,8 @@ static inline size_t rt6_nlmsg_size(void) +nla_total_size (sizeof (struct rta_cacheinfo )); } -static int rt6_fill_node (struct sk_buff *skb,struct rt6_info *rt, +static int rt6_fill_node (struct net *net, +struct sk_buff *skb,struct rt6_info *rt,struct in6_addr *dst,struct in6_addr *src,int iif,int type,u32 pid,u32 seq,int prefix,int nowait,unsigned int flags)@@ -2189,7 +2190,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, }else if (dst) {struct inet6_dev *idev =ip6_dst_idev (&rt->u.dst);struct in6_addr saddr_buf; -if (ipv6_dev_get_saddr (idev ? idev->dev :NULL , +if (ipv6_dev_get_saddr (net, idev ? idev->dev :NULL , dst,0 , &saddr_buf) ==0 )NLA_PUT (skb,RTA_PREFSRC ,16 , &saddr_buf); }@@ -2234,7 +2235,8 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg) }else prefix =0 ; -return rt6_fill_node (arg->skb, rt,NULL ,NULL ,0 ,RTM_NEWROUTE , +return rt6_fill_node (arg->net, + arg->skb, rt,NULL ,NULL ,0 ,RTM_NEWROUTE ,NETLINK_CB (arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq, prefix,0 ,NLM_F_MULTI ); }@@ -2300,7 +2302,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void rt = (struct rt6_info *)ip6_route_output (net,NULL , &fl); skb->dst = &rt->u.dst; - err =rt6_fill_node (skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, + err =rt6_fill_node (net, skb, rt, &fl.fl6_dst, &fl.fl6_src, iif,RTM_NEWROUTE ,NETLINK_CB (in_skb).pid, nlh->nlmsg_seq,0 ,0 ,0 );if (err <0 ) {@@ -2327,7 +2329,7 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)if (skb ==NULL ) goto errout; - err =rt6_fill_node (skb, rt,NULL ,NULL ,0 , + err =rt6_fill_node (net, skb, rt,NULL ,NULL ,0 , event, info->pid, seq,0 ,0 ,0 );if (err <0 ) {/* -EMSGSIZE implies BUG in rt6_nlmsg_size() */ net/ipv6/xfrm6_policy.c +0
-0
net/ipv6/xfrm6_policy.c static int xfrm6_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr) · line 60
Quoted 5 lines
net/ipv6/xfrm6_policy.c +1
-1@@ -57,7 +57,7 @@ static int xfrm6_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr)if (IS_ERR (dst))return -EHOSTUNREACH ; - ipv6_dev_get_saddr(ip6_dst_idev(dst)->dev, + ipv6_dev_get_saddr(NULL, ip6_dst_idev(dst)->dev,
ipv6_dev_get_saddr(&init_net, ...
net/sctp/ipv6.c static void sctp_v6_get_saddr(struct sctp_sock *sk, · line 322
Quoted 13 lines
net/ipv6/xfrm6_policy.c +0
-0(struct in6_addr *)&daddr->a6,0 , (struct in6_addr *)&saddr->a6);dst_release (dst);net/sctp/ipv6.c +1
-1@@ -319,7 +319,8 @@ static void sctp_v6_get_saddr(struct sctp_sock *sk, __func__, asoc, dst, NIP6(daddr->v6.sin6_addr));if (!asoc) { - ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, + ipv6_dev_get_saddr(NULL,
ipv6_dev_get_saddr(&init_net, ...
Using init_net instead of NULL makes sense for xfrm6 and sctp, because they are not yet supported by the namespaces :) Furthermore it is more practical to track the places where we have to take care of the namespaces.
Thanks.
-- Daniel
David Miller
maintainerFrom: Daniel Lezcano <[email protected]>
Date: Sun, 17 Aug 2008 00:47:12 +0200
Quoted 2 lines
The approach looks correct except with the network namespace passed as parameter, it must never be NULL.
You're reviewing the patches that Brian retracted, we added a different version of these fixes in the end.
A message that is not in the archive (sent off-list or not yet received): 20080817.153526.109132408.davem-fT/PcQaiUtIeIZ0/[email protected]
Quoted 8 lines · David Miller
From: Daniel Lezcano <dlezcano-NmTC/[email protected]>
Date: Sun, 17 Aug 2008 00:47:12 +0200Quoted 2 lines
The approach looks correct except with the network namespace passed as parameter, it must never be NULL.
You're reviewing the patches that Brian retracted, we added a different version of these fixes in the end.
Yes thanks, I received the emails delayed, so I saw the first version and no reply to them, neither the V2.
The second version is much better.
Thanks Brian for fixing this :)
-- Daniel