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 43 if (atomic_read(&action->usecnt)) 44 return -EBUSY; 45 46 return action->device->ops.destroy_flow_action(action); 47 } 48 49 static u64 esp_flags_uverbs_to_verbs(struct uverbs_attr_bundle *attrs, 50 u32 flags, bool is_modify) 51 { 52 u64 verbs_flags = flags; 53 54 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_ESN)) 55 verbs_flags |= IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED; 56 57 if (is_modify && uverbs_attr_is_valid(attrs, 58 UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS)) 59 verbs_flags |= IB_FLOW_ACTION_ESP_FLAGS_MOD_ESP_ATTRS; 60 61 return verbs_flags; 62 }; 63 64 static int validate_flow_action_esp_keymat_aes_gcm(struct ib_flow_action_attrs_esp_keymats *keymat) 65 { 66 struct ib_uverbs_flow_action_esp_keymat_aes_gcm *aes_gcm = 67 &keymat->keymat.aes_gcm; 68 69 if (aes_gcm->iv_algo > IB_UVERBS_FLOW_ACTION_IV_ALGO_SEQ) 70 return -EOPNOTSUPP; 71 72 if (aes_gcm->key_len != 32 && 73 aes_gcm->key_len != 24 && 74 aes_gcm->key_len != 16) 75 return -EINVAL; 76 77 if (aes_gcm->icv_len != 16 && 78 aes_gcm->icv_len != 8 && 79 aes_gcm->icv_len != 12) 80 return -EINVAL; 81 82 return 0; 83 } 84 85 static int (* const flow_action_esp_keymat_validate[])(struct ib_flow_action_attrs_esp_keymats *keymat) = { 86 [IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM] = validate_flow_action_esp_keymat_aes_gcm, 87 }; 88 89 static int flow_action_esp_replay_none(struct ib_flow_action_attrs_esp_replays *replay, 90 bool is_modify) 91 { 92 /* This is used in order to modify an esp flow action with an enabled 93 * replay protection to a disabled one. This is only supported via 94 * modify, as in create verb we can simply drop the REPLAY attribute and 95 * achieve the same thing. 96 */ 97 return is_modify ? 0 : -EINVAL; 98 } 99 100 static int flow_action_esp_replay_def_ok(struct ib_flow_action_attrs_esp_replays *replay, 101 bool is_modify) 102 { 103 /* Some replay protections could always be enabled without validating 104 * anything. 105 */ 106 return 0; 107 } 108 109 static int (* const flow_action_esp_replay_validate[])(struct ib_flow_action_attrs_esp_replays *replay, 110 bool is_modify) = { 111 [IB_UVERBS_FLOW_ACTION_ESP_REPLAY_NONE] = flow_action_esp_replay_none, 112 [IB_UVERBS_FLOW_ACTION_ESP_REPLAY_BMP] = flow_action_esp_replay_def_ok, 113 }; 114 115 static int parse_esp_ip(enum ib_flow_spec_type proto, 116 const void __user *val_ptr, 117 size_t len, union ib_flow_spec *out) 118 { 119 int ret; 120 const struct ib_uverbs_flow_ipv4_filter ipv4 = { 121 .src_ip = cpu_to_be32(0xffffffffUL), 122 .dst_ip = cpu_to_be32(0xffffffffUL), 123 .proto = 0xff, 124 .tos = 0xff, 125 .ttl = 0xff, 126 .flags = 0xff, 127 }; 128 const struct ib_uverbs_flow_ipv6_filter ipv6 = { 129 .src_ip = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 130 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 131 .dst_ip = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 132 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 133 .flow_label = cpu_to_be32(0xffffffffUL), 134 .next_hdr = 0xff, 135 .traffic_class = 0xff, 136 .hop_limit = 0xff, 137 }; 138 union { 139 struct ib_uverbs_flow_ipv4_filter ipv4; 140 struct ib_uverbs_flow_ipv6_filter ipv6; 141 } user_val = {}; 142 const void *user_pmask; 143 size_t val_len; 144 145 /* If the flow IPv4/IPv6 flow specifications are extended, the mask 146 * should be changed as well. 147 */ 148 BUILD_BUG_ON(offsetof(struct ib_uverbs_flow_ipv4_filter, flags) + 149 sizeof(ipv4.flags) != sizeof(ipv4)); 150 BUILD_BUG_ON(offsetof(struct ib_uverbs_flow_ipv6_filter, reserved) + 151 sizeof(ipv6.reserved) != sizeof(ipv6)); 152 153 switch (proto) { 154 case IB_FLOW_SPEC_IPV4: 155 if (len > sizeof(user_val.ipv4) && 156 !ib_is_buffer_cleared(val_ptr + sizeof(user_val.ipv4), 157 len - sizeof(user_val.ipv4))) 158 return -EOPNOTSUPP; 159 160 val_len = min_t(size_t, len, sizeof(user_val.ipv4)); 161 ret = copy_from_user(&user_val.ipv4, val_ptr, 162 val_len); 163 if (ret) 164 return -EFAULT; 165 166 user_pmask = &ipv4; 167 break; 168 case IB_FLOW_SPEC_IPV6: 169 if (len > sizeof(user_val.ipv6) && 170 !ib_is_buffer_cleared(val_ptr + sizeof(user_val.ipv6), 171 len - sizeof(user_val.ipv6))) 172 return -EOPNOTSUPP; 173 174 val_len = min_t(size_t, len, sizeof(user_val.ipv6)); 175 ret = copy_from_user(&user_val.ipv6, val_ptr, 176 val_len); 177 if (ret) 178 return -EFAULT; 179 180 user_pmask = &ipv6; 181 break; 182 default: 183 return -EOPNOTSUPP; 184 } 185 186 return ib_uverbs_kern_spec_to_ib_spec_filter(proto, user_pmask, 187 &user_val, 188 val_len, out); 189 } 190 191 static int flow_action_esp_get_encap(struct ib_flow_spec_list *out, 192 struct uverbs_attr_bundle *attrs) 193 { 194 struct ib_uverbs_flow_action_esp_encap uverbs_encap; 195 int ret; 196 197 ret = uverbs_copy_from(&uverbs_encap, attrs, 198 UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP); 199 if (ret) 200 return ret; 201 202 /* We currently support only one encap */ 203 if (uverbs_encap.next_ptr) 204 return -EOPNOTSUPP; 205 206 if (uverbs_encap.type != IB_FLOW_SPEC_IPV4 && 207 uverbs_encap.type != IB_FLOW_SPEC_IPV6) 208 return -EOPNOTSUPP; 209 210 return parse_esp_ip(uverbs_encap.type, 211 u64_to_user_ptr(uverbs_encap.val_ptr), 212 uverbs_encap.len, 213 &out->spec); 214 } 215 216 struct ib_flow_action_esp_attr { 217 struct ib_flow_action_attrs_esp hdr; 218 struct ib_flow_action_attrs_esp_keymats keymat; 219 struct ib_flow_action_attrs_esp_replays replay; 220 /* We currently support only one spec */ 221 struct ib_flow_spec_list encap; 222 }; 223 224 #define ESP_LAST_SUPPORTED_FLAG IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW 225 static int parse_flow_action_esp(struct ib_device *ib_dev, 226 struct uverbs_attr_bundle *attrs, 227 struct ib_flow_action_esp_attr *esp_attr, 228 bool is_modify) 229 { 230 struct ib_uverbs_flow_action_esp uverbs_esp = {}; 231 int ret; 232 233 /* Optional param, if it doesn't exist, we get -ENOENT and skip it */ 234 ret = uverbs_copy_from(&esp_attr->hdr.esn, attrs, 235 UVERBS_ATTR_FLOW_ACTION_ESP_ESN); 236 if (IS_UVERBS_COPY_ERR(ret)) 237 return ret; 238 239 /* This can be called from FLOW_ACTION_ESP_MODIFY where 240 * UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS is optional 241 */ 242 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS)) { 243 ret = uverbs_copy_from_or_zero(&uverbs_esp, attrs, 244 UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS); 245 if (ret) 246 return ret; 247 248 if (uverbs_esp.flags & ~((ESP_LAST_SUPPORTED_FLAG << 1) - 1)) 249 return -EOPNOTSUPP; 250 251 esp_attr->hdr.spi = uverbs_esp.spi; 252 esp_attr->hdr.seq = uverbs_esp.seq; 253 esp_attr->hdr.tfc_pad = uverbs_esp.tfc_pad; 254 esp_attr->hdr.hard_limit_pkts = uverbs_esp.hard_limit_pkts; 255 } 256 esp_attr->hdr.flags = esp_flags_uverbs_to_verbs(attrs, uverbs_esp.flags, 257 is_modify); 258 259 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT)) { 260 esp_attr->keymat.protocol = 261 uverbs_attr_get_enum_id(attrs, 262 UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT); 263 ret = uverbs_copy_from_or_zero(&esp_attr->keymat.keymat, 264 attrs, 265 UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT); 266 if (ret) 267 return ret; 268 269 ret = flow_action_esp_keymat_validate[esp_attr->keymat.protocol](&esp_attr->keymat); 270 if (ret) 271 return ret; 272 273 esp_attr->hdr.keymat = &esp_attr->keymat; 274 } 275 276 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY)) { 277 esp_attr->replay.protocol = 278 uverbs_attr_get_enum_id(attrs, 279 UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY); 280 281 ret = uverbs_copy_from_or_zero(&esp_attr->replay.replay, 282 attrs, 283 UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY); 284 if (ret) 285 return ret; 286 287 ret = flow_action_esp_replay_validate[esp_attr->replay.protocol](&esp_attr->replay, 288 is_modify); 289 if (ret) 290 return ret; 291 292 esp_attr->hdr.replay = &esp_attr->replay; 293 } 294 295 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP)) { 296 ret = flow_action_esp_get_encap(&esp_attr->encap, attrs); 297 if (ret) 298 return ret; 299 300 esp_attr->hdr.encap = &esp_attr->encap; 301 } 302 303 return 0; 304 } 305 306 static int UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE)( 307 struct uverbs_attr_bundle *attrs) 308 { 309 struct ib_uobject *uobj = uverbs_attr_get_uobject( 310 attrs, UVERBS_ATTR_CREATE_FLOW_ACTION_ESP_HANDLE); 311 struct ib_device *ib_dev = attrs->context->device; 312 int ret; 313 struct ib_flow_action *action; 314 struct ib_flow_action_esp_attr esp_attr = {}; 315 316 if (!ib_dev->ops.create_flow_action_esp) 317 return -EOPNOTSUPP; 318 319 ret = parse_flow_action_esp(ib_dev, attrs, &esp_attr, false); 320 if (ret) 321 return ret; 322 323 /* No need to check as this attribute is marked as MANDATORY */ 324 action = ib_dev->ops.create_flow_action_esp(ib_dev, &esp_attr.hdr, 325 attrs); 326 if (IS_ERR(action)) 327 return PTR_ERR(action); 328 329 uverbs_flow_action_fill_action(action, uobj, ib_dev, 330 IB_FLOW_ACTION_ESP); 331 332 return 0; 333 } 334 335 static int UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY)( 336 struct uverbs_attr_bundle *attrs) 337 { 338 struct ib_uobject *uobj = uverbs_attr_get_uobject( 339 attrs, UVERBS_ATTR_MODIFY_FLOW_ACTION_ESP_HANDLE); 340 struct ib_flow_action *action = uobj->object; 341 int ret; 342 struct ib_flow_action_esp_attr esp_attr = {}; 343 344 if (!action->device->ops.modify_flow_action_esp) 345 return -EOPNOTSUPP; 346 347 ret = parse_flow_action_esp(action->device, attrs, &esp_attr, true); 348 if (ret) 349 return ret; 350 351 if (action->type != IB_FLOW_ACTION_ESP) 352 return -EINVAL; 353 354 return action->device->ops.modify_flow_action_esp(action, 355 &esp_attr.hdr, 356 attrs); 357 } 358 359 static const struct uverbs_attr_spec uverbs_flow_action_esp_keymat[] = { 360 [IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM] = { 361 .type = UVERBS_ATTR_TYPE_PTR_IN, 362 UVERBS_ATTR_STRUCT( 363 struct ib_uverbs_flow_action_esp_keymat_aes_gcm, 364 aes_key), 365 }, 366 }; 367 368 static const struct uverbs_attr_spec uverbs_flow_action_esp_replay[] = { 369 [IB_UVERBS_FLOW_ACTION_ESP_REPLAY_NONE] = { 370 .type = UVERBS_ATTR_TYPE_PTR_IN, 371 UVERBS_ATTR_NO_DATA(), 372 }, 373 [IB_UVERBS_FLOW_ACTION_ESP_REPLAY_BMP] = { 374 .type = UVERBS_ATTR_TYPE_PTR_IN, 375 UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp_replay_bmp, 376 size), 377 }, 378 }; 379 380 DECLARE_UVERBS_NAMED_METHOD( 381 UVERBS_METHOD_FLOW_ACTION_ESP_CREATE, 382 UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_FLOW_ACTION_ESP_HANDLE, 383 UVERBS_OBJECT_FLOW_ACTION, 384 UVERBS_ACCESS_NEW, 385 UA_MANDATORY), 386 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS, 387 UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp, 388 hard_limit_pkts), 389 UA_MANDATORY), 390 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ESN, 391 UVERBS_ATTR_TYPE(__u32), 392 UA_OPTIONAL), 393 UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT, 394 uverbs_flow_action_esp_keymat, 395 UA_MANDATORY), 396 UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY, 397 uverbs_flow_action_esp_replay, 398 UA_OPTIONAL), 399 UVERBS_ATTR_PTR_IN( 400 UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP, 401 UVERBS_ATTR_TYPE(struct ib_uverbs_flow_action_esp_encap), 402 UA_OPTIONAL)); 403 404 DECLARE_UVERBS_NAMED_METHOD( 405 UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY, 406 UVERBS_ATTR_IDR(UVERBS_ATTR_MODIFY_FLOW_ACTION_ESP_HANDLE, 407 UVERBS_OBJECT_FLOW_ACTION, 408 UVERBS_ACCESS_WRITE, 409 UA_MANDATORY), 410 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS, 411 UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp, 412 hard_limit_pkts), 413 UA_OPTIONAL), 414 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ESN, 415 UVERBS_ATTR_TYPE(__u32), 416 UA_OPTIONAL), 417 UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT, 418 uverbs_flow_action_esp_keymat, 419 UA_OPTIONAL), 420 UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY, 421 uverbs_flow_action_esp_replay, 422 UA_OPTIONAL), 423 UVERBS_ATTR_PTR_IN( 424 UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP, 425 UVERBS_ATTR_TYPE(struct ib_uverbs_flow_action_esp_encap), 426 UA_OPTIONAL)); 427 428 DECLARE_UVERBS_NAMED_METHOD_DESTROY( 429 UVERBS_METHOD_FLOW_ACTION_DESTROY, 430 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_FLOW_ACTION_HANDLE, 431 UVERBS_OBJECT_FLOW_ACTION, 432 UVERBS_ACCESS_DESTROY, 433 UA_MANDATORY)); 434 435 DECLARE_UVERBS_NAMED_OBJECT( 436 UVERBS_OBJECT_FLOW_ACTION, 437 UVERBS_TYPE_ALLOC_IDR(uverbs_free_flow_action), 438 &UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE), 439 &UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_DESTROY), 440 &UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY)); 441 442 const struct uapi_definition uverbs_def_obj_flow_action[] = { 443 UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 444 UVERBS_OBJECT_FLOW_ACTION, 445 UAPI_DEF_OBJ_NEEDS_FN(destroy_flow_action)), 446 {} 447 }; 448