Linux Audio

Check our new training course

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