diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2020-02-17 20:25:14 +0300 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2020-07-27 21:31:07 +0300 |
commit | dc12d7968f9c9540494deb1285854b18ca4465ec (patch) | |
tree | 5d62016a11db4117707189853899ee466b5bcafb /kernel/regset.c | |
parent | 1e56f6d28954248f01849c359b1b7210bb6c1add (diff) | |
download | linux-dc12d7968f9c9540494deb1285854b18ca4465ec.tar.xz |
copy_regset_to_user(): do all copyout at once.
Turn copy_regset_to_user() into regset_get_alloc() + copy_to_user().
Now all ->get() calls have a kernel buffer as destination.
Note that we'd already eliminated the callers of copy_regset_to_user()
with non-zero offset; now that argument is simply unused.
Uninlined, while we are at it.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel/regset.c')
-rw-r--r-- | kernel/regset.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/kernel/regset.c b/kernel/regset.c index 6b39fa0993ec..0a610983ce43 100644 --- a/kernel/regset.c +++ b/kernel/regset.c @@ -52,3 +52,29 @@ int regset_get_alloc(struct task_struct *target, return __regset_get(target, regset, size, data); } EXPORT_SYMBOL(regset_get_alloc); + +/** + * copy_regset_to_user - fetch a thread's user_regset data into user memory + * @target: thread to be examined + * @view: &struct user_regset_view describing user thread machine state + * @setno: index in @view->regsets + * @offset: offset into the regset data, in bytes + * @size: amount of data to copy, in bytes + * @data: user-mode pointer to copy into + */ +int copy_regset_to_user(struct task_struct *target, + const struct user_regset_view *view, + unsigned int setno, + unsigned int offset, unsigned int size, + void __user *data) +{ + const struct user_regset *regset = &view->regsets[setno]; + void *buf; + int ret; + + ret = regset_get_alloc(target, regset, size, &buf); + if (ret > 0) + ret = copy_to_user(data, buf, ret) ? -EFAULT : 0; + kfree(buf); + return ret; +} |