ip_valid_fib_dump_req() does two things: performs strict checking on netlink attributes for dump requests, and sets a dump filter if netlink attributes require it.
We might want to just set a filter, without performing strict validation. Rename it to ip_filter_fib_dump_req(), and add a 'strict' boolean argument that must be set if strict validation is requested. This patch doesn't introduce any functional changes. Signed-off-by: Stefano Brivio <sbri...@redhat.com> --- v4: New patch include/net/ip_fib.h | 6 +++--- net/ipv4/fib_frontend.c | 34 ++++++++++++++++++++++------------ net/ipv4/ipmr.c | 4 ++-- net/ipv6/ip6_fib.c | 2 +- net/ipv6/ip6mr.c | 4 ++-- net/mpls/af_mpls.c | 2 +- 6 files changed, 31 insertions(+), 21 deletions(-) diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index bbeff32fb6cb..76094a0b97cf 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -493,9 +493,9 @@ static inline void fib_proc_exit(struct net *net) u32 ip_mtu_from_fib_result(struct fib_result *res, __be32 daddr); -int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, - struct fib_dump_filter *filter, - struct netlink_callback *cb); +int ip_filter_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, + struct fib_dump_filter *filter, + struct netlink_callback *cb, bool strict); int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh, unsigned char *flags, bool skip_oif); diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index e54c2bcbb465..873fc5c4721c 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -859,9 +859,9 @@ static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, return err; } -int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, - struct fib_dump_filter *filter, - struct netlink_callback *cb) +int ip_filter_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, + struct fib_dump_filter *filter, + struct netlink_callback *cb, bool strict) { struct netlink_ext_ack *extack = cb->extack; struct nlattr *tb[RTA_MAX + 1]; @@ -876,12 +876,12 @@ int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, } rtm = nlmsg_data(nlh); - if (rtm->rtm_dst_len || rtm->rtm_src_len || rtm->rtm_tos || - rtm->rtm_scope) { + if (strict && (rtm->rtm_dst_len || rtm->rtm_src_len || rtm->rtm_tos || + rtm->rtm_scope)) { NL_SET_ERR_MSG(extack, "Invalid values in header for FIB dump request"); return -EINVAL; } - if (rtm->rtm_flags & ~(RTM_F_CLONED | RTM_F_PREFIX)) { + if (strict && rtm->rtm_flags & ~(RTM_F_CLONED | RTM_F_PREFIX)) { NL_SET_ERR_MSG(extack, "Invalid flags for FIB dump request"); return -EINVAL; } @@ -892,10 +892,18 @@ int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, filter->rt_type = rtm->rtm_type; filter->table_id = rtm->rtm_table; - err = nlmsg_parse_deprecated_strict(nlh, sizeof(*rtm), tb, RTA_MAX, - rtm_ipv4_policy, extack); - if (err < 0) - return err; + if (strict) { + err = nlmsg_parse_deprecated_strict(nlh, sizeof(*rtm), tb, + RTA_MAX, rtm_ipv4_policy, + extack); + if (err < 0) + return err; + } else { + err = nlmsg_parse_deprecated(nlh, sizeof(*rtm), tb, RTA_MAX, + rtm_ipv4_policy, extack); + if (err < 0) + return err; + } for (i = 0; i <= RTA_MAX; ++i) { int ifindex; @@ -914,6 +922,8 @@ int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, return -ENODEV; break; default: + if (!strict) + break; NL_SET_ERR_MSG(extack, "Unsupported attribute in dump request"); return -EINVAL; } @@ -927,7 +937,7 @@ int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, return 0; } -EXPORT_SYMBOL_GPL(ip_valid_fib_dump_req); +EXPORT_SYMBOL_GPL(ip_filter_fib_dump_req); static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) { @@ -941,7 +951,7 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) int dumped = 0, err; if (cb->strict_check) { - err = ip_valid_fib_dump_req(net, nlh, &filter, cb); + err = ip_filter_fib_dump_req(net, nlh, &filter, cb, true); if (err < 0) return err; } else if (nlmsg_len(nlh) >= sizeof(struct rtmsg)) { diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index c07bc82cbbe9..1e089acc9479 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -2597,8 +2597,8 @@ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) int err; if (cb->strict_check) { - err = ip_valid_fib_dump_req(sock_net(skb->sk), cb->nlh, - &filter, cb); + err = ip_filter_fib_dump_req(sock_net(skb->sk), cb->nlh, + &filter, cb, true); if (err < 0) return err; } diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 9180c8b6f764..b21a9ec02891 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -571,7 +571,7 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) if (cb->strict_check) { int err; - err = ip_valid_fib_dump_req(net, nlh, &arg.filter, cb); + err = ip_filter_fib_dump_req(net, nlh, &arg.filter, cb, true); if (err < 0) return err; } else if (nlmsg_len(nlh) >= sizeof(struct rtmsg)) { diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index e80d36c5073d..4960c3fe8e83 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -2487,8 +2487,8 @@ static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) int err; if (cb->strict_check) { - err = ip_valid_fib_dump_req(sock_net(skb->sk), nlh, - &filter, cb); + err = ip_filter_fib_dump_req(sock_net(skb->sk), nlh, &filter, + cb, true); if (err < 0) return err; } diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c index 198ec4fe4148..f54d2f5834f8 100644 --- a/net/mpls/af_mpls.c +++ b/net/mpls/af_mpls.c @@ -2078,7 +2078,7 @@ static int mpls_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, struct fib_dump_filter *filter, struct netlink_callback *cb) { - return ip_valid_fib_dump_req(net, nlh, filter, cb); + return ip_filter_fib_dump_req(net, nlh, filter, cb, true); } #else static int mpls_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, -- 2.20.1