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