Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/netlink/policy.c
26278 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* NETLINK Policy advertisement to userspace
4
*
5
* Authors: Johannes Berg <[email protected]>
6
*
7
* Copyright 2019 Intel Corporation
8
*/
9
10
#include <linux/kernel.h>
11
#include <linux/errno.h>
12
#include <linux/types.h>
13
#include <net/netlink.h>
14
15
#define INITIAL_POLICIES_ALLOC 10
16
17
struct netlink_policy_dump_state {
18
unsigned int policy_idx;
19
unsigned int attr_idx;
20
unsigned int n_alloc;
21
struct {
22
const struct nla_policy *policy;
23
unsigned int maxtype;
24
} policies[] __counted_by(n_alloc);
25
};
26
27
static int add_policy(struct netlink_policy_dump_state **statep,
28
const struct nla_policy *policy,
29
unsigned int maxtype)
30
{
31
struct netlink_policy_dump_state *state = *statep;
32
unsigned int old_n_alloc, n_alloc, i;
33
34
if (!policy || !maxtype)
35
return 0;
36
37
for (i = 0; i < state->n_alloc; i++) {
38
if (state->policies[i].policy == policy &&
39
state->policies[i].maxtype == maxtype)
40
return 0;
41
42
if (!state->policies[i].policy) {
43
state->policies[i].policy = policy;
44
state->policies[i].maxtype = maxtype;
45
return 0;
46
}
47
}
48
49
n_alloc = state->n_alloc + INITIAL_POLICIES_ALLOC;
50
state = krealloc(state, struct_size(state, policies, n_alloc),
51
GFP_KERNEL);
52
if (!state)
53
return -ENOMEM;
54
55
old_n_alloc = state->n_alloc;
56
state->n_alloc = n_alloc;
57
memset(&state->policies[old_n_alloc], 0,
58
flex_array_size(state, policies, n_alloc - old_n_alloc));
59
60
state->policies[old_n_alloc].policy = policy;
61
state->policies[old_n_alloc].maxtype = maxtype;
62
*statep = state;
63
64
return 0;
65
}
66
67
/**
68
* netlink_policy_dump_get_policy_idx - retrieve policy index
69
* @state: the policy dump state
70
* @policy: the policy to find
71
* @maxtype: the policy's maxattr
72
*
73
* Returns: the index of the given policy in the dump state
74
*
75
* Call this to find a policy index when you've added multiple and e.g.
76
* need to tell userspace which command has which policy (by index).
77
*
78
* Note: this will WARN and return 0 if the policy isn't found, which
79
* means it wasn't added in the first place, which would be an
80
* internal consistency bug.
81
*/
82
int netlink_policy_dump_get_policy_idx(struct netlink_policy_dump_state *state,
83
const struct nla_policy *policy,
84
unsigned int maxtype)
85
{
86
unsigned int i;
87
88
if (WARN_ON(!policy || !maxtype))
89
return 0;
90
91
for (i = 0; i < state->n_alloc; i++) {
92
if (state->policies[i].policy == policy &&
93
state->policies[i].maxtype == maxtype)
94
return i;
95
}
96
97
WARN_ON(1);
98
return 0;
99
}
100
101
static struct netlink_policy_dump_state *alloc_state(void)
102
{
103
struct netlink_policy_dump_state *state;
104
105
state = kzalloc(struct_size(state, policies, INITIAL_POLICIES_ALLOC),
106
GFP_KERNEL);
107
if (!state)
108
return ERR_PTR(-ENOMEM);
109
state->n_alloc = INITIAL_POLICIES_ALLOC;
110
111
return state;
112
}
113
114
/**
115
* netlink_policy_dump_add_policy - add a policy to the dump
116
* @pstate: state to add to, may be reallocated, must be %NULL the first time
117
* @policy: the new policy to add to the dump
118
* @maxtype: the new policy's max attr type
119
*
120
* Returns: 0 on success, a negative error code otherwise.
121
*
122
* Call this to allocate a policy dump state, and to add policies to it. This
123
* should be called from the dump start() callback.
124
*
125
* Note: on failures, any previously allocated state is freed.
126
*/
127
int netlink_policy_dump_add_policy(struct netlink_policy_dump_state **pstate,
128
const struct nla_policy *policy,
129
unsigned int maxtype)
130
{
131
struct netlink_policy_dump_state *state = *pstate;
132
unsigned int policy_idx;
133
int err;
134
135
if (!state) {
136
state = alloc_state();
137
if (IS_ERR(state))
138
return PTR_ERR(state);
139
}
140
141
/*
142
* walk the policies and nested ones first, and build
143
* a linear list of them.
144
*/
145
146
err = add_policy(&state, policy, maxtype);
147
if (err)
148
goto err_try_undo;
149
150
for (policy_idx = 0;
151
policy_idx < state->n_alloc && state->policies[policy_idx].policy;
152
policy_idx++) {
153
const struct nla_policy *policy;
154
unsigned int type;
155
156
policy = state->policies[policy_idx].policy;
157
158
for (type = 0;
159
type <= state->policies[policy_idx].maxtype;
160
type++) {
161
switch (policy[type].type) {
162
case NLA_NESTED:
163
case NLA_NESTED_ARRAY:
164
err = add_policy(&state,
165
policy[type].nested_policy,
166
policy[type].len);
167
if (err)
168
goto err_try_undo;
169
break;
170
default:
171
break;
172
}
173
}
174
}
175
176
*pstate = state;
177
return 0;
178
179
err_try_undo:
180
/* Try to preserve reasonable unwind semantics - if we're starting from
181
* scratch clean up fully, otherwise record what we got and caller will.
182
*/
183
if (!*pstate)
184
netlink_policy_dump_free(state);
185
else
186
*pstate = state;
187
return err;
188
}
189
190
static bool
191
netlink_policy_dump_finished(struct netlink_policy_dump_state *state)
192
{
193
return state->policy_idx >= state->n_alloc ||
194
!state->policies[state->policy_idx].policy;
195
}
196
197
/**
198
* netlink_policy_dump_loop - dumping loop indicator
199
* @state: the policy dump state
200
*
201
* Returns: %true if the dump continues, %false otherwise
202
*
203
* Note: this frees the dump state when finishing
204
*/
205
bool netlink_policy_dump_loop(struct netlink_policy_dump_state *state)
206
{
207
return !netlink_policy_dump_finished(state);
208
}
209
210
int netlink_policy_dump_attr_size_estimate(const struct nla_policy *pt)
211
{
212
/* nested + type */
213
int common = 2 * nla_attr_size(sizeof(u32));
214
215
switch (pt->type) {
216
case NLA_UNSPEC:
217
case NLA_REJECT:
218
/* these actually don't need any space */
219
return 0;
220
case NLA_NESTED:
221
case NLA_NESTED_ARRAY:
222
/* common, policy idx, policy maxattr */
223
return common + 2 * nla_attr_size(sizeof(u32));
224
case NLA_U8:
225
case NLA_U16:
226
case NLA_U32:
227
case NLA_U64:
228
case NLA_MSECS:
229
case NLA_S8:
230
case NLA_S16:
231
case NLA_S32:
232
case NLA_S64:
233
case NLA_SINT:
234
case NLA_UINT:
235
/* maximum is common, u64 min/max with padding */
236
return common +
237
2 * (nla_attr_size(0) + nla_attr_size(sizeof(u64)));
238
case NLA_BITFIELD32:
239
return common + nla_attr_size(sizeof(u32));
240
case NLA_STRING:
241
case NLA_NUL_STRING:
242
case NLA_BINARY:
243
/* maximum is common, u32 min-length/max-length */
244
return common + 2 * nla_attr_size(sizeof(u32));
245
case NLA_FLAG:
246
return common;
247
}
248
249
/* this should then cause a warning later */
250
return 0;
251
}
252
253
static int
254
__netlink_policy_dump_write_attr(struct netlink_policy_dump_state *state,
255
struct sk_buff *skb,
256
const struct nla_policy *pt,
257
int nestattr)
258
{
259
int estimate = netlink_policy_dump_attr_size_estimate(pt);
260
enum netlink_attribute_type type;
261
struct nlattr *attr;
262
263
attr = nla_nest_start(skb, nestattr);
264
if (!attr)
265
return -ENOBUFS;
266
267
switch (pt->type) {
268
default:
269
case NLA_UNSPEC:
270
case NLA_REJECT:
271
/* skip - use NLA_MIN_LEN to advertise such */
272
nla_nest_cancel(skb, attr);
273
return -ENODATA;
274
case NLA_NESTED:
275
type = NL_ATTR_TYPE_NESTED;
276
fallthrough;
277
case NLA_NESTED_ARRAY:
278
if (pt->type == NLA_NESTED_ARRAY)
279
type = NL_ATTR_TYPE_NESTED_ARRAY;
280
if (state && pt->nested_policy && pt->len &&
281
(nla_put_u32(skb, NL_POLICY_TYPE_ATTR_POLICY_IDX,
282
netlink_policy_dump_get_policy_idx(state,
283
pt->nested_policy,
284
pt->len)) ||
285
nla_put_u32(skb, NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE,
286
pt->len)))
287
goto nla_put_failure;
288
break;
289
case NLA_U8:
290
case NLA_U16:
291
case NLA_U32:
292
case NLA_U64:
293
case NLA_UINT:
294
case NLA_MSECS: {
295
struct netlink_range_validation range;
296
297
if (pt->type == NLA_U8)
298
type = NL_ATTR_TYPE_U8;
299
else if (pt->type == NLA_U16)
300
type = NL_ATTR_TYPE_U16;
301
else if (pt->type == NLA_U32)
302
type = NL_ATTR_TYPE_U32;
303
else if (pt->type == NLA_U64)
304
type = NL_ATTR_TYPE_U64;
305
else
306
type = NL_ATTR_TYPE_UINT;
307
308
if (pt->validation_type == NLA_VALIDATE_MASK) {
309
if (nla_put_u64_64bit(skb, NL_POLICY_TYPE_ATTR_MASK,
310
pt->mask,
311
NL_POLICY_TYPE_ATTR_PAD))
312
goto nla_put_failure;
313
break;
314
} else if (pt->validation_type == NLA_VALIDATE_FUNCTION) {
315
break;
316
}
317
318
nla_get_range_unsigned(pt, &range);
319
320
if (nla_put_u64_64bit(skb, NL_POLICY_TYPE_ATTR_MIN_VALUE_U,
321
range.min, NL_POLICY_TYPE_ATTR_PAD) ||
322
nla_put_u64_64bit(skb, NL_POLICY_TYPE_ATTR_MAX_VALUE_U,
323
range.max, NL_POLICY_TYPE_ATTR_PAD))
324
goto nla_put_failure;
325
break;
326
}
327
case NLA_S8:
328
case NLA_S16:
329
case NLA_S32:
330
case NLA_S64:
331
case NLA_SINT: {
332
struct netlink_range_validation_signed range;
333
334
if (pt->type == NLA_S8)
335
type = NL_ATTR_TYPE_S8;
336
else if (pt->type == NLA_S16)
337
type = NL_ATTR_TYPE_S16;
338
else if (pt->type == NLA_S32)
339
type = NL_ATTR_TYPE_S32;
340
else if (pt->type == NLA_S64)
341
type = NL_ATTR_TYPE_S64;
342
else
343
type = NL_ATTR_TYPE_SINT;
344
345
if (pt->validation_type == NLA_VALIDATE_FUNCTION)
346
break;
347
348
nla_get_range_signed(pt, &range);
349
350
if (nla_put_s64(skb, NL_POLICY_TYPE_ATTR_MIN_VALUE_S,
351
range.min, NL_POLICY_TYPE_ATTR_PAD) ||
352
nla_put_s64(skb, NL_POLICY_TYPE_ATTR_MAX_VALUE_S,
353
range.max, NL_POLICY_TYPE_ATTR_PAD))
354
goto nla_put_failure;
355
break;
356
}
357
case NLA_BITFIELD32:
358
type = NL_ATTR_TYPE_BITFIELD32;
359
if (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_BITFIELD32_MASK,
360
pt->bitfield32_valid))
361
goto nla_put_failure;
362
break;
363
case NLA_STRING:
364
case NLA_NUL_STRING:
365
case NLA_BINARY:
366
if (pt->type == NLA_STRING)
367
type = NL_ATTR_TYPE_STRING;
368
else if (pt->type == NLA_NUL_STRING)
369
type = NL_ATTR_TYPE_NUL_STRING;
370
else
371
type = NL_ATTR_TYPE_BINARY;
372
373
if (pt->validation_type == NLA_VALIDATE_RANGE ||
374
pt->validation_type == NLA_VALIDATE_RANGE_WARN_TOO_LONG) {
375
struct netlink_range_validation range;
376
377
nla_get_range_unsigned(pt, &range);
378
379
if (range.min &&
380
nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MIN_LENGTH,
381
range.min))
382
goto nla_put_failure;
383
384
if (range.max < U16_MAX &&
385
nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MAX_LENGTH,
386
range.max))
387
goto nla_put_failure;
388
} else if (pt->len &&
389
nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MAX_LENGTH,
390
pt->len)) {
391
goto nla_put_failure;
392
}
393
break;
394
case NLA_FLAG:
395
type = NL_ATTR_TYPE_FLAG;
396
break;
397
}
398
399
if (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_TYPE, type))
400
goto nla_put_failure;
401
402
nla_nest_end(skb, attr);
403
WARN_ON(attr->nla_len > estimate);
404
405
return 0;
406
nla_put_failure:
407
nla_nest_cancel(skb, attr);
408
return -ENOBUFS;
409
}
410
411
/**
412
* netlink_policy_dump_write_attr - write a given attribute policy
413
* @skb: the message skb to write to
414
* @pt: the attribute's policy
415
* @nestattr: the nested attribute ID to use
416
*
417
* Returns: 0 on success, an error code otherwise; -%ENODATA is
418
* special, indicating that there's no policy data and
419
* the attribute is generally rejected.
420
*/
421
int netlink_policy_dump_write_attr(struct sk_buff *skb,
422
const struct nla_policy *pt,
423
int nestattr)
424
{
425
return __netlink_policy_dump_write_attr(NULL, skb, pt, nestattr);
426
}
427
428
/**
429
* netlink_policy_dump_write - write current policy dump attributes
430
* @skb: the message skb to write to
431
* @state: the policy dump state
432
*
433
* Returns: 0 on success, an error code otherwise
434
*/
435
int netlink_policy_dump_write(struct sk_buff *skb,
436
struct netlink_policy_dump_state *state)
437
{
438
const struct nla_policy *pt;
439
struct nlattr *policy;
440
bool again;
441
int err;
442
443
send_attribute:
444
again = false;
445
446
pt = &state->policies[state->policy_idx].policy[state->attr_idx];
447
448
policy = nla_nest_start(skb, state->policy_idx);
449
if (!policy)
450
return -ENOBUFS;
451
452
err = __netlink_policy_dump_write_attr(state, skb, pt, state->attr_idx);
453
if (err == -ENODATA) {
454
nla_nest_cancel(skb, policy);
455
again = true;
456
goto next;
457
} else if (err) {
458
goto nla_put_failure;
459
}
460
461
/* finish and move state to next attribute */
462
nla_nest_end(skb, policy);
463
464
next:
465
state->attr_idx += 1;
466
if (state->attr_idx > state->policies[state->policy_idx].maxtype) {
467
state->attr_idx = 0;
468
state->policy_idx++;
469
}
470
471
if (again) {
472
if (netlink_policy_dump_finished(state))
473
return -ENODATA;
474
goto send_attribute;
475
}
476
477
return 0;
478
479
nla_put_failure:
480
nla_nest_cancel(skb, policy);
481
return -ENOBUFS;
482
}
483
484
/**
485
* netlink_policy_dump_free - free policy dump state
486
* @state: the policy dump state to free
487
*
488
* Call this from the done() method to ensure dump state is freed.
489
*/
490
void netlink_policy_dump_free(struct netlink_policy_dump_state *state)
491
{
492
kfree(state);
493
}
494
495