1 /*
2 * Copyright (c) 2018, Mellanox Technologies inc. All rights reserved.
3 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 */
32
33 #include "rdma_core.h"
34 #include "uverbs.h"
35 #include <rdma/uverbs_std_types.h>
36
uverbs_free_flow_action(struct ib_uobject * uobject,enum rdma_remove_reason why,struct uverbs_attr_bundle * attrs)37 static int uverbs_free_flow_action(struct ib_uobject *uobject,
38 enum rdma_remove_reason why,
39 struct uverbs_attr_bundle *attrs)
40 {
41 struct ib_flow_action *action = uobject->object;
42 int ret;
43
44 ret = ib_destroy_usecnt(&action->usecnt, why, uobject);
45 if (ret)
46 return ret;
47
48 return action->device->destroy_flow_action(action);
49 }
50
esp_flags_uverbs_to_verbs(struct uverbs_attr_bundle * attrs,u32 flags,bool is_modify)51 static u64 esp_flags_uverbs_to_verbs(struct uverbs_attr_bundle *attrs,
52 u32 flags, bool is_modify)
53 {
54 u64 verbs_flags = flags;
55
56 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_ESN))
57 verbs_flags |= IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED;
58
59 if (is_modify && uverbs_attr_is_valid(attrs,
60 UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS))
61 verbs_flags |= IB_FLOW_ACTION_ESP_FLAGS_MOD_ESP_ATTRS;
62
63 return verbs_flags;
64 };
65
validate_flow_action_esp_keymat_aes_gcm(struct ib_flow_action_attrs_esp_keymats * keymat)66 static int validate_flow_action_esp_keymat_aes_gcm(struct ib_flow_action_attrs_esp_keymats *keymat)
67 {
68 struct ib_uverbs_flow_action_esp_keymat_aes_gcm *aes_gcm =
69 &keymat->keymat.aes_gcm;
70
71 if (aes_gcm->iv_algo > IB_UVERBS_FLOW_ACTION_IV_ALGO_SEQ)
72 return -EOPNOTSUPP;
73
74 if (aes_gcm->key_len != 32 &&
75 aes_gcm->key_len != 24 &&
76 aes_gcm->key_len != 16)
77 return -EINVAL;
78
79 if (aes_gcm->icv_len != 16 &&
80 aes_gcm->icv_len != 8 &&
81 aes_gcm->icv_len != 12)
82 return -EINVAL;
83
84 return 0;
85 }
86
87 static int (* const flow_action_esp_keymat_validate[])(struct ib_flow_action_attrs_esp_keymats *keymat) = {
88 [IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM] = validate_flow_action_esp_keymat_aes_gcm,
89 };
90
flow_action_esp_replay_none(struct ib_flow_action_attrs_esp_replays * replay,bool is_modify)91 static int flow_action_esp_replay_none(struct ib_flow_action_attrs_esp_replays *replay,
92 bool is_modify)
93 {
94 /* This is used in order to modify an esp flow action with an enabled
95 * replay protection to a disabled one. This is only supported via
96 * modify, as in create verb we can simply drop the REPLAY attribute and
97 * achieve the same thing.
98 */
99 return is_modify ? 0 : -EINVAL;
100 }
101
flow_action_esp_replay_def_ok(struct ib_flow_action_attrs_esp_replays * replay,bool is_modify)102 static int flow_action_esp_replay_def_ok(struct ib_flow_action_attrs_esp_replays *replay,
103 bool is_modify)
104 {
105 /* Some replay protections could always be enabled without validating
106 * anything.
107 */
108 return 0;
109 }
110
111 static int (* const flow_action_esp_replay_validate[])(struct ib_flow_action_attrs_esp_replays *replay,
112 bool is_modify) = {
113 [IB_UVERBS_FLOW_ACTION_ESP_REPLAY_NONE] = flow_action_esp_replay_none,
114 [IB_UVERBS_FLOW_ACTION_ESP_REPLAY_BMP] = flow_action_esp_replay_def_ok,
115 };
116
parse_esp_ip(enum ib_flow_spec_type proto,const void __user * val_ptr,size_t len,union ib_flow_spec * out)117 static int parse_esp_ip(enum ib_flow_spec_type proto,
118 const void __user *val_ptr,
119 size_t len, union ib_flow_spec *out)
120 {
121 int ret;
122 const struct ib_uverbs_flow_ipv4_filter ipv4 = {
123 .src_ip = cpu_to_be32(0xffffffffUL),
124 .dst_ip = cpu_to_be32(0xffffffffUL),
125 .proto = 0xff,
126 .tos = 0xff,
127 .ttl = 0xff,
128 .flags = 0xff,
129 };
130 const struct ib_uverbs_flow_ipv6_filter ipv6 = {
131 .src_ip = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
132 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
133 .dst_ip = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
134 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
135 .flow_label = cpu_to_be32(0xffffffffUL),
136 .next_hdr = 0xff,
137 .traffic_class = 0xff,
138 .hop_limit = 0xff,
139 };
140 union {
141 struct ib_uverbs_flow_ipv4_filter ipv4;
142 struct ib_uverbs_flow_ipv6_filter ipv6;
143 } user_val = {};
144 const void *user_pmask;
145 size_t val_len;
146
147 /* If the flow IPv4/IPv6 flow specifications are extended, the mask
148 * should be changed as well.
149 */
150 BUILD_BUG_ON(offsetof(struct ib_uverbs_flow_ipv4_filter, flags) +
151 sizeof(ipv4.flags) != sizeof(ipv4));
152 BUILD_BUG_ON(offsetof(struct ib_uverbs_flow_ipv6_filter, reserved) +
153 sizeof(ipv6.reserved) != sizeof(ipv6));
154
155 switch (proto) {
156 case IB_FLOW_SPEC_IPV4:
157 if (len > sizeof(user_val.ipv4) &&
158 !ib_is_buffer_cleared((const u8 *)val_ptr + sizeof(user_val.ipv4),
159 len - sizeof(user_val.ipv4)))
160 return -EOPNOTSUPP;
161
162 val_len = min_t(size_t, len, sizeof(user_val.ipv4));
163 ret = copy_from_user(&user_val.ipv4, val_ptr,
164 val_len);
165 if (ret)
166 return -EFAULT;
167
168 user_pmask = &ipv4;
169 break;
170 case IB_FLOW_SPEC_IPV6:
171 if (len > sizeof(user_val.ipv6) &&
172 !ib_is_buffer_cleared((const u8 *)val_ptr + sizeof(user_val.ipv6),
173 len - sizeof(user_val.ipv6)))
174 return -EOPNOTSUPP;
175
176 val_len = min_t(size_t, len, sizeof(user_val.ipv6));
177 ret = copy_from_user(&user_val.ipv6, val_ptr,
178 val_len);
179 if (ret)
180 return -EFAULT;
181
182 user_pmask = &ipv6;
183 break;
184 default:
185 return -EOPNOTSUPP;
186 }
187
188 return ib_uverbs_kern_spec_to_ib_spec_filter(proto, user_pmask,
189 &user_val,
190 val_len, out);
191 }
192
flow_action_esp_get_encap(struct ib_flow_spec_list * out,struct uverbs_attr_bundle * attrs)193 static int flow_action_esp_get_encap(struct ib_flow_spec_list *out,
194 struct uverbs_attr_bundle *attrs)
195 {
196 struct ib_uverbs_flow_action_esp_encap uverbs_encap;
197 int ret;
198
199 ret = uverbs_copy_from(&uverbs_encap, attrs,
200 UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP);
201 if (ret)
202 return ret;
203
204 /* We currently support only one encap */
205 if (uverbs_encap.next_ptr)
206 return -EOPNOTSUPP;
207
208 if (uverbs_encap.type != IB_FLOW_SPEC_IPV4 &&
209 uverbs_encap.type != IB_FLOW_SPEC_IPV6)
210 return -EOPNOTSUPP;
211
212 return parse_esp_ip(uverbs_encap.type,
213 u64_to_user_ptr(uverbs_encap.val_ptr),
214 uverbs_encap.len,
215 &out->spec);
216 }
217
218 struct ib_flow_action_esp_attr {
219 struct ib_flow_action_attrs_esp hdr;
220 struct ib_flow_action_attrs_esp_keymats keymat;
221 struct ib_flow_action_attrs_esp_replays replay;
222 /* We currently support only one spec */
223 struct ib_flow_spec_list encap;
224 };
225
226 #define ESP_LAST_SUPPORTED_FLAG IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW
parse_flow_action_esp(struct ib_device * ib_dev,struct uverbs_attr_bundle * attrs,struct ib_flow_action_esp_attr * esp_attr,bool is_modify)227 static int parse_flow_action_esp(struct ib_device *ib_dev,
228 struct uverbs_attr_bundle *attrs,
229 struct ib_flow_action_esp_attr *esp_attr,
230 bool is_modify)
231 {
232 struct ib_uverbs_flow_action_esp uverbs_esp = {};
233 int ret;
234
235 /* Optional param, if it doesn't exist, we get -ENOENT and skip it */
236 ret = uverbs_copy_from(&esp_attr->hdr.esn, attrs,
237 UVERBS_ATTR_FLOW_ACTION_ESP_ESN);
238 if (IS_UVERBS_COPY_ERR(ret))
239 return ret;
240
241 /* This can be called from FLOW_ACTION_ESP_MODIFY where
242 * UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS is optional
243 */
244 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS)) {
245 ret = uverbs_copy_from_or_zero(&uverbs_esp, attrs,
246 UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS);
247 if (ret)
248 return ret;
249
250 if (uverbs_esp.flags & ~((ESP_LAST_SUPPORTED_FLAG << 1) - 1))
251 return -EOPNOTSUPP;
252
253 esp_attr->hdr.spi = uverbs_esp.spi;
254 esp_attr->hdr.seq = uverbs_esp.seq;
255 esp_attr->hdr.tfc_pad = uverbs_esp.tfc_pad;
256 esp_attr->hdr.hard_limit_pkts = uverbs_esp.hard_limit_pkts;
257 }
258 esp_attr->hdr.flags = esp_flags_uverbs_to_verbs(attrs, uverbs_esp.flags,
259 is_modify);
260
261 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT)) {
262 esp_attr->keymat.protocol =
263 uverbs_attr_get_enum_id(attrs,
264 UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT);
265 ret = uverbs_copy_from_or_zero(&esp_attr->keymat.keymat,
266 attrs,
267 UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT);
268 if (ret)
269 return ret;
270
271 ret = flow_action_esp_keymat_validate[esp_attr->keymat.protocol](&esp_attr->keymat);
272 if (ret)
273 return ret;
274
275 esp_attr->hdr.keymat = &esp_attr->keymat;
276 }
277
278 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY)) {
279 esp_attr->replay.protocol =
280 uverbs_attr_get_enum_id(attrs,
281 UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY);
282
283 ret = uverbs_copy_from_or_zero(&esp_attr->replay.replay,
284 attrs,
285 UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY);
286 if (ret)
287 return ret;
288
289 ret = flow_action_esp_replay_validate[esp_attr->replay.protocol](&esp_attr->replay,
290 is_modify);
291 if (ret)
292 return ret;
293
294 esp_attr->hdr.replay = &esp_attr->replay;
295 }
296
297 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP)) {
298 ret = flow_action_esp_get_encap(&esp_attr->encap, attrs);
299 if (ret)
300 return ret;
301
302 esp_attr->hdr.encap = &esp_attr->encap;
303 }
304
305 return 0;
306 }
307
UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE)308 static int UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE)(
309 struct uverbs_attr_bundle *attrs)
310 {
311 struct ib_uobject *uobj = uverbs_attr_get_uobject(
312 attrs, UVERBS_ATTR_CREATE_FLOW_ACTION_ESP_HANDLE);
313 struct ib_device *ib_dev = attrs->context->device;
314 int ret;
315 struct ib_flow_action *action;
316 struct ib_flow_action_esp_attr esp_attr = {};
317
318 if (!ib_dev->create_flow_action_esp)
319 return -EOPNOTSUPP;
320
321 ret = parse_flow_action_esp(ib_dev, attrs, &esp_attr, false);
322 if (ret)
323 return ret;
324
325 /* No need to check as this attribute is marked as MANDATORY */
326 action = ib_dev->create_flow_action_esp(ib_dev, &esp_attr.hdr,
327 attrs);
328 if (IS_ERR(action))
329 return PTR_ERR(action);
330
331 uverbs_flow_action_fill_action(action, uobj, ib_dev,
332 IB_FLOW_ACTION_ESP);
333
334 return 0;
335 }
336
UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY)337 static int UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY)(
338 struct uverbs_attr_bundle *attrs)
339 {
340 struct ib_uobject *uobj = uverbs_attr_get_uobject(
341 attrs, UVERBS_ATTR_MODIFY_FLOW_ACTION_ESP_HANDLE);
342 struct ib_flow_action *action = uobj->object;
343 int ret;
344 struct ib_flow_action_esp_attr esp_attr = {};
345
346 if (!action->device->modify_flow_action_esp)
347 return -EOPNOTSUPP;
348
349 ret = parse_flow_action_esp(action->device, attrs, &esp_attr, true);
350 if (ret)
351 return ret;
352
353 if (action->type != IB_FLOW_ACTION_ESP)
354 return -EINVAL;
355
356 return action->device->modify_flow_action_esp(action,
357 &esp_attr.hdr,
358 attrs);
359 }
360
361 static const struct uverbs_attr_spec uverbs_flow_action_esp_keymat[] = {
362 [IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM] = {
363 .type = UVERBS_ATTR_TYPE_PTR_IN,
364 UVERBS_ATTR_STRUCT(
365 struct ib_uverbs_flow_action_esp_keymat_aes_gcm,
366 aes_key),
367 },
368 };
369
370 static const struct uverbs_attr_spec uverbs_flow_action_esp_replay[] = {
371 [IB_UVERBS_FLOW_ACTION_ESP_REPLAY_NONE] = {
372 .type = UVERBS_ATTR_TYPE_PTR_IN,
373 UVERBS_ATTR_NO_DATA(),
374 },
375 [IB_UVERBS_FLOW_ACTION_ESP_REPLAY_BMP] = {
376 .type = UVERBS_ATTR_TYPE_PTR_IN,
377 UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp_replay_bmp,
378 size),
379 },
380 };
381
382 DECLARE_UVERBS_NAMED_METHOD(
383 UVERBS_METHOD_FLOW_ACTION_ESP_CREATE,
384 UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_FLOW_ACTION_ESP_HANDLE,
385 UVERBS_OBJECT_FLOW_ACTION,
386 UVERBS_ACCESS_NEW,
387 UA_MANDATORY),
388 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS,
389 UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp,
390 hard_limit_pkts),
391 UA_MANDATORY),
392 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ESN,
393 UVERBS_ATTR_TYPE(__u32),
394 UA_OPTIONAL),
395 UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT,
396 uverbs_flow_action_esp_keymat,
397 UA_MANDATORY),
398 UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY,
399 uverbs_flow_action_esp_replay,
400 UA_OPTIONAL),
401 UVERBS_ATTR_PTR_IN(
402 UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP,
403 UVERBS_ATTR_TYPE(struct ib_uverbs_flow_action_esp_encap),
404 UA_OPTIONAL));
405
406 DECLARE_UVERBS_NAMED_METHOD(
407 UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY,
408 UVERBS_ATTR_IDR(UVERBS_ATTR_MODIFY_FLOW_ACTION_ESP_HANDLE,
409 UVERBS_OBJECT_FLOW_ACTION,
410 UVERBS_ACCESS_WRITE,
411 UA_MANDATORY),
412 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS,
413 UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp,
414 hard_limit_pkts),
415 UA_OPTIONAL),
416 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ESN,
417 UVERBS_ATTR_TYPE(__u32),
418 UA_OPTIONAL),
419 UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT,
420 uverbs_flow_action_esp_keymat,
421 UA_OPTIONAL),
422 UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY,
423 uverbs_flow_action_esp_replay,
424 UA_OPTIONAL),
425 UVERBS_ATTR_PTR_IN(
426 UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP,
427 UVERBS_ATTR_TYPE(struct ib_uverbs_flow_action_esp_encap),
428 UA_OPTIONAL));
429
430 DECLARE_UVERBS_NAMED_METHOD_DESTROY(
431 UVERBS_METHOD_FLOW_ACTION_DESTROY,
432 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_FLOW_ACTION_HANDLE,
433 UVERBS_OBJECT_FLOW_ACTION,
434 UVERBS_ACCESS_DESTROY,
435 UA_MANDATORY));
436
437 DECLARE_UVERBS_NAMED_OBJECT(
438 UVERBS_OBJECT_FLOW_ACTION,
439 UVERBS_TYPE_ALLOC_IDR(uverbs_free_flow_action),
440 &UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE),
441 &UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_DESTROY),
442 &UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY));
443
444 const struct uapi_definition uverbs_def_obj_flow_action[] = {
445 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
446 UVERBS_OBJECT_FLOW_ACTION,
447 UAPI_DEF_OBJ_NEEDS_FN(destroy_flow_action)),
448 {}
449 };
450