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 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->ops.destroy_flow_action(action); 49 } 50 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 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 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 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 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(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(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 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 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 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->ops.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->ops.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 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->ops.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->ops.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