summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Ahern <dsahern@gmail.com>2017-11-08 06:59:40 +0100
committerDavid S. Miller <davem@davemloft.net>2017-11-11 07:14:38 +0100
commit28033ae4e0f59782b3f3357d9c28852a7e84a894 (patch)
tree28b50e6aced09e14ff02b907745ec511d2ee8790
parentnet: ipv6: sysctl to specify IPv6 ND traffic class (diff)
downloadlinux-28033ae4e0f59782b3f3357d9c28852a7e84a894.tar.xz
linux-28033ae4e0f59782b3f3357d9c28852a7e84a894.zip
net: netlink: Update attr validation to require exact length for some types
Attributes using NLA_U* and NLA_S* (where * is 8, 16,32 and 64) are expected to be an exact length. Split these data types from nla_attr_minlen into nla_attr_len and update validate_nla to require the attribute to have exact length for them. Signed-off-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--lib/nlattr.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/lib/nlattr.c b/lib/nlattr.c
index 3d8295c85505..8bf78b4b78f0 100644
--- a/lib/nlattr.c
+++ b/lib/nlattr.c
@@ -15,19 +15,23 @@
#include <linux/types.h>
#include <net/netlink.h>
-static const u8 nla_attr_minlen[NLA_TYPE_MAX+1] = {
+/* for these data types attribute length must be exactly given size */
+static const u8 nla_attr_len[NLA_TYPE_MAX+1] = {
[NLA_U8] = sizeof(u8),
[NLA_U16] = sizeof(u16),
[NLA_U32] = sizeof(u32),
[NLA_U64] = sizeof(u64),
- [NLA_MSECS] = sizeof(u64),
- [NLA_NESTED] = NLA_HDRLEN,
[NLA_S8] = sizeof(s8),
[NLA_S16] = sizeof(s16),
[NLA_S32] = sizeof(s32),
[NLA_S64] = sizeof(s64),
};
+static const u8 nla_attr_minlen[NLA_TYPE_MAX+1] = {
+ [NLA_MSECS] = sizeof(u64),
+ [NLA_NESTED] = NLA_HDRLEN,
+};
+
static int validate_nla_bitfield32(const struct nlattr *nla,
u32 *valid_flags_allowed)
{
@@ -65,6 +69,13 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
BUG_ON(pt->type > NLA_TYPE_MAX);
+ /* for data types NLA_U* and NLA_S* require exact length */
+ if (nla_attr_len[pt->type]) {
+ if (attrlen != nla_attr_len[pt->type])
+ return -ERANGE;
+ return 0;
+ }
+
switch (pt->type) {
case NLA_FLAG:
if (attrlen > 0)
@@ -191,6 +202,8 @@ nla_policy_len(const struct nla_policy *p, int n)
for (i = 0; i < n; i++, p++) {
if (p->len)
len += nla_total_size(p->len);
+ else if (nla_attr_len[p->type])
+ len += nla_total_size(nla_attr_len[p->type]);
else if (nla_attr_minlen[p->type])
len += nla_total_size(nla_attr_minlen[p->type]);
}