18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * SPDX-License-Identifier: MIT 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright © 2018 Intel Corporation 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/nospec.h> 88c2ecf20Sopenharmony_ci#include <linux/sched/signal.h> 98c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <uapi/drm/i915_drm.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include "i915_user_extensions.h" 148c2ecf20Sopenharmony_ci#include "i915_utils.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ciint i915_user_extensions(struct i915_user_extension __user *ext, 178c2ecf20Sopenharmony_ci const i915_user_extension_fn *tbl, 188c2ecf20Sopenharmony_ci unsigned int count, 198c2ecf20Sopenharmony_ci void *data) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci unsigned int stackdepth = 512; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci while (ext) { 248c2ecf20Sopenharmony_ci int i, err; 258c2ecf20Sopenharmony_ci u32 name; 268c2ecf20Sopenharmony_ci u64 next; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci if (!stackdepth--) /* recursion vs useful flexibility */ 298c2ecf20Sopenharmony_ci return -E2BIG; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci err = check_user_mbz(&ext->flags); 328c2ecf20Sopenharmony_ci if (err) 338c2ecf20Sopenharmony_ci return err; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ext->rsvd); i++) { 368c2ecf20Sopenharmony_ci err = check_user_mbz(&ext->rsvd[i]); 378c2ecf20Sopenharmony_ci if (err) 388c2ecf20Sopenharmony_ci return err; 398c2ecf20Sopenharmony_ci } 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci if (get_user(name, &ext->name)) 428c2ecf20Sopenharmony_ci return -EFAULT; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci err = -EINVAL; 458c2ecf20Sopenharmony_ci if (name < count) { 468c2ecf20Sopenharmony_ci name = array_index_nospec(name, count); 478c2ecf20Sopenharmony_ci if (tbl[name]) 488c2ecf20Sopenharmony_ci err = tbl[name](ext, data); 498c2ecf20Sopenharmony_ci } 508c2ecf20Sopenharmony_ci if (err) 518c2ecf20Sopenharmony_ci return err; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci if (get_user(next, &ext->next_extension) || 548c2ecf20Sopenharmony_ci overflows_type(next, ext)) 558c2ecf20Sopenharmony_ci return -EFAULT; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci ext = u64_to_user_ptr(next); 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci return 0; 618c2ecf20Sopenharmony_ci} 62