1 // SPDX-License-Identifier: GPL-2.0-only 1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <linux/export.h> 2 #include <linux/export.h> 3 #include <linux/slab.h> 3 #include <linux/slab.h> 4 #include <linux/regset.h> 4 #include <linux/regset.h> 5 5 6 static int __regset_get(struct task_struct *ta 6 static int __regset_get(struct task_struct *target, 7 const struct user_regs 7 const struct user_regset *regset, 8 unsigned int size, 8 unsigned int size, 9 void **data) 9 void **data) 10 { 10 { 11 void *p = *data, *to_free = NULL; 11 void *p = *data, *to_free = NULL; 12 int res; 12 int res; 13 13 14 if (!regset->regset_get) 14 if (!regset->regset_get) 15 return -EOPNOTSUPP; 15 return -EOPNOTSUPP; 16 if (size > regset->n * regset->size) 16 if (size > regset->n * regset->size) 17 size = regset->n * regset->siz 17 size = regset->n * regset->size; 18 if (!p) { 18 if (!p) { 19 to_free = p = kvzalloc(size, G !! 19 to_free = p = kzalloc(size, GFP_KERNEL); 20 if (!p) 20 if (!p) 21 return -ENOMEM; 21 return -ENOMEM; 22 } 22 } 23 res = regset->regset_get(target, regse 23 res = regset->regset_get(target, regset, 24 (struct membuf){.p 24 (struct membuf){.p = p, .left = size}); 25 if (res < 0) { 25 if (res < 0) { 26 kvfree(to_free); !! 26 kfree(to_free); 27 return res; 27 return res; 28 } 28 } 29 *data = p; 29 *data = p; 30 return size - res; 30 return size - res; 31 } 31 } 32 32 33 int regset_get(struct task_struct *target, 33 int regset_get(struct task_struct *target, 34 const struct user_regset *regse 34 const struct user_regset *regset, 35 unsigned int size, 35 unsigned int size, 36 void *data) 36 void *data) 37 { 37 { 38 return __regset_get(target, regset, si 38 return __regset_get(target, regset, size, &data); 39 } 39 } 40 EXPORT_SYMBOL(regset_get); 40 EXPORT_SYMBOL(regset_get); 41 41 42 int regset_get_alloc(struct task_struct *targe 42 int regset_get_alloc(struct task_struct *target, 43 const struct user_regset 43 const struct user_regset *regset, 44 unsigned int size, 44 unsigned int size, 45 void **data) 45 void **data) 46 { 46 { 47 *data = NULL; 47 *data = NULL; 48 return __regset_get(target, regset, si 48 return __regset_get(target, regset, size, data); 49 } 49 } 50 EXPORT_SYMBOL(regset_get_alloc); 50 EXPORT_SYMBOL(regset_get_alloc); 51 51 52 /** 52 /** 53 * copy_regset_to_user - fetch a thread's user 53 * copy_regset_to_user - fetch a thread's user_regset data into user memory 54 * @target: thread to be examined 54 * @target: thread to be examined 55 * @view: &struct user_regset_view descr 55 * @view: &struct user_regset_view describing user thread machine state 56 * @setno: index in @view->regsets 56 * @setno: index in @view->regsets 57 * @offset: offset into the regset data, i 57 * @offset: offset into the regset data, in bytes 58 * @size: amount of data to copy, in byt 58 * @size: amount of data to copy, in bytes 59 * @data: user-mode pointer to copy into 59 * @data: user-mode pointer to copy into 60 */ 60 */ 61 int copy_regset_to_user(struct task_struct *ta 61 int copy_regset_to_user(struct task_struct *target, 62 const struct user_regs 62 const struct user_regset_view *view, 63 unsigned int setno, 63 unsigned int setno, 64 unsigned int offset, u 64 unsigned int offset, unsigned int size, 65 void __user *data) 65 void __user *data) 66 { 66 { 67 const struct user_regset *regset = &vi 67 const struct user_regset *regset = &view->regsets[setno]; 68 void *buf; 68 void *buf; 69 int ret; 69 int ret; 70 70 71 ret = regset_get_alloc(target, regset, 71 ret = regset_get_alloc(target, regset, size, &buf); 72 if (ret > 0) 72 if (ret > 0) 73 ret = copy_to_user(data, buf, 73 ret = copy_to_user(data, buf, ret) ? -EFAULT : 0; 74 kvfree(buf); !! 74 kfree(buf); 75 return ret; 75 return ret; 76 } 76 } 77 77
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.