blob: 017ccf75890ce7e1b866fc1d68585d1c2584c94e [file] [log] [blame]
Matan Baraka0aa3092017-08-03 16:06:55 +03001/*
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>
Matan Barak35410302017-08-03 16:07:01 +030037#include <linux/uaccess.h>
38#include <rdma/rdma_user_ioctl.h>
Matan Barakd70724f2017-08-03 16:07:04 +030039#include <rdma/ib_user_ioctl_verbs.h>
Matan Barak1f7ff9d2018-03-19 15:02:33 +020040#include <rdma/ib_user_ioctl_cmds.h>
Matan Baraka0aa3092017-08-03 16:06:55 +030041
42/*
43 * =======================================
44 * Verbs action specifications
45 * =======================================
46 */
47
Matan Barakf43dbeb2017-08-03 16:06:56 +030048enum uverbs_attr_type {
49 UVERBS_ATTR_TYPE_NA,
Matan Barakfac96582017-08-03 16:06:57 +030050 UVERBS_ATTR_TYPE_PTR_IN,
51 UVERBS_ATTR_TYPE_PTR_OUT,
Matan Barakf43dbeb2017-08-03 16:06:56 +030052 UVERBS_ATTR_TYPE_IDR,
53 UVERBS_ATTR_TYPE_FD,
Matan Barak494c5582018-03-28 09:27:42 +030054 UVERBS_ATTR_TYPE_ENUM_IN,
Matan Barakf43dbeb2017-08-03 16:06:56 +030055};
56
Matan Baraka0aa3092017-08-03 16:06:55 +030057enum uverbs_obj_access {
58 UVERBS_ACCESS_READ,
59 UVERBS_ACCESS_WRITE,
60 UVERBS_ACCESS_NEW,
61 UVERBS_ACCESS_DESTROY
62};
63
Matan Barak1f07e08f2018-03-19 15:02:35 +020064/* Specification of a single attribute inside the ioctl message */
Jason Gunthorpe83bb4442018-07-04 08:50:29 +030065/* good size 16 */
Matan Barakf43dbeb2017-08-03 16:06:56 +030066struct uverbs_attr_spec {
Jason Gunthorped108dac2018-07-04 08:50:25 +030067 u8 type;
Jason Gunthorpe83bb4442018-07-04 08:50:29 +030068
69 /*
Jason Gunthorpe422e3d32018-07-04 08:50:31 +030070 * Support extending attributes by length. Allow the user to provide
71 * more bytes than ptr.len, but check that everything after is zero'd
72 * by the user.
Jason Gunthorpe83bb4442018-07-04 08:50:29 +030073 */
Jason Gunthorpe422e3d32018-07-04 08:50:31 +030074 u8 zero_trailing:1;
Jason Gunthorpe83bb4442018-07-04 08:50:29 +030075 /*
76 * Valid only for PTR_IN. Allocate and copy the data inside
77 * the parser
78 */
79 u8 alloc_and_copy:1;
80 u8 mandatory:1;
Jason Gunthorped108dac2018-07-04 08:50:25 +030081
Matan Barakfac96582017-08-03 16:06:57 +030082 union {
Matan Barakfac96582017-08-03 16:06:57 +030083 struct {
Matan Barakc66db312018-03-19 15:02:36 +020084 /* Current known size to kernel */
Jason Gunthorped108dac2018-07-04 08:50:25 +030085 u16 len;
Matan Barakc66db312018-03-19 15:02:36 +020086 /* User isn't allowed to provide something < min_len */
Jason Gunthorped108dac2018-07-04 08:50:25 +030087 u16 min_len;
Matan Barak1f07e08f2018-03-19 15:02:35 +020088 } ptr;
Jason Gunthorped108dac2018-07-04 08:50:25 +030089
Matan Barak1f07e08f2018-03-19 15:02:35 +020090 struct {
Matan Barakfac96582017-08-03 16:06:57 +030091 /*
92 * higher bits mean the namespace and lower bits mean
93 * the type id within the namespace.
94 */
Jason Gunthorped108dac2018-07-04 08:50:25 +030095 u16 obj_type;
96 u8 access;
Matan Barakfac96582017-08-03 16:06:57 +030097 } obj;
Jason Gunthorped108dac2018-07-04 08:50:25 +030098
Matan Barak494c5582018-03-28 09:27:42 +030099 struct {
Jason Gunthorped108dac2018-07-04 08:50:25 +0300100 u8 num_elems;
101 } enum_def;
102 } u;
103
104 /* This weird split of the enum lets us remove some padding */
105 union {
106 struct {
Matan Barak494c5582018-03-28 09:27:42 +0300107 /*
108 * The enum attribute can select one of the attributes
109 * contained in the ids array. Currently only PTR_IN
110 * attributes are supported in the ids array.
111 */
Jason Gunthorped108dac2018-07-04 08:50:25 +0300112 const struct uverbs_attr_spec *ids;
Matan Barak494c5582018-03-28 09:27:42 +0300113 } enum_def;
Jason Gunthorped108dac2018-07-04 08:50:25 +0300114 } u2;
Matan Barakf43dbeb2017-08-03 16:06:56 +0300115};
116
117struct uverbs_attr_spec_hash {
118 size_t num_attrs;
Matan Barakfac96582017-08-03 16:06:57 +0300119 unsigned long *mandatory_attrs_bitmask;
Matan Barakf43dbeb2017-08-03 16:06:56 +0300120 struct uverbs_attr_spec attrs[0];
121};
122
Matan Barakfac96582017-08-03 16:06:57 +0300123struct uverbs_attr_bundle;
124struct ib_uverbs_file;
125
126enum {
127 /*
128 * Action marked with this flag creates a context (or root for all
129 * objects).
130 */
131 UVERBS_ACTION_FLAG_CREATE_ROOT = 1U << 0,
132};
133
134struct uverbs_method_spec {
135 /* Combination of bits from enum UVERBS_ACTION_FLAG_XXXX */
136 u32 flags;
137 size_t num_buckets;
138 size_t num_child_attrs;
139 int (*handler)(struct ib_device *ib_dev, struct ib_uverbs_file *ufile,
140 struct uverbs_attr_bundle *ctx);
141 struct uverbs_attr_spec_hash *attr_buckets[0];
142};
143
144struct uverbs_method_spec_hash {
145 size_t num_methods;
146 struct uverbs_method_spec *methods[0];
147};
148
149struct uverbs_object_spec {
150 const struct uverbs_obj_type *type_attrs;
151 size_t num_buckets;
152 struct uverbs_method_spec_hash *method_buckets[0];
153};
154
155struct uverbs_object_spec_hash {
156 size_t num_objects;
157 struct uverbs_object_spec *objects[0];
158};
159
160struct uverbs_root_spec {
161 size_t num_buckets;
162 struct uverbs_object_spec_hash *object_buckets[0];
163};
164
Matan Barak50090102017-08-03 16:06:58 +0300165/*
166 * =======================================
167 * Verbs definitions
168 * =======================================
169 */
170
Matan Barak09e3ebf2017-08-03 16:06:59 +0300171struct uverbs_attr_def {
172 u16 id;
173 struct uverbs_attr_spec attr;
174};
175
176struct uverbs_method_def {
177 u16 id;
178 /* Combination of bits from enum UVERBS_ACTION_FLAG_XXXX */
179 u32 flags;
180 size_t num_attrs;
181 const struct uverbs_attr_def * const (*attrs)[];
182 int (*handler)(struct ib_device *ib_dev, struct ib_uverbs_file *ufile,
183 struct uverbs_attr_bundle *ctx);
184};
185
Matan Barak50090102017-08-03 16:06:58 +0300186struct uverbs_object_def {
Matan Barak09e3ebf2017-08-03 16:06:59 +0300187 u16 id;
Matan Barak50090102017-08-03 16:06:58 +0300188 const struct uverbs_obj_type *type_attrs;
Matan Barak09e3ebf2017-08-03 16:06:59 +0300189 size_t num_methods;
190 const struct uverbs_method_def * const (*methods)[];
191};
192
193struct uverbs_object_tree_def {
194 size_t num_objects;
195 const struct uverbs_object_def * const (*objects)[];
Matan Barak50090102017-08-03 16:06:58 +0300196};
197
Jason Gunthorped108dac2018-07-04 08:50:25 +0300198/*
199 * =======================================
200 * Attribute Specifications
201 * =======================================
202 */
Matan Barakc66db312018-03-19 15:02:36 +0200203
Matan Barakc66db312018-03-19 15:02:36 +0200204#define UVERBS_ATTR_SIZE(_min_len, _len) \
Jason Gunthorped108dac2018-07-04 08:50:25 +0300205 .u.ptr.min_len = _min_len, .u.ptr.len = _len
Jason Gunthorpe422e3d32018-07-04 08:50:31 +0300206
207/*
208 * Specifies a uapi structure that cannot be extended. The user must always
209 * supply the whole structure and nothing more. The structure must be declared
210 * in a header under include/uapi/rdma.
211 */
212#define UVERBS_ATTR_TYPE(_type) \
213 .u.ptr.min_len = sizeof(_type), .u.ptr.len = sizeof(_type)
214/*
215 * Specifies a uapi structure where the user must provide at least up to
216 * member 'last'. Anything after last and up until the end of the structure
217 * can be non-zero, anything longer than the end of the structure must be
218 * zero. The structure must be declared in a header under include/uapi/rdma.
219 */
220#define UVERBS_ATTR_STRUCT(_type, _last) \
221 .zero_trailing = 1, \
222 UVERBS_ATTR_SIZE(((uintptr_t)(&((_type *)0)->_last + 1)), \
223 sizeof(_type))
Jason Gunthorpe540cd692018-07-04 08:50:30 +0300224/*
225 * Specifies at least min_len bytes must be passed in, but the amount can be
226 * larger, up to the protocol maximum size. No check for zeroing is done.
227 */
228#define UVERBS_ATTR_MIN_SIZE(_min_len) UVERBS_ATTR_SIZE(_min_len, USHRT_MAX)
Matan Barakc66db312018-03-19 15:02:36 +0200229
Jason Gunthorped108dac2018-07-04 08:50:25 +0300230/* Must be used in the '...' of any UVERBS_ATTR */
Jason Gunthorpe83bb4442018-07-04 08:50:29 +0300231#define UA_ALLOC_AND_COPY .alloc_and_copy = 1
232#define UA_MANDATORY .mandatory = 1
Jason Gunthorpe83bb4442018-07-04 08:50:29 +0300233#define UA_OPTIONAL .mandatory = 0
Jason Gunthorped108dac2018-07-04 08:50:25 +0300234
235#define UVERBS_ATTR_IDR(_attr_id, _idr_type, _access, ...) \
Jason Gunthorpe9a119cd2018-07-04 08:50:28 +0300236 (&(const struct uverbs_attr_def){ \
Jason Gunthorped108dac2018-07-04 08:50:25 +0300237 .id = _attr_id, \
238 .attr = { .type = UVERBS_ATTR_TYPE_IDR, \
239 .u.obj.obj_type = _idr_type, \
240 .u.obj.access = _access, \
241 __VA_ARGS__ } })
242
243#define UVERBS_ATTR_FD(_attr_id, _fd_type, _access, ...) \
Jason Gunthorpe9a119cd2018-07-04 08:50:28 +0300244 (&(const struct uverbs_attr_def){ \
Jason Gunthorped108dac2018-07-04 08:50:25 +0300245 .id = (_attr_id) + \
246 BUILD_BUG_ON_ZERO((_access) != UVERBS_ACCESS_NEW && \
247 (_access) != UVERBS_ACCESS_READ), \
248 .attr = { .type = UVERBS_ATTR_TYPE_FD, \
249 .u.obj.obj_type = _fd_type, \
250 .u.obj.access = _access, \
251 __VA_ARGS__ } })
252
253#define UVERBS_ATTR_PTR_IN(_attr_id, _type, ...) \
Jason Gunthorpe9a119cd2018-07-04 08:50:28 +0300254 (&(const struct uverbs_attr_def){ \
Jason Gunthorped108dac2018-07-04 08:50:25 +0300255 .id = _attr_id, \
256 .attr = { .type = UVERBS_ATTR_TYPE_PTR_IN, \
257 _type, \
258 __VA_ARGS__ } })
259
260#define UVERBS_ATTR_PTR_OUT(_attr_id, _type, ...) \
Jason Gunthorpe9a119cd2018-07-04 08:50:28 +0300261 (&(const struct uverbs_attr_def){ \
Jason Gunthorped108dac2018-07-04 08:50:25 +0300262 .id = _attr_id, \
263 .attr = { .type = UVERBS_ATTR_TYPE_PTR_OUT, \
264 _type, \
265 __VA_ARGS__ } })
266
267/* _enum_arry should be a 'static const union uverbs_attr_spec[]' */
268#define UVERBS_ATTR_ENUM_IN(_attr_id, _enum_arr, ...) \
Jason Gunthorpe9a119cd2018-07-04 08:50:28 +0300269 (&(const struct uverbs_attr_def){ \
Jason Gunthorped108dac2018-07-04 08:50:25 +0300270 .id = _attr_id, \
271 .attr = { .type = UVERBS_ATTR_TYPE_ENUM_IN, \
272 .u2.enum_def.ids = _enum_arr, \
273 .u.enum_def.num_elems = ARRAY_SIZE(_enum_arr), \
274 __VA_ARGS__ }, \
275 })
Matan Barak35410302017-08-03 16:07:01 +0300276
277/*
Jason Gunthorpe6c61d2a2018-07-04 08:50:27 +0300278 * This spec is used in order to pass information to the hardware driver in a
279 * legacy way. Every verb that could get driver specific data should get this
280 * spec.
281 */
282#define UVERBS_ATTR_UHW() \
Jason Gunthorpe9a119cd2018-07-04 08:50:28 +0300283 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_UHW_IN, \
Jason Gunthorpe540cd692018-07-04 08:50:30 +0300284 UVERBS_ATTR_MIN_SIZE(0), \
285 UA_OPTIONAL), \
Jason Gunthorpe9a119cd2018-07-04 08:50:28 +0300286 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_UHW_OUT, \
Jason Gunthorpe540cd692018-07-04 08:50:30 +0300287 UVERBS_ATTR_MIN_SIZE(0), \
288 UA_OPTIONAL)
Jason Gunthorpe6c61d2a2018-07-04 08:50:27 +0300289
290/*
Jason Gunthorped108dac2018-07-04 08:50:25 +0300291 * =======================================
292 * Declaration helpers
293 * =======================================
Matan Barak35410302017-08-03 16:07:01 +0300294 */
Jason Gunthorpe6c61d2a2018-07-04 08:50:27 +0300295
296#define DECLARE_UVERBS_OBJECT_TREE(_name, ...) \
297 static const struct uverbs_object_def *const _name##_ptr[] = { \
298 __VA_ARGS__, \
299 }; \
300 static const struct uverbs_object_tree_def _name = { \
301 .num_objects = ARRAY_SIZE(_name##_ptr), \
302 .objects = &_name##_ptr, \
303 }
Matan Barak09e3ebf2017-08-03 16:06:59 +0300304
Matan Barakfac96582017-08-03 16:06:57 +0300305/* =================================================
306 * Parsing infrastructure
307 * =================================================
308 */
309
310struct uverbs_ptr_attr {
Matan Barak8762d142018-06-17 12:59:52 +0300311 /*
312 * If UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY is set then the 'ptr' is
313 * used.
314 */
315 union {
316 void *ptr;
317 u64 data;
318 };
Matan Barakfac96582017-08-03 16:06:57 +0300319 u16 len;
320 /* Combination of bits from enum UVERBS_ATTR_F_XXXX */
321 u16 flags;
Matan Barak494c5582018-03-28 09:27:42 +0300322 u8 enum_id;
Matan Barakfac96582017-08-03 16:06:57 +0300323};
324
Matan Barakf43dbeb2017-08-03 16:06:56 +0300325struct uverbs_obj_attr {
326 struct ib_uobject *uobject;
327};
328
329struct uverbs_attr {
Matan Barakfac96582017-08-03 16:06:57 +0300330 /*
331 * pointer to the user-space given attribute, in order to write the
332 * new uobject's id or update flags.
333 */
334 struct ib_uverbs_attr __user *uattr;
335 union {
336 struct uverbs_ptr_attr ptr_attr;
337 struct uverbs_obj_attr obj_attr;
338 };
Matan Barakf43dbeb2017-08-03 16:06:56 +0300339};
340
341struct uverbs_attr_bundle_hash {
342 /* if bit i is set, it means attrs[i] contains valid information */
343 unsigned long *valid_bitmap;
344 size_t num_attrs;
345 /*
346 * arrays of attributes, each element corresponds to the specification
347 * of the attribute in the same index.
348 */
349 struct uverbs_attr *attrs;
350};
351
352struct uverbs_attr_bundle {
353 size_t num_buckets;
354 struct uverbs_attr_bundle_hash hash[];
355};
356
357static inline bool uverbs_attr_is_valid_in_hash(const struct uverbs_attr_bundle_hash *attrs_hash,
358 unsigned int idx)
359{
360 return test_bit(idx, attrs_hash->valid_bitmap);
361}
362
Matan Barak35410302017-08-03 16:07:01 +0300363static inline bool uverbs_attr_is_valid(const struct uverbs_attr_bundle *attrs_bundle,
364 unsigned int idx)
365{
366 u16 idx_bucket = idx >> UVERBS_ID_NS_SHIFT;
367
368 if (attrs_bundle->num_buckets <= idx_bucket)
369 return false;
370
371 return uverbs_attr_is_valid_in_hash(&attrs_bundle->hash[idx_bucket],
372 idx & ~UVERBS_ID_NS_MASK);
373}
374
Matan Barak41b2a712018-03-19 15:02:38 +0200375#define IS_UVERBS_COPY_ERR(_ret) ((_ret) && (_ret) != -ENOENT)
376
Matan Barakd70724f2017-08-03 16:07:04 +0300377static inline const struct uverbs_attr *uverbs_attr_get(const struct uverbs_attr_bundle *attrs_bundle,
378 u16 idx)
379{
380 u16 idx_bucket = idx >> UVERBS_ID_NS_SHIFT;
381
382 if (!uverbs_attr_is_valid(attrs_bundle, idx))
383 return ERR_PTR(-ENOENT);
384
385 return &attrs_bundle->hash[idx_bucket].attrs[idx & ~UVERBS_ID_NS_MASK];
386}
387
Matan Barak494c5582018-03-28 09:27:42 +0300388static inline int uverbs_attr_get_enum_id(const struct uverbs_attr_bundle *attrs_bundle,
389 u16 idx)
390{
391 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
392
393 if (IS_ERR(attr))
394 return PTR_ERR(attr);
395
396 return attr->ptr_attr.enum_id;
397}
398
Ariel Levkovichbe934cc2018-04-05 18:53:25 +0300399static inline void *uverbs_attr_get_obj(const struct uverbs_attr_bundle *attrs_bundle,
400 u16 idx)
401{
Jason Gunthorpef4602cb2018-05-22 15:56:51 -0600402 const struct uverbs_attr *attr;
Ariel Levkovichbe934cc2018-04-05 18:53:25 +0300403
Jason Gunthorpef4602cb2018-05-22 15:56:51 -0600404 attr = uverbs_attr_get(attrs_bundle, idx);
405 if (IS_ERR(attr))
406 return ERR_CAST(attr);
Ariel Levkovichbe934cc2018-04-05 18:53:25 +0300407
Jason Gunthorpef4602cb2018-05-22 15:56:51 -0600408 return attr->obj_attr.uobject->object;
Ariel Levkovichbe934cc2018-04-05 18:53:25 +0300409}
410
Matan Barak3efa3812018-05-31 16:43:28 +0300411static inline struct ib_uobject *uverbs_attr_get_uobject(const struct uverbs_attr_bundle *attrs_bundle,
412 u16 idx)
413{
414 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
415
416 if (IS_ERR(attr))
417 return ERR_CAST(attr);
418
419 return attr->obj_attr.uobject;
420}
421
Matan Barak8762d142018-06-17 12:59:52 +0300422static inline int
423uverbs_attr_get_len(const struct uverbs_attr_bundle *attrs_bundle, u16 idx)
424{
425 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
426
427 if (IS_ERR(attr))
428 return PTR_ERR(attr);
429
430 return attr->ptr_attr.len;
431}
432
Matan Barakd70724f2017-08-03 16:07:04 +0300433static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle,
Matan Barak89d9e8d2018-02-13 12:18:29 +0200434 size_t idx, const void *from, size_t size)
Matan Barakd70724f2017-08-03 16:07:04 +0300435{
436 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
437 u16 flags;
Matan Barak89d9e8d2018-02-13 12:18:29 +0200438 size_t min_size;
Matan Barakd70724f2017-08-03 16:07:04 +0300439
440 if (IS_ERR(attr))
441 return PTR_ERR(attr);
442
Matan Barak89d9e8d2018-02-13 12:18:29 +0200443 min_size = min_t(size_t, attr->ptr_attr.len, size);
Jason Gunthorpe2f360282018-02-13 12:18:31 +0200444 if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size))
Matan Barak89d9e8d2018-02-13 12:18:29 +0200445 return -EFAULT;
446
Matan Barakd70724f2017-08-03 16:07:04 +0300447 flags = attr->ptr_attr.flags | UVERBS_ATTR_F_VALID_OUTPUT;
Matan Barak89d9e8d2018-02-13 12:18:29 +0200448 if (put_user(flags, &attr->uattr->flags))
449 return -EFAULT;
450
451 return 0;
Matan Barakd70724f2017-08-03 16:07:04 +0300452}
453
Matan Barak89d9e8d2018-02-13 12:18:29 +0200454static inline bool uverbs_attr_ptr_is_inline(const struct uverbs_attr *attr)
455{
456 return attr->ptr_attr.len <= sizeof(attr->ptr_attr.data);
457}
458
Matan Barak8762d142018-06-17 12:59:52 +0300459static inline void *uverbs_attr_get_alloced_ptr(
460 const struct uverbs_attr_bundle *attrs_bundle, u16 idx)
461{
462 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
463
464 if (IS_ERR(attr))
465 return (void *)attr;
466
467 return uverbs_attr_ptr_is_inline(attr) ? (void *)&attr->ptr_attr.data :
468 attr->ptr_attr.ptr;
469}
470
Matan Barak89d9e8d2018-02-13 12:18:29 +0200471static inline int _uverbs_copy_from(void *to,
Matan Barakd70724f2017-08-03 16:07:04 +0300472 const struct uverbs_attr_bundle *attrs_bundle,
Matan Barak89d9e8d2018-02-13 12:18:29 +0200473 size_t idx,
474 size_t size)
Matan Barakd70724f2017-08-03 16:07:04 +0300475{
476 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
477
478 if (IS_ERR(attr))
479 return PTR_ERR(attr);
480
Matan Barak89d9e8d2018-02-13 12:18:29 +0200481 /*
482 * Validation ensures attr->ptr_attr.len >= size. If the caller is
Matan Barakc66db312018-03-19 15:02:36 +0200483 * using UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO then it must call
484 * uverbs_copy_from_or_zero.
Matan Barak89d9e8d2018-02-13 12:18:29 +0200485 */
486 if (unlikely(size < attr->ptr_attr.len))
487 return -EINVAL;
488
489 if (uverbs_attr_ptr_is_inline(attr))
Matan Barakd70724f2017-08-03 16:07:04 +0300490 memcpy(to, &attr->ptr_attr.data, attr->ptr_attr.len);
Jason Gunthorpe2f360282018-02-13 12:18:31 +0200491 else if (copy_from_user(to, u64_to_user_ptr(attr->ptr_attr.data),
492 attr->ptr_attr.len))
Matan Barakd70724f2017-08-03 16:07:04 +0300493 return -EFAULT;
494
495 return 0;
496}
497
Matan Barakc66db312018-03-19 15:02:36 +0200498static inline int _uverbs_copy_from_or_zero(void *to,
499 const struct uverbs_attr_bundle *attrs_bundle,
500 size_t idx,
501 size_t size)
502{
503 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
504 size_t min_size;
505
506 if (IS_ERR(attr))
507 return PTR_ERR(attr);
508
509 min_size = min_t(size_t, size, attr->ptr_attr.len);
510
511 if (uverbs_attr_ptr_is_inline(attr))
512 memcpy(to, &attr->ptr_attr.data, min_size);
513 else if (copy_from_user(to, u64_to_user_ptr(attr->ptr_attr.data),
514 min_size))
515 return -EFAULT;
516
517 if (size > min_size)
518 memset(to + min_size, 0, size - min_size);
519
520 return 0;
521}
522
Matan Barakd70724f2017-08-03 16:07:04 +0300523#define uverbs_copy_from(to, attrs_bundle, idx) \
Matan Barak89d9e8d2018-02-13 12:18:29 +0200524 _uverbs_copy_from(to, attrs_bundle, idx, sizeof(*to))
Matan Barakd70724f2017-08-03 16:07:04 +0300525
Matan Barakc66db312018-03-19 15:02:36 +0200526#define uverbs_copy_from_or_zero(to, attrs_bundle, idx) \
527 _uverbs_copy_from_or_zero(to, attrs_bundle, idx, sizeof(*to))
528
Matan Barak118620d2017-08-03 16:07:00 +0300529/* =================================================
530 * Definitions -> Specs infrastructure
531 * =================================================
532 */
Matan Baraka0aa3092017-08-03 16:06:55 +0300533
Matan Barak118620d2017-08-03 16:07:00 +0300534/*
535 * uverbs_alloc_spec_tree - Merges different common and driver specific feature
536 * into one parsing tree that every uverbs command will be parsed upon.
537 *
538 * @num_trees: Number of trees in the array @trees.
539 * @trees: Array of pointers to tree root definitions to merge. Each such tree
540 * possibly contains objects, methods and attributes definitions.
541 *
542 * Returns:
543 * uverbs_root_spec *: The root of the merged parsing tree.
544 * On error, we return an error code. Error is checked via IS_ERR.
545 *
546 * The following merges could take place:
547 * a. Two trees representing the same method with different handler
548 * -> We take the handler of the tree that its handler != NULL
549 * and its index in the trees array is greater. The incentive for that
550 * is that developers are expected to first merge common trees and then
551 * merge trees that gives specialized the behaviour.
552 * b. Two trees representing the same object with different
553 * type_attrs (struct uverbs_obj_type):
554 * -> We take the type_attrs of the tree that its type_attr != NULL
555 * and its index in the trees array is greater. This could be used
556 * in order to override the free function, allocation size, etc.
557 * c. Two trees representing the same method attribute (same id but possibly
558 * different attributes):
559 * -> ERROR (-ENOENT), we believe that's not the programmer's intent.
560 *
561 * An object without any methods is considered invalid and will abort the
562 * function with -ENOENT error.
563 */
Matan Barak52427112017-08-03 16:07:06 +0300564#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
Matan Barak118620d2017-08-03 16:07:00 +0300565struct uverbs_root_spec *uverbs_alloc_spec_tree(unsigned int num_trees,
566 const struct uverbs_object_tree_def **trees);
567void uverbs_free_spec_tree(struct uverbs_root_spec *root);
Matan Barak52427112017-08-03 16:07:06 +0300568#else
569static inline struct uverbs_root_spec *uverbs_alloc_spec_tree(unsigned int num_trees,
570 const struct uverbs_object_tree_def **trees)
571{
572 return NULL;
573}
574
575static inline void uverbs_free_spec_tree(struct uverbs_root_spec *root)
576{
577}
578#endif
Matan Barak118620d2017-08-03 16:07:00 +0300579
580#endif