Skip to content

Commit

Permalink
bpf: add signature to eBPF instructions
Browse files Browse the repository at this point in the history
When loading a BPF program, pass a signature which is used to validate
the instructions.
The signature type is the same used to validate the kernel modules.

Signed-off-by: Matteo Croce <mcroce@microsoft.com>
  • Loading branch information
teknoraver authored and intel-lab-lkp committed Oct 12, 2021
1 parent 431bfb9 commit 45c21d2
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
2 changes: 2 additions & 0 deletions include/uapi/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -1336,6 +1336,8 @@ union bpf_attr {
};
__u32 :32; /* pad */
__aligned_u64 fd_array; /* array of FDs */
__aligned_u64 signature; /* instruction's signature */
__u32 sig_len; /* signature size */
};

struct { /* anonymous struct used by BPF_OBJ_* commands */
Expand Down
33 changes: 32 additions & 1 deletion kernel/bpf/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include <linux/bpf-netns.h>
#include <linux/rcupdate_trace.h>
#include <linux/memcontrol.h>
#include <linux/verification.h>
#include <linux/module_signature.h>

#define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \
(map)->map_type == BPF_MAP_TYPE_CGROUP_ARRAY || \
Expand Down Expand Up @@ -2156,7 +2158,7 @@ static bool is_perfmon_prog_type(enum bpf_prog_type prog_type)
}

/* last field in 'union bpf_attr' used by this command */
#define BPF_PROG_LOAD_LAST_FIELD fd_array
#define BPF_PROG_LOAD_LAST_FIELD sig_len

static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr)
{
Expand Down Expand Up @@ -2274,6 +2276,35 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr)
bpf_prog_insn_size(prog)) != 0)
goto free_prog_sec;

if (attr->sig_len) {
char *signature;

signature = kmalloc(attr->sig_len, GFP_USER);
if (!signature) {
err = -ENOMEM;
goto free_prog_sec;
}

if (copy_from_user(signature, (char *)attr->signature, attr->sig_len)) {
err = -EFAULT;
kfree(signature);
goto free_prog_sec;
}

err = verify_pkcs7_signature(prog->insns,
prog->len * sizeof(struct bpf_insn),
signature, attr->sig_len,
VERIFY_USE_SECONDARY_KEYRING,
VERIFYING_MODULE_SIGNATURE,
NULL, NULL);
kfree(signature);

if (err) {
printk("verify_pkcs7_signature(): %pe\n", (void*)(uintptr_t)err);
goto free_prog_sec;
}
}

prog->orig_prog = NULL;
prog->jited = 0;

Expand Down

0 comments on commit 45c21d2

Please sign in to comment.