Merge branch 'work.regset' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull ptrace regset updates from Al Viro:
"Internal regset API changes:
- regularize copy_regset_{to,from}_user() callers
- switch to saner calling conventions for ->get()
- kill user_regset_copyout()
The ->put() side of things will have to wait for the next cycle,
unfortunately.
The balance is about -1KLoC and replacements for ->get() instances are
a lot saner"
* 'work.regset' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (41 commits)
regset: kill user_regset_copyout{,_zero}()
regset(): kill ->get_size()
regset: kill ->get()
csky: switch to ->regset_get()
xtensa: switch to ->regset_get()
parisc: switch to ->regset_get()
nds32: switch to ->regset_get()
nios2: switch to ->regset_get()
hexagon: switch to ->regset_get()
h8300: switch to ->regset_get()
openrisc: switch to ->regset_get()
riscv: switch to ->regset_get()
c6x: switch to ->regset_get()
ia64: switch to ->regset_get()
arc: switch to ->regset_get()
arm: switch to ->regset_get()
sh: convert to ->regset_get()
arm64: switch to ->regset_get()
mips: switch to ->regset_get()
sparc: switch to ->regset_get()
...
This commit is contained in:
@@ -10,7 +10,7 @@ obj-y = fork.o exec_domain.o panic.o \
|
||||
extable.o params.o \
|
||||
kthread.o sys_ni.o nsproxy.o \
|
||||
notifier.o ksysfs.o cred.o reboot.o \
|
||||
async.o range.o smpboot.o ucount.o
|
||||
async.o range.o smpboot.o ucount.o regset.o
|
||||
|
||||
obj-$(CONFIG_BPFILTER) += usermode_driver.o
|
||||
obj-$(CONFIG_MODULES) += kmod.o
|
||||
|
||||
76
kernel/regset.c
Normal file
76
kernel/regset.c
Normal file
@@ -0,0 +1,76 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#include <linux/export.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/regset.h>
|
||||
|
||||
static int __regset_get(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int size,
|
||||
void **data)
|
||||
{
|
||||
void *p = *data, *to_free = NULL;
|
||||
int res;
|
||||
|
||||
if (!regset->regset_get)
|
||||
return -EOPNOTSUPP;
|
||||
if (size > regset->n * regset->size)
|
||||
size = regset->n * regset->size;
|
||||
if (!p) {
|
||||
to_free = p = kzalloc(size, GFP_KERNEL);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
}
|
||||
res = regset->regset_get(target, regset,
|
||||
(struct membuf){.p = p, .left = size});
|
||||
if (res < 0) {
|
||||
kfree(to_free);
|
||||
return res;
|
||||
}
|
||||
*data = p;
|
||||
return size - res;
|
||||
}
|
||||
|
||||
int regset_get(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int size,
|
||||
void *data)
|
||||
{
|
||||
return __regset_get(target, regset, size, &data);
|
||||
}
|
||||
EXPORT_SYMBOL(regset_get);
|
||||
|
||||
int regset_get_alloc(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int size,
|
||||
void **data)
|
||||
{
|
||||
*data = NULL;
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user