From: Björn Töpel <bjorn.to...@intel.com> The added bpf_prog_load_builtin can be used to load and verify a BPF program that originates from the kernel. We call this a "builtin BPF program". A builtin program can be used for convenience, e.g. it allows for the kernel to use the bpf infrastructure for internal tasks.
This functionality will be used by AF_XDP sockets in a later commit. Signed-off-by: Björn Töpel <bjorn.to...@intel.com> --- include/linux/bpf.h | 2 ++ kernel/bpf/syscall.c | 32 ++++++++++++++++++++++++-------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index e82b7039fc66..e810bfeb6239 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -563,6 +563,8 @@ static inline int bpf_map_attr_numa_node(const union bpf_attr *attr) struct bpf_prog *bpf_prog_get_type_path(const char *name, enum bpf_prog_type type); int array_map_alloc_check(union bpf_attr *attr); +struct bpf_prog *bpf_prog_load_builtin(union bpf_attr *attr); + #else /* !CONFIG_BPF_SYSCALL */ static inline struct bpf_prog *bpf_prog_get(u32 ufd) { diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index ee1328625330..323831e1a1e2 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -1461,10 +1461,16 @@ static struct bpf_prog *__bpf_prog_load(union bpf_attr *attr, !capable(CAP_SYS_ADMIN)) return ERR_PTR(-EPERM); - /* copy eBPF program license from user space */ - if (strncpy_from_user(license, u64_to_user_ptr(attr->license), - sizeof(license) - 1) < 0) - return ERR_PTR(-EFAULT); + /* NB! If uattr is NULL, a builtin BPF is being loaded. */ + if (uattr) { + /* copy eBPF program license from user space */ + if (strncpy_from_user(license, u64_to_user_ptr(attr->license), + sizeof(license) - 1) < 0) + return ERR_PTR(-EFAULT); + } else { + strncpy(license, (const char *)(unsigned long)attr->license, + sizeof(license) - 1); + } license[sizeof(license) - 1] = 0; /* eBPF programs must be GPL compatible to use GPL-ed functions */ @@ -1505,10 +1511,15 @@ static struct bpf_prog *__bpf_prog_load(union bpf_attr *attr, prog->len = attr->insn_cnt; - err = -EFAULT; - if (copy_from_user(prog->insns, u64_to_user_ptr(attr->insns), - bpf_prog_insn_size(prog)) != 0) - goto free_prog; + if (uattr) { + err = -EFAULT; + if (copy_from_user(prog->insns, u64_to_user_ptr(attr->insns), + bpf_prog_insn_size(prog)) != 0) + goto free_prog; + } else { + memcpy(prog->insns, (void *)(unsigned long)attr->insns, + bpf_prog_insn_size(prog)); + } prog->orig_prog = NULL; prog->jited = 0; @@ -1584,6 +1595,11 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr) return fd; } +struct bpf_prog *bpf_prog_load_builtin(union bpf_attr *attr) +{ + return __bpf_prog_load(attr, NULL); +} + #define BPF_OBJ_LAST_FIELD file_flags static int bpf_obj_pin(const union bpf_attr *attr) -- 2.19.1