summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2014-03-20 18:18:42 (GMT)
committerThomas Haller <thaller@redhat.com>2014-03-21 11:27:18 (GMT)
commitdfd0a80ec845a800504fecb936c2b33d6918fc9c (patch)
tree23ce1f2f87ae3c3d1f4ac7cbc93a92b475903065
parentc0a5b393086e052d45f0f43ae1ec3b65b6de0d97 (diff)
downloadlibnl-dfd0a80ec845a800504fecb936c2b33d6918fc9c.zip
libnl-dfd0a80ec845a800504fecb936c2b33d6918fc9c.tar.gz
libnl-dfd0a80ec845a800504fecb936c2b33d6918fc9c.tar.bz2
route: don't enforce minlen in inet6_parse_protinfo() (IFLA_PROTINFO) and inet_parse_af() (IFLA_AF_SPEC)
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>
-rw-r--r--lib/route/link/inet.c4
-rw-r--r--lib/route/link/inet6.c18
2 files changed, 16 insertions, 6 deletions
diff --git a/lib/route/link/inet.c b/lib/route/link/inet.c
index e2c867d..eb2e8ae 100644
--- a/lib/route/link/inet.c
+++ b/lib/route/link/inet.c
@@ -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));
diff --git a/lib/route/link/inet6.c b/lib/route/link/inet6.c
index 4c627bd..f171fed 100644
--- a/lib/route/link/inet6.c
+++ b/lib/route/link/inet6.c
@@ -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);