mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
bpf: Add bpf_copy_from_user_task_str() kfunc
This new kfunc will be able to copy a zero-terminated C strings from another task's address space. This is similar to `bpf_copy_from_user_str()` but reads memory of specified task. Signed-off-by: Jordan Rome <linux@jordanrome.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20250213152125.1837400-2-linux@jordanrome.com
This commit is contained in:
parent
f0b79944e6
commit
f0f8a5b58f
|
|
@ -3067,6 +3067,50 @@ __bpf_kfunc int bpf_copy_from_user_str(void *dst, u32 dst__sz, const void __user
|
|||
return ret + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* bpf_copy_from_user_task_str() - Copy a string from an task's address space
|
||||
* @dst: Destination address, in kernel space. This buffer must be
|
||||
* at least @dst__sz bytes long.
|
||||
* @dst__sz: Maximum number of bytes to copy, includes the trailing NUL.
|
||||
* @unsafe_ptr__ign: Source address in the task's address space.
|
||||
* @tsk: The task whose address space will be used
|
||||
* @flags: The only supported flag is BPF_F_PAD_ZEROS
|
||||
*
|
||||
* Copies a NUL terminated string from a task's address space to @dst__sz
|
||||
* buffer. If user string is too long this will still ensure zero termination
|
||||
* in the @dst__sz buffer unless buffer size is 0.
|
||||
*
|
||||
* If BPF_F_PAD_ZEROS flag is set, memset the tail of @dst__sz to 0 on success
|
||||
* and memset all of @dst__sz on failure.
|
||||
*
|
||||
* Return: The number of copied bytes on success including the NUL terminator.
|
||||
* A negative error code on failure.
|
||||
*/
|
||||
__bpf_kfunc int bpf_copy_from_user_task_str(void *dst, u32 dst__sz,
|
||||
const void __user *unsafe_ptr__ign,
|
||||
struct task_struct *tsk, u64 flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (unlikely(flags & ~BPF_F_PAD_ZEROS))
|
||||
return -EINVAL;
|
||||
|
||||
if (unlikely(dst__sz == 0))
|
||||
return 0;
|
||||
|
||||
ret = copy_remote_vm_str(tsk, (unsigned long)unsafe_ptr__ign, dst, dst__sz, 0);
|
||||
if (ret < 0) {
|
||||
if (flags & BPF_F_PAD_ZEROS)
|
||||
memset(dst, 0, dst__sz);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (flags & BPF_F_PAD_ZEROS)
|
||||
memset(dst + ret, 0, dst__sz - ret);
|
||||
|
||||
return ret + 1;
|
||||
}
|
||||
|
||||
/* Keep unsinged long in prototype so that kfunc is usable when emitted to
|
||||
* vmlinux.h in BPF programs directly, but note that while in BPF prog, the
|
||||
* unsigned long always points to 8-byte region on stack, the kernel may only
|
||||
|
|
@ -3174,6 +3218,7 @@ BTF_ID_FLAGS(func, bpf_iter_bits_new, KF_ITER_NEW)
|
|||
BTF_ID_FLAGS(func, bpf_iter_bits_next, KF_ITER_NEXT | KF_RET_NULL)
|
||||
BTF_ID_FLAGS(func, bpf_iter_bits_destroy, KF_ITER_DESTROY)
|
||||
BTF_ID_FLAGS(func, bpf_copy_from_user_str, KF_SLEEPABLE)
|
||||
BTF_ID_FLAGS(func, bpf_copy_from_user_task_str, KF_SLEEPABLE)
|
||||
BTF_ID_FLAGS(func, bpf_get_kmem_cache)
|
||||
BTF_ID_FLAGS(func, bpf_iter_kmem_cache_new, KF_ITER_NEW | KF_SLEEPABLE)
|
||||
BTF_ID_FLAGS(func, bpf_iter_kmem_cache_next, KF_ITER_NEXT | KF_RET_NULL | KF_SLEEPABLE)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user