In PCuABI, when copying a block of memory to/from userspace containing capabilities/pointers, the copy_{to,from}_user_with_ptr variants need to be used to ensure capabilities are preserved in full.
Introduce bpf specific helper methods/macros to support this.
Since compat64 syscalls do not contain capabilities, the _with_ptr variants are not required in the in_compat64_syscall() case.
Signed-off-by: Zachary Leaf zachary.leaf@arm.com --- include/linux/bpf.h | 4 ++++ include/linux/bpfptr.h | 13 +++++++++++++ 2 files changed, 17 insertions(+)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 8bc99afd0fc0..efacb3151549 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -68,6 +68,10 @@ extern bool bpf_global_ma_set; __bpf_put_uattr(x, (union compat_bpf_attr __user *)uattr, to_field) : \ __bpf_put_uattr(x, (union bpf_attr __user *)uattr, to_field))
+#define bpf_copy_to_user_with_ptr(dest, src, size) \ + (in_compat64_syscall() ? copy_to_user(dest, src, size) \ + : copy_to_user_with_ptr(dest, src, size)) + #define bpf_field_exists(uattr_size, field) \ (in_compat64_syscall() ? \ (uattr_size >= offsetofend(union compat_bpf_attr, field)) : \ diff --git a/include/linux/bpfptr.h b/include/linux/bpfptr.h index f798677e1b8e..ff923e4bb713 100644 --- a/include/linux/bpfptr.h +++ b/include/linux/bpfptr.h @@ -63,11 +63,24 @@ static inline int copy_from_bpfptr_offset(void *dst, bpfptr_t src, return copy_from_kernel_nofault(dst, src.kernel + offset, size); }
+static inline int copy_from_bpfptr_offset_with_ptr(void *dst, bpfptr_t src, + size_t offset, size_t size) +{ + if (!bpfptr_is_kernel(src)) + return copy_from_user_with_ptr(dst, src.user + offset, size); + return copy_from_kernel_nofault(dst, src.kernel + offset, size); +} + static inline int copy_from_bpfptr(void *dst, bpfptr_t src, size_t size) { return copy_from_bpfptr_offset(dst, src, 0, size); }
+static inline int copy_from_bpfptr_with_ptr(void *dst, bpfptr_t src, size_t size) +{ + return copy_from_bpfptr_offset_with_ptr(dst, src, 0, size); +} + static inline int copy_to_bpfptr_offset(bpfptr_t dst, size_t offset, const void *src, size_t size) {