mirror of
https://github.com/torvalds/linux.git
synced 2024-10-23 05:30:55 +00:00
bpf: Add bpf_copy_from_user_str kfunc
This adds a kfunc wrapper around strncpy_from_user, which can be called from sleepable BPF programs. This matches the non-sleepable 'bpf_probe_read_user_str' helper except it includes an additional 'flags' param, which allows consumers to clear the entire destination buffer on success or failure. Signed-off-by: Jordan Rome <linux@jordanrome.com> Link: https://lore.kernel.org/r/20240823195101.3621028-1-linux@jordanrome.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
5772c3458b
commit
65ab5ac4df
|
@ -7513,4 +7513,13 @@ struct bpf_iter_num {
|
|||
__u64 __opaque[1];
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
/*
|
||||
* Flags to control BPF kfunc behaviour.
|
||||
* - BPF_F_PAD_ZEROS: Pad destination buffer with zeros. (See the respective
|
||||
* helper documentation for details.)
|
||||
*/
|
||||
enum bpf_kfunc_flags {
|
||||
BPF_F_PAD_ZEROS = (1ULL << 0),
|
||||
};
|
||||
|
||||
#endif /* _UAPI__LINUX_BPF_H__ */
|
||||
|
|
|
@ -2962,6 +2962,47 @@ __bpf_kfunc void bpf_iter_bits_destroy(struct bpf_iter_bits *it)
|
|||
bpf_mem_free(&bpf_global_ma, kit->bits);
|
||||
}
|
||||
|
||||
/**
|
||||
* bpf_copy_from_user_str() - Copy a string from an unsafe user address
|
||||
* @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 user space.
|
||||
* @flags: The only supported flag is BPF_F_PAD_ZEROS
|
||||
*
|
||||
* Copies a NUL-terminated string from userspace to BPF space. If user string is
|
||||
* too long this will still ensure zero termination in the dst buffer unless
|
||||
* buffer size is 0.
|
||||
*
|
||||
* If BPF_F_PAD_ZEROS flag is set, memset the tail of @dst to 0 on success and
|
||||
* memset all of @dst on failure.
|
||||
*/
|
||||
__bpf_kfunc int bpf_copy_from_user_str(void *dst, u32 dst__sz, const void __user *unsafe_ptr__ign, u64 flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (unlikely(flags & ~BPF_F_PAD_ZEROS))
|
||||
return -EINVAL;
|
||||
|
||||
if (unlikely(!dst__sz))
|
||||
return 0;
|
||||
|
||||
ret = strncpy_from_user(dst, unsafe_ptr__ign, dst__sz - 1);
|
||||
if (ret < 0) {
|
||||
if (flags & BPF_F_PAD_ZEROS)
|
||||
memset((char *)dst, 0, dst__sz);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (flags & BPF_F_PAD_ZEROS)
|
||||
memset((char *)dst + ret, 0, dst__sz - ret);
|
||||
else
|
||||
((char *)dst)[ret] = '\0';
|
||||
|
||||
return ret + 1;
|
||||
}
|
||||
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
BTF_KFUNCS_START(generic_btf_ids)
|
||||
|
@ -3047,6 +3088,7 @@ BTF_ID_FLAGS(func, bpf_preempt_enable)
|
|||
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_KFUNCS_END(common_btf_ids)
|
||||
|
||||
static const struct btf_kfunc_id_set common_kfunc_set = {
|
||||
|
|
|
@ -7512,4 +7512,13 @@ struct bpf_iter_num {
|
|||
__u64 __opaque[1];
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
/*
|
||||
* Flags to control BPF kfunc behaviour.
|
||||
* - BPF_F_PAD_ZEROS: Pad destination buffer with zeros. (See the respective
|
||||
* helper documentation for details.)
|
||||
*/
|
||||
enum bpf_kfunc_flags {
|
||||
BPF_F_PAD_ZEROS = (1ULL << 0),
|
||||
};
|
||||
|
||||
#endif /* _UAPI__LINUX_BPF_H__ */
|
||||
|
|
Loading…
Reference in New Issue
Block a user