1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * NETLINK Policy advertisement to userspace 4 * 5 * Authors: Johannes Berg <johannes@sipsolutions.net> 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 nl_policy_dump { 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[]; 25 }; 26 27 static int add_policy(struct nl_policy_dump **statep, 28 const struct nla_policy *policy, 29 unsigned int maxtype) 30 { 31 struct nl_policy_dump *state = *statep; 32 unsigned int 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 return 0; 40 41 if (!state->policies[i].policy) { 42 state->policies[i].policy = policy; 43 state->policies[i].maxtype = maxtype; 44 return 0; 45 } 46 } 47 48 n_alloc = state->n_alloc + INITIAL_POLICIES_ALLOC; 49 state = krealloc(state, struct_size(state, policies, n_alloc), 50 GFP_KERNEL); 51 if (!state) 52 return -ENOMEM; 53 54 memset(&state->policies[state->n_alloc], 0, 55 flex_array_size(state, policies, n_alloc - state->n_alloc)); 56 57 state->policies[state->n_alloc].policy = policy; 58 state->policies[state->n_alloc].maxtype = maxtype; 59 state->n_alloc = n_alloc; 60 *statep = state; 61 62 return 0; 63 } 64 65 static unsigned int get_policy_idx(struct nl_policy_dump *state, 66 const struct nla_policy *policy) 67 { 68 unsigned int i; 69 70 for (i = 0; i < state->n_alloc; i++) { 71 if (state->policies[i].policy == policy) 72 return i; 73 } 74 75 WARN_ON_ONCE(1); 76 return -1; 77 } 78 79 int netlink_policy_dump_start(const struct nla_policy *policy, 80 unsigned int maxtype, 81 unsigned long *_state) 82 { 83 struct nl_policy_dump *state; 84 unsigned int policy_idx; 85 int err; 86 87 /* also returns 0 if "*_state" is our ERR_PTR() end marker */ 88 if (*_state) 89 return 0; 90 91 /* 92 * walk the policies and nested ones first, and build 93 * a linear list of them. 94 */ 95 96 state = kzalloc(struct_size(state, policies, INITIAL_POLICIES_ALLOC), 97 GFP_KERNEL); 98 if (!state) 99 return -ENOMEM; 100 state->n_alloc = INITIAL_POLICIES_ALLOC; 101 102 err = add_policy(&state, policy, maxtype); 103 if (err) 104 return err; 105 106 for (policy_idx = 0; 107 policy_idx < state->n_alloc && state->policies[policy_idx].policy; 108 policy_idx++) { 109 const struct nla_policy *policy; 110 unsigned int type; 111 112 policy = state->policies[policy_idx].policy; 113 114 for (type = 0; 115 type <= state->policies[policy_idx].maxtype; 116 type++) { 117 switch (policy[type].type) { 118 case NLA_NESTED: 119 case NLA_NESTED_ARRAY: 120 err = add_policy(&state, 121 policy[type].nested_policy, 122 policy[type].len); 123 if (err) 124 return err; 125 break; 126 default: 127 break; 128 } 129 } 130 } 131 132 *_state = (unsigned long)state; 133 134 return 0; 135 } 136 137 static bool netlink_policy_dump_finished(struct nl_policy_dump *state) 138 { 139 return state->policy_idx >= state->n_alloc || 140 !state->policies[state->policy_idx].policy; 141 } 142 143 bool netlink_policy_dump_loop(unsigned long *_state) 144 { 145 struct nl_policy_dump *state = (void *)*_state; 146 147 if (IS_ERR(state)) 148 return false; 149 150 if (netlink_policy_dump_finished(state)) { 151 kfree(state); 152 /* store end marker instead of freed state */ 153 *_state = (unsigned long)ERR_PTR(-ENOENT); 154 return false; 155 } 156 157 return true; 158 } 159 160 int netlink_policy_dump_write(struct sk_buff *skb, unsigned long _state) 161 { 162 struct nl_policy_dump *state = (void *)_state; 163 const struct nla_policy *pt; 164 struct nlattr *policy, *attr; 165 enum netlink_attribute_type type; 166 bool again; 167 168 send_attribute: 169 again = false; 170 171 pt = &state->policies[state->policy_idx].policy[state->attr_idx]; 172 173 policy = nla_nest_start(skb, state->policy_idx); 174 if (!policy) 175 return -ENOBUFS; 176 177 attr = nla_nest_start(skb, state->attr_idx); 178 if (!attr) 179 goto nla_put_failure; 180 181 switch (pt->type) { 182 default: 183 case NLA_UNSPEC: 184 case NLA_REJECT: 185 /* skip - use NLA_MIN_LEN to advertise such */ 186 nla_nest_cancel(skb, policy); 187 again = true; 188 goto next; 189 case NLA_NESTED: 190 type = NL_ATTR_TYPE_NESTED; 191 fallthrough; 192 case NLA_NESTED_ARRAY: 193 if (pt->type == NLA_NESTED_ARRAY) 194 type = NL_ATTR_TYPE_NESTED_ARRAY; 195 if (pt->nested_policy && pt->len && 196 (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_POLICY_IDX, 197 get_policy_idx(state, pt->nested_policy)) || 198 nla_put_u32(skb, NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE, 199 pt->len))) 200 goto nla_put_failure; 201 break; 202 case NLA_U8: 203 case NLA_U16: 204 case NLA_U32: 205 case NLA_U64: 206 case NLA_MSECS: { 207 struct netlink_range_validation range; 208 209 if (pt->type == NLA_U8) 210 type = NL_ATTR_TYPE_U8; 211 else if (pt->type == NLA_U16) 212 type = NL_ATTR_TYPE_U16; 213 else if (pt->type == NLA_U32) 214 type = NL_ATTR_TYPE_U32; 215 else 216 type = NL_ATTR_TYPE_U64; 217 218 nla_get_range_unsigned(pt, &range); 219 220 if (nla_put_u64_64bit(skb, NL_POLICY_TYPE_ATTR_MIN_VALUE_U, 221 range.min, NL_POLICY_TYPE_ATTR_PAD) || 222 nla_put_u64_64bit(skb, NL_POLICY_TYPE_ATTR_MAX_VALUE_U, 223 range.max, NL_POLICY_TYPE_ATTR_PAD)) 224 goto nla_put_failure; 225 break; 226 } 227 case NLA_S8: 228 case NLA_S16: 229 case NLA_S32: 230 case NLA_S64: { 231 struct netlink_range_validation_signed range; 232 233 if (pt->type == NLA_S8) 234 type = NL_ATTR_TYPE_S8; 235 else if (pt->type == NLA_S16) 236 type = NL_ATTR_TYPE_S16; 237 else if (pt->type == NLA_S32) 238 type = NL_ATTR_TYPE_S32; 239 else 240 type = NL_ATTR_TYPE_S64; 241 242 nla_get_range_signed(pt, &range); 243 244 if (nla_put_s64(skb, NL_POLICY_TYPE_ATTR_MIN_VALUE_S, 245 range.min, NL_POLICY_TYPE_ATTR_PAD) || 246 nla_put_s64(skb, NL_POLICY_TYPE_ATTR_MAX_VALUE_S, 247 range.max, NL_POLICY_TYPE_ATTR_PAD)) 248 goto nla_put_failure; 249 break; 250 } 251 case NLA_BITFIELD32: 252 type = NL_ATTR_TYPE_BITFIELD32; 253 if (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_BITFIELD32_MASK, 254 pt->bitfield32_valid)) 255 goto nla_put_failure; 256 break; 257 case NLA_EXACT_LEN: 258 type = NL_ATTR_TYPE_BINARY; 259 if (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MIN_LENGTH, pt->len) || 260 nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MAX_LENGTH, pt->len)) 261 goto nla_put_failure; 262 break; 263 case NLA_STRING: 264 case NLA_NUL_STRING: 265 case NLA_BINARY: 266 if (pt->type == NLA_STRING) 267 type = NL_ATTR_TYPE_STRING; 268 else if (pt->type == NLA_NUL_STRING) 269 type = NL_ATTR_TYPE_NUL_STRING; 270 else 271 type = NL_ATTR_TYPE_BINARY; 272 if (pt->len && nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MAX_LENGTH, 273 pt->len)) 274 goto nla_put_failure; 275 break; 276 case NLA_MIN_LEN: 277 type = NL_ATTR_TYPE_BINARY; 278 if (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MIN_LENGTH, pt->len)) 279 goto nla_put_failure; 280 break; 281 case NLA_FLAG: 282 type = NL_ATTR_TYPE_FLAG; 283 break; 284 } 285 286 if (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_TYPE, type)) 287 goto nla_put_failure; 288 289 /* finish and move state to next attribute */ 290 nla_nest_end(skb, attr); 291 nla_nest_end(skb, policy); 292 293 next: 294 state->attr_idx += 1; 295 if (state->attr_idx > state->policies[state->policy_idx].maxtype) { 296 state->attr_idx = 0; 297 state->policy_idx++; 298 } 299 300 if (again) { 301 if (netlink_policy_dump_finished(state)) 302 return -ENODATA; 303 goto send_attribute; 304 } 305 306 return 0; 307 308 nla_put_failure: 309 nla_nest_cancel(skb, policy); 310 return -ENOBUFS; 311 } 312