aboutsummaryrefslogtreecommitdiff
path: root/net/netlink
diff options
context:
space:
mode:
authorThomas Graf2006-08-26 20:11:47 -0700
committerDavid S. Miller2006-09-22 15:18:24 -0700
commita5531a5d852008be40811496029012f4ad3093d1 (patch)
treef59a1b240753ef4f0a672f256fc01d8a965793d1 /net/netlink
parente3b4eadbea77ecb3c3a74d1bc81b392f454c7f2e (diff)
[NETLINK]: Improve string attribute validation
Introduces a new attribute type NLA_NUL_STRING to support NUL terminated strings. Attributes of this kind require to carry a terminating NUL within the maximum specified in the policy. The `old' NLA_STRING which is not required to be NUL terminated is extended to provide means to specify a maximum length of the string. Aims at easing the pain with using nla_strlcpy() on temporary buffers. Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlink')
-rw-r--r--net/netlink/attr.c49
1 files changed, 39 insertions, 10 deletions
diff --git a/net/netlink/attr.c b/net/netlink/attr.c
index 136e529e5780..004139557e09 100644
--- a/net/netlink/attr.c
+++ b/net/netlink/attr.c
@@ -20,7 +20,6 @@ static u16 nla_attr_minlen[NLA_TYPE_MAX+1] __read_mostly = {
[NLA_U16] = sizeof(u16),
[NLA_U32] = sizeof(u32),
[NLA_U64] = sizeof(u64),
- [NLA_STRING] = 1,
[NLA_NESTED] = NLA_HDRLEN,
};
@@ -28,7 +27,7 @@ static int validate_nla(struct nlattr *nla, int maxtype,
struct nla_policy *policy)
{
struct nla_policy *pt;
- int minlen = 0;
+ int minlen = 0, attrlen = nla_len(nla);
if (nla->nla_type <= 0 || nla->nla_type > maxtype)
return 0;
@@ -37,16 +36,46 @@ static int validate_nla(struct nlattr *nla, int maxtype,
BUG_ON(pt->type > NLA_TYPE_MAX);
- if (pt->minlen)
- minlen = pt->minlen;
- else if (pt->type != NLA_UNSPEC)
- minlen = nla_attr_minlen[pt->type];
+ switch (pt->type) {
+ case NLA_FLAG:
+ if (attrlen > 0)
+ return -ERANGE;
+ break;
- if (pt->type == NLA_FLAG && nla_len(nla) > 0)
- return -ERANGE;
+ case NLA_NUL_STRING:
+ if (pt->len)
+ minlen = min_t(int, attrlen, pt->len + 1);
+ else
+ minlen = attrlen;
- if (nla_len(nla) < minlen)
- return -ERANGE;
+ if (!minlen || memchr(nla_data(nla), '\0', minlen) == NULL)
+ return -EINVAL;
+ /* fall through */
+
+ case NLA_STRING:
+ if (attrlen < 1)
+ return -ERANGE;
+
+ if (pt->len) {
+ char *buf = nla_data(nla);
+
+ if (buf[attrlen - 1] == '\0')
+ attrlen--;
+
+ if (attrlen > pt->len)
+ return -ERANGE;
+ }
+ break;
+
+ default:
+ if (pt->len)
+ minlen = pt->len;
+ else if (pt->type != NLA_UNSPEC)
+ minlen = nla_attr_minlen[pt->type];
+
+ if (attrlen < minlen)
+ return -ERANGE;
+ }
return 0;
}