Add generic BPF syscall support for passing common attributes.

The initial set of common attributes includes:

1. 'log_buf': User-provided buffer for storing logs.
2. 'log_size': Size of the log buffer.
3. 'log_level': Log verbosity level.
4. 'log_true_size': Actual log size reported by kernel.

The common-attribute pointer and its size are passed as the 4th and 5th
syscall arguments. A new command bit, 'BPF_COMMON_ATTRS' ('1 << 16'),
indicates that common attributes are supplied.

This commit adds syscall and uapi plumbing. Command-specific handling is
added in follow-up patches.

Signed-off-by: Leon Hwang <[email protected]>
---
 include/linux/syscalls.h       |  3 ++-
 include/uapi/linux/bpf.h       |  8 ++++++++
 kernel/bpf/syscall.c           | 25 +++++++++++++++++++++----
 tools/include/uapi/linux/bpf.h |  8 ++++++++
 4 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 6c8a570cf44a..aadbb7164ea5 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -937,7 +937,8 @@ asmlinkage long sys_seccomp(unsigned int op, unsigned int 
flags,
 asmlinkage long sys_getrandom(char __user *buf, size_t count,
                              unsigned int flags);
 asmlinkage long sys_memfd_create(const char __user *uname_ptr, unsigned int 
flags);
-asmlinkage long sys_bpf(int cmd, union bpf_attr __user *attr, unsigned int 
size);
+asmlinkage long sys_bpf(int cmd, union bpf_attr __user *attr, unsigned int 
size,
+                       struct bpf_common_attr __user *attr_common, unsigned 
int size_common);
 asmlinkage long sys_execveat(int dfd, const char __user *filename,
                        const char __user *const __user *argv,
                        const char __user *const __user *envp, int flags);
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index c8d400b7680a..b2126c9641ec 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -994,6 +994,7 @@ enum bpf_cmd {
        BPF_PROG_STREAM_READ_BY_FD,
        BPF_PROG_ASSOC_STRUCT_OPS,
        __MAX_BPF_CMD,
+       BPF_COMMON_ATTRS = 1 << 16, /* Indicate carrying syscall common attrs. 
*/
 };
 
 enum bpf_map_type {
@@ -1500,6 +1501,13 @@ struct bpf_stack_build_id {
        };
 };
 
+struct bpf_common_attr {
+       __u64 log_buf;
+       __u32 log_size;
+       __u32 log_level;
+       __u32 log_true_size;
+};
+
 #define BPF_OBJ_NAME_LEN 16U
 
 enum {
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 683c332dbafb..0e231c0b1d04 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -6186,8 +6186,10 @@ static int prog_assoc_struct_ops(union bpf_attr *attr)
        return ret;
 }
 
-static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size)
+static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size,
+                    bpfptr_t uattr_common, unsigned int size_common)
 {
+       struct bpf_common_attr attr_common;
        union bpf_attr attr;
        int err;
 
@@ -6201,6 +6203,20 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, 
unsigned int size)
        if (copy_from_bpfptr(&attr, uattr, size) != 0)
                return -EFAULT;
 
+       memset(&attr_common, 0, sizeof(attr_common));
+       if (cmd & BPF_COMMON_ATTRS) {
+               err = bpf_check_uarg_tail_zero(uattr_common, 
sizeof(attr_common), size_common);
+               if (err)
+                       return err;
+
+               cmd &= ~BPF_COMMON_ATTRS;
+               size_common = min_t(u32, size_common, sizeof(attr_common));
+               if (copy_from_bpfptr(&attr_common, uattr_common, size_common) 
!= 0)
+                       return -EFAULT;
+       } else {
+               size_common = 0;
+       }
+
        err = security_bpf(cmd, &attr, size, uattr.is_kernel);
        if (err < 0)
                return err;
@@ -6336,9 +6352,10 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, 
unsigned int size)
        return err;
 }
 
-SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, 
size)
+SYSCALL_DEFINE5(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, 
size,
+               struct bpf_common_attr __user *, uattr_common, unsigned int, 
size_common)
 {
-       return __sys_bpf(cmd, USER_BPFPTR(uattr), size);
+       return __sys_bpf(cmd, USER_BPFPTR(uattr), size, 
USER_BPFPTR(uattr_common), size_common);
 }
 
 static bool syscall_prog_is_valid_access(int off, int size,
@@ -6369,7 +6386,7 @@ BPF_CALL_3(bpf_sys_bpf, int, cmd, union bpf_attr *, attr, 
u32, attr_size)
        default:
                return -EINVAL;
        }
-       return __sys_bpf(cmd, KERNEL_BPFPTR(attr), attr_size);
+       return __sys_bpf(cmd, KERNEL_BPFPTR(attr), attr_size, 
KERNEL_BPFPTR(NULL), 0);
 }
 
 
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 5e38b4887de6..c4934c2370fd 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -994,6 +994,7 @@ enum bpf_cmd {
        BPF_PROG_STREAM_READ_BY_FD,
        BPF_PROG_ASSOC_STRUCT_OPS,
        __MAX_BPF_CMD,
+       BPF_COMMON_ATTRS = 1 << 16, /* Indicate carrying syscall common attrs. 
*/
 };
 
 enum bpf_map_type {
@@ -1500,6 +1501,13 @@ struct bpf_stack_build_id {
        };
 };
 
+struct bpf_common_attr {
+       __u64 log_buf;
+       __u32 log_size;
+       __u32 log_level;
+       __u32 log_true_size;
+};
+
 #define BPF_OBJ_NAME_LEN 16U
 
 enum {
-- 
2.52.0


Reply via email to