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