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 attr_slot = 77 uapi_add_elm(uapi, method_key | uapi_key_attr(attr->id), 78 sizeof(*attr_slot)); 79 /* Attributes are not allowed to be modified by drivers */ 80 if (IS_ERR(attr_slot)) 81 return PTR_ERR(attr_slot); 82 83 attr_slot->spec = attr->attr; 84 } 85 86 return 0; 87 } 88 89 static int uapi_merge_tree(struct uverbs_api *uapi, 90 const struct uverbs_object_tree_def *tree, 91 bool is_driver) 92 { 93 unsigned int i, j; 94 int rc; 95 96 if (!tree->objects) 97 return 0; 98 99 for (i = 0; i != tree->num_objects; i++) { 100 const struct uverbs_object_def *obj = (*tree->objects)[i]; 101 struct uverbs_api_object *obj_elm; 102 u32 obj_key; 103 104 if (!obj) 105 continue; 106 107 obj_key = uapi_key_obj(obj->id); 108 obj_elm = uapi_add_elm(uapi, obj_key, sizeof(*obj_elm)); 109 if (IS_ERR(obj_elm)) { 110 if (obj_elm != ERR_PTR(-EEXIST)) 111 return PTR_ERR(obj_elm); 112 113 /* This occurs when a driver uses ADD_UVERBS_METHODS */ 114 if (WARN_ON(obj->type_attrs)) 115 return -EINVAL; 116 obj_elm = radix_tree_lookup(&uapi->radix, obj_key); 117 if (WARN_ON(!obj_elm)) 118 return -EINVAL; 119 } else { 120 obj_elm->type_attrs = obj->type_attrs; 121 if (obj->type_attrs) { 122 obj_elm->type_class = 123 obj->type_attrs->type_class; 124 /* 125 * Today drivers are only permitted to use 126 * idr_class types. They cannot use FD types 127 * because we currently have no way to revoke 128 * the fops pointer after device 129 * disassociation. 130 */ 131 if (WARN_ON(is_driver && 132 obj->type_attrs->type_class != 133 &uverbs_idr_class)) 134 return -EINVAL; 135 } 136 } 137 138 if (!obj->methods) 139 continue; 140 141 for (j = 0; j != obj->num_methods; j++) { 142 const struct uverbs_method_def *method = 143 (*obj->methods)[j]; 144 if (!method) 145 continue; 146 147 rc = uapi_merge_method(uapi, obj_elm, obj_key, method, 148 is_driver); 149 if (rc) 150 return rc; 151 } 152 } 153 154 return 0; 155 } 156 157 static int 158 uapi_finalize_ioctl_method(struct uverbs_api *uapi, 159 struct uverbs_api_ioctl_method *method_elm, 160 u32 method_key) 161 { 162 struct radix_tree_iter iter; 163 unsigned int num_attrs = 0; 164 unsigned int max_bkey = 0; 165 bool single_uobj = false; 166 void __rcu **slot; 167 168 method_elm->destroy_bkey = UVERBS_API_ATTR_BKEY_LEN; 169 radix_tree_for_each_slot (slot, &uapi->radix, &iter, 170 uapi_key_attrs_start(method_key)) { 171 struct uverbs_api_attr *elm = 172 rcu_dereference_protected(*slot, true); 173 u32 attr_key = iter.index & UVERBS_API_ATTR_KEY_MASK; 174 u32 attr_bkey = uapi_bkey_attr(attr_key); 175 u8 type = elm->spec.type; 176 177 if (uapi_key_attr_to_method(iter.index) != 178 uapi_key_attr_to_method(method_key)) 179 break; 180 181 if (elm->spec.mandatory) 182 __set_bit(attr_bkey, method_elm->attr_mandatory); 183 184 if (type == UVERBS_ATTR_TYPE_IDR || 185 type == UVERBS_ATTR_TYPE_FD) { 186 u8 access = elm->spec.u.obj.access; 187 188 /* 189 * Verbs specs may only have one NEW/DESTROY, we don't 190 * have the infrastructure to abort multiple NEW's or 191 * cope with multiple DESTROY failure. 192 */ 193 if (access == UVERBS_ACCESS_NEW || 194 access == UVERBS_ACCESS_DESTROY) { 195 if (WARN_ON(single_uobj)) 196 return -EINVAL; 197 198 single_uobj = true; 199 if (WARN_ON(!elm->spec.mandatory)) 200 return -EINVAL; 201 } 202 203 if (access == UVERBS_ACCESS_DESTROY) 204 method_elm->destroy_bkey = attr_bkey; 205 } 206 207 max_bkey = max(max_bkey, attr_bkey); 208 num_attrs++; 209 } 210 211 method_elm->key_bitmap_len = max_bkey + 1; 212 WARN_ON(method_elm->key_bitmap_len > UVERBS_API_ATTR_BKEY_LEN); 213 214 uapi_compute_bundle_size(method_elm, num_attrs); 215 return 0; 216 } 217 218 static int uapi_finalize(struct uverbs_api *uapi) 219 { 220 struct radix_tree_iter iter; 221 void __rcu **slot; 222 int rc; 223 224 radix_tree_for_each_slot (slot, &uapi->radix, &iter, 0) { 225 struct uverbs_api_ioctl_method *method_elm = 226 rcu_dereference_protected(*slot, true); 227 228 if (uapi_key_is_ioctl_method(iter.index)) { 229 rc = uapi_finalize_ioctl_method(uapi, method_elm, 230 iter.index); 231 if (rc) 232 return rc; 233 } 234 } 235 236 return 0; 237 } 238 239 void uverbs_destroy_api(struct uverbs_api *uapi) 240 { 241 struct radix_tree_iter iter; 242 void __rcu **slot; 243 244 if (!uapi) 245 return; 246 247 radix_tree_for_each_slot (slot, &uapi->radix, &iter, 0) { 248 kfree(rcu_dereference_protected(*slot, true)); 249 radix_tree_iter_delete(&uapi->radix, &iter, slot); 250 } 251 } 252 253 struct uverbs_api *uverbs_alloc_api( 254 const struct uverbs_object_tree_def *const *driver_specs, 255 enum rdma_driver_id driver_id) 256 { 257 struct uverbs_api *uapi; 258 int rc; 259 260 uapi = kzalloc(sizeof(*uapi), GFP_KERNEL); 261 if (!uapi) 262 return ERR_PTR(-ENOMEM); 263 264 INIT_RADIX_TREE(&uapi->radix, GFP_KERNEL); 265 uapi->driver_id = driver_id; 266 267 rc = uapi_merge_tree(uapi, uverbs_default_get_objects(), false); 268 if (rc) 269 goto err; 270 271 for (; driver_specs && *driver_specs; driver_specs++) { 272 rc = uapi_merge_tree(uapi, *driver_specs, true); 273 if (rc) 274 goto err; 275 } 276 277 rc = uapi_finalize(uapi); 278 if (rc) 279 goto err; 280 281 return uapi; 282 err: 283 if (rc != -ENOMEM) 284 pr_err("Setup of uverbs_api failed, kernel parsing tree description is not valid (%d)??\n", 285 rc); 286 287 uverbs_destroy_api(uapi); 288 return ERR_PTR(rc); 289 } 290 291 /* 292 * The pre version is done before destroying the HW objects, it only blocks 293 * off method access. All methods that require the ib_dev or the module data 294 * must test one of these assignments prior to continuing. 295 */ 296 void uverbs_disassociate_api_pre(struct ib_uverbs_device *uverbs_dev) 297 { 298 struct uverbs_api *uapi = uverbs_dev->uapi; 299 struct radix_tree_iter iter; 300 void __rcu **slot; 301 302 rcu_assign_pointer(uverbs_dev->ib_dev, NULL); 303 304 radix_tree_for_each_slot (slot, &uapi->radix, &iter, 0) { 305 if (uapi_key_is_ioctl_method(iter.index)) { 306 struct uverbs_api_ioctl_method *method_elm = 307 rcu_dereference_protected(*slot, true); 308 309 if (method_elm->driver_method) 310 rcu_assign_pointer(method_elm->handler, NULL); 311 } 312 } 313 314 synchronize_srcu(&uverbs_dev->disassociate_srcu); 315 } 316 317 /* 318 * Called when a driver disassociates from the ib_uverbs_device. The 319 * assumption is that the driver module will unload after. Replace everything 320 * related to the driver with NULL as a safety measure. 321 */ 322 void uverbs_disassociate_api(struct uverbs_api *uapi) 323 { 324 struct radix_tree_iter iter; 325 void __rcu **slot; 326 327 radix_tree_for_each_slot (slot, &uapi->radix, &iter, 0) { 328 if (uapi_key_is_object(iter.index)) { 329 struct uverbs_api_object *object_elm = 330 rcu_dereference_protected(*slot, true); 331 332 /* 333 * Some type_attrs are in the driver module. We don't 334 * bother to keep track of which since there should be 335 * no use of this after disassociate. 336 */ 337 object_elm->type_attrs = NULL; 338 } else if (uapi_key_is_attr(iter.index)) { 339 struct uverbs_api_attr *elm = 340 rcu_dereference_protected(*slot, true); 341 342 if (elm->spec.type == UVERBS_ATTR_TYPE_ENUM_IN) 343 elm->spec.u2.enum_def.ids = NULL; 344 } 345 } 346 } 347