1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 /* 3 * Copyright (c) 2017, Mellanox Technologies inc. All rights reserved. 4 */ 5 #include <rdma/uverbs_ioctl.h> 6 #include <rdma/rdma_user_ioctl.h> 7 #include <linux/bitops.h> 8 #include "rdma_core.h" 9 #include "uverbs.h" 10 11 static void *uapi_add_elm(struct uverbs_api *uapi, u32 key, size_t alloc_size) 12 { 13 void *elm; 14 int rc; 15 16 if (key == UVERBS_API_KEY_ERR) 17 return ERR_PTR(-EOVERFLOW); 18 19 elm = kzalloc(alloc_size, GFP_KERNEL); 20 rc = radix_tree_insert(&uapi->radix, key, elm); 21 if (rc) { 22 kfree(elm); 23 return ERR_PTR(rc); 24 } 25 26 return elm; 27 } 28 29 static int uapi_merge_method(struct uverbs_api *uapi, 30 struct uverbs_api_object *obj_elm, u32 obj_key, 31 const struct uverbs_method_def *method, 32 bool is_driver) 33 { 34 u32 method_key = obj_key | uapi_key_ioctl_method(method->id); 35 struct uverbs_api_ioctl_method *method_elm; 36 unsigned int i; 37 38 if (!method->attrs) 39 return 0; 40 41 method_elm = uapi_add_elm(uapi, method_key, sizeof(*method_elm)); 42 if (IS_ERR(method_elm)) { 43 if (method_elm != ERR_PTR(-EEXIST)) 44 return PTR_ERR(method_elm); 45 46 /* 47 * This occurs when a driver uses ADD_UVERBS_ATTRIBUTES_SIMPLE 48 */ 49 if (WARN_ON(method->handler)) 50 return -EINVAL; 51 method_elm = radix_tree_lookup(&uapi->radix, method_key); 52 if (WARN_ON(!method_elm)) 53 return -EINVAL; 54 } else { 55 WARN_ON(!method->handler); 56 rcu_assign_pointer(method_elm->handler, method->handler); 57 if (method->handler != uverbs_destroy_def_handler) 58 method_elm->driver_method = is_driver; 59 } 60 61 for (i = 0; i != method->num_attrs; i++) { 62 const struct uverbs_attr_def *attr = (*method->attrs)[i]; 63 struct uverbs_api_attr *attr_slot; 64 65 if (!attr) 66 continue; 67 68 /* 69 * ENUM_IN contains the 'ids' pointer to the driver's .rodata, 70 * so if it is specified by a driver then it always makes this 71 * into a driver method. 72 */ 73 if (attr->attr.type == UVERBS_ATTR_TYPE_ENUM_IN) 74 method_elm->driver_method |= is_driver; 75 76 /* 77 * Like other uobject based things we only support a single 78 * uobject being NEW'd or DESTROY'd 79 */ 80 if (attr->attr.type == UVERBS_ATTR_TYPE_IDRS_ARRAY) { 81 u8 access = attr->attr.u2.objs_arr.access; 82 83 if (WARN_ON(access == UVERBS_ACCESS_NEW || 84 access == UVERBS_ACCESS_DESTROY)) 85 return -EINVAL; 86 } 87 88 attr_slot = 89 uapi_add_elm(uapi, method_key | uapi_key_attr(attr->id), 90 sizeof(*attr_slot)); 91 /* Attributes are not allowed to be modified by drivers */ 92 if (IS_ERR(attr_slot)) 93 return PTR_ERR(attr_slot); 94 95 attr_slot->spec = attr->attr; 96 } 97 98 return 0; 99 } 100 101 static int uapi_merge_tree(struct uverbs_api *uapi, 102 const struct uverbs_object_tree_def *tree, 103 bool is_driver) 104 { 105 unsigned int i, j; 106 int rc; 107 108 if (!tree->objects) 109 return 0; 110 111 for (i = 0; i != tree->num_objects; i++) { 112 const struct uverbs_object_def *obj = (*tree->objects)[i]; 113 struct uverbs_api_object *obj_elm; 114 u32 obj_key; 115 116 if (!obj) 117 continue; 118 119 obj_key = uapi_key_obj(obj->id); 120 obj_elm = uapi_add_elm(uapi, obj_key, sizeof(*obj_elm)); 121 if (IS_ERR(obj_elm)) { 122 if (obj_elm != ERR_PTR(-EEXIST)) 123 return PTR_ERR(obj_elm); 124 125 /* This occurs when a driver uses ADD_UVERBS_METHODS */ 126 if (WARN_ON(obj->type_attrs)) 127 return -EINVAL; 128 obj_elm = radix_tree_lookup(&uapi->radix, obj_key); 129 if (WARN_ON(!obj_elm)) 130 return -EINVAL; 131 } else { 132 obj_elm->type_attrs = obj->type_attrs; 133 if (obj->type_attrs) { 134 obj_elm->type_class = 135 obj->type_attrs->type_class; 136 /* 137 * Today drivers are only permitted to use 138 * idr_class types. They cannot use FD types 139 * because we currently have no way to revoke 140 * the fops pointer after device 141 * disassociation. 142 */ 143 if (WARN_ON(is_driver && 144 obj->type_attrs->type_class != 145 &uverbs_idr_class)) 146 return -EINVAL; 147 } 148 } 149 150 if (!obj->methods) 151 continue; 152 153 for (j = 0; j != obj->num_methods; j++) { 154 const struct uverbs_method_def *method = 155 (*obj->methods)[j]; 156 if (!method) 157 continue; 158 159 rc = uapi_merge_method(uapi, obj_elm, obj_key, method, 160 is_driver); 161 if (rc) 162 return rc; 163 } 164 } 165 166 return 0; 167 } 168 169 static int 170 uapi_finalize_ioctl_method(struct uverbs_api *uapi, 171 struct uverbs_api_ioctl_method *method_elm, 172 u32 method_key) 173 { 174 struct radix_tree_iter iter; 175 unsigned int num_attrs = 0; 176 unsigned int max_bkey = 0; 177 bool single_uobj = false; 178 void __rcu **slot; 179 180 method_elm->destroy_bkey = UVERBS_API_ATTR_BKEY_LEN; 181 radix_tree_for_each_slot (slot, &uapi->radix, &iter, 182 uapi_key_attrs_start(method_key)) { 183 struct uverbs_api_attr *elm = 184 rcu_dereference_protected(*slot, true); 185 u32 attr_key = iter.index & UVERBS_API_ATTR_KEY_MASK; 186 u32 attr_bkey = uapi_bkey_attr(attr_key); 187 u8 type = elm->spec.type; 188 189 if (uapi_key_attr_to_method(iter.index) != 190 uapi_key_attr_to_method(method_key)) 191 break; 192 193 if (elm->spec.mandatory) 194 __set_bit(attr_bkey, method_elm->attr_mandatory); 195 196 if (type == UVERBS_ATTR_TYPE_IDR || 197 type == UVERBS_ATTR_TYPE_FD) { 198 u8 access = elm->spec.u.obj.access; 199 200 /* 201 * Verbs specs may only have one NEW/DESTROY, we don't 202 * have the infrastructure to abort multiple NEW's or 203 * cope with multiple DESTROY failure. 204 */ 205 if (access == UVERBS_ACCESS_NEW || 206 access == UVERBS_ACCESS_DESTROY) { 207 if (WARN_ON(single_uobj)) 208 return -EINVAL; 209 210 single_uobj = true; 211 if (WARN_ON(!elm->spec.mandatory)) 212 return -EINVAL; 213 } 214 215 if (access == UVERBS_ACCESS_DESTROY) 216 method_elm->destroy_bkey = attr_bkey; 217 } 218 219 max_bkey = max(max_bkey, attr_bkey); 220 num_attrs++; 221 } 222 223 method_elm->key_bitmap_len = max_bkey + 1; 224 WARN_ON(method_elm->key_bitmap_len > UVERBS_API_ATTR_BKEY_LEN); 225 226 uapi_compute_bundle_size(method_elm, num_attrs); 227 return 0; 228 } 229 230 static int uapi_finalize(struct uverbs_api *uapi) 231 { 232 struct radix_tree_iter iter; 233 void __rcu **slot; 234 int rc; 235 236 radix_tree_for_each_slot (slot, &uapi->radix, &iter, 0) { 237 struct uverbs_api_ioctl_method *method_elm = 238 rcu_dereference_protected(*slot, true); 239 240 if (uapi_key_is_ioctl_method(iter.index)) { 241 rc = uapi_finalize_ioctl_method(uapi, method_elm, 242 iter.index); 243 if (rc) 244 return rc; 245 } 246 } 247 248 return 0; 249 } 250 251 void uverbs_destroy_api(struct uverbs_api *uapi) 252 { 253 struct radix_tree_iter iter; 254 void __rcu **slot; 255 256 if (!uapi) 257 return; 258 259 radix_tree_for_each_slot (slot, &uapi->radix, &iter, 0) { 260 kfree(rcu_dereference_protected(*slot, true)); 261 radix_tree_iter_delete(&uapi->radix, &iter, slot); 262 } 263 kfree(uapi); 264 } 265 266 struct uverbs_api *uverbs_alloc_api( 267 const struct uverbs_object_tree_def *const *driver_specs, 268 enum rdma_driver_id driver_id) 269 { 270 struct uverbs_api *uapi; 271 int rc; 272 273 uapi = kzalloc(sizeof(*uapi), GFP_KERNEL); 274 if (!uapi) 275 return ERR_PTR(-ENOMEM); 276 277 INIT_RADIX_TREE(&uapi->radix, GFP_KERNEL); 278 uapi->driver_id = driver_id; 279 280 rc = uapi_merge_tree(uapi, uverbs_default_get_objects(), false); 281 if (rc) 282 goto err; 283 284 for (; driver_specs && *driver_specs; driver_specs++) { 285 rc = uapi_merge_tree(uapi, *driver_specs, true); 286 if (rc) 287 goto err; 288 } 289 290 rc = uapi_finalize(uapi); 291 if (rc) 292 goto err; 293 294 return uapi; 295 err: 296 if (rc != -ENOMEM) 297 pr_err("Setup of uverbs_api failed, kernel parsing tree description is not valid (%d)??\n", 298 rc); 299 300 uverbs_destroy_api(uapi); 301 return ERR_PTR(rc); 302 } 303 304 /* 305 * The pre version is done before destroying the HW objects, it only blocks 306 * off method access. All methods that require the ib_dev or the module data 307 * must test one of these assignments prior to continuing. 308 */ 309 void uverbs_disassociate_api_pre(struct ib_uverbs_device *uverbs_dev) 310 { 311 struct uverbs_api *uapi = uverbs_dev->uapi; 312 struct radix_tree_iter iter; 313 void __rcu **slot; 314 315 rcu_assign_pointer(uverbs_dev->ib_dev, NULL); 316 317 radix_tree_for_each_slot (slot, &uapi->radix, &iter, 0) { 318 if (uapi_key_is_ioctl_method(iter.index)) { 319 struct uverbs_api_ioctl_method *method_elm = 320 rcu_dereference_protected(*slot, true); 321 322 if (method_elm->driver_method) 323 rcu_assign_pointer(method_elm->handler, NULL); 324 } 325 } 326 327 synchronize_srcu(&uverbs_dev->disassociate_srcu); 328 } 329 330 /* 331 * Called when a driver disassociates from the ib_uverbs_device. The 332 * assumption is that the driver module will unload after. Replace everything 333 * related to the driver with NULL as a safety measure. 334 */ 335 void uverbs_disassociate_api(struct uverbs_api *uapi) 336 { 337 struct radix_tree_iter iter; 338 void __rcu **slot; 339 340 radix_tree_for_each_slot (slot, &uapi->radix, &iter, 0) { 341 if (uapi_key_is_object(iter.index)) { 342 struct uverbs_api_object *object_elm = 343 rcu_dereference_protected(*slot, true); 344 345 /* 346 * Some type_attrs are in the driver module. We don't 347 * bother to keep track of which since there should be 348 * no use of this after disassociate. 349 */ 350 object_elm->type_attrs = NULL; 351 } else if (uapi_key_is_attr(iter.index)) { 352 struct uverbs_api_attr *elm = 353 rcu_dereference_protected(*slot, true); 354 355 if (elm->spec.type == UVERBS_ATTR_TYPE_ENUM_IN) 356 elm->spec.u2.enum_def.ids = NULL; 357 } 358 } 359 } 360