Skip to content

Commit e8ba330

Browse files
dsaherndavem330
authored andcommitted
rtnetlink: Update fib dumps for strict data checking
Add helper to check netlink message for route dumps. If the strict flag is set the dump request is expected to have an rtmsg struct as the header. All elements of the struct are expected to be 0 with the exception of rtm_flags (which is used by both ipv4 and ipv6 dumps) and no attributes can be appended. rtm_flags can only have RTM_F_CLONED and RTM_F_PREFIX set. Update inet_dump_fib, inet6_dump_fib, mpls_dump_routes, ipmr_rtm_dumproute, and ip6mr_rtm_dumproute to call this helper if strict data checking is enabled. Signed-off-by: David Ahern <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 14fc5bb commit e8ba330

File tree

6 files changed

+74
-2
lines changed

6 files changed

+74
-2
lines changed

include/net/ip_fib.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,4 +452,6 @@ static inline void fib_proc_exit(struct net *net)
452452

453453
u32 ip_mtu_from_fib_result(struct fib_result *res, __be32 daddr);
454454

455+
int ip_valid_fib_dump_req(const struct nlmsghdr *nlh,
456+
struct netlink_ext_ack *extack);
455457
#endif /* _NET_FIB_H */

net/ipv4/fib_frontend.c

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -802,17 +802,55 @@ static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh,
802802
return err;
803803
}
804804

805+
int ip_valid_fib_dump_req(const struct nlmsghdr *nlh,
806+
struct netlink_ext_ack *extack)
807+
{
808+
struct rtmsg *rtm;
809+
810+
if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*rtm))) {
811+
NL_SET_ERR_MSG(extack, "Invalid header for FIB dump request");
812+
return -EINVAL;
813+
}
814+
815+
rtm = nlmsg_data(nlh);
816+
if (rtm->rtm_dst_len || rtm->rtm_src_len || rtm->rtm_tos ||
817+
rtm->rtm_table || rtm->rtm_protocol || rtm->rtm_scope ||
818+
rtm->rtm_type) {
819+
NL_SET_ERR_MSG(extack, "Invalid values in header for FIB dump request");
820+
return -EINVAL;
821+
}
822+
if (rtm->rtm_flags & ~(RTM_F_CLONED | RTM_F_PREFIX)) {
823+
NL_SET_ERR_MSG(extack, "Invalid flags for FIB dump request");
824+
return -EINVAL;
825+
}
826+
827+
if (nlmsg_attrlen(nlh, sizeof(*rtm))) {
828+
NL_SET_ERR_MSG(extack, "Invalid data after header in FIB dump request");
829+
return -EINVAL;
830+
}
831+
832+
return 0;
833+
}
834+
EXPORT_SYMBOL_GPL(ip_valid_fib_dump_req);
835+
805836
static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
806837
{
838+
const struct nlmsghdr *nlh = cb->nlh;
807839
struct net *net = sock_net(skb->sk);
808840
unsigned int h, s_h;
809841
unsigned int e = 0, s_e;
810842
struct fib_table *tb;
811843
struct hlist_head *head;
812844
int dumped = 0, err;
813845

814-
if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) &&
815-
((struct rtmsg *) nlmsg_data(cb->nlh))->rtm_flags & RTM_F_CLONED)
846+
if (cb->strict_check) {
847+
err = ip_valid_fib_dump_req(nlh, cb->extack);
848+
if (err < 0)
849+
return err;
850+
}
851+
852+
if (nlmsg_len(nlh) >= sizeof(struct rtmsg) &&
853+
((struct rtmsg *)nlmsg_data(nlh))->rtm_flags & RTM_F_CLONED)
816854
return skb->len;
817855

818856
s_h = cb->args[0];

net/ipv4/ipmr.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2527,6 +2527,13 @@ static int ipmr_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
25272527

25282528
static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
25292529
{
2530+
if (cb->strict_check) {
2531+
int err = ip_valid_fib_dump_req(cb->nlh, cb->extack);
2532+
2533+
if (err < 0)
2534+
return err;
2535+
}
2536+
25302537
return mr_rtm_dumproute(skb, cb, ipmr_mr_table_iter,
25312538
_ipmr_fill_mroute, &mfc_unres_lock);
25322539
}

net/ipv6/ip6_fib.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,7 @@ static int fib6_dump_table(struct fib6_table *table, struct sk_buff *skb,
564564

565565
static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
566566
{
567+
const struct nlmsghdr *nlh = cb->nlh;
567568
struct net *net = sock_net(skb->sk);
568569
unsigned int h, s_h;
569570
unsigned int e = 0, s_e;
@@ -573,6 +574,13 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
573574
struct hlist_head *head;
574575
int res = 0;
575576

577+
if (cb->strict_check) {
578+
int err = ip_valid_fib_dump_req(nlh, cb->extack);
579+
580+
if (err < 0)
581+
return err;
582+
}
583+
576584
s_h = cb->args[0];
577585
s_e = cb->args[1];
578586

net/ipv6/ip6mr.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2457,6 +2457,15 @@ static void mrt6msg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt)
24572457

24582458
static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
24592459
{
2460+
const struct nlmsghdr *nlh = cb->nlh;
2461+
2462+
if (cb->strict_check) {
2463+
int err = ip_valid_fib_dump_req(nlh, cb->extack);
2464+
2465+
if (err < 0)
2466+
return err;
2467+
}
2468+
24602469
return mr_rtm_dumproute(skb, cb, ip6mr_mr_table_iter,
24612470
_ip6mr_fill_mroute, &mfc_unres_lock);
24622471
}

net/mpls/af_mpls.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2017,13 +2017,21 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event,
20172017

20182018
static int mpls_dump_routes(struct sk_buff *skb, struct netlink_callback *cb)
20192019
{
2020+
const struct nlmsghdr *nlh = cb->nlh;
20202021
struct net *net = sock_net(skb->sk);
20212022
struct mpls_route __rcu **platform_label;
20222023
size_t platform_labels;
20232024
unsigned int index;
20242025

20252026
ASSERT_RTNL();
20262027

2028+
if (cb->strict_check) {
2029+
int err = ip_valid_fib_dump_req(nlh, cb->extack);
2030+
2031+
if (err < 0)
2032+
return err;
2033+
}
2034+
20272035
index = cb->args[0];
20282036
if (index < MPLS_LABEL_FIRST_UNRESERVED)
20292037
index = MPLS_LABEL_FIRST_UNRESERVED;

0 commit comments

Comments
 (0)