]> git.ipfire.org Git - thirdparty/libnl.git/commitdiff
route: don't enforce minlen in inet6_parse_protinfo() (IFLA_PROTINFO) and inet_parse_...
authorThomas Haller <thaller@redhat.com>
Thu, 20 Mar 2014 18:18:42 +0000 (19:18 +0100)
committerThomas Haller <thaller@redhat.com>
Fri, 21 Mar 2014 11:27:18 +0000 (12:27 +0100)
Older kernel version might have fewer values defined, so they would send
netlink messages that got rejected. Only check that at least one value
got sent.

This is especially grave as libnl uses an internal copy of the
kernel header files. Thus not only it is bound to the installed kernel
headers but to the libnl internal header copies that might easily be out
of sync with the kernel.

This affects IFLA_PROTINFO, inet6_parse_protinfo():
  - tb[IFLA_INET6_CONF], expecting DEVCONF_MAX
  - tb[IFLA_INET6_STATS], expecting __IPSTATS_MIB_MAX
  - tb[IFLA_INET6_ICMP6STATS], expecting __ICMP6_MIB_MAX
and IFLA_AF_SPEC, inet_parse_af():
  - tb[IFLA_INET_CONF], expecting IPV4_DEVCONF_MAX

https://bugzilla.redhat.com/show_bug.cgi?id=1062533

Acked-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Thomas Haller <thaller@redhat.com>
lib/route/link/inet.c
lib/route/link/inet6.c

index e2c867d11f2e47988515eb3233a60c17cd9db2fd..eb2e8aef7801306f43954c217b5fd26a254515f1 100644 (file)
@@ -92,7 +92,7 @@ static void inet_free(struct rtnl_link *link, void *data)
 }
 
 static struct nla_policy inet_policy[IFLA_INET6_MAX+1] = {
-       [IFLA_INET_CONF]        = { .minlen = IPV4_DEVCONF_MAX * 4 },
+       [IFLA_INET_CONF]        = { .minlen = 4 },
 };
 
 static int inet_parse_af(struct rtnl_link *link, struct nlattr *attr, void *data)
@@ -104,6 +104,8 @@ static int inet_parse_af(struct rtnl_link *link, struct nlattr *attr, void *data
        err = nla_parse_nested(tb, IFLA_INET_MAX, attr, inet_policy);
        if (err < 0)
                return err;
+       if (tb[IFLA_INET_CONF] && nla_len(tb[IFLA_INET_CONF]) % 4)
+               return -EINVAL;
 
        if (tb[IFLA_INET_CONF])
                nla_memcpy(&id->i_conf, tb[IFLA_INET_CONF], sizeof(id->i_conf));
index 4c627bd8b1ae3983ff9285a6e29b371f3ed983db..f171fedff0c2a28a73a35efe0cd9b2ecd8edc1d0 100644 (file)
@@ -45,9 +45,9 @@ static void inet6_free(struct rtnl_link *link, void *data)
 static struct nla_policy inet6_policy[IFLA_INET6_MAX+1] = {
        [IFLA_INET6_FLAGS]      = { .type = NLA_U32 },
        [IFLA_INET6_CACHEINFO]  = { .minlen = sizeof(struct ifla_cacheinfo) },
-       [IFLA_INET6_CONF]       = { .minlen = DEVCONF_MAX * 4 },
-       [IFLA_INET6_STATS]      = { .minlen = __IPSTATS_MIB_MAX * 8 },
-       [IFLA_INET6_ICMP6STATS] = { .minlen = __ICMP6_MIB_MAX * 8 },
+       [IFLA_INET6_CONF]       = { .minlen = 4 },
+       [IFLA_INET6_STATS]      = { .minlen = 8 },
+       [IFLA_INET6_ICMP6STATS] = { .minlen = 8 },
 };
 
 static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
@@ -60,6 +60,12 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
        err = nla_parse_nested(tb, IFLA_INET6_MAX, attr, inet6_policy);
        if (err < 0)
                return err;
+       if (tb[IFLA_INET6_CONF] && nla_len(tb[IFLA_INET6_CONF]) % 4)
+               return -EINVAL;
+       if (tb[IFLA_INET6_STATS] && nla_len(tb[IFLA_INET6_STATS]) % 8)
+               return -EINVAL;
+       if (tb[IFLA_INET6_ICMP6STATS] && nla_len(tb[IFLA_INET6_ICMP6STATS]) % 8)
+               return -EINVAL;
 
        if (tb[IFLA_INET6_FLAGS])
                i6->i6_flags = nla_get_u32(tb[IFLA_INET6_FLAGS]);
@@ -80,8 +86,9 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
                unsigned char *cnt = nla_data(tb[IFLA_INET6_STATS]);
                uint64_t stat;
                int i;
+               int len = min_t(int, __IPSTATS_MIB_MAX, nla_len(tb[IFLA_INET6_STATS]) / 8);
 
-               for (i = 1; i < __IPSTATS_MIB_MAX; i++) {
+               for (i = 1; i < len; i++) {
                        memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat));
                        rtnl_link_set_stat(link, RTNL_LINK_IP6_INPKTS + i - 1,
                                           stat);
@@ -92,8 +99,9 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
                unsigned char *cnt = nla_data(tb[IFLA_INET6_ICMP6STATS]);
                uint64_t stat;
                int i;
+               int len = min_t(int, __ICMP6_MIB_MAX, nla_len(tb[IFLA_INET6_ICMP6STATS]) / 8);
 
-               for (i = 1; i < __ICMP6_MIB_MAX; i++) {
+               for (i = 1; i < len; i++) {
                        memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat));
                        rtnl_link_set_stat(link, RTNL_LINK_ICMP6_INMSGS + i - 1,
                                           stat);