|
@@ -802,8 +802,40 @@ errout:
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+int ip_valid_fib_dump_req(const struct nlmsghdr *nlh,
|
|
|
|
+ struct netlink_ext_ack *extack)
|
|
|
|
+{
|
|
|
|
+ struct rtmsg *rtm;
|
|
|
|
+
|
|
|
|
+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*rtm))) {
|
|
|
|
+ NL_SET_ERR_MSG(extack, "Invalid header for FIB dump request");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rtm = nlmsg_data(nlh);
|
|
|
|
+ if (rtm->rtm_dst_len || rtm->rtm_src_len || rtm->rtm_tos ||
|
|
|
|
+ rtm->rtm_table || rtm->rtm_protocol || rtm->rtm_scope ||
|
|
|
|
+ rtm->rtm_type) {
|
|
|
|
+ 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)) {
|
|
|
|
+ NL_SET_ERR_MSG(extack, "Invalid flags for FIB dump request");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (nlmsg_attrlen(nlh, sizeof(*rtm))) {
|
|
|
|
+ NL_SET_ERR_MSG(extack, "Invalid data after header in FIB dump request");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL_GPL(ip_valid_fib_dump_req);
|
|
|
|
+
|
|
static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
|
|
static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
|
|
{
|
|
{
|
|
|
|
+ const struct nlmsghdr *nlh = cb->nlh;
|
|
struct net *net = sock_net(skb->sk);
|
|
struct net *net = sock_net(skb->sk);
|
|
unsigned int h, s_h;
|
|
unsigned int h, s_h;
|
|
unsigned int e = 0, s_e;
|
|
unsigned int e = 0, s_e;
|
|
@@ -811,8 +843,14 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
|
|
struct hlist_head *head;
|
|
struct hlist_head *head;
|
|
int dumped = 0, err;
|
|
int dumped = 0, err;
|
|
|
|
|
|
- if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) &&
|
|
|
|
- ((struct rtmsg *) nlmsg_data(cb->nlh))->rtm_flags & RTM_F_CLONED)
|
|
|
|
|
|
+ if (cb->strict_check) {
|
|
|
|
+ err = ip_valid_fib_dump_req(nlh, cb->extack);
|
|
|
|
+ if (err < 0)
|
|
|
|
+ return err;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (nlmsg_len(nlh) >= sizeof(struct rtmsg) &&
|
|
|
|
+ ((struct rtmsg *)nlmsg_data(nlh))->rtm_flags & RTM_F_CLONED)
|
|
return skb->len;
|
|
return skb->len;
|
|
|
|
|
|
s_h = cb->args[0];
|
|
s_h = cb->args[0];
|