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