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