Commit 33188bd6 authored by Johannes Berg's avatar Johannes Berg Committed by David S. Miller

netlink: add validation function to policy

Add the ability to have an arbitrary validation function attached
to a netlink policy that doesn't already use the validation_data
pointer in another way.

This can be useful to validate for example the content of a binary
attribute, like in nl80211 the "(information) elements", which must
be valid streams of "u8 type, u8 length, u8 value[length]".
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3e48be05
...@@ -193,13 +193,14 @@ enum nla_policy_validation { ...@@ -193,13 +193,14 @@ enum nla_policy_validation {
NLA_VALIDATE_RANGE, NLA_VALIDATE_RANGE,
NLA_VALIDATE_MIN, NLA_VALIDATE_MIN,
NLA_VALIDATE_MAX, NLA_VALIDATE_MAX,
NLA_VALIDATE_FUNCTION,
}; };
/** /**
* 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
* @validation_type: type of attribute validation done in addition to * @validation_type: type of attribute validation done in addition to
* type-specific validation (e.g. range), see * type-specific validation (e.g. range, function call), see
* &enum nla_policy_validation * &enum nla_policy_validation
* @len: Type specific length of payload * @len: Type specific length of payload
* *
...@@ -269,6 +270,13 @@ enum nla_policy_validation { ...@@ -269,6 +270,13 @@ enum nla_policy_validation {
* of s16 - do that as usual in the code instead. * of s16 - do that as usual in the code instead.
* All other Unused - but note that it's a union * All other Unused - but note that it's a union
* *
* Meaning of `validate' field, use via NLA_POLICY_VALIDATE_FN:
* NLA_BINARY Validation function called for the attribute,
* not compatible with use of the validation_data
* as in NLA_BITFIELD32, NLA_REJECT, NLA_NESTED and
* NLA_NESTED_ARRAY.
* All other Unused - but note that it's a union
*
* Example: * Example:
* static const struct nla_policy my_policy[ATTR_MAX+1] = { * static const struct nla_policy my_policy[ATTR_MAX+1] = {
* [ATTR_FOO] = { .type = NLA_U16 }, * [ATTR_FOO] = { .type = NLA_U16 },
...@@ -286,6 +294,8 @@ struct nla_policy { ...@@ -286,6 +294,8 @@ struct nla_policy {
struct { struct {
s16 min, max; s16 min, max;
}; };
int (*validate)(const struct nlattr *attr,
struct netlink_ext_ack *extack);
}; };
}; };
...@@ -307,6 +317,11 @@ struct nla_policy { ...@@ -307,6 +317,11 @@ struct nla_policy {
tp == NLA_S16 || tp == NLA_U16 || \ tp == NLA_S16 || tp == NLA_U16 || \
tp == NLA_S32 || tp == NLA_U32 || \ tp == NLA_S32 || tp == NLA_U32 || \
tp == NLA_S64 || tp == NLA_U64) + tp) tp == NLA_S64 || tp == NLA_U64) + tp)
#define NLA_ENSURE_NO_VALIDATION_PTR(tp) \
(__NLA_ENSURE(tp != NLA_BITFIELD32 && \
tp != NLA_REJECT && \
tp != NLA_NESTED && \
tp != NLA_NESTED_ARRAY) + tp)
#define NLA_POLICY_RANGE(tp, _min, _max) { \ #define NLA_POLICY_RANGE(tp, _min, _max) { \
.type = NLA_ENSURE_INT_TYPE(tp), \ .type = NLA_ENSURE_INT_TYPE(tp), \
...@@ -327,6 +342,13 @@ struct nla_policy { ...@@ -327,6 +342,13 @@ struct nla_policy {
.max = _max, \ .max = _max, \
} }
#define NLA_POLICY_VALIDATE_FN(tp, fn, ...) { \
.type = NLA_ENSURE_NO_VALIDATION_PTR(tp), \
.validation_type = NLA_VALIDATE_FUNCTION, \
.validate = fn, \
.len = __VA_ARGS__ + 0, \
}
/** /**
* struct nl_info - netlink source information * struct nl_info - netlink source information
* @nlh: Netlink message header of original request * @nlh: Netlink message header of original request
......
...@@ -300,6 +300,13 @@ static int validate_nla(const struct nlattr *nla, int maxtype, ...@@ -300,6 +300,13 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
if (err) if (err)
return err; return err;
break; break;
case NLA_VALIDATE_FUNCTION:
if (pt->validate) {
err = pt->validate(nla, extack);
if (err)
return err;
}
break;
} }
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