xref: /openbmc/linux/drivers/gpu/drm/i915/i915_user_extensions.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
19d1305efSChris Wilson /*
29d1305efSChris Wilson  * SPDX-License-Identifier: MIT
39d1305efSChris Wilson  *
49d1305efSChris Wilson  * Copyright © 2018 Intel Corporation
59d1305efSChris Wilson  */
69d1305efSChris Wilson 
79d1305efSChris Wilson #include <linux/nospec.h>
89d1305efSChris Wilson #include <linux/sched/signal.h>
99d1305efSChris Wilson #include <linux/uaccess.h>
109d1305efSChris Wilson 
119d1305efSChris Wilson #include <uapi/drm/i915_drm.h>
129d1305efSChris Wilson 
139d1305efSChris Wilson #include "i915_user_extensions.h"
149d1305efSChris Wilson #include "i915_utils.h"
159d1305efSChris Wilson 
i915_user_extensions(struct i915_user_extension __user * ext,const i915_user_extension_fn * tbl,unsigned int count,void * data)169d1305efSChris Wilson int i915_user_extensions(struct i915_user_extension __user *ext,
179d1305efSChris Wilson 			 const i915_user_extension_fn *tbl,
189d1305efSChris Wilson 			 unsigned int count,
199d1305efSChris Wilson 			 void *data)
209d1305efSChris Wilson {
219d1305efSChris Wilson 	unsigned int stackdepth = 512;
229d1305efSChris Wilson 
239d1305efSChris Wilson 	while (ext) {
249d1305efSChris Wilson 		int i, err;
259d1305efSChris Wilson 		u32 name;
269d1305efSChris Wilson 		u64 next;
279d1305efSChris Wilson 
289d1305efSChris Wilson 		if (!stackdepth--) /* recursion vs useful flexibility */
299d1305efSChris Wilson 			return -E2BIG;
309d1305efSChris Wilson 
319d1305efSChris Wilson 		err = check_user_mbz(&ext->flags);
329d1305efSChris Wilson 		if (err)
339d1305efSChris Wilson 			return err;
349d1305efSChris Wilson 
359d1305efSChris Wilson 		for (i = 0; i < ARRAY_SIZE(ext->rsvd); i++) {
369d1305efSChris Wilson 			err = check_user_mbz(&ext->rsvd[i]);
379d1305efSChris Wilson 			if (err)
389d1305efSChris Wilson 				return err;
399d1305efSChris Wilson 		}
409d1305efSChris Wilson 
419d1305efSChris Wilson 		if (get_user(name, &ext->name))
429d1305efSChris Wilson 			return -EFAULT;
439d1305efSChris Wilson 
449d1305efSChris Wilson 		err = -EINVAL;
459d1305efSChris Wilson 		if (name < count) {
469d1305efSChris Wilson 			name = array_index_nospec(name, count);
479d1305efSChris Wilson 			if (tbl[name])
489d1305efSChris Wilson 				err = tbl[name](ext, data);
499d1305efSChris Wilson 		}
509d1305efSChris Wilson 		if (err)
519d1305efSChris Wilson 			return err;
529d1305efSChris Wilson 
539d1305efSChris Wilson 		if (get_user(next, &ext->next_extension) ||
54*4b21d25bSKees Cook 		    overflows_type(next, uintptr_t))
559d1305efSChris Wilson 			return -EFAULT;
569d1305efSChris Wilson 
579d1305efSChris Wilson 		ext = u64_to_user_ptr(next);
589d1305efSChris Wilson 	}
599d1305efSChris Wilson 
609d1305efSChris Wilson 	return 0;
619d1305efSChris Wilson }
62