diff options
author | Johannes Berg <johannes.berg@intel.com> | 2018-09-27 05:28:36 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-10-02 02:05:31 -0400 |
commit | 33188bd6430ef06d206ae4fda2cc92f14f16fd20 (patch) | |
tree | bd3980a02a9896a5a1d60936b451ce40efc44349 | |
parent | 3e48be05f3c7eb6f6126939e9d957903c5cfeee5 (diff) |
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: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/netlink.h | 24 | ||||
-rw-r--r-- | lib/nlattr.c | 7 |
2 files changed, 30 insertions, 1 deletions
diff --git a/include/net/netlink.h b/include/net/netlink.h index d34ceeba82a8..6a106ef5ca56 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h | |||
@@ -193,13 +193,14 @@ enum nla_policy_validation { | |||
193 | NLA_VALIDATE_RANGE, | 193 | NLA_VALIDATE_RANGE, |
194 | NLA_VALIDATE_MIN, | 194 | NLA_VALIDATE_MIN, |
195 | NLA_VALIDATE_MAX, | 195 | NLA_VALIDATE_MAX, |
196 | NLA_VALIDATE_FUNCTION, | ||
196 | }; | 197 | }; |
197 | 198 | ||
198 | /** | 199 | /** |
199 | * struct nla_policy - attribute validation policy | 200 | * struct nla_policy - attribute validation policy |
200 | * @type: Type of attribute or NLA_UNSPEC | 201 | * @type: Type of attribute or NLA_UNSPEC |
201 | * @validation_type: type of attribute validation done in addition to | 202 | * @validation_type: type of attribute validation done in addition to |
202 | * type-specific validation (e.g. range), see | 203 | * type-specific validation (e.g. range, function call), see |
203 | * &enum nla_policy_validation | 204 | * &enum nla_policy_validation |
204 | * @len: Type specific length of payload | 205 | * @len: Type specific length of payload |
205 | * | 206 | * |
@@ -269,6 +270,13 @@ enum nla_policy_validation { | |||
269 | * of s16 - do that as usual in the code instead. | 270 | * of s16 - do that as usual in the code instead. |
270 | * All other Unused - but note that it's a union | 271 | * All other Unused - but note that it's a union |
271 | * | 272 | * |
273 | * Meaning of `validate' field, use via NLA_POLICY_VALIDATE_FN: | ||
274 | * NLA_BINARY Validation function called for the attribute, | ||
275 | * not compatible with use of the validation_data | ||
276 | * as in NLA_BITFIELD32, NLA_REJECT, NLA_NESTED and | ||
277 | * NLA_NESTED_ARRAY. | ||
278 | * All other Unused - but note that it's a union | ||
279 | * | ||
272 | * Example: | 280 | * Example: |
273 | * static const struct nla_policy my_policy[ATTR_MAX+1] = { | 281 | * static const struct nla_policy my_policy[ATTR_MAX+1] = { |
274 | * [ATTR_FOO] = { .type = NLA_U16 }, | 282 | * [ATTR_FOO] = { .type = NLA_U16 }, |
@@ -286,6 +294,8 @@ struct nla_policy { | |||
286 | struct { | 294 | struct { |
287 | s16 min, max; | 295 | s16 min, max; |
288 | }; | 296 | }; |
297 | int (*validate)(const struct nlattr *attr, | ||
298 | struct netlink_ext_ack *extack); | ||
289 | }; | 299 | }; |
290 | }; | 300 | }; |
291 | 301 | ||
@@ -307,6 +317,11 @@ struct nla_policy { | |||
307 | tp == NLA_S16 || tp == NLA_U16 || \ | 317 | tp == NLA_S16 || tp == NLA_U16 || \ |
308 | tp == NLA_S32 || tp == NLA_U32 || \ | 318 | tp == NLA_S32 || tp == NLA_U32 || \ |
309 | tp == NLA_S64 || tp == NLA_U64) + tp) | 319 | tp == NLA_S64 || tp == NLA_U64) + tp) |
320 | #define NLA_ENSURE_NO_VALIDATION_PTR(tp) \ | ||
321 | (__NLA_ENSURE(tp != NLA_BITFIELD32 && \ | ||
322 | tp != NLA_REJECT && \ | ||
323 | tp != NLA_NESTED && \ | ||
324 | tp != NLA_NESTED_ARRAY) + tp) | ||
310 | 325 | ||
311 | #define NLA_POLICY_RANGE(tp, _min, _max) { \ | 326 | #define NLA_POLICY_RANGE(tp, _min, _max) { \ |
312 | .type = NLA_ENSURE_INT_TYPE(tp), \ | 327 | .type = NLA_ENSURE_INT_TYPE(tp), \ |
@@ -327,6 +342,13 @@ struct nla_policy { | |||
327 | .max = _max, \ | 342 | .max = _max, \ |
328 | } | 343 | } |
329 | 344 | ||
345 | #define NLA_POLICY_VALIDATE_FN(tp, fn, ...) { \ | ||
346 | .type = NLA_ENSURE_NO_VALIDATION_PTR(tp), \ | ||
347 | .validation_type = NLA_VALIDATE_FUNCTION, \ | ||
348 | .validate = fn, \ | ||
349 | .len = __VA_ARGS__ + 0, \ | ||
350 | } | ||
351 | |||
330 | /** | 352 | /** |
331 | * struct nl_info - netlink source information | 353 | * struct nl_info - netlink source information |
332 | * @nlh: Netlink message header of original request | 354 | * @nlh: Netlink message header of original request |
diff --git a/lib/nlattr.c b/lib/nlattr.c index 5670e4b7dfef..1e900bb414ef 100644 --- a/lib/nlattr.c +++ b/lib/nlattr.c | |||
@@ -300,6 +300,13 @@ static int validate_nla(const struct nlattr *nla, int maxtype, | |||
300 | if (err) | 300 | if (err) |
301 | return err; | 301 | return err; |
302 | break; | 302 | break; |
303 | case NLA_VALIDATE_FUNCTION: | ||
304 | if (pt->validate) { | ||
305 | err = pt->validate(nla, extack); | ||
306 | if (err) | ||
307 | return err; | ||
308 | } | ||
309 | break; | ||
303 | } | 310 | } |
304 | 311 | ||
305 | return 0; | 312 | return 0; |