1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
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
67 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO = 1U << 1,
68};
69
70
71struct uverbs_attr_spec {
72 union {
73
74 struct {
75 enum uverbs_attr_type type;
76
77 u8 flags;
78 };
79 struct {
80 enum uverbs_attr_type type;
81
82 u8 flags;
83
84 u16 len;
85
86 u16 min_len;
87 } ptr;
88 struct {
89 enum uverbs_attr_type type;
90
91 u8 flags;
92
93
94
95
96 u16 obj_type;
97 u8 access;
98 } obj;
99 struct {
100 enum uverbs_attr_type type;
101
102 u8 flags;
103 u8 num_elems;
104
105
106
107
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
126
127
128 UVERBS_ACTION_FLAG_CREATE_ROOT = 1U << 0,
129};
130
131struct uverbs_method_spec {
132
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
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
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
217
218
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
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
238
239
240
241
242
243
244
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
322
323
324
325struct uverbs_ptr_attr {
326 u64 data;
327 u16 len;
328
329 u16 flags;
330 u8 enum_id;
331};
332
333struct uverbs_obj_attr {
334
335 const struct uverbs_obj_type *type;
336 struct ib_uobject *uobject;
337
338 int id;
339};
340
341struct uverbs_attr {
342
343
344
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
355 unsigned long *valid_bitmap;
356 size_t num_attrs;
357
358
359
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 struct ib_uobject *uverbs_attr_get_uobject(const struct uverbs_attr_bundle *attrs_bundle,
424 u16 idx)
425{
426 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
427
428 if (IS_ERR(attr))
429 return ERR_CAST(attr);
430
431 return attr->obj_attr.uobject;
432}
433
434static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle,
435 size_t idx, const void *from, size_t size)
436{
437 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
438 u16 flags;
439 size_t min_size;
440
441 if (IS_ERR(attr))
442 return PTR_ERR(attr);
443
444 min_size = min_t(size_t, attr->ptr_attr.len, size);
445 if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size))
446 return -EFAULT;
447
448 flags = attr->ptr_attr.flags | UVERBS_ATTR_F_VALID_OUTPUT;
449 if (put_user(flags, &attr->uattr->flags))
450 return -EFAULT;
451
452 return 0;
453}
454
455static inline bool uverbs_attr_ptr_is_inline(const struct uverbs_attr *attr)
456{
457 return attr->ptr_attr.len <= sizeof(attr->ptr_attr.data);
458}
459
460static inline int _uverbs_copy_from(void *to,
461 const struct uverbs_attr_bundle *attrs_bundle,
462 size_t idx,
463 size_t size)
464{
465 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
466
467 if (IS_ERR(attr))
468 return PTR_ERR(attr);
469
470
471
472
473
474
475 if (unlikely(size < attr->ptr_attr.len))
476 return -EINVAL;
477
478 if (uverbs_attr_ptr_is_inline(attr))
479 memcpy(to, &attr->ptr_attr.data, attr->ptr_attr.len);
480 else if (copy_from_user(to, u64_to_user_ptr(attr->ptr_attr.data),
481 attr->ptr_attr.len))
482 return -EFAULT;
483
484 return 0;
485}
486
487static inline int _uverbs_copy_from_or_zero(void *to,
488 const struct uverbs_attr_bundle *attrs_bundle,
489 size_t idx,
490 size_t size)
491{
492 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
493 size_t min_size;
494
495 if (IS_ERR(attr))
496 return PTR_ERR(attr);
497
498 min_size = min_t(size_t, size, attr->ptr_attr.len);
499
500 if (uverbs_attr_ptr_is_inline(attr))
501 memcpy(to, &attr->ptr_attr.data, min_size);
502 else if (copy_from_user(to, u64_to_user_ptr(attr->ptr_attr.data),
503 min_size))
504 return -EFAULT;
505
506 if (size > min_size)
507 memset(to + min_size, 0, size - min_size);
508
509 return 0;
510}
511
512#define uverbs_copy_from(to, attrs_bundle, idx) \
513 _uverbs_copy_from(to, attrs_bundle, idx, sizeof(*to))
514
515#define uverbs_copy_from_or_zero(to, attrs_bundle, idx) \
516 _uverbs_copy_from_or_zero(to, attrs_bundle, idx, sizeof(*to))
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
554struct uverbs_root_spec *uverbs_alloc_spec_tree(unsigned int num_trees,
555 const struct uverbs_object_tree_def **trees);
556void uverbs_free_spec_tree(struct uverbs_root_spec *root);
557#else
558static inline struct uverbs_root_spec *uverbs_alloc_spec_tree(unsigned int num_trees,
559 const struct uverbs_object_tree_def **trees)
560{
561 return NULL;
562}
563
564static inline void uverbs_free_spec_tree(struct uverbs_root_spec *root)
565{
566}
567#endif
568
569#endif
570