diff mbox

[PATCHv2,net] ipv6: should not return rt->dst.error if it is prohibit or blk hole entry.

Message ID 1500608835-24845-1-git-send-email-liuhangbin@gmail.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Hangbin Liu July 21, 2017, 3:47 a.m. UTC
After commit 18c3a61c4264 ("net: ipv6: RTM_GETROUTE: return matched fib
result when requested"). When we get a prohibit ertry, we will return
-EACCES directly.

Before:
+ ip netns exec client ip -6 route get 2003::1
prohibit 2003::1 dev lo table unspec proto kernel src 2001::1 metric
4294967295 error -13

After:
+ ip netns exec server ip -6 route get 2002::1
RTNETLINK answers: Permission denied

Fix this by add prohibit and blk hole check. Since ip6_null_entry's
error is already -ENETUNREACH. Merge the ip6_null_entry check and error
check together.

Fixes: 18c3a61c4264 ("net: ipv6: RTM_GETROUTE: return matched fib...")
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
 net/ipv6/route.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

Comments

kernel test robot July 21, 2017, 3:29 p.m. UTC | #1
Hi Hangbin,

[auto build test ERROR on net/master]

url:    https://github.com/0day-ci/linux/commits/Hangbin-Liu/ipv6-should-not-return-rt-dst-error-if-it-is-prohibit-or-blk-hole-entry/20170721-204554
config: m68k-sun3_defconfig (attached as .config)
compiler: m68k-linux-gcc (GCC) 4.9.0
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=m68k 

All errors (new ones prefixed by >>):

   net//ipv6/route.c: In function 'inet6_rtm_getroute':
>> net//ipv6/route.c:3640:38: error: 'struct netns_ipv6' has no member named 'ip6_prohibit_entry'
     if (rt->dst.error && rt != net->ipv6.ip6_prohibit_entry &&
                                         ^
>> net//ipv6/route.c:3641:21: error: 'struct netns_ipv6' has no member named 'ip6_blk_hole_entry'
         rt != net->ipv6.ip6_blk_hole_entry) {
                        ^

vim +3640 net//ipv6/route.c

  3558	
  3559	static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
  3560				      struct netlink_ext_ack *extack)
  3561	{
  3562		struct net *net = sock_net(in_skb->sk);
  3563		struct nlattr *tb[RTA_MAX+1];
  3564		int err, iif = 0, oif = 0;
  3565		struct dst_entry *dst;
  3566		struct rt6_info *rt;
  3567		struct sk_buff *skb;
  3568		struct rtmsg *rtm;
  3569		struct flowi6 fl6;
  3570		bool fibmatch;
  3571	
  3572		err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy,
  3573				  extack);
  3574		if (err < 0)
  3575			goto errout;
  3576	
  3577		err = -EINVAL;
  3578		memset(&fl6, 0, sizeof(fl6));
  3579		rtm = nlmsg_data(nlh);
  3580		fl6.flowlabel = ip6_make_flowinfo(rtm->rtm_tos, 0);
  3581		fibmatch = !!(rtm->rtm_flags & RTM_F_FIB_MATCH);
  3582	
  3583		if (tb[RTA_SRC]) {
  3584			if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr))
  3585				goto errout;
  3586	
  3587			fl6.saddr = *(struct in6_addr *)nla_data(tb[RTA_SRC]);
  3588		}
  3589	
  3590		if (tb[RTA_DST]) {
  3591			if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr))
  3592				goto errout;
  3593	
  3594			fl6.daddr = *(struct in6_addr *)nla_data(tb[RTA_DST]);
  3595		}
  3596	
  3597		if (tb[RTA_IIF])
  3598			iif = nla_get_u32(tb[RTA_IIF]);
  3599	
  3600		if (tb[RTA_OIF])
  3601			oif = nla_get_u32(tb[RTA_OIF]);
  3602	
  3603		if (tb[RTA_MARK])
  3604			fl6.flowi6_mark = nla_get_u32(tb[RTA_MARK]);
  3605	
  3606		if (tb[RTA_UID])
  3607			fl6.flowi6_uid = make_kuid(current_user_ns(),
  3608						   nla_get_u32(tb[RTA_UID]));
  3609		else
  3610			fl6.flowi6_uid = iif ? INVALID_UID : current_uid();
  3611	
  3612		if (iif) {
  3613			struct net_device *dev;
  3614			int flags = 0;
  3615	
  3616			dev = __dev_get_by_index(net, iif);
  3617			if (!dev) {
  3618				err = -ENODEV;
  3619				goto errout;
  3620			}
  3621	
  3622			fl6.flowi6_iif = iif;
  3623	
  3624			if (!ipv6_addr_any(&fl6.saddr))
  3625				flags |= RT6_LOOKUP_F_HAS_SADDR;
  3626	
  3627			if (!fibmatch)
  3628				dst = ip6_route_input_lookup(net, dev, &fl6, flags);
  3629		} else {
  3630			fl6.flowi6_oif = oif;
  3631	
  3632			if (!fibmatch)
  3633				dst = ip6_route_output(net, NULL, &fl6);
  3634		}
  3635	
  3636		if (fibmatch)
  3637			dst = ip6_route_lookup(net, &fl6, 0);
  3638	
  3639		rt = container_of(dst, struct rt6_info, dst);
