aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink/attr.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/netlink/attr.c')
-rw-r--r--net/netlink/attr.c124
1 files changed, 114 insertions, 10 deletions
diff --git a/net/netlink/attr.c b/net/netlink/attr.c
index dddbd15135a8..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 = {
20 [NLA_U16] = sizeof(u16), 20 [NLA_U16] = sizeof(u16),
21 [NLA_U32] = sizeof(u32), 21 [NLA_U32] = sizeof(u32),
22 [NLA_U64] = sizeof(u64), 22 [NLA_U64] = sizeof(u64),
23 [NLA_STRING] = 1,
24 [NLA_NESTED] = NLA_HDRLEN, 23 [NLA_NESTED] = NLA_HDRLEN,
25}; 24};
26 25
@@ -28,7 +27,7 @@ static int validate_nla(struct nlattr *nla, int maxtype,
28 struct nla_policy *policy) 27 struct nla_policy *policy)
29{ 28{
30 struct nla_policy *pt; 29 struct nla_policy *pt;
31 int minlen = 0; 30 int minlen = 0, attrlen = nla_len(nla);
32 31
33 if (nla->nla_type <= 0 || nla->nla_type > maxtype) 32 if (nla->nla_type <= 0 || nla->nla_type > maxtype)
34 return 0; 33 return 0;
@@ -37,16 +36,46 @@ static int validate_nla(struct nlattr *nla, int maxtype,
37 36
38 BUG_ON(pt->type > NLA_TYPE_MAX); 37 BUG_ON(pt->type > NLA_TYPE_MAX);
39 38
40 if (pt->minlen) 39 switch (pt->type) {
41 minlen = pt->minlen; 40 case NLA_FLAG:
42 else if (pt->type != NLA_UNSPEC) 41 if (attrlen > 0)
43 minlen = nla_attr_minlen[pt->type]; 42 return -ERANGE;
43 break;
44 44
45 if (pt->type == NLA_FLAG && nla_len(nla) > 0) 45 case NLA_NUL_STRING:
46 return -ERANGE; 46 if (pt->len)
47 minlen = min_t(int, attrlen, pt->len + 1);
48 else
49 minlen = attrlen;
47 50
48 if (nla_len(nla) < minlen) 51 if (!minlen || memchr(nla_data(nla), '\0', minlen) == NULL)
49 return -ERANGE; 52 return -EINVAL;
53 /* fall through */
54
55 case NLA_STRING:
56 if (attrlen < 1)
57 return -ERANGE;
58
59 if (pt->len) {
60 char *buf = nla_data(nla);
61
62 if (buf[attrlen - 1] == '\0')
63 attrlen--;
64
65 if (attrlen > pt->len)
66 return -ERANGE;
67 }
68 break;
69
70 default:
71 if (pt->len)
72 minlen = pt->len;
73 else if (pt->type != NLA_UNSPEC)
74 minlen = nla_attr_minlen[pt->type];
75
76 if (attrlen < minlen)
77 return -ERANGE;
78 }
50 79
51 return 0; 80 return 0;
52} 81}
@@ -255,6 +284,26 @@ struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
255} 284}
256 285
257/** 286/**
287 * __nla_reserve_nohdr - reserve room for attribute without header
288 * @skb: socket buffer to reserve room on
289 * @attrlen: length of attribute payload
290 *
291 * Reserves room for attribute payload without a header.
292 *
293 * The caller is responsible to ensure that the skb provides enough
294 * tailroom for the payload.
295 */
296void *__nla_reserve_nohdr(struct sk_buff *skb, int attrlen)
297{
298 void *start;
299
300 start = skb_put(skb, NLA_ALIGN(attrlen));
301 memset(start, 0, NLA_ALIGN(attrlen));
302
303 return start;
304}
305
306/**
258 * nla_reserve - reserve room for attribute on the skb 307 * nla_reserve - reserve room for attribute on the skb
259 * @skb: socket buffer to reserve room on 308 * @skb: socket buffer to reserve room on
260 * @attrtype: attribute type 309 * @attrtype: attribute type
@@ -275,6 +324,24 @@ struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
275} 324}
276 325
277/** 326/**
327 * nla_reserve - reserve room for attribute without header
328 * @skb: socket buffer to reserve room on
329 * @len: length of attribute payload
330 *
331 * Reserves room for attribute payload without a header.
332 *
333 * Returns NULL if the tailroom of the skb is insufficient to store
334 * the attribute payload.
335 */
336void *nla_reserve_nohdr(struct sk_buff *skb, int attrlen)
337{
338 if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
339 return NULL;
340
341 return __nla_reserve_nohdr(skb, attrlen);
342}
343
344/**
278 * __nla_put - Add a netlink attribute to a socket buffer 345 * __nla_put - Add a netlink attribute to a socket buffer
279 * @skb: socket buffer to add attribute to 346 * @skb: socket buffer to add attribute to
280 * @attrtype: attribute type 347 * @attrtype: attribute type
@@ -293,6 +360,22 @@ void __nla_put(struct sk_buff *skb, int attrtype, int attrlen,
293 memcpy(nla_data(nla), data, attrlen); 360 memcpy(nla_data(nla), data, attrlen);
294} 361}
295 362
363/**
364 * __nla_put_nohdr - Add a netlink attribute without header
365 * @skb: socket buffer to add attribute to
366 * @attrlen: length of attribute payload
367 * @data: head of attribute payload
368 *
369 * The caller is responsible to ensure that the skb provides enough
370 * tailroom for the attribute payload.
371 */
372void __nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data)
373{
374 void *start;
375
376 start = __nla_reserve_nohdr(skb, attrlen);
377 memcpy(start, data, attrlen);
378}
296 379
297/** 380/**
298 * nla_put - Add a netlink attribute to a socket buffer 381 * nla_put - Add a netlink attribute to a socket buffer
@@ -313,15 +396,36 @@ int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
313 return 0; 396 return 0;
314} 397}
315 398
399/**
400 * nla_put_nohdr - Add a netlink attribute without header
401 * @skb: socket buffer to add attribute to
402 * @attrlen: length of attribute payload
403 * @data: head of attribute payload
404 *
405 * Returns -1 if the tailroom of the skb is insufficient to store
406 * the attribute payload.
407 */
408int nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data)
409{
410 if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
411 return -1;
412
413 __nla_put_nohdr(skb, attrlen, data);
414 return 0;
415}
316 416
317EXPORT_SYMBOL(nla_validate); 417EXPORT_SYMBOL(nla_validate);
318EXPORT_SYMBOL(nla_parse); 418EXPORT_SYMBOL(nla_parse);
319EXPORT_SYMBOL(nla_find); 419EXPORT_SYMBOL(nla_find);
320EXPORT_SYMBOL(nla_strlcpy); 420EXPORT_SYMBOL(nla_strlcpy);
321EXPORT_SYMBOL(__nla_reserve); 421EXPORT_SYMBOL(__nla_reserve);
422EXPORT_SYMBOL(__nla_reserve_nohdr);
322EXPORT_SYMBOL(nla_reserve); 423EXPORT_SYMBOL(nla_reserve);
424EXPORT_SYMBOL(nla_reserve_nohdr);
323EXPORT_SYMBOL(__nla_put); 425EXPORT_SYMBOL(__nla_put);
426EXPORT_SYMBOL(__nla_put_nohdr);
324EXPORT_SYMBOL(nla_put); 427EXPORT_SYMBOL(nla_put);
428EXPORT_SYMBOL(nla_put_nohdr);
325EXPORT_SYMBOL(nla_memcpy); 429EXPORT_SYMBOL(nla_memcpy);
326EXPORT_SYMBOL(nla_memcmp); 430EXPORT_SYMBOL(nla_memcmp);
327EXPORT_SYMBOL(nla_strcmp); 431EXPORT_SYMBOL(nla_strcmp);