76 lines · 1.9 KB · C
RawDownload
// 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;}