Home | History | Annotate | Line # | Download | only in i915
      1  1.1  riastrad /*	$NetBSD: i915_user_extensions.c,v 1.2 2021/12/18 23:45:28 riastradh Exp $	*/
      2  1.1  riastrad 
      3  1.1  riastrad /*
      4  1.1  riastrad  * SPDX-License-Identifier: MIT
      5  1.1  riastrad  *
      6  1.1  riastrad  * Copyright  2018 Intel Corporation
      7  1.1  riastrad  */
      8  1.1  riastrad 
      9  1.1  riastrad #include <sys/cdefs.h>
     10  1.1  riastrad __KERNEL_RCSID(0, "$NetBSD: i915_user_extensions.c,v 1.2 2021/12/18 23:45:28 riastradh Exp $");
     11  1.1  riastrad 
     12  1.1  riastrad #include <linux/nospec.h>
     13  1.1  riastrad #include <linux/sched/signal.h>
     14  1.1  riastrad #include <linux/uaccess.h>
     15  1.1  riastrad 
     16  1.1  riastrad #include <uapi/drm/i915_drm.h>
     17  1.1  riastrad 
     18  1.1  riastrad #include "i915_user_extensions.h"
     19  1.1  riastrad #include "i915_utils.h"
     20  1.1  riastrad 
     21  1.1  riastrad int i915_user_extensions(struct i915_user_extension __user *ext,
     22  1.1  riastrad 			 const i915_user_extension_fn *tbl,
     23  1.1  riastrad 			 unsigned int count,
     24  1.1  riastrad 			 void *data)
     25  1.1  riastrad {
     26  1.1  riastrad 	unsigned int stackdepth = 512;
     27  1.1  riastrad 
     28  1.1  riastrad 	while (ext) {
     29  1.1  riastrad 		int i, err;
     30  1.1  riastrad 		u32 name;
     31  1.1  riastrad 		u64 next;
     32  1.1  riastrad 
     33  1.1  riastrad 		if (!stackdepth--) /* recursion vs useful flexibility */
     34  1.1  riastrad 			return -E2BIG;
     35  1.1  riastrad 
     36  1.1  riastrad 		err = check_user_mbz(&ext->flags);
     37  1.1  riastrad 		if (err)
     38  1.1  riastrad 			return err;
     39  1.1  riastrad 
     40  1.1  riastrad 		for (i = 0; i < ARRAY_SIZE(ext->rsvd); i++) {
     41  1.1  riastrad 			err = check_user_mbz(&ext->rsvd[i]);
     42  1.1  riastrad 			if (err)
     43  1.1  riastrad 				return err;
     44  1.1  riastrad 		}
     45  1.1  riastrad 
     46  1.1  riastrad 		if (get_user(name, &ext->name))
     47  1.1  riastrad 			return -EFAULT;
     48  1.1  riastrad 
     49  1.1  riastrad 		err = -EINVAL;
     50  1.1  riastrad 		if (name < count) {
     51  1.1  riastrad 			name = array_index_nospec(name, count);
     52  1.1  riastrad 			if (tbl[name])
     53  1.1  riastrad 				err = tbl[name](ext, data);
     54  1.1  riastrad 		}
     55  1.1  riastrad 		if (err)
     56  1.1  riastrad 			return err;
     57  1.1  riastrad 
     58  1.1  riastrad 		if (get_user(next, &ext->next_extension) ||
     59  1.1  riastrad 		    overflows_type(next, ext))
     60  1.1  riastrad 			return -EFAULT;
     61  1.1  riastrad 
     62  1.1  riastrad 		ext = u64_to_user_ptr(next);
     63  1.1  riastrad 	}
     64  1.1  riastrad 
     65  1.1  riastrad 	return 0;
     66  1.1  riastrad }
     67