Loading...
Note: File does not exist in v3.1.
1/*
2 * Copyright (c) 2017, 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#ifndef _UVERBS_IOCTL_
34#define _UVERBS_IOCTL_
35
36#include <rdma/uverbs_types.h>
37#include <linux/uaccess.h>
38#include <rdma/rdma_user_ioctl.h>
39#include <rdma/ib_user_ioctl_verbs.h>
40#include <rdma/ib_user_ioctl_cmds.h>
41
42/*
43 * =======================================
44 * Verbs action specifications
45 * =======================================
46 */
47
48enum uverbs_attr_type {
49 UVERBS_ATTR_TYPE_NA,
50 UVERBS_ATTR_TYPE_PTR_IN,
51 UVERBS_ATTR_TYPE_PTR_OUT,
52 UVERBS_ATTR_TYPE_IDR,
53 UVERBS_ATTR_TYPE_FD,
54 UVERBS_ATTR_TYPE_ENUM_IN,
55};
56
57enum uverbs_obj_access {
58 UVERBS_ACCESS_READ,
59 UVERBS_ACCESS_WRITE,
60 UVERBS_ACCESS_NEW,
61 UVERBS_ACCESS_DESTROY
62};
63
64enum {
65 UVERBS_ATTR_SPEC_F_MANDATORY = 1U << 0,
66 /* Support extending attributes by length, validate all unknown size == zero */
67 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO = 1U << 1,
68};
69
70/* Specification of a single attribute inside the ioctl message */
71struct uverbs_attr_spec {
72 union {
73 /* Header shared by all following union members - to reduce space. */
74 struct {
75 enum uverbs_attr_type type;
76 /* Combination of bits from enum UVERBS_ATTR_SPEC_F_XXXX */
77 u8 flags;
78 };
79 struct {
80 enum uverbs_attr_type type;
81 /* Combination of bits from enum UVERBS_ATTR_SPEC_F_XXXX */
82 u8 flags;
83 /* Current known size to kernel */
84 u16 len;
85 /* User isn't allowed to provide something < min_len */
86 u16 min_len;
87 } ptr;
88 struct {
89 enum uverbs_attr_type type;
90 /* Combination of bits from enum UVERBS_ATTR_SPEC_F_XXXX */
91 u8 flags;
92 /*
93 * higher bits mean the namespace and lower bits mean
94 * the type id within the namespace.
95 */
96 u16 obj_type;
97 u8 access;
98 } obj;
99 struct {
100 enum uverbs_attr_type type;
101 /* Combination of bits from enum UVERBS_ATTR_SPEC_F_XXXX */
102 u8 flags;
103 u8 num_elems;
104 /*
105 * The enum attribute can select one of the attributes
106 * contained in the ids array. Currently only PTR_IN
107 * attributes are supported in the ids array.
108 */
109 const struct uverbs_attr_spec *ids;
110 } enum_def;
111 };
112};
113
114struct uverbs_attr_spec_hash {
115 size_t num_attrs;
116 unsigned long *mandatory_attrs_bitmask;
117 struct uverbs_attr_spec attrs[0];
118};
119
120struct uverbs_attr_bundle;
121struct ib_uverbs_file;
122
123enum {
124 /*
125 * Action marked with this flag creates a context (or root for all
126 * objects).
127 */
128 UVERBS_ACTION_FLAG_CREATE_ROOT = 1U << 0,
129};
130
131struct uverbs_method_spec {
132 /* Combination of bits from enum UVERBS_ACTION_FLAG_XXXX */
133 u32 flags;
134 size_t num_buckets;
135 size_t num_child_attrs;
136 int (*handler)(struct ib_device *ib_dev, struct ib_uverbs_file *ufile,
137 struct uverbs_attr_bundle *ctx);
138 struct uverbs_attr_spec_hash *attr_buckets[0];
139};
140
141struct uverbs_method_spec_hash {
142 size_t num_methods;
143 struct uverbs_method_spec *methods[0];
144};
145
146struct uverbs_object_spec {
147 const struct uverbs_obj_type *type_attrs;
148 size_t num_buckets;
149 struct uverbs_method_spec_hash *method_buckets[0];
150};
151
152struct uverbs_object_spec_hash {
153 size_t num_objects;
154 struct uverbs_object_spec *objects[0];
155};
156
157struct uverbs_root_spec {
158 size_t num_buckets;
159 struct uverbs_object_spec_hash *object_buckets[0];
160};
161
162/*
163 * =======================================
164 * Verbs definitions
165 * =======================================
166 */
167
168struct uverbs_attr_def {
169 u16 id;
170 struct uverbs_attr_spec attr;
171};
172
173struct uverbs_method_def {
174 u16 id;
175 /* Combination of bits from enum UVERBS_ACTION_FLAG_XXXX */
176 u32 flags;
177 size_t num_attrs;
178 const struct uverbs_attr_def * const (*attrs)[];
179 int (*handler)(struct ib_device *ib_dev, struct ib_uverbs_file *ufile,
180 struct uverbs_attr_bundle *ctx);
181};
182
183struct uverbs_object_def {
184 u16 id;
185 const struct uverbs_obj_type *type_attrs;
186 size_t num_methods;
187 const struct uverbs_method_def * const (*methods)[];
188};
189
190struct uverbs_object_tree_def {
191 size_t num_objects;
192 const struct uverbs_object_def * const (*objects)[];
193};
194
195#define UA_FLAGS(_flags) .flags = _flags
196#define __UVERBS_ATTR0(_id, _type, _fld, _attr, ...) \
197 ((const struct uverbs_attr_def) \
198 {.id = _id, .attr = {{._fld = {.type = _type, _attr, .flags = 0, } }, } })
199#define __UVERBS_ATTR1(_id, _type, _fld, _attr, _extra1, ...) \
200 ((const struct uverbs_attr_def) \
201 {.id = _id, .attr = {{._fld = {.type = _type, _attr, _extra1 } },} })
202#define __UVERBS_ATTR2(_id, _type, _fld, _attr, _extra1, _extra2) \
203 ((const struct uverbs_attr_def) \
204 {.id = _id, .attr = {{._fld = {.type = _type, _attr, _extra1, _extra2 } },} })
205#define __UVERBS_ATTR(_id, _type, _fld, _attr, _extra1, _extra2, _n, ...) \
206 __UVERBS_ATTR##_n(_id, _type, _fld, _attr, _extra1, _extra2)
207
208#define UVERBS_ATTR_TYPE(_type) \
209 .min_len = sizeof(_type), .len = sizeof(_type)
210#define UVERBS_ATTR_STRUCT(_type, _last) \
211 .min_len = ((uintptr_t)(&((_type *)0)->_last + 1)), .len = sizeof(_type)
212#define UVERBS_ATTR_SIZE(_min_len, _len) \
213 .min_len = _min_len, .len = _len
214
215/*
216 * In new compiler, UVERBS_ATTR could be simplified by declaring it as
217 * [_id] = {.type = _type, .len = _len, ##__VA_ARGS__}
218 * But since we support older compilers too, we need the more complex code.
219 */
220#define UVERBS_ATTR(_id, _type, _fld, _attr, ...) \
221 __UVERBS_ATTR(_id, _type, _fld, _attr, ##__VA_ARGS__, 2, 1, 0)
222#define UVERBS_ATTR_PTR_IN_SZ(_id, _len, ...) \
223 UVERBS_ATTR(_id, UVERBS_ATTR_TYPE_PTR_IN, ptr, _len, ##__VA_ARGS__)
224/* If sizeof(_type) <= sizeof(u64), this will be inlined rather than a pointer */
225#define UVERBS_ATTR_PTR_IN(_id, _type, ...) \
226 UVERBS_ATTR_PTR_IN_SZ(_id, _type, ##__VA_ARGS__)
227#define UVERBS_ATTR_PTR_OUT_SZ(_id, _len, ...) \
228 UVERBS_ATTR(_id, UVERBS_ATTR_TYPE_PTR_OUT, ptr, _len, ##__VA_ARGS__)
229#define UVERBS_ATTR_PTR_OUT(_id, _type, ...) \
230 UVERBS_ATTR_PTR_OUT_SZ(_id, _type, ##__VA_ARGS__)
231#define UVERBS_ATTR_ENUM_IN(_id, _enum_arr, ...) \
232 UVERBS_ATTR(_id, UVERBS_ATTR_TYPE_ENUM_IN, enum_def, \
233 .ids = (_enum_arr), \
234 .num_elems = ARRAY_SIZE(_enum_arr), ##__VA_ARGS__)
235
236/*
237 * In new compiler, UVERBS_ATTR_IDR (and FD) could be simplified by declaring
238 * it as
239 * {.id = _id, \
240 * .attr {.type = __obj_class, \
241 * .obj = {.obj_type = _idr_type, \
242 * .access = _access \
243 * }, ##__VA_ARGS__ } }
244 * But since we support older compilers too, we need the more complex code.
245 */
246#define ___UVERBS_ATTR_OBJ0(_id, _obj_class, _obj_type, _access, ...)\
247 ((const struct uverbs_attr_def) \
248 {.id = _id, \
249 .attr = { {.obj = {.type = _obj_class, .obj_type = _obj_type, \
250 .access = _access, .flags = 0 } }, } })
251#define ___UVERBS_ATTR_OBJ1(_id, _obj_class, _obj_type, _access, _flags)\
252 ((const struct uverbs_attr_def) \
253 {.id = _id, \
254 .attr = { {.obj = {.type = _obj_class, .obj_type = _obj_type, \
255 .access = _access, _flags} }, } })
256#define ___UVERBS_ATTR_OBJ(_id, _obj_class, _obj_type, _access, _flags, \
257 _n, ...) \
258 ___UVERBS_ATTR_OBJ##_n(_id, _obj_class, _obj_type, _access, _flags)
259#define __UVERBS_ATTR_OBJ(_id, _obj_class, _obj_type, _access, ...) \
260 ___UVERBS_ATTR_OBJ(_id, _obj_class, _obj_type, _access, \
261 ##__VA_ARGS__, 1, 0)
262#define UVERBS_ATTR_IDR(_id, _idr_type, _access, ...) \
263 __UVERBS_ATTR_OBJ(_id, UVERBS_ATTR_TYPE_IDR, _idr_type, _access,\
264 ##__VA_ARGS__)
265#define UVERBS_ATTR_FD(_id, _fd_type, _access, ...) \
266 __UVERBS_ATTR_OBJ(_id, UVERBS_ATTR_TYPE_FD, _fd_type, \
267 (_access) + BUILD_BUG_ON_ZERO( \
268 (_access) != UVERBS_ACCESS_NEW && \
269 (_access) != UVERBS_ACCESS_READ), \
270 ##__VA_ARGS__)
271#define DECLARE_UVERBS_ATTR_SPEC(_name, ...) \
272 const struct uverbs_attr_def _name = __VA_ARGS__
273
274#define DECLARE_UVERBS_ENUM(_name, ...) \
275 const struct uverbs_enum_spec _name = { \
276 .len = ARRAY_SIZE(((struct uverbs_attr_spec[]){__VA_ARGS__})),\
277 .ids = {__VA_ARGS__}, \
278 }
279#define _UVERBS_METHOD_ATTRS_SZ(...) \
280 (sizeof((const struct uverbs_attr_def * const []){__VA_ARGS__}) /\
281 sizeof(const struct uverbs_attr_def *))
282#define _UVERBS_METHOD(_id, _handler, _flags, ...) \
283 ((const struct uverbs_method_def) { \
284 .id = _id, \
285 .flags = _flags, \
286 .handler = _handler, \
287 .num_attrs = _UVERBS_METHOD_ATTRS_SZ(__VA_ARGS__), \
288 .attrs = &(const struct uverbs_attr_def * const []){__VA_ARGS__} })
289#define DECLARE_UVERBS_METHOD(_name, _id, _handler, ...) \
290 const struct uverbs_method_def _name = \
291 _UVERBS_METHOD(_id, _handler, 0, ##__VA_ARGS__)
292#define DECLARE_UVERBS_CTX_METHOD(_name, _id, _handler, _flags, ...) \
293 const struct uverbs_method_def _name = \
294 _UVERBS_METHOD(_id, _handler, \
295 UVERBS_ACTION_FLAG_CREATE_ROOT, \
296 ##__VA_ARGS__)
297#define _UVERBS_OBJECT_METHODS_SZ(...) \
298 (sizeof((const struct uverbs_method_def * const []){__VA_ARGS__}) / \
299 sizeof(const struct uverbs_method_def *))
300#define _UVERBS_OBJECT(_id, _type_attrs, ...) \
301 ((const struct uverbs_object_def) { \
302 .id = _id, \
303 .type_attrs = _type_attrs, \
304 .num_methods = _UVERBS_OBJECT_METHODS_SZ(__VA_ARGS__), \
305 .methods = &(const struct uverbs_method_def * const []){__VA_ARGS__} })
306#define DECLARE_UVERBS_OBJECT(_name, _id, _type_attrs, ...) \
307 const struct uverbs_object_def _name = \
308 _UVERBS_OBJECT(_id, _type_attrs, ##__VA_ARGS__)
309#define _UVERBS_TREE_OBJECTS_SZ(...) \
310 (sizeof((const struct uverbs_object_def * const []){__VA_ARGS__}) / \
311 sizeof(const struct uverbs_object_def *))
312#define _UVERBS_OBJECT_TREE(...) \
313 ((const struct uverbs_object_tree_def) { \
314 .num_objects = _UVERBS_TREE_OBJECTS_SZ(__VA_ARGS__), \
315 .objects = &(const struct uverbs_object_def * const []){__VA_ARGS__} })
316#define DECLARE_UVERBS_OBJECT_TREE(_name, ...) \
317 const struct uverbs_object_tree_def _name = \
318 _UVERBS_OBJECT_TREE(__VA_ARGS__)
319
320/* =================================================
321 * Parsing infrastructure
322 * =================================================
323 */
324
325struct uverbs_ptr_attr {
326 u64 data;
327 u16 len;
328 /* Combination of bits from enum UVERBS_ATTR_F_XXXX */
329 u16 flags;
330 u8 enum_id;
331};
332
333struct uverbs_obj_attr {
334 /* pointer to the kernel descriptor -> type, access, etc */
335 const struct uverbs_obj_type *type;
336 struct ib_uobject *uobject;
337 /* fd or id in idr of this object */
338 int id;
339};
340
341struct uverbs_attr {
342 /*
343 * pointer to the user-space given attribute, in order to write the
344 * new uobject's id or update flags.
345 */
346 struct ib_uverbs_attr __user *uattr;
347 union {
348 struct uverbs_ptr_attr ptr_attr;
349 struct uverbs_obj_attr obj_attr;
350 };
351};
352
353struct uverbs_attr_bundle_hash {
354 /* if bit i is set, it means attrs[i] contains valid information */
355 unsigned long *valid_bitmap;
356 size_t num_attrs;
357 /*
358 * arrays of attributes, each element corresponds to the specification
359 * of the attribute in the same index.
360 */
361 struct uverbs_attr *attrs;
362};
363
364struct uverbs_attr_bundle {
365 size_t num_buckets;
366 struct uverbs_attr_bundle_hash hash[];
367};
368
369static inline bool uverbs_attr_is_valid_in_hash(const struct uverbs_attr_bundle_hash *attrs_hash,
370 unsigned int idx)
371{
372 return test_bit(idx, attrs_hash->valid_bitmap);
373}
374
375static inline bool uverbs_attr_is_valid(const struct uverbs_attr_bundle *attrs_bundle,
376 unsigned int idx)
377{
378 u16 idx_bucket = idx >> UVERBS_ID_NS_SHIFT;
379
380 if (attrs_bundle->num_buckets <= idx_bucket)
381 return false;
382
383 return uverbs_attr_is_valid_in_hash(&attrs_bundle->hash[idx_bucket],
384 idx & ~UVERBS_ID_NS_MASK);
385}
386
387#define IS_UVERBS_COPY_ERR(_ret) ((_ret) && (_ret) != -ENOENT)
388
389static inline const struct uverbs_attr *uverbs_attr_get(const struct uverbs_attr_bundle *attrs_bundle,
390 u16 idx)
391{
392 u16 idx_bucket = idx >> UVERBS_ID_NS_SHIFT;
393
394 if (!uverbs_attr_is_valid(attrs_bundle, idx))
395 return ERR_PTR(-ENOENT);
396
397 return &attrs_bundle->hash[idx_bucket].attrs[idx & ~UVERBS_ID_NS_MASK];
398}
399
400static inline int uverbs_attr_get_enum_id(const struct uverbs_attr_bundle *attrs_bundle,
401 u16 idx)
402{
403 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
404
405 if (IS_ERR(attr))
406 return PTR_ERR(attr);
407
408 return attr->ptr_attr.enum_id;
409}
410
411static inline void *uverbs_attr_get_obj(const struct uverbs_attr_bundle *attrs_bundle,
412 u16 idx)
413{
414 const struct uverbs_attr *attr;
415
416 attr = uverbs_attr_get(attrs_bundle, idx);
417 if (IS_ERR(attr))
418 return ERR_CAST(attr);
419
420 return attr->obj_attr.uobject->object;
421}
422
423static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle,
424 size_t idx, const void *from, size_t size)
425{
426 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
427 u16 flags;
428 size_t min_size;
429
430 if (IS_ERR(attr))
431 return PTR_ERR(attr);
432
433 min_size = min_t(size_t, attr->ptr_attr.len, size);
434 if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size))
435 return -EFAULT;
436
437 flags = attr->ptr_attr.flags | UVERBS_ATTR_F_VALID_OUTPUT;
438 if (put_user(flags, &attr->uattr->flags))
439 return -EFAULT;
440
441 return 0;
442}
443
444static inline bool uverbs_attr_ptr_is_inline(const struct uverbs_attr *attr)
445{
446 return attr->ptr_attr.len <= sizeof(attr->ptr_attr.data);
447}
448
449static inline int _uverbs_copy_from(void *to,
450 const struct uverbs_attr_bundle *attrs_bundle,
451 size_t idx,
452 size_t size)
453{
454 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
455
456 if (IS_ERR(attr))
457 return PTR_ERR(attr);
458
459 /*
460 * Validation ensures attr->ptr_attr.len >= size. If the caller is
461 * using UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO then it must call
462 * uverbs_copy_from_or_zero.
463 */
464 if (unlikely(size < attr->ptr_attr.len))
465 return -EINVAL;
466
467 if (uverbs_attr_ptr_is_inline(attr))
468 memcpy(to, &attr->ptr_attr.data, attr->ptr_attr.len);
469 else if (copy_from_user(to, u64_to_user_ptr(attr->ptr_attr.data),
470 attr->ptr_attr.len))
471 return -EFAULT;
472
473 return 0;
474}
475
476static inline int _uverbs_copy_from_or_zero(void *to,
477 const struct uverbs_attr_bundle *attrs_bundle,
478 size_t idx,
479 size_t size)
480{
481 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
482 size_t min_size;
483
484 if (IS_ERR(attr))
485 return PTR_ERR(attr);
486
487 min_size = min_t(size_t, size, attr->ptr_attr.len);
488
489 if (uverbs_attr_ptr_is_inline(attr))
490 memcpy(to, &attr->ptr_attr.data, min_size);
491 else if (copy_from_user(to, u64_to_user_ptr(attr->ptr_attr.data),
492 min_size))
493 return -EFAULT;
494
495 if (size > min_size)
496 memset(to + min_size, 0, size - min_size);
497
498 return 0;
499}
500
501#define uverbs_copy_from(to, attrs_bundle, idx) \
502 _uverbs_copy_from(to, attrs_bundle, idx, sizeof(*to))
503
504#define uverbs_copy_from_or_zero(to, attrs_bundle, idx) \
505 _uverbs_copy_from_or_zero(to, attrs_bundle, idx, sizeof(*to))
506
507/* =================================================
508 * Definitions -> Specs infrastructure
509 * =================================================
510 */
511
512/*
513 * uverbs_alloc_spec_tree - Merges different common and driver specific feature
514 * into one parsing tree that every uverbs command will be parsed upon.
515 *
516 * @num_trees: Number of trees in the array @trees.
517 * @trees: Array of pointers to tree root definitions to merge. Each such tree
518 * possibly contains objects, methods and attributes definitions.
519 *
520 * Returns:
521 * uverbs_root_spec *: The root of the merged parsing tree.
522 * On error, we return an error code. Error is checked via IS_ERR.
523 *
524 * The following merges could take place:
525 * a. Two trees representing the same method with different handler
526 * -> We take the handler of the tree that its handler != NULL
527 * and its index in the trees array is greater. The incentive for that
528 * is that developers are expected to first merge common trees and then
529 * merge trees that gives specialized the behaviour.
530 * b. Two trees representing the same object with different
531 * type_attrs (struct uverbs_obj_type):
532 * -> We take the type_attrs of the tree that its type_attr != NULL
533 * and its index in the trees array is greater. This could be used
534 * in order to override the free function, allocation size, etc.
535 * c. Two trees representing the same method attribute (same id but possibly
536 * different attributes):
537 * -> ERROR (-ENOENT), we believe that's not the programmer's intent.
538 *
539 * An object without any methods is considered invalid and will abort the
540 * function with -ENOENT error.
541 */
542#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
543struct uverbs_root_spec *uverbs_alloc_spec_tree(unsigned int num_trees,
544 const struct uverbs_object_tree_def **trees);
545void uverbs_free_spec_tree(struct uverbs_root_spec *root);
546#else
547static inline struct uverbs_root_spec *uverbs_alloc_spec_tree(unsigned int num_trees,
548 const struct uverbs_object_tree_def **trees)
549{
550 return NULL;
551}
552
553static inline void uverbs_free_spec_tree(struct uverbs_root_spec *root)
554{
555}
556#endif
557
558#endif