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 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[]; 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 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 netlink_policy_dump_state *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 struct netlink_policy_dump_state **statep) 82 { 83 struct netlink_policy_dump_state *state; 84 unsigned int policy_idx; 85 int err; 86 87 if (*statep) 88 return 0; 89 90 /* 91 * walk the policies and nested ones first, and build 92 * a linear list of them. 93 */ 94 95 state = kzalloc(struct_size(state, policies, INITIAL_POLICIES_ALLOC), 96 GFP_KERNEL); 97 if (!state) 98 return -ENOMEM; 99 state->n_alloc = INITIAL_POLICIES_ALLOC; 100 101 err = add_policy(&state, policy, maxtype); 102 if (err) 103 return err; 104 105 for (policy_idx = 0; 106 policy_idx < state->n_alloc && state->policies[policy_idx].policy; 107 policy_idx++) { 108 const struct nla_policy *policy; 109 unsigned int type; 110 111 policy = state->policies[policy_idx].policy; 112 113 for (type = 0; 114 type <= state->policies[policy_idx].maxtype; 115 type++) { 116 switch (policy[type].type) { 117 case NLA_NESTED: 118 case NLA_NESTED_ARRAY: 119 err = add_policy(&state, 120 policy[type].nested_policy, 121 policy[type].len); 122 if (err) 123 return err; 124 break; 125 default: 126 break; 127 } 128 } 129 } 130 131 *statep = state; 132 133 return 0; 134 } 135 136 static bool 137 netlink_policy_dump_finished(struct netlink_policy_dump_state *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(struct netlink_policy_dump_state *state) 144 { 145 return !netlink_policy_dump_finished(state); 146 } 147 148 int netlink_policy_dump_write(struct sk_buff *skb, 149 struct netlink_policy_dump_state *state) 150 { 151 const struct nla_policy *pt; 152 struct nlattr *policy, *attr; 153 enum netlink_attribute_type type; 154 bool again; 155 156 send_attribute: 157 again = false; 158 159 pt = &state->policies[state->policy_idx].policy[state->attr_idx]; 160 161 policy = nla_nest_start(skb, state->policy_idx); 162 if (!policy) 163 return -ENOBUFS; 164 165 attr = nla_nest_start(skb, state->attr_idx); 166 if (!attr) 167 goto nla_put_failure; 168 169 switch (pt->type) { 170 default: 171 case NLA_UNSPEC: 172 case NLA_REJECT: 173 /* skip - use NLA_MIN_LEN to advertise such */ 174 nla_nest_cancel(skb, policy); 175 again = true; 176 goto next; 177 case NLA_NESTED: 178 type = NL_ATTR_TYPE_NESTED; 179 fallthrough; 180 case NLA_NESTED_ARRAY: 181 if (pt->type == NLA_NESTED_ARRAY) 182 type = NL_ATTR_TYPE_NESTED_ARRAY; 183 if (pt->nested_policy && pt->len && 184 (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_POLICY_IDX, 185 get_policy_idx(state, pt->nested_policy)) || 186 nla_put_u32(skb, NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE, 187 pt->len))) 188 goto nla_put_failure; 189 break; 190 case NLA_U8: 191 case NLA_U16: 192 case NLA_U32: 193 case NLA_U64: 194 case NLA_MSECS: { 195 struct netlink_range_validation range; 196 197 if (pt->type == NLA_U8) 198 type = NL_ATTR_TYPE_U8; 199 else if (pt->type == NLA_U16) 200 type = NL_ATTR_TYPE_U16; 201 else if (pt->type == NLA_U32) 202 type = NL_ATTR_TYPE_U32; 203 else 204 type = NL_ATTR_TYPE_U64; 205 206 nla_get_range_unsigned(pt, &range); 207 208 if (nla_put_u64_64bit(skb, NL_POLICY_TYPE_ATTR_MIN_VALUE_U, 209 range.min, NL_POLICY_TYPE_ATTR_PAD) || 210 nla_put_u64_64bit(skb, NL_POLICY_TYPE_ATTR_MAX_VALUE_U, 211 range.max, NL_POLICY_TYPE_ATTR_PAD)) 212 goto nla_put_failure; 213 break; 214 } 215 case NLA_S8: 216 case NLA_S16: 217 case NLA_S32: 218 case NLA_S64: { 219 struct netlink_range_validation_signed range; 220 221 if (pt->type == NLA_S8) 222 type = NL_ATTR_TYPE_S8; 223 else if (pt->type == NLA_S16) 224 type = NL_ATTR_TYPE_S16; 225 else if (pt->type == NLA_S32) 226 type = NL_ATTR_TYPE_S32; 227 else 228 type = NL_ATTR_TYPE_S64; 229 230 nla_get_range_signed(pt, &range); 231 232 if (nla_put_s64(skb, NL_POLICY_TYPE_ATTR_MIN_VALUE_S, 233 range.min, NL_POLICY_TYPE_ATTR_PAD) || 234 nla_put_s64(skb, NL_POLICY_TYPE_ATTR_MAX_VALUE_S, 235 range.max, NL_POLICY_TYPE_ATTR_PAD)) 236 goto nla_put_failure; 237 break; 238 } 239 case NLA_BITFIELD32: 240 type = NL_ATTR_TYPE_BITFIELD32; 241 if (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_BITFIELD32_MASK, 242 pt->bitfield32_valid)) 243 goto nla_put_failure; 244 break; 245 case NLA_STRING: 246 case NLA_NUL_STRING: 247 case NLA_BINARY: 248 if (pt->type == NLA_STRING) 249 type = NL_ATTR_TYPE_STRING; 250 else if (pt->type == NLA_NUL_STRING) 251 type = NL_ATTR_TYPE_NUL_STRING; 252 else 253 type = NL_ATTR_TYPE_BINARY; 254 255 if (pt->validation_type == NLA_VALIDATE_RANGE || 256 pt->validation_type == NLA_VALIDATE_RANGE_WARN_TOO_LONG) { 257 struct netlink_range_validation range; 258 259 nla_get_range_unsigned(pt, &range); 260 261 if (range.min && 262 nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MIN_LENGTH, 263 range.min)) 264 goto nla_put_failure; 265 266 if (range.max < U16_MAX && 267 nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MAX_LENGTH, 268 range.max)) 269 goto nla_put_failure; 270 } else if (pt->len && 271 nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MAX_LENGTH, 272 pt->len)) { 273 goto nla_put_failure; 274 } 275 break; 276 case NLA_FLAG: 277 type = NL_ATTR_TYPE_FLAG; 278 break; 279 } 280 281 if (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_TYPE, type)) 282 goto nla_put_failure; 283 284 /* finish and move state to next attribute */ 285 nla_nest_end(skb, attr); 286 nla_nest_end(skb, policy); 287 288 next: 289 state->attr_idx += 1; 290 if (state->attr_idx > state->policies[state->policy_idx].maxtype) { 291 state->attr_idx = 0; 292 state->policy_idx++; 293 } 294 295 if (again) { 296 if (netlink_policy_dump_finished(state)) 297 return -ENODATA; 298 goto send_attribute; 299 } 300 301 return 0; 302 303 nla_put_failure: 304 nla_nest_cancel(skb, policy); 305 return -ENOBUFS; 306 } 307 308 void netlink_policy_dump_free(struct netlink_policy_dump_state *state) 309 { 310 kfree(state); 311 } 312