On Mon, Oct 30, 2023 at 11:00 PM Hengqi Chen <hengqi.chen@xxxxxxxxx> wrote: > > This adds minimal support for seccomp eBPF programs > which can be hooked into the existing seccomp framework. > This allows users to write seccomp filter in eBPF language > and enables seccomp filter reuse through bpf prog fd and > bpffs. Currently, no helper calls are allowed just like > its cBPF version. > > Signed-off-by: Hengqi Chen <hengqi.chen@xxxxxxxxx> > --- > include/linux/bpf_types.h | 4 +++ > include/uapi/linux/bpf.h | 1 + > kernel/seccomp.c | 54 +++++++++++++++++++++++++++++++++++ > tools/lib/bpf/libbpf.c | 2 ++ > tools/lib/bpf/libbpf_probes.c | 1 + > 5 files changed, 62 insertions(+) > Let's make sure that bpf_prog_load_check_attach() errors out on non-zero attach type for this new program type? Ideally, if you can, let's refactor bpf_prog_load_check_attach() in such a way as to default to failing on non-zero attach type for any new program type. You'll need to explicitly list program types for which we don't enforce attach type. Thanks! > diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h > index fc0d6f32c687..7c0a9fc0b150 100644 > --- a/include/linux/bpf_types.h > +++ b/include/linux/bpf_types.h > @@ -83,6 +83,10 @@ BPF_PROG_TYPE(BPF_PROG_TYPE_SYSCALL, bpf_syscall, > BPF_PROG_TYPE(BPF_PROG_TYPE_NETFILTER, netfilter, > struct bpf_nf_ctx, struct bpf_nf_ctx) > #endif > +#ifdef CONFIG_SECCOMP_FILTER > +BPF_PROG_TYPE(BPF_PROG_TYPE_SECCOMP, seccomp, > + struct seccomp_data, struct seccomp_data) > +#endif > > BPF_MAP_TYPE(BPF_MAP_TYPE_ARRAY, array_map_ops) > BPF_MAP_TYPE(BPF_MAP_TYPE_PERCPU_ARRAY, percpu_array_map_ops) > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h > index 0f6cdf52b1da..f0fcfe0ccb2e 100644 > --- a/include/uapi/linux/bpf.h > +++ b/include/uapi/linux/bpf.h > @@ -995,6 +995,7 @@ enum bpf_prog_type { > BPF_PROG_TYPE_SK_LOOKUP, > BPF_PROG_TYPE_SYSCALL, /* a program that can execute syscalls */ > BPF_PROG_TYPE_NETFILTER, > + BPF_PROG_TYPE_SECCOMP, > }; > > enum bpf_attach_type { > diff --git a/kernel/seccomp.c b/kernel/seccomp.c > index 255999ba9190..5a6ed8630566 100644 > --- a/kernel/seccomp.c > +++ b/kernel/seccomp.c > @@ -15,6 +15,7 @@ > */ > #define pr_fmt(fmt) "seccomp: " fmt > > +#include <linux/bpf.h> > #include <linux/refcount.h> > #include <linux/audit.h> > #include <linux/compat.h> > @@ -2513,3 +2514,56 @@ int proc_pid_seccomp_cache(struct seq_file *m, struct pid_namespace *ns, > return 0; > } > #endif /* CONFIG_SECCOMP_CACHE_DEBUG */ > + > +#if defined(CONFIG_SECCOMP_FILTER) && defined(CONFIG_BPF_SYSCALL) > +const struct bpf_prog_ops seccomp_prog_ops = { > +}; > + > +static bool seccomp_is_valid_access(int off, int size, enum bpf_access_type type, > + const struct bpf_prog *prog, > + struct bpf_insn_access_aux *info) > +{ > + if (off < 0 || off >= sizeof(struct seccomp_data)) > + return false; > + > + if (off % size != 0) > + return false; > + > + if (type == BPF_WRITE) > + return false; > + > + switch (off) { > + case bpf_ctx_range(struct seccomp_data, nr): > + if (size != sizeof_field(struct seccomp_data, nr)) > + return false; > + return true; > + case bpf_ctx_range(struct seccomp_data, arch): > + if (size != sizeof_field(struct seccomp_data, arch)) > + return false; > + return true; > + case bpf_ctx_range(struct seccomp_data, instruction_pointer): > + if (size != sizeof_field(struct seccomp_data, instruction_pointer)) > + return false; > + return true; > + case bpf_ctx_range(struct seccomp_data, args): > + if (size != sizeof(__u64)) > + return false; > + return true; > + default: > + return false; > + } > + > + return false; > +} > + > +static const struct bpf_func_proto * > +bpf_seccomp_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) > +{ > + return NULL; > +} > + > +const struct bpf_verifier_ops seccomp_verifier_ops = { > + .is_valid_access = seccomp_is_valid_access, > + .get_func_proto = bpf_seccomp_func_proto, > +}; > +#endif /* CONFIG_SECCOMP_FILTER && CONFIG_BPF_SYSCALL */ > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c > index e067be95da3c..455d733f7315 100644 > --- a/tools/lib/bpf/libbpf.c > +++ b/tools/lib/bpf/libbpf.c > @@ -217,6 +217,7 @@ static const char * const prog_type_name[] = { > [BPF_PROG_TYPE_SK_LOOKUP] = "sk_lookup", > [BPF_PROG_TYPE_SYSCALL] = "syscall", > [BPF_PROG_TYPE_NETFILTER] = "netfilter", > + [BPF_PROG_TYPE_SECCOMP] = "seccomp", > }; > > static int __base_pr(enum libbpf_print_level level, const char *format, > @@ -8991,6 +8992,7 @@ static const struct bpf_sec_def section_defs[] = { > SEC_DEF("struct_ops.s+", STRUCT_OPS, 0, SEC_SLEEPABLE), > SEC_DEF("sk_lookup", SK_LOOKUP, BPF_SK_LOOKUP, SEC_ATTACHABLE), > SEC_DEF("netfilter", NETFILTER, BPF_NETFILTER, SEC_NONE), > + SEC_DEF("seccomp", SECCOMP, 0, SEC_NONE), > }; > > int libbpf_register_prog_handler(const char *sec, > diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c > index 9c4db90b92b6..b3ef3c0747be 100644 > --- a/tools/lib/bpf/libbpf_probes.c > +++ b/tools/lib/bpf/libbpf_probes.c > @@ -180,6 +180,7 @@ static int probe_prog_load(enum bpf_prog_type prog_type, > case BPF_PROG_TYPE_SK_REUSEPORT: > case BPF_PROG_TYPE_FLOW_DISSECTOR: > case BPF_PROG_TYPE_CGROUP_SYSCTL: > + case BPF_PROG_TYPE_SECCOMP: > break; > case BPF_PROG_TYPE_NETFILTER: > opts.expected_attach_type = BPF_NETFILTER; > -- > 2.34.1 >