summaryrefslogtreecommitdiffstats
path: root/lib/nlattr.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2018-09-17 11:57:28 +0200
committerDavid S. Miller <davem@davemloft.net>2018-09-19 04:51:29 +0200
commit568b742a9d9888aca876b6ad9fa45490f18bee0a (patch)
treee8d1bcd4126ebbf1216768d38d74ef332382c75a /lib/nlattr.c
parentMerge branch '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirshe... (diff)
downloadlinux-568b742a9d9888aca876b6ad9fa45490f18bee0a.tar.xz
linux-568b742a9d9888aca876b6ad9fa45490f18bee0a.zip
netlink: add NLA_REJECT policy type
In some situations some netlink attributes may be used for output only (kernel->userspace) or may be reserved for future use. It's then helpful to be able to prevent userspace from using them in messages sent to the kernel, since they'd otherwise be ignored and any future will become impossible if this happens. Add NLA_REJECT to the policy which does nothing but reject (with EINVAL) validation of any messages containing this attribute. Allow for returning a specific extended ACK error message in the validation_data pointer. While at it clear up the documentation a bit - the NLA_BITFIELD32 documentation was added to the list of len field descriptions. Also, use NL_SET_BAD_ATTR() in one place where it's open-coded. The specific case I have in mind now is a shared nested attribute containing request/response data, and it would be pointless and potentially confusing to have userspace include response data in the messages that actually contain a request. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'lib/nlattr.c')
-rw-r--r--lib/nlattr.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/lib/nlattr.c b/lib/nlattr.c
index e335bcafa9e4..36d74b079151 100644
--- a/lib/nlattr.c
+++ b/lib/nlattr.c
@@ -69,7 +69,8 @@ static int validate_nla_bitfield32(const struct nlattr *nla,
}
static int validate_nla(const struct nlattr *nla, int maxtype,
- const struct nla_policy *policy)
+ const struct nla_policy *policy,
+ const char **error_msg)
{
const struct nla_policy *pt;
int minlen = 0, attrlen = nla_len(nla), type = nla_type(nla);
@@ -87,6 +88,11 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
}
switch (pt->type) {
+ case NLA_REJECT:
+ if (pt->validation_data && error_msg)
+ *error_msg = pt->validation_data;
+ return -EINVAL;
+
case NLA_FLAG:
if (attrlen > 0)
return -ERANGE;
@@ -180,11 +186,10 @@ int nla_validate(const struct nlattr *head, int len, int maxtype,
int rem;
nla_for_each_attr(nla, head, len, rem) {
- int err = validate_nla(nla, maxtype, policy);
+ int err = validate_nla(nla, maxtype, policy, NULL);
if (err < 0) {
- if (extack)
- extack->bad_attr = nla;
+ NL_SET_BAD_ATTR(extack, nla);
return err;
}
}
@@ -250,11 +255,15 @@ int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
u16 type = nla_type(nla);
if (type > 0 && type <= maxtype) {
+ static const char _msg[] = "Attribute failed policy validation";
+ const char *msg = _msg;
+
if (policy) {
- err = validate_nla(nla, maxtype, policy);
+ err = validate_nla(nla, maxtype, policy, &msg);
if (err < 0) {
- NL_SET_ERR_MSG_ATTR(extack, nla,
- "Attribute failed policy validation");
+ NL_SET_BAD_ATTR(extack, nla);
+ if (extack)
+ extack->_msg = msg;
goto errout;
}
}