Commit a5531a5d authored by Thomas Graf's avatar Thomas Graf Committed by David S. Miller

[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: default avatarThomas Graf <tgraf@suug.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e3b4eadb
...@@ -167,6 +167,7 @@ enum { ...@@ -167,6 +167,7 @@ enum {
NLA_FLAG, NLA_FLAG,
NLA_MSECS, NLA_MSECS,
NLA_NESTED, NLA_NESTED,
NLA_NUL_STRING,
__NLA_TYPE_MAX, __NLA_TYPE_MAX,
}; };
...@@ -175,21 +176,27 @@ enum { ...@@ -175,21 +176,27 @@ enum {
/** /**
* struct nla_policy - attribute validation policy * struct nla_policy - attribute validation policy
* @type: Type of attribute or NLA_UNSPEC * @type: Type of attribute or NLA_UNSPEC
* @minlen: Minimal length of payload required to be available * @len: Type specific length of payload
* *
* Policies are defined as arrays of this struct, the array must be * Policies are defined as arrays of this struct, the array must be
* accessible by attribute type up to the highest identifier to be expected. * accessible by attribute type up to the highest identifier to be expected.
* *
* Meaning of `len' field:
* NLA_STRING Maximum length of string
* NLA_NUL_STRING Maximum length of string (excluding NUL)
* NLA_FLAG Unused
* All other Exact length of attribute payload
*
* Example: * Example:
* static struct nla_policy my_policy[ATTR_MAX+1] __read_mostly = { * static struct nla_policy my_policy[ATTR_MAX+1] __read_mostly = {
* [ATTR_FOO] = { .type = NLA_U16 }, * [ATTR_FOO] = { .type = NLA_U16 },
* [ATTR_BAR] = { .type = NLA_STRING }, * [ATTR_BAR] = { .type = NLA_STRING, len = BARSIZ },
* [ATTR_BAZ] = { .minlen = sizeof(struct mystruct) }, * [ATTR_BAZ] = { .len = sizeof(struct mystruct) },
* }; * };
*/ */
struct nla_policy { struct nla_policy {
u16 type; u16 type;
u16 minlen; u16 len;
}; };
/** /**
......
...@@ -20,7 +20,6 @@ static u16 nla_attr_minlen[NLA_TYPE_MAX+1] __read_mostly = { ...@@ -20,7 +20,6 @@ static u16 nla_attr_minlen[NLA_TYPE_MAX+1] __read_mostly = {
[NLA_U16] = sizeof(u16), [NLA_U16] = sizeof(u16),
[NLA_U32] = sizeof(u32), [NLA_U32] = sizeof(u32),
[NLA_U64] = sizeof(u64), [NLA_U64] = sizeof(u64),
[NLA_STRING] = 1,
[NLA_NESTED] = NLA_HDRLEN, [NLA_NESTED] = NLA_HDRLEN,
}; };
...@@ -28,7 +27,7 @@ static int validate_nla(struct nlattr *nla, int maxtype, ...@@ -28,7 +27,7 @@ static int validate_nla(struct nlattr *nla, int maxtype,
struct nla_policy *policy) struct nla_policy *policy)
{ {
struct nla_policy *pt; struct nla_policy *pt;
int minlen = 0; int minlen = 0, attrlen = nla_len(nla);
if (nla->nla_type <= 0 || nla->nla_type > maxtype) if (nla->nla_type <= 0 || nla->nla_type > maxtype)
return 0; return 0;
...@@ -37,16 +36,46 @@ static int validate_nla(struct nlattr *nla, int maxtype, ...@@ -37,16 +36,46 @@ static int validate_nla(struct nlattr *nla, int maxtype,
BUG_ON(pt->type > NLA_TYPE_MAX); BUG_ON(pt->type > NLA_TYPE_MAX);
if (pt->minlen) switch (pt->type) {
minlen = pt->minlen; case NLA_FLAG:
else if (pt->type != NLA_UNSPEC) if (attrlen > 0)
minlen = nla_attr_minlen[pt->type]; return -ERANGE;
break;
case NLA_NUL_STRING:
if (pt->len)
minlen = min_t(int, attrlen, pt->len + 1);
else
minlen = attrlen;
if (!minlen || memchr(nla_data(nla), '\0', minlen) == NULL)
return -EINVAL;
/* fall through */
case NLA_STRING:
if (attrlen < 1)
return -ERANGE;
if (pt->type == NLA_FLAG && nla_len(nla) > 0) if (pt->len) {
char *buf = nla_data(nla);
if (buf[attrlen - 1] == '\0')
attrlen--;
if (attrlen > pt->len)
return -ERANGE; return -ERANGE;
}
break;
if (nla_len(nla) < minlen) 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 -ERANGE;
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment