Blame view

lib/nlattr.c 26.7 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
2
3
4
5
6
7
  /*
   * NETLINK      Netlink attributes
   *
   * 		Authors:	Thomas Graf <tgraf@suug.ch>
   * 				Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
   */
8bc3bcc93   Paul Gortmaker   lib: reduce the u...
8
  #include <linux/export.h>
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
9
10
11
  #include <linux/kernel.h>
  #include <linux/errno.h>
  #include <linux/jiffies.h>
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
12
13
14
15
  #include <linux/skbuff.h>
  #include <linux/string.h>
  #include <linux/types.h>
  #include <net/netlink.h>
6e237d099   David Ahern   netlink: Relax at...
16
17
18
19
20
  /* For these data types, attribute length should be exactly the given
   * size. However, to maintain compatibility with broken commands, if the
   * attribute length does not match the expected size a warning is emitted
   * to the user that the command is sending invalid data and needs to be fixed.
   */
28033ae4e   David Ahern   net: netlink: Upd...
21
  static const u8 nla_attr_len[NLA_TYPE_MAX+1] = {
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
22
23
24
25
  	[NLA_U8]	= sizeof(u8),
  	[NLA_U16]	= sizeof(u16),
  	[NLA_U32]	= sizeof(u32),
  	[NLA_U64]	= sizeof(u64),
9eca2eb99   Julian Anastasov   netlink: add minl...
26
27
28
29
  	[NLA_S8]	= sizeof(s8),
  	[NLA_S16]	= sizeof(s16),
  	[NLA_S32]	= sizeof(s32),
  	[NLA_S64]	= sizeof(s64),
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
30
  };
28033ae4e   David Ahern   net: netlink: Upd...
31
  static const u8 nla_attr_minlen[NLA_TYPE_MAX+1] = {
6e237d099   David Ahern   netlink: Relax at...
32
33
34
35
  	[NLA_U8]	= sizeof(u8),
  	[NLA_U16]	= sizeof(u16),
  	[NLA_U32]	= sizeof(u32),
  	[NLA_U64]	= sizeof(u64),
28033ae4e   David Ahern   net: netlink: Upd...
36
37
  	[NLA_MSECS]	= sizeof(u64),
  	[NLA_NESTED]	= NLA_HDRLEN,
6e237d099   David Ahern   netlink: Relax at...
38
39
40
41
  	[NLA_S8]	= sizeof(s8),
  	[NLA_S16]	= sizeof(s16),
  	[NLA_S32]	= sizeof(s32),
  	[NLA_S64]	= sizeof(s64),
28033ae4e   David Ahern   net: netlink: Upd...
42
  };
7690aa1cd   Johannes Berg   netlink: limit re...
43
44
45
46
47
48
49
50
51
52
53
54
55
  /*
   * Nested policies might refer back to the original
   * policy in some cases, and userspace could try to
   * abuse that and recurse by nesting in the right
   * ways. Limit recursion to avoid this problem.
   */
  #define MAX_POLICY_RECURSION_DEPTH	10
  
  static int __nla_validate_parse(const struct nlattr *head, int len, int maxtype,
  				const struct nla_policy *policy,
  				unsigned int validate,
  				struct netlink_ext_ack *extack,
  				struct nlattr **tb, unsigned int depth);
64c83d837   Jamal Hadi Salim   net netlink: Add ...
56
  static int validate_nla_bitfield32(const struct nlattr *nla,
47a1494b8   Johannes Berg   netlink: remove t...
57
  				   const u32 valid_flags_mask)
64c83d837   Jamal Hadi Salim   net netlink: Add ...
58
59
  {
  	const struct nla_bitfield32 *bf = nla_data(nla);
64c83d837   Jamal Hadi Salim   net netlink: Add ...
60

48fde90a7   Johannes Berg   netlink: make val...
61
  	if (!valid_flags_mask)
64c83d837   Jamal Hadi Salim   net netlink: Add ...
62
63
64
  		return -EINVAL;
  
  	/*disallow invalid bit selector */
47a1494b8   Johannes Berg   netlink: remove t...
65
  	if (bf->selector & ~valid_flags_mask)
64c83d837   Jamal Hadi Salim   net netlink: Add ...
66
67
68
  		return -EINVAL;
  
  	/*disallow invalid bit values */
47a1494b8   Johannes Berg   netlink: remove t...
69
  	if (bf->value & ~valid_flags_mask)
64c83d837   Jamal Hadi Salim   net netlink: Add ...
70
71
72
73
74
75
76
77
  		return -EINVAL;
  
  	/*disallow valid bit values that are not selected*/
  	if (bf->value & ~bf->selector)
  		return -EINVAL;
  
  	return 0;
  }
1501d1359   Johannes Berg   netlink: add nest...
78
79
  static int nla_validate_array(const struct nlattr *head, int len, int maxtype,
  			      const struct nla_policy *policy,
8cb081746   Johannes Berg   netlink: make val...
80
  			      struct netlink_ext_ack *extack,
7690aa1cd   Johannes Berg   netlink: limit re...
81
  			      unsigned int validate, unsigned int depth)
1501d1359   Johannes Berg   netlink: add nest...
82
83
84
85
86
87
88
89
90
91
92
  {
  	const struct nlattr *entry;
  	int rem;
  
  	nla_for_each_attr(entry, head, len, rem) {
  		int ret;
  
  		if (nla_len(entry) == 0)
  			continue;
  
  		if (nla_len(entry) < NLA_HDRLEN) {
44f3625bc   Johannes Berg   netlink: export p...
93
94
  			NL_SET_ERR_MSG_ATTR_POL(extack, entry, policy,
  						"Array element too short");
1501d1359   Johannes Berg   netlink: add nest...
95
96
  			return -ERANGE;
  		}
7690aa1cd   Johannes Berg   netlink: limit re...
97
98
99
  		ret = __nla_validate_parse(nla_data(entry), nla_len(entry),
  					   maxtype, policy, validate, extack,
  					   NULL, depth + 1);
1501d1359   Johannes Berg   netlink: add nest...
100
101
102
103
104
105
  		if (ret < 0)
  			return ret;
  	}
  
  	return 0;
  }
2c28ae48f   Johannes Berg   netlink: factor o...
106
107
  void nla_get_range_unsigned(const struct nla_policy *pt,
  			    struct netlink_range_validation *range)
3e48be05f   Johannes Berg   netlink: add attr...
108
  {
d06a09b94   Johannes Berg   netlink: extend p...
109
110
  	WARN_ON_ONCE(pt->validation_type != NLA_VALIDATE_RANGE_PTR &&
  		     (pt->min < 0 || pt->max < 0));
2c28ae48f   Johannes Berg   netlink: factor o...
111
112
113
114
115
116
117
  	range->min = 0;
  
  	switch (pt->type) {
  	case NLA_U8:
  		range->max = U8_MAX;
  		break;
  	case NLA_U16:
8aa26c575   Johannes Berg   netlink: make NLA...
118
  	case NLA_BINARY:
2c28ae48f   Johannes Berg   netlink: factor o...
119
120
121
122
123
124
125
126
127
128
129
130
131
  		range->max = U16_MAX;
  		break;
  	case NLA_U32:
  		range->max = U32_MAX;
  		break;
  	case NLA_U64:
  	case NLA_MSECS:
  		range->max = U64_MAX;
  		break;
  	default:
  		WARN_ON_ONCE(1);
  		return;
  	}
d06a09b94   Johannes Berg   netlink: extend p...
132
133
  	switch (pt->validation_type) {
  	case NLA_VALIDATE_RANGE:
8aa26c575   Johannes Berg   netlink: make NLA...
134
  	case NLA_VALIDATE_RANGE_WARN_TOO_LONG:
d06a09b94   Johannes Berg   netlink: extend p...
135
136
137
138
  		range->min = pt->min;
  		range->max = pt->max;
  		break;
  	case NLA_VALIDATE_RANGE_PTR:
2c28ae48f   Johannes Berg   netlink: factor o...
139
  		*range = *pt->range;
d06a09b94   Johannes Berg   netlink: extend p...
140
141
142
143
144
145
146
  		break;
  	case NLA_VALIDATE_MIN:
  		range->min = pt->min;
  		break;
  	case NLA_VALIDATE_MAX:
  		range->max = pt->max;
  		break;
2c28ae48f   Johannes Berg   netlink: factor o...
147
148
  	default:
  		break;
d06a09b94   Johannes Berg   netlink: extend p...
149
  	}
2c28ae48f   Johannes Berg   netlink: factor o...
150
  }
8aa26c575   Johannes Berg   netlink: make NLA...
151
152
153
154
  static int nla_validate_range_unsigned(const struct nla_policy *pt,
  				       const struct nlattr *nla,
  				       struct netlink_ext_ack *extack,
  				       unsigned int validate)
2c28ae48f   Johannes Berg   netlink: factor o...
155
156
157
  {
  	struct netlink_range_validation range;
  	u64 value;
3e48be05f   Johannes Berg   netlink: add attr...
158
159
160
161
162
163
164
165
166
167
168
  
  	switch (pt->type) {
  	case NLA_U8:
  		value = nla_get_u8(nla);
  		break;
  	case NLA_U16:
  		value = nla_get_u16(nla);
  		break;
  	case NLA_U32:
  		value = nla_get_u32(nla);
  		break;
d06a09b94   Johannes Berg   netlink: extend p...
169
  	case NLA_U64:
da4063bdf   Johannes Berg   netlink: allow NL...
170
  	case NLA_MSECS:
d06a09b94   Johannes Berg   netlink: extend p...
171
172
  		value = nla_get_u64(nla);
  		break;
8aa26c575   Johannes Berg   netlink: make NLA...
173
174
175
  	case NLA_BINARY:
  		value = nla_len(nla);
  		break;
d06a09b94   Johannes Berg   netlink: extend p...
176
177
178
  	default:
  		return -EINVAL;
  	}
2c28ae48f   Johannes Berg   netlink: factor o...
179
  	nla_get_range_unsigned(pt, &range);
8aa26c575   Johannes Berg   netlink: make NLA...
180
181
182
183
184
185
  	if (pt->validation_type == NLA_VALIDATE_RANGE_WARN_TOO_LONG &&
  	    pt->type == NLA_BINARY && value > range.max) {
  		pr_warn_ratelimited("netlink: '%s': attribute type %d has an invalid length.
  ",
  				    current->comm, pt->type);
  		if (validate & NL_VALIDATE_STRICT_ATTRS) {
44f3625bc   Johannes Berg   netlink: export p...
186
187
  			NL_SET_ERR_MSG_ATTR_POL(extack, nla, pt,
  						"invalid attribute length");
8aa26c575   Johannes Berg   netlink: make NLA...
188
189
190
191
192
193
  			return -EINVAL;
  		}
  
  		/* this assumes min <= max (don't validate against min) */
  		return 0;
  	}
2c28ae48f   Johannes Berg   netlink: factor o...
194
  	if (value < range.min || value > range.max) {
8aa26c575   Johannes Berg   netlink: make NLA...
195
196
197
  		bool binary = pt->type == NLA_BINARY;
  
  		if (binary)
44f3625bc   Johannes Berg   netlink: export p...
198
199
  			NL_SET_ERR_MSG_ATTR_POL(extack, nla, pt,
  						"binary attribute size out of range");
8aa26c575   Johannes Berg   netlink: make NLA...
200
  		else
44f3625bc   Johannes Berg   netlink: export p...
201
202
  			NL_SET_ERR_MSG_ATTR_POL(extack, nla, pt,
  						"integer out of range");
8aa26c575   Johannes Berg   netlink: make NLA...
203

d06a09b94   Johannes Berg   netlink: extend p...
204
205
206
207
208
  		return -ERANGE;
  	}
  
  	return 0;
  }
2c28ae48f   Johannes Berg   netlink: factor o...
209
210
  void nla_get_range_signed(const struct nla_policy *pt,
  			  struct netlink_range_validation_signed *range)
d06a09b94   Johannes Berg   netlink: extend p...
211
  {
2c28ae48f   Johannes Berg   netlink: factor o...
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  	switch (pt->type) {
  	case NLA_S8:
  		range->min = S8_MIN;
  		range->max = S8_MAX;
  		break;
  	case NLA_S16:
  		range->min = S16_MIN;
  		range->max = S16_MAX;
  		break;
  	case NLA_S32:
  		range->min = S32_MIN;
  		range->max = S32_MAX;
  		break;
  	case NLA_S64:
  		range->min = S64_MIN;
  		range->max = S64_MAX;
  		break;
  	default:
  		WARN_ON_ONCE(1);
  		return;
  	}
d06a09b94   Johannes Berg   netlink: extend p...
233
234
235
236
237
238
239
  
  	switch (pt->validation_type) {
  	case NLA_VALIDATE_RANGE:
  		range->min = pt->min;
  		range->max = pt->max;
  		break;
  	case NLA_VALIDATE_RANGE_PTR:
2c28ae48f   Johannes Berg   netlink: factor o...
240
  		*range = *pt->range_signed;
d06a09b94   Johannes Berg   netlink: extend p...
241
242
243
244
245
246
247
  		break;
  	case NLA_VALIDATE_MIN:
  		range->min = pt->min;
  		break;
  	case NLA_VALIDATE_MAX:
  		range->max = pt->max;
  		break;
2c28ae48f   Johannes Berg   netlink: factor o...
248
249
  	default:
  		break;
d06a09b94   Johannes Berg   netlink: extend p...
250
  	}
2c28ae48f   Johannes Berg   netlink: factor o...
251
252
253
254
255
256
257
258
  }
  
  static int nla_validate_int_range_signed(const struct nla_policy *pt,
  					 const struct nlattr *nla,
  					 struct netlink_ext_ack *extack)
  {
  	struct netlink_range_validation_signed range;
  	s64 value;
d06a09b94   Johannes Berg   netlink: extend p...
259
260
  
  	switch (pt->type) {
3e48be05f   Johannes Berg   netlink: add attr...
261
262
263
264
265
266
267
268
269
270
271
272
  	case NLA_S8:
  		value = nla_get_s8(nla);
  		break;
  	case NLA_S16:
  		value = nla_get_s16(nla);
  		break;
  	case NLA_S32:
  		value = nla_get_s32(nla);
  		break;
  	case NLA_S64:
  		value = nla_get_s64(nla);
  		break;
3e48be05f   Johannes Berg   netlink: add attr...
273
  	default:
3e48be05f   Johannes Berg   netlink: add attr...
274
275
  		return -EINVAL;
  	}
2c28ae48f   Johannes Berg   netlink: factor o...
276
277
278
  	nla_get_range_signed(pt, &range);
  
  	if (value < range.min || value > range.max) {
44f3625bc   Johannes Berg   netlink: export p...
279
280
  		NL_SET_ERR_MSG_ATTR_POL(extack, nla, pt,
  					"integer out of range");
3e48be05f   Johannes Berg   netlink: add attr...
281
282
283
284
285
  		return -ERANGE;
  	}
  
  	return 0;
  }
d06a09b94   Johannes Berg   netlink: extend p...
286
287
  static int nla_validate_int_range(const struct nla_policy *pt,
  				  const struct nlattr *nla,
8aa26c575   Johannes Berg   netlink: make NLA...
288
289
  				  struct netlink_ext_ack *extack,
  				  unsigned int validate)
d06a09b94   Johannes Berg   netlink: extend p...
290
291
292
293
294
295
  {
  	switch (pt->type) {
  	case NLA_U8:
  	case NLA_U16:
  	case NLA_U32:
  	case NLA_U64:
da4063bdf   Johannes Berg   netlink: allow NL...
296
  	case NLA_MSECS:
8aa26c575   Johannes Berg   netlink: make NLA...
297
298
  	case NLA_BINARY:
  		return nla_validate_range_unsigned(pt, nla, extack, validate);
d06a09b94   Johannes Berg   netlink: extend p...
299
300
301
302
303
304
305
306
307
308
  	case NLA_S8:
  	case NLA_S16:
  	case NLA_S32:
  	case NLA_S64:
  		return nla_validate_int_range_signed(pt, nla, extack);
  	default:
  		WARN_ON(1);
  		return -EINVAL;
  	}
  }
bdbb4e29d   Jakub Kicinski   netlink: add mask...
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
  static int nla_validate_mask(const struct nla_policy *pt,
  			     const struct nlattr *nla,
  			     struct netlink_ext_ack *extack)
  {
  	u64 value;
  
  	switch (pt->type) {
  	case NLA_U8:
  		value = nla_get_u8(nla);
  		break;
  	case NLA_U16:
  		value = nla_get_u16(nla);
  		break;
  	case NLA_U32:
  		value = nla_get_u32(nla);
  		break;
  	case NLA_U64:
  		value = nla_get_u64(nla);
  		break;
  	default:
  		return -EINVAL;
  	}
  
  	if (value & ~(u64)pt->mask) {
  		NL_SET_ERR_MSG_ATTR(extack, nla, "reserved bit set");
  		return -EINVAL;
  	}
  
  	return 0;
  }
3654654f7   Jan Engelhardt   netlink: let nlms...
339
  static int validate_nla(const struct nlattr *nla, int maxtype,
8cb081746   Johannes Berg   netlink: make val...
340
  			const struct nla_policy *policy, unsigned int validate,
7690aa1cd   Johannes Berg   netlink: limit re...
341
  			struct netlink_ext_ack *extack, unsigned int depth)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
342
  {
56738f460   Johannes Berg   netlink: add stri...
343
  	u16 strict_start_type = policy[0].strict_start_type;
ef7c79ed6   Patrick McHardy   [NETLINK]: Mark n...
344
  	const struct nla_policy *pt;
8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
345
  	int minlen = 0, attrlen = nla_len(nla), type = nla_type(nla);
c29f1845b   Johannes Berg   netlink: move ext...
346
  	int err = -ERANGE;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
347

56738f460   Johannes Berg   netlink: add stri...
348
349
  	if (strict_start_type && type >= strict_start_type)
  		validate |= NL_VALIDATE_STRICT;
8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
350
  	if (type <= 0 || type > maxtype)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
351
  		return 0;
8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
352
  	pt = &policy[type];
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
353
354
  
  	BUG_ON(pt->type > NLA_TYPE_MAX);
8aa26c575   Johannes Berg   netlink: make NLA...
355
  	if (nla_attr_len[pt->type] && attrlen != nla_attr_len[pt->type]) {
6e237d099   David Ahern   netlink: Relax at...
356
357
358
  		pr_warn_ratelimited("netlink: '%s': attribute type %d has an invalid length.
  ",
  				    current->comm, type);
8cb081746   Johannes Berg   netlink: make val...
359
  		if (validate & NL_VALIDATE_STRICT_ATTRS) {
44f3625bc   Johannes Berg   netlink: export p...
360
361
  			NL_SET_ERR_MSG_ATTR_POL(extack, nla, pt,
  						"invalid attribute length");
8cb081746   Johannes Berg   netlink: make val...
362
363
  			return -EINVAL;
  		}
28033ae4e   David Ahern   net: netlink: Upd...
364
  	}
b424e432e   Michal Kubecek   netlink: add vali...
365
366
367
  	if (validate & NL_VALIDATE_NESTED) {
  		if ((pt->type == NLA_NESTED || pt->type == NLA_NESTED_ARRAY) &&
  		    !(nla->nla_type & NLA_F_NESTED)) {
44f3625bc   Johannes Berg   netlink: export p...
368
369
  			NL_SET_ERR_MSG_ATTR_POL(extack, nla, pt,
  						"NLA_F_NESTED is missing");
b424e432e   Michal Kubecek   netlink: add vali...
370
371
372
373
  			return -EINVAL;
  		}
  		if (pt->type != NLA_NESTED && pt->type != NLA_NESTED_ARRAY &&
  		    pt->type != NLA_UNSPEC && (nla->nla_type & NLA_F_NESTED)) {
44f3625bc   Johannes Berg   netlink: export p...
374
375
  			NL_SET_ERR_MSG_ATTR_POL(extack, nla, pt,
  						"NLA_F_NESTED not expected");
b424e432e   Michal Kubecek   netlink: add vali...
376
377
378
  			return -EINVAL;
  		}
  	}
a5531a5d8   Thomas Graf   [NETLINK]: Improv...
379
  	switch (pt->type) {
568b742a9   Johannes Berg   netlink: add NLA_...
380
  	case NLA_REJECT:
47a1494b8   Johannes Berg   netlink: remove t...
381
  		if (extack && pt->reject_message) {
c29f1845b   Johannes Berg   netlink: move ext...
382
  			NL_SET_BAD_ATTR(extack, nla);
47a1494b8   Johannes Berg   netlink: remove t...
383
  			extack->_msg = pt->reject_message;
c29f1845b   Johannes Berg   netlink: move ext...
384
385
386
387
  			return -EINVAL;
  		}
  		err = -EINVAL;
  		goto out_err;
568b742a9   Johannes Berg   netlink: add NLA_...
388

a5531a5d8   Thomas Graf   [NETLINK]: Improv...
389
390
  	case NLA_FLAG:
  		if (attrlen > 0)
c29f1845b   Johannes Berg   netlink: move ext...
391
  			goto out_err;
a5531a5d8   Thomas Graf   [NETLINK]: Improv...
392
  		break;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
393

64c83d837   Jamal Hadi Salim   net netlink: Add ...
394
395
  	case NLA_BITFIELD32:
  		if (attrlen != sizeof(struct nla_bitfield32))
c29f1845b   Johannes Berg   netlink: move ext...
396
  			goto out_err;
64c83d837   Jamal Hadi Salim   net netlink: Add ...
397

47a1494b8   Johannes Berg   netlink: remove t...
398
  		err = validate_nla_bitfield32(nla, pt->bitfield32_valid);
c29f1845b   Johannes Berg   netlink: move ext...
399
400
401
  		if (err)
  			goto out_err;
  		break;
64c83d837   Jamal Hadi Salim   net netlink: Add ...
402

a5531a5d8   Thomas Graf   [NETLINK]: Improv...
403
404
405
406
407
  	case NLA_NUL_STRING:
  		if (pt->len)
  			minlen = min_t(int, attrlen, pt->len + 1);
  		else
  			minlen = attrlen;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
408

c29f1845b   Johannes Berg   netlink: move ext...
409
410
411
412
  		if (!minlen || memchr(nla_data(nla), '\0', minlen) == NULL) {
  			err = -EINVAL;
  			goto out_err;
  		}
a5531a5d8   Thomas Graf   [NETLINK]: Improv...
413
414
415
416
  		/* fall through */
  
  	case NLA_STRING:
  		if (attrlen < 1)
c29f1845b   Johannes Berg   netlink: move ext...
417
  			goto out_err;
a5531a5d8   Thomas Graf   [NETLINK]: Improv...
418
419
420
421
422
423
424
425
  
  		if (pt->len) {
  			char *buf = nla_data(nla);
  
  			if (buf[attrlen - 1] == '\0')
  				attrlen--;
  
  			if (attrlen > pt->len)
c29f1845b   Johannes Berg   netlink: move ext...
426
  				goto out_err;
a5531a5d8   Thomas Graf   [NETLINK]: Improv...
427
428
  		}
  		break;
d30045a0b   Johannes Berg   [NETLINK]: introd...
429
430
  	case NLA_BINARY:
  		if (pt->len && attrlen > pt->len)
c29f1845b   Johannes Berg   netlink: move ext...
431
  			goto out_err;
d30045a0b   Johannes Berg   [NETLINK]: introd...
432
  		break;
ea5693ccc   Patrick McHardy   netlink: allow em...
433
434
435
436
437
438
  	case NLA_NESTED:
  		/* a nested attributes is allowed to be empty; if its not,
  		 * it must have a size of at least NLA_HDRLEN.
  		 */
  		if (attrlen == 0)
  			break;
9a659a35b   Johannes Berg   netlink: allow NL...
439
440
  		if (attrlen < NLA_HDRLEN)
  			goto out_err;
47a1494b8   Johannes Berg   netlink: remove t...
441
  		if (pt->nested_policy) {
7690aa1cd   Johannes Berg   netlink: limit re...
442
443
444
445
  			err = __nla_validate_parse(nla_data(nla), nla_len(nla),
  						   pt->len, pt->nested_policy,
  						   validate, extack, NULL,
  						   depth + 1);
9a659a35b   Johannes Berg   netlink: allow NL...
446
447
448
449
450
451
452
453
454
  			if (err < 0) {
  				/*
  				 * return directly to preserve the inner
  				 * error message/attribute pointer
  				 */
  				return err;
  			}
  		}
  		break;
1501d1359   Johannes Berg   netlink: add nest...
455
456
457
458
459
460
461
462
  	case NLA_NESTED_ARRAY:
  		/* a nested array attribute is allowed to be empty; if its not,
  		 * it must have a size of at least NLA_HDRLEN.
  		 */
  		if (attrlen == 0)
  			break;
  		if (attrlen < NLA_HDRLEN)
  			goto out_err;
47a1494b8   Johannes Berg   netlink: remove t...
463
  		if (pt->nested_policy) {
1501d1359   Johannes Berg   netlink: add nest...
464
465
466
  			int err;
  
  			err = nla_validate_array(nla_data(nla), nla_len(nla),
47a1494b8   Johannes Berg   netlink: remove t...
467
  						 pt->len, pt->nested_policy,
7690aa1cd   Johannes Berg   netlink: limit re...
468
  						 extack, validate, depth);
1501d1359   Johannes Berg   netlink: add nest...
469
470
471
472
473
474
475
476
477
  			if (err < 0) {
  				/*
  				 * return directly to preserve the inner
  				 * error message/attribute pointer
  				 */
  				return err;
  			}
  		}
  		break;
6f455f5f4   Johannes Berg   netlink: add NLA_...
478
479
  
  	case NLA_UNSPEC:
8cb081746   Johannes Berg   netlink: make val...
480
481
482
483
484
  		if (validate & NL_VALIDATE_UNSPEC) {
  			NL_SET_ERR_MSG_ATTR(extack, nla,
  					    "Unsupported attribute");
  			return -EINVAL;
  		}
6f455f5f4   Johannes Berg   netlink: add NLA_...
485
486
487
  		if (attrlen < pt->len)
  			goto out_err;
  		break;
a5531a5d8   Thomas Graf   [NETLINK]: Improv...
488
489
490
  	default:
  		if (pt->len)
  			minlen = pt->len;
6f455f5f4   Johannes Berg   netlink: add NLA_...
491
  		else
a5531a5d8   Thomas Graf   [NETLINK]: Improv...
492
493
494
  			minlen = nla_attr_minlen[pt->type];
  
  		if (attrlen < minlen)
c29f1845b   Johannes Berg   netlink: move ext...
495
  			goto out_err;
a5531a5d8   Thomas Graf   [NETLINK]: Improv...
496
  	}
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
497

3e48be05f   Johannes Berg   netlink: add attr...
498
499
500
501
502
  	/* further validation */
  	switch (pt->validation_type) {
  	case NLA_VALIDATE_NONE:
  		/* nothing to do */
  		break;
d06a09b94   Johannes Berg   netlink: extend p...
503
  	case NLA_VALIDATE_RANGE_PTR:
3e48be05f   Johannes Berg   netlink: add attr...
504
  	case NLA_VALIDATE_RANGE:
8aa26c575   Johannes Berg   netlink: make NLA...
505
  	case NLA_VALIDATE_RANGE_WARN_TOO_LONG:
3e48be05f   Johannes Berg   netlink: add attr...
506
507
  	case NLA_VALIDATE_MIN:
  	case NLA_VALIDATE_MAX:
8aa26c575   Johannes Berg   netlink: make NLA...
508
  		err = nla_validate_int_range(pt, nla, extack, validate);
3e48be05f   Johannes Berg   netlink: add attr...
509
510
511
  		if (err)
  			return err;
  		break;
bdbb4e29d   Jakub Kicinski   netlink: add mask...
512
513
514
515
516
  	case NLA_VALIDATE_MASK:
  		err = nla_validate_mask(pt, nla, extack);
  		if (err)
  			return err;
  		break;
33188bd64   Johannes Berg   netlink: add vali...
517
518
519
520
521
522
523
  	case NLA_VALIDATE_FUNCTION:
  		if (pt->validate) {
  			err = pt->validate(nla, extack);
  			if (err)
  				return err;
  		}
  		break;
3e48be05f   Johannes Berg   netlink: add attr...
524
  	}
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
525
  	return 0;
c29f1845b   Johannes Berg   netlink: move ext...
526
  out_err:
44f3625bc   Johannes Berg   netlink: export p...
527
528
  	NL_SET_ERR_MSG_ATTR_POL(extack, nla, pt,
  				"Attribute failed policy validation");
c29f1845b   Johannes Berg   netlink: move ext...
529
  	return err;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
530
  }
8cb081746   Johannes Berg   netlink: make val...
531
532
533
534
  static int __nla_validate_parse(const struct nlattr *head, int len, int maxtype,
  				const struct nla_policy *policy,
  				unsigned int validate,
  				struct netlink_ext_ack *extack,
7690aa1cd   Johannes Berg   netlink: limit re...
535
  				struct nlattr **tb, unsigned int depth)
8cb081746   Johannes Berg   netlink: make val...
536
537
538
  {
  	const struct nlattr *nla;
  	int rem;
7690aa1cd   Johannes Berg   netlink: limit re...
539
540
541
542
543
  	if (depth >= MAX_POLICY_RECURSION_DEPTH) {
  		NL_SET_ERR_MSG(extack,
  			       "allowed policy recursion depth exceeded");
  		return -EINVAL;
  	}
8cb081746   Johannes Berg   netlink: make val...
544
545
546
547
548
549
550
551
  	if (tb)
  		memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
  
  	nla_for_each_attr(nla, head, len, rem) {
  		u16 type = nla_type(nla);
  
  		if (type == 0 || type > maxtype) {
  			if (validate & NL_VALIDATE_MAXTYPE) {
d54a16b20   Michal Kubecek   netlink: set bad ...
552
553
  				NL_SET_ERR_MSG_ATTR(extack, nla,
  						    "Unknown attribute type");
8cb081746   Johannes Berg   netlink: make val...
554
555
556
557
558
559
  				return -EINVAL;
  			}
  			continue;
  		}
  		if (policy) {
  			int err = validate_nla(nla, maxtype, policy,
7690aa1cd   Johannes Berg   netlink: limit re...
560
  					       validate, extack, depth);
8cb081746   Johannes Berg   netlink: make val...
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
  
  			if (err < 0)
  				return err;
  		}
  
  		if (tb)
  			tb[type] = (struct nlattr *)nla;
  	}
  
  	if (unlikely(rem > 0)) {
  		pr_warn_ratelimited("netlink: %d bytes leftover after parsing attributes in process `%s'.
  ",
  				    rem, current->comm);
  		NL_SET_ERR_MSG(extack, "bytes leftover after parsing attributes");
  		if (validate & NL_VALIDATE_TRAILING)
  			return -EINVAL;
  	}
  
  	return 0;
  }
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
581
  /**
8cb081746   Johannes Berg   netlink: make val...
582
   * __nla_validate - Validate a stream of attributes
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
583
584
585
586
   * @head: head of attribute stream
   * @len: length of attribute stream
   * @maxtype: maximum attribute type to be expected
   * @policy: validation policy
8cb081746   Johannes Berg   netlink: make val...
587
   * @validate: validation strictness
fceb6435e   Johannes Berg   netlink: pass ext...
588
   * @extack: extended ACK report struct
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
589
590
   *
   * Validates all attributes in the specified attribute stream against the
8cb081746   Johannes Berg   netlink: make val...
591
592
593
   * specified policy. Validation depends on the validate flags passed, see
   * &enum netlink_validation for more details on that.
   * See documenation of struct nla_policy for more details.
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
594
595
596
   *
   * Returns 0 on success or a negative error code.
   */
8cb081746   Johannes Berg   netlink: make val...
597
598
599
  int __nla_validate(const struct nlattr *head, int len, int maxtype,
  		   const struct nla_policy *policy, unsigned int validate,
  		   struct netlink_ext_ack *extack)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
600
  {
8cb081746   Johannes Berg   netlink: make val...
601
  	return __nla_validate_parse(head, len, maxtype, policy, validate,
7690aa1cd   Johannes Berg   netlink: limit re...
602
  				    extack, NULL, 0);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
603
  }
8cb081746   Johannes Berg   netlink: make val...
604
  EXPORT_SYMBOL(__nla_validate);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
605
606
  
  /**
e487eb99c   Holger Eitzenberger   netlink: add nla_...
607
608
609
610
611
612
613
614
615
616
617
618
619
620
   * nla_policy_len - Determin the max. length of a policy
   * @policy: policy to use
   * @n: number of policies
   *
   * Determines the max. length of the policy.  It is currently used
   * to allocated Netlink buffers roughly the size of the actual
   * message.
   *
   * Returns 0 on success or a negative error code.
   */
  int
  nla_policy_len(const struct nla_policy *p, int n)
  {
  	int i, len = 0;
e3fa3aff0   Lars Ellenberg   net: fix nla_poli...
621
  	for (i = 0; i < n; i++, p++) {
e487eb99c   Holger Eitzenberger   netlink: add nla_...
622
623
  		if (p->len)
  			len += nla_total_size(p->len);
28033ae4e   David Ahern   net: netlink: Upd...
624
625
  		else if (nla_attr_len[p->type])
  			len += nla_total_size(nla_attr_len[p->type]);
e487eb99c   Holger Eitzenberger   netlink: add nla_...
626
627
628
629
630
631
  		else if (nla_attr_minlen[p->type])
  			len += nla_total_size(nla_attr_minlen[p->type]);
  	}
  
  	return len;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
632
  EXPORT_SYMBOL(nla_policy_len);
e487eb99c   Holger Eitzenberger   netlink: add nla_...
633
634
  
  /**
8cb081746   Johannes Berg   netlink: make val...
635
   * __nla_parse - Parse a stream of attributes into a tb buffer
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
636
637
638
639
   * @tb: destination array with maxtype+1 elements
   * @maxtype: maximum attribute type to be expected
   * @head: head of attribute stream
   * @len: length of attribute stream
10b595aff   Julius Volz   netlink: Fix some...
640
   * @policy: validation policy
8cb081746   Johannes Berg   netlink: make val...
641
642
   * @validate: validation strictness
   * @extack: extended ACK pointer
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
643
644
   *
   * Parses a stream of attributes and stores a pointer to each attribute in
8cb081746   Johannes Berg   netlink: make val...
645
646
   * the tb array accessible via the attribute type.
   * Validation is controlled by the @validate parameter.
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
647
648
649
   *
   * Returns 0 on success or a negative error code.
   */
8cb081746   Johannes Berg   netlink: make val...
650
651
652
653
  int __nla_parse(struct nlattr **tb, int maxtype,
  		const struct nlattr *head, int len,
  		const struct nla_policy *policy, unsigned int validate,
  		struct netlink_ext_ack *extack)
a5f6cba29   David Ahern   netlink: Add stri...
654
  {
8cb081746   Johannes Berg   netlink: make val...
655
  	return __nla_validate_parse(head, len, maxtype, policy, validate,
7690aa1cd   Johannes Berg   netlink: limit re...
656
  				    extack, tb, 0);
a5f6cba29   David Ahern   netlink: Add stri...
657
  }
8cb081746   Johannes Berg   netlink: make val...
658
  EXPORT_SYMBOL(__nla_parse);
a5f6cba29   David Ahern   netlink: Add stri...
659

bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
660
661
662
663
664
665
666
667
  /**
   * nla_find - Find a specific attribute in a stream of attributes
   * @head: head of attribute stream
   * @len: length of attribute stream
   * @attrtype: type of attribute to look for
   *
   * Returns the first attribute in the stream matching the specified type.
   */
3654654f7   Jan Engelhardt   netlink: let nlms...
668
  struct nlattr *nla_find(const struct nlattr *head, int len, int attrtype)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
669
  {
3654654f7   Jan Engelhardt   netlink: let nlms...
670
  	const struct nlattr *nla;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
671
672
673
  	int rem;
  
  	nla_for_each_attr(nla, head, len, rem)
8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
674
  		if (nla_type(nla) == attrtype)
3654654f7   Jan Engelhardt   netlink: let nlms...
675
  			return (struct nlattr *)nla;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
676
677
678
  
  	return NULL;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
679
  EXPORT_SYMBOL(nla_find);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
680
681
682
683
  
  /**
   * nla_strlcpy - Copy string attribute payload into a sized buffer
   * @dst: where to copy the string to
10b595aff   Julius Volz   netlink: Fix some...
684
   * @nla: attribute to copy the string from
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
   * @dstsize: size of destination buffer
   *
   * Copies at most dstsize - 1 bytes into the destination buffer.
   * The result is always a valid NUL-terminated string. Unlike
   * strlcpy the destination buffer is always padded out.
   *
   * Returns the length of the source buffer.
   */
  size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
  {
  	size_t srclen = nla_len(nla);
  	char *src = nla_data(nla);
  
  	if (srclen > 0 && src[srclen - 1] == '\0')
  		srclen--;
  
  	if (dstsize > 0) {
  		size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
  
  		memset(dst, 0, dstsize);
  		memcpy(dst, src, len);
  	}
  
  	return srclen;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
710
  EXPORT_SYMBOL(nla_strlcpy);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
711
712
  
  /**
2cf0c8b3e   Phil Sutter   netlink: Introduc...
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
   * nla_strdup - Copy string attribute payload into a newly allocated buffer
   * @nla: attribute to copy the string from
   * @flags: the type of memory to allocate (see kmalloc).
   *
   * Returns a pointer to the allocated buffer or NULL on error.
   */
  char *nla_strdup(const struct nlattr *nla, gfp_t flags)
  {
  	size_t srclen = nla_len(nla);
  	char *src = nla_data(nla), *dst;
  
  	if (srclen > 0 && src[srclen - 1] == '\0')
  		srclen--;
  
  	dst = kmalloc(srclen + 1, flags);
  	if (dst != NULL) {
  		memcpy(dst, src, srclen);
  		dst[srclen] = '\0';
  	}
  	return dst;
  }
  EXPORT_SYMBOL(nla_strdup);
  
  /**
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
737
738
739
740
741
742
743
744
745
746
   * nla_memcpy - Copy a netlink attribute into another memory area
   * @dest: where to copy to memcpy
   * @src: netlink attribute to copy from
   * @count: size of the destination area
   *
   * Note: The number of bytes copied is limited by the length of
   *       attribute's payload. memcpy
   *
   * Returns the number of bytes copied.
   */
b057efd4d   Patrick McHardy   netlink: constify...
747
  int nla_memcpy(void *dest, const struct nlattr *src, int count)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
748
749
750
751
  {
  	int minlen = min_t(int, count, nla_len(src));
  
  	memcpy(dest, nla_data(src), minlen);
5899f0478   Jiri Benc   netlink: pad nla_...
752
753
  	if (count > minlen)
  		memset(dest + minlen, 0, count - minlen);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
754
755
756
  
  	return minlen;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
757
  EXPORT_SYMBOL(nla_memcpy);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
  
  /**
   * nla_memcmp - Compare an attribute with sized memory area
   * @nla: netlink attribute
   * @data: memory area
   * @size: size of memory area
   */
  int nla_memcmp(const struct nlattr *nla, const void *data,
  			     size_t size)
  {
  	int d = nla_len(nla) - size;
  
  	if (d == 0)
  		d = memcmp(nla_data(nla), data, size);
  
  	return d;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
775
  EXPORT_SYMBOL(nla_memcmp);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
776
777
778
779
780
781
782
783
  
  /**
   * nla_strcmp - Compare a string attribute against a string
   * @nla: netlink string attribute
   * @str: another string
   */
  int nla_strcmp(const struct nlattr *nla, const char *str)
  {
8b7b93243   Pablo Neira   netlink: don't co...
784
785
786
787
  	int len = strlen(str);
  	char *buf = nla_data(nla);
  	int attrlen = nla_len(nla);
  	int d;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
788

8b7b93243   Pablo Neira   netlink: don't co...
789
790
791
792
  	if (attrlen > 0 && buf[attrlen - 1] == '\0')
  		attrlen--;
  
  	d = attrlen - len;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
793
794
795
796
797
  	if (d == 0)
  		d = memcmp(nla_data(nla), str, len);
  
  	return d;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
798
  EXPORT_SYMBOL(nla_strcmp);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
799

908002161   Herbert Xu   nlattr: Fix build...
800
  #ifdef CONFIG_NET
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
  /**
   * __nla_reserve - reserve room for attribute on the skb
   * @skb: socket buffer to reserve room on
   * @attrtype: attribute type
   * @attrlen: length of attribute payload
   *
   * Adds a netlink attribute header to a socket buffer and reserves
   * room for the payload but does not copy it.
   *
   * The caller is responsible to ensure that the skb provides enough
   * tailroom for the attribute header and payload.
   */
  struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
  {
  	struct nlattr *nla;
4df864c1d   Johannes Berg   networking: make ...
816
  	nla = skb_put(skb, nla_total_size(attrlen));
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
817
818
819
820
821
822
823
  	nla->nla_type = attrtype;
  	nla->nla_len = nla_attr_size(attrlen);
  
  	memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen));
  
  	return nla;
  }
908002161   Herbert Xu   nlattr: Fix build...
824
  EXPORT_SYMBOL(__nla_reserve);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
825
826
  
  /**
089bf1a6a   Nicolas Dichtel   libnl: add more h...
827
828
829
830
   * __nla_reserve_64bit - reserve room for attribute on the skb and align it
   * @skb: socket buffer to reserve room on
   * @attrtype: attribute type
   * @attrlen: length of attribute payload
11a995730   Nicolas Dichtel   libnl: fix help o...
831
   * @padattr: attribute type for the padding
089bf1a6a   Nicolas Dichtel   libnl: add more h...
832
833
834
   *
   * Adds a netlink attribute header to a socket buffer and reserves
   * room for the payload but does not copy it. It also ensure that this
11a995730   Nicolas Dichtel   libnl: fix help o...
835
   * attribute will have a 64-bit aligned nla_data() area.
089bf1a6a   Nicolas Dichtel   libnl: add more h...
836
837
838
839
840
841
842
   *
   * The caller is responsible to ensure that the skb provides enough
   * tailroom for the attribute header and payload.
   */
  struct nlattr *__nla_reserve_64bit(struct sk_buff *skb, int attrtype,
  				   int attrlen, int padattr)
  {
4718a471f   Miaohe Lin   netlink: remove d...
843
  	nla_align_64bit(skb, padattr);
089bf1a6a   Nicolas Dichtel   libnl: add more h...
844
845
846
847
848
849
  
  	return __nla_reserve(skb, attrtype, attrlen);
  }
  EXPORT_SYMBOL(__nla_reserve_64bit);
  
  /**
fe4944e59   Thomas Graf   [NETLINK]: Extend...
850
851
852
853
854
855
856
857
858
859
860
   * __nla_reserve_nohdr - reserve room for attribute without header
   * @skb: socket buffer to reserve room on
   * @attrlen: length of attribute payload
   *
   * Reserves room for attribute payload without a header.
   *
   * The caller is responsible to ensure that the skb provides enough
   * tailroom for the payload.
   */
  void *__nla_reserve_nohdr(struct sk_buff *skb, int attrlen)
  {
b952f4dff   yuan linyu   net: manual clean...
861
  	return skb_put_zero(skb, NLA_ALIGN(attrlen));
fe4944e59   Thomas Graf   [NETLINK]: Extend...
862
  }
908002161   Herbert Xu   nlattr: Fix build...
863
  EXPORT_SYMBOL(__nla_reserve_nohdr);
fe4944e59   Thomas Graf   [NETLINK]: Extend...
864
865
  
  /**
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
   * nla_reserve - reserve room for attribute on the skb
   * @skb: socket buffer to reserve room on
   * @attrtype: attribute type
   * @attrlen: length of attribute payload
   *
   * Adds a netlink attribute header to a socket buffer and reserves
   * room for the payload but does not copy it.
   *
   * Returns NULL if the tailroom of the skb is insufficient to store
   * the attribute header and payload.
   */
  struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
  {
  	if (unlikely(skb_tailroom(skb) < nla_total_size(attrlen)))
  		return NULL;
  
  	return __nla_reserve(skb, attrtype, attrlen);
  }
908002161   Herbert Xu   nlattr: Fix build...
884
  EXPORT_SYMBOL(nla_reserve);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
885
886
  
  /**
089bf1a6a   Nicolas Dichtel   libnl: add more h...
887
888
889
890
   * nla_reserve_64bit - reserve room for attribute on the skb and align it
   * @skb: socket buffer to reserve room on
   * @attrtype: attribute type
   * @attrlen: length of attribute payload
11a995730   Nicolas Dichtel   libnl: fix help o...
891
   * @padattr: attribute type for the padding
089bf1a6a   Nicolas Dichtel   libnl: add more h...
892
893
894
   *
   * Adds a netlink attribute header to a socket buffer and reserves
   * room for the payload but does not copy it. It also ensure that this
11a995730   Nicolas Dichtel   libnl: fix help o...
895
   * attribute will have a 64-bit aligned nla_data() area.
089bf1a6a   Nicolas Dichtel   libnl: add more h...
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
   *
   * Returns NULL if the tailroom of the skb is insufficient to store
   * the attribute header and payload.
   */
  struct nlattr *nla_reserve_64bit(struct sk_buff *skb, int attrtype, int attrlen,
  				 int padattr)
  {
  	size_t len;
  
  	if (nla_need_padding_for_64bit(skb))
  		len = nla_total_size_64bit(attrlen);
  	else
  		len = nla_total_size(attrlen);
  	if (unlikely(skb_tailroom(skb) < len))
  		return NULL;
  
  	return __nla_reserve_64bit(skb, attrtype, attrlen, padattr);
  }
  EXPORT_SYMBOL(nla_reserve_64bit);
  
  /**
10b595aff   Julius Volz   netlink: Fix some...
917
   * nla_reserve_nohdr - reserve room for attribute without header
fe4944e59   Thomas Graf   [NETLINK]: Extend...
918
   * @skb: socket buffer to reserve room on
10b595aff   Julius Volz   netlink: Fix some...
919
   * @attrlen: length of attribute payload
fe4944e59   Thomas Graf   [NETLINK]: Extend...
920
921
922
923
924
925
926
927
928
929
930
931
932
   *
   * Reserves room for attribute payload without a header.
   *
   * Returns NULL if the tailroom of the skb is insufficient to store
   * the attribute payload.
   */
  void *nla_reserve_nohdr(struct sk_buff *skb, int attrlen)
  {
  	if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
  		return NULL;
  
  	return __nla_reserve_nohdr(skb, attrlen);
  }
908002161   Herbert Xu   nlattr: Fix build...
933
  EXPORT_SYMBOL(nla_reserve_nohdr);
fe4944e59   Thomas Graf   [NETLINK]: Extend...
934
935
  
  /**
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
   * __nla_put - Add a netlink attribute to a socket buffer
   * @skb: socket buffer to add attribute to
   * @attrtype: attribute type
   * @attrlen: length of attribute payload
   * @data: head of attribute payload
   *
   * The caller is responsible to ensure that the skb provides enough
   * tailroom for the attribute header and payload.
   */
  void __nla_put(struct sk_buff *skb, int attrtype, int attrlen,
  			     const void *data)
  {
  	struct nlattr *nla;
  
  	nla = __nla_reserve(skb, attrtype, attrlen);
  	memcpy(nla_data(nla), data, attrlen);
  }
908002161   Herbert Xu   nlattr: Fix build...
953
  EXPORT_SYMBOL(__nla_put);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
954

fe4944e59   Thomas Graf   [NETLINK]: Extend...
955
  /**
089bf1a6a   Nicolas Dichtel   libnl: add more h...
956
957
958
959
960
   * __nla_put_64bit - Add a netlink attribute to a socket buffer and align it
   * @skb: socket buffer to add attribute to
   * @attrtype: attribute type
   * @attrlen: length of attribute payload
   * @data: head of attribute payload
11a995730   Nicolas Dichtel   libnl: fix help o...
961
   * @padattr: attribute type for the padding
089bf1a6a   Nicolas Dichtel   libnl: add more h...
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
   *
   * The caller is responsible to ensure that the skb provides enough
   * tailroom for the attribute header and payload.
   */
  void __nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen,
  		     const void *data, int padattr)
  {
  	struct nlattr *nla;
  
  	nla = __nla_reserve_64bit(skb, attrtype, attrlen, padattr);
  	memcpy(nla_data(nla), data, attrlen);
  }
  EXPORT_SYMBOL(__nla_put_64bit);
  
  /**
fe4944e59   Thomas Graf   [NETLINK]: Extend...
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
   * __nla_put_nohdr - Add a netlink attribute without header
   * @skb: socket buffer to add attribute to
   * @attrlen: length of attribute payload
   * @data: head of attribute payload
   *
   * The caller is responsible to ensure that the skb provides enough
   * tailroom for the attribute payload.
   */
  void __nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data)
  {
  	void *start;
  
  	start = __nla_reserve_nohdr(skb, attrlen);
  	memcpy(start, data, attrlen);
  }
908002161   Herbert Xu   nlattr: Fix build...
992
  EXPORT_SYMBOL(__nla_put_nohdr);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
993
994
995
996
997
998
999
1000
  
  /**
   * nla_put - Add a netlink attribute to a socket buffer
   * @skb: socket buffer to add attribute to
   * @attrtype: attribute type
   * @attrlen: length of attribute payload
   * @data: head of attribute payload
   *
bc3ed28ca   Thomas Graf   netlink: Improve ...
1001
   * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
1002
1003
1004
1005
1006
   * the attribute header and payload.
   */
  int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
  {
  	if (unlikely(skb_tailroom(skb) < nla_total_size(attrlen)))
bc3ed28ca   Thomas Graf   netlink: Improve ...
1007
  		return -EMSGSIZE;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
1008
1009
1010
1011
  
  	__nla_put(skb, attrtype, attrlen, data);
  	return 0;
  }
908002161   Herbert Xu   nlattr: Fix build...
1012
  EXPORT_SYMBOL(nla_put);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
1013

fe4944e59   Thomas Graf   [NETLINK]: Extend...
1014
  /**
089bf1a6a   Nicolas Dichtel   libnl: add more h...
1015
1016
1017
1018
1019
   * nla_put_64bit - Add a netlink attribute to a socket buffer and align it
   * @skb: socket buffer to add attribute to
   * @attrtype: attribute type
   * @attrlen: length of attribute payload
   * @data: head of attribute payload
11a995730   Nicolas Dichtel   libnl: fix help o...
1020
   * @padattr: attribute type for the padding
089bf1a6a   Nicolas Dichtel   libnl: add more h...
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
   *
   * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
   * the attribute header and payload.
   */
  int nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen,
  		  const void *data, int padattr)
  {
  	size_t len;
  
  	if (nla_need_padding_for_64bit(skb))
  		len = nla_total_size_64bit(attrlen);
  	else
  		len = nla_total_size(attrlen);
  	if (unlikely(skb_tailroom(skb) < len))
  		return -EMSGSIZE;
  
  	__nla_put_64bit(skb, attrtype, attrlen, data, padattr);
  	return 0;
  }
  EXPORT_SYMBOL(nla_put_64bit);
  
  /**
fe4944e59   Thomas Graf   [NETLINK]: Extend...
1043
1044
1045
1046
1047
   * nla_put_nohdr - Add a netlink attribute without header
   * @skb: socket buffer to add attribute to
   * @attrlen: length of attribute payload
   * @data: head of attribute payload
   *
bc3ed28ca   Thomas Graf   netlink: Improve ...
1048
   * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
fe4944e59   Thomas Graf   [NETLINK]: Extend...
1049
1050
1051
1052
1053
   * the attribute payload.
   */
  int nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data)
  {
  	if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
bc3ed28ca   Thomas Graf   netlink: Improve ...
1054
  		return -EMSGSIZE;
fe4944e59   Thomas Graf   [NETLINK]: Extend...
1055
1056
1057
1058
  
  	__nla_put_nohdr(skb, attrlen, data);
  	return 0;
  }
908002161   Herbert Xu   nlattr: Fix build...
1059
  EXPORT_SYMBOL(nla_put_nohdr);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
1060

01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
1061
1062
1063
1064
1065
1066
  /**
   * nla_append - Add a netlink attribute without header or padding
   * @skb: socket buffer to add attribute to
   * @attrlen: length of attribute payload
   * @data: head of attribute payload
   *
bc3ed28ca   Thomas Graf   netlink: Improve ...
1067
   * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
1068
1069
1070
1071
1072
   * the attribute payload.
   */
  int nla_append(struct sk_buff *skb, int attrlen, const void *data)
  {
  	if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
bc3ed28ca   Thomas Graf   netlink: Improve ...
1073
  		return -EMSGSIZE;
01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
1074

59ae1d127   Johannes Berg   networking: intro...
1075
  	skb_put_data(skb, data, attrlen);
01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
1076
1077
  	return 0;
  }
908002161   Herbert Xu   nlattr: Fix build...
1078
1079
  EXPORT_SYMBOL(nla_append);
  #endif