> 3640		if (rt->dst.error && rt != net->ipv6.ip6_prohibit_entry &&
> 3641		    rt != net->ipv6.ip6_blk_hole_entry) {
  3642			err = rt->dst.error;
  3643			ip6_rt_put(rt);
  3644			goto errout;
  3645		}
  3646	
  3647		skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
  3648		if (!skb) {
  3649			ip6_rt_put(rt);
  3650			err = -ENOBUFS;
  3651			goto errout;
  3652		}
  3653	
  3654		skb_dst_set(skb, &rt->dst);
  3655		if (fibmatch)
  3656			err = rt6_fill_node(net, skb, rt, NULL, NULL, iif,
  3657					    RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
  3658					    nlh->nlmsg_seq, 0);
  3659		else
  3660			err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif,
  3661					    RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
  3662					    nlh->nlmsg_seq, 0);
  3663		if (err < 0) {
  3664			kfree_skb(skb);
  3665			goto errout;
  3666		}
  3667	
  3668		err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
  3669	errout:
  3670		return err;
  3671	}
  3672	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
kernel test robot July 21, 2017, 4:34 p.m. UTC | #2
Hi Hangbin,

[auto build test WARNING on net/master]

url:    https://github.com/0day-ci/linux/commits/Hangbin-Liu/ipv6-should-not-return-rt-dst-error-if-it-is-prohibit-or-blk-hole-entry/20170721-204554
config: x86_64-randconfig-x003-07211556 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

   In file included from include/uapi/linux/stddef.h:1:0,
                    from include/linux/stddef.h:4,
                    from include/uapi/linux/posix_types.h:4,
                    from include/uapi/linux/types.h:13,
                    from include/linux/types.h:5,
                    from include/uapi/linux/capability.h:16,
                    from include/linux/capability.h:15,
                    from net/ipv6/route.c:29:
   net/ipv6/route.c: In function 'inet6_rtm_getroute':
   net/ipv6/route.c:3640:38: error: 'struct netns_ipv6' has no member named 'ip6_prohibit_entry'; did you mean 'ip6_null_entry'?
     if (rt->dst.error && rt != net->ipv6.ip6_prohibit_entry &&
                                         ^
   include/linux/compiler.h:156:30: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                 ^~~~
>> net/ipv6/route.c:3640:2: note: in expansion of macro 'if'
     if (rt->dst.error && rt != net->ipv6.ip6_prohibit_entry &&
     ^~
   net/ipv6/route.c:3641:21: error: 'struct netns_ipv6' has no member named 'ip6_blk_hole_entry'; did you mean 'ip6_null_entry'?
         rt != net->ipv6.ip6_blk_hole_entry) {
                        ^
   include/linux/compiler.h:156:30: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                 ^~~~
>> net/ipv6/route.c:3640:2: note: in expansion of macro 'if'
     if (rt->dst.error && rt != net->ipv6.ip6_prohibit_entry &&
     ^~
   net/ipv6/route.c:3640:38: error: 'struct netns_ipv6' has no member named 'ip6_prohibit_entry'; did you mean 'ip6_null_entry'?
     if (rt->dst.error && rt != net->ipv6.ip6_prohibit_entry &&
                                         ^
   include/linux/compiler.h:156:42: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                             ^~~~
>> net/ipv6/route.c:3640:2: note: in expansion of macro 'if'
     if (rt->dst.error && rt != net->ipv6.ip6_prohibit_entry &&
     ^~
   net/ipv6/route.c:3641:21: error: 'struct netns_ipv6' has no member named 'ip6_blk_hole_entry'; did you mean 'ip6_null_entry'?
         rt != net->ipv6.ip6_blk_hole_entry) {
                        ^
   include/linux/compiler.h:156:42: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                             ^~~~
>> net/ipv6/route.c:3640:2: note: in expansion of macro 'if'
     if (rt->dst.error && rt != net->ipv6.ip6_prohibit_entry &&
     ^~
   net/ipv6/route.c:3640:38: error: 'struct netns_ipv6' has no member named 'ip6_prohibit_entry'; did you mean 'ip6_null_entry'?
     if (rt->dst.error && rt != net->ipv6.ip6_prohibit_entry &&
                                         ^
   include/linux/compiler.h:167:16: note: in definition of macro '__trace_if'
      ______r = !!(cond);     \
                   ^~~~
>> net/ipv6/route.c:3640:2: note: in expansion of macro 'if'
     if (rt->dst.error && rt != net->ipv6.ip6_prohibit_entry &&
     ^~
   net/ipv6/route.c:3641:21: error: 'struct netns_ipv6' has no member named 'ip6_blk_hole_entry'; did you mean 'ip6_null_entry'?
         rt != net->ipv6.ip6_blk_hole_entry) {
                        ^
   include/linux/compiler.h:167:16: note: in definition of macro '__trace_if'
      ______r = !!(cond);     \
                   ^~~~
>> net/ipv6/route.c:3640:2: note: in expansion of macro 'if'
     if (rt->dst.error && rt != net->ipv6.ip6_prohibit_entry &&
     ^~
   net/ipv6/route.c: At top level:
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'strcpy' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:390:2: note: in expansion of macro 'if'
     if (p_size == (size_t)-1 && q_size == (size_t)-1)
     ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'kmemdup' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:380:2: note: in expansion of macro 'if'
     if (p_size < size)
     ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'kmemdup' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:378:2: note: in expansion of macro 'if'
     if (__builtin_constant_p(size) && p_size < size)
     ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memchr_inv' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:369:2: note: in expansion of macro 'if'
     if (p_size < size)
     ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memchr_inv' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:367:2: note: in expansion of macro 'if'
     if (__builtin_constant_p(size) && p_size < size)
     ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memchr' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:358:2: note: in expansion of macro 'if'
     if (p_size < size)
     ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memchr' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:356:2: note: in expansion of macro 'if'
     if (__builtin_constant_p(size) && p_size < size)
     ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memcmp' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:348:2: note: in expansion of macro 'if'
     if (p_size < size || q_size < size)
     ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memcmp' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:345:3: note: in expansion of macro 'if'
      if (q_size < size)
      ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memcmp' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:343:3: note: in expansion of macro 'if'
      if (p_size < size)
      ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memcmp' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:342:2: note: in expansion of macro 'if'

vim +/if +3640 net/ipv6/route.c

  3558	
  3559	static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
  3560				      struct netlink_ext_ack *extack)
  3561	{
  3562		struct net *net = sock_net(in_skb->sk);
  3563		struct nlattr *tb[RTA_MAX+1];
  3564		int err, iif = 0, oif = 0;
  3565		struct dst_entry *dst;
  3566		struct rt6_info *rt;
  3567		struct sk_buff *skb;
  3568		struct rtmsg *rtm;
  3569		struct flowi6 fl6;
  3570		bool fibmatch;
  3571	
  3572		err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy,
  3573				  extack);
  3574		if (err < 0)
  3575			goto errout;
  3576	
  3577		err = -EINVAL;
  3578		memset(&fl6, 0, sizeof(fl6));
  3579		rtm = nlmsg_data(nlh);
  3580		fl6.flowlabel = ip6_make_flowinfo(rtm->rtm_tos, 0);
  3581		fibmatch = !!(rtm->rtm_flags & RTM_F_FIB_MATCH);
  3582	
  3583		if (tb[RTA_SRC]) {
  3584			if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr))
  3585				goto errout;
  3586	
  3587			fl6.saddr = *(struct in6_addr *)nla_data(tb[RTA_SRC]);
  3588		}
  3589	
  3590		if (tb[RTA_DST]) {
  3591			if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr))
  3592				goto errout;
  3593	
  3594			fl6.daddr = *(struct in6_addr *)nla_data(tb[RTA_DST]);
  3595		}
  3596	
  3597		if (tb[RTA_IIF])
  3598			iif = nla_get_u32(tb[RTA_IIF]);
  3599	
  3600		if (tb[RTA_OIF])
  3601			oif = nla_get_u32(tb[RTA_OIF]);
  3602	
  3603		if (tb[RTA_MARK])
  3604			fl6.flowi6_mark = nla_get_u32(tb[RTA_MARK]);
  3605	
  3606		if (tb[RTA_UID])
  3607			fl6.flowi6_uid = make_kuid(current_user_ns(),
  3608						   nla_get_u32(tb[RTA_UID]));
  3609		else
  3610			fl6.flowi6_uid = iif ? INVALID_UID : current_uid();
  3611	
  3612		if (iif) {
  3613			struct net_device *dev;
  3614			int flags = 0;
  3615	
  3616			dev = __dev_get_by_index(net, iif);
  3617			if (!dev) {
  3618				err = -ENODEV;
  3619				goto errout;
  3620			}
  3621	
  3622			fl6.flowi6_iif = iif;
  3623	
  3624			if (!ipv6_addr_any(&fl6.saddr))
  3625				flags |= RT6_LOOKUP_F_HAS_SADDR;
  3626	
  3627			if (!fibmatch)
  3628				dst = ip6_route_input_lookup(net, dev, &fl6, flags);
  3629		} else {
  3630			fl6.flowi6_oif = oif;
  3631	
  3632			if (!fibmatch)
  3633				dst = ip6_route_output(net, NULL, &fl6);
  3634		}
  3635	
  3636		if (fibmatch)
  3637			dst = ip6_route_lookup(net, &fl6, 0);
  3638	
  3639		rt = container_of(dst, struct rt6_info, dst);
> 3640		if (rt->dst.error && rt != net->ipv6.ip6_prohibit_entry &&
  3641		    rt != net->ipv6.ip6_blk_hole_entry) {
  3642			err = rt->dst.error;
  3643			ip6_rt_put(rt);
  3644			goto errout;
  3645		}
  3646	
  3647		skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
  3648		if (!skb) {
  3649			ip6_rt_put(rt);
  3650			err = -ENOBUFS;
  3651			goto errout;
  3652		}
  3653	
  3654		skb_dst_set(skb, &rt->dst);
  3655		if (fibmatch)
  3656			err = rt6_fill_node(net, skb, rt, NULL, NULL, iif,
  3657					    RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
  3658					    nlh->nlmsg_seq, 0);
  3659		else
  3660			err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif,
  3661					    RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
  3662					    nlh->nlmsg_seq, 0);
  3663		if (err < 0) {
  3664			kfree_skb(skb);
  3665			goto errout;
  3666		}
  3667	
  3668		err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
  3669	errout:
  3670		return err;
  3671	}
  3672	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 4d30c96..c290aa4 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -3637,13 +3637,8 @@  static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 		dst = ip6_route_lookup(net, &fl6, 0);
 
 	rt = container_of(dst, struct rt6_info, dst);
-	if (rt->dst.error) {
-		err = rt->dst.error;
-		ip6_rt_put(rt);
-		goto errout;
-	}
-
-	if (rt == net->ipv6.ip6_null_entry) {
+	if (rt->dst.error && rt != net->ipv6.ip6_prohibit_entry &&
+	    rt != net->ipv6.ip6_blk_hole_entry) {
 		err = rt->dst.error;
 		ip6_rt_put(rt);
 		goto errout;