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