* [PATCH bpf-next 0/6] bpf: Add seccomp program type
@ 2023-10-31 1:24 Hengqi Chen
2023-10-31 1:24 ` [PATCH bpf-next 1/6] bpf: Introduce BPF_PROG_TYPE_SECCOMP Hengqi Chen
` (5 more replies)
0 siblings, 6 replies; 14+ messages in thread
From: Hengqi Chen @ 2023-10-31 1:24 UTC (permalink / raw)
To: bpf; +Cc: ast, daniel, andrii, keescook, luto, wad, hengqi.chen
This patchset introduces seccomp program type which can be
used to attach to the existing seccomp framework.
The motivation is to enable sharing of seccomp filter through
bpf prog fd and bpffs. With this in place, we can eliminate
a hot path of JITing cBPF program (seccomp filter) where we apply
the same seccomp filter to thousands of micro VMs on a bare metal
instance.
This also allows us to write seccomp filter in an intuitive way,
see selftests for reference.
Hengqi Chen (6):
bpf: Introduce BPF_PROG_TYPE_SECCOMP
bpf: Add test_run support for seccomp program type
seccomp: Refactor filter copy/create for reuse
seccomp: Support attaching BPF_PROG_TYPE_SECCOMP progs
selftests/bpf: Add seccomp verifier tests
selftests/bpf: Test BPF_PROG_TYPE_SECCOMP
include/linux/bpf.h | 3 +
include/linux/bpf_types.h | 4 +
include/linux/seccomp.h | 3 +-
include/uapi/linux/bpf.h | 1 +
include/uapi/linux/seccomp.h | 2 +
kernel/seccomp.c | 142 ++++++++++++++--
net/bpf/test_run.c | 27 +++
tools/include/uapi/linux/bpf.h | 1 +
tools/include/uapi/linux/seccomp.h | 2 +
tools/lib/bpf/libbpf.c | 2 +
tools/lib/bpf/libbpf_probes.c | 1 +
.../selftests/bpf/prog_tests/seccomp.c | 40 +++++
.../selftests/bpf/prog_tests/verifier.c | 2 +
.../selftests/bpf/progs/test_seccomp.c | 24 +++
.../selftests/bpf/progs/verifier_seccomp.c | 154 ++++++++++++++++++
15 files changed, 390 insertions(+), 18 deletions(-)
create mode 100644 tools/testing/selftests/bpf/prog_tests/seccomp.c
create mode 100644 tools/testing/selftests/bpf/progs/test_seccomp.c
create mode 100644 tools/testing/selftests/bpf/progs/verifier_seccomp.c
--
2.34.1
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH bpf-next 1/6] bpf: Introduce BPF_PROG_TYPE_SECCOMP
2023-10-31 1:24 [PATCH bpf-next 0/6] bpf: Add seccomp program type Hengqi Chen
@ 2023-10-31 1:24 ` Hengqi Chen
2023-11-02 17:30 ` Andrii Nakryiko
2023-11-02 19:49 ` Kees Cook
2023-10-31 1:24 ` [PATCH bpf-next 2/6] bpf: Add test_run support for seccomp program type Hengqi Chen
` (4 subsequent siblings)
5 siblings, 2 replies; 14+ messages in thread
From: Hengqi Chen @ 2023-10-31 1:24 UTC (permalink / raw)
To: bpf; +Cc: ast, daniel, andrii, keescook, luto, wad, hengqi.chen
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@gmail.com>
---
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(+)
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
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH bpf-next 2/6] bpf: Add test_run support for seccomp program type
2023-10-31 1:24 [PATCH bpf-next 0/6] bpf: Add seccomp program type Hengqi Chen
2023-10-31 1:24 ` [PATCH bpf-next 1/6] bpf: Introduce BPF_PROG_TYPE_SECCOMP Hengqi Chen
@ 2023-10-31 1:24 ` Hengqi Chen
2023-11-02 17:32 ` Andrii Nakryiko
2023-10-31 1:24 ` [PATCH bpf-next 3/6] seccomp: Refactor filter copy/create for reuse Hengqi Chen
` (3 subsequent siblings)
5 siblings, 1 reply; 14+ messages in thread
From: Hengqi Chen @ 2023-10-31 1:24 UTC (permalink / raw)
To: bpf; +Cc: ast, daniel, andrii, keescook, luto, wad, hengqi.chen
Implement test_run for seccomp program type. Default
is to use an empty struct seccomp_data as bpf_context,
but can be overridden by userspace. This will be used
in selftests.
Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
---
include/linux/bpf.h | 3 +++
kernel/seccomp.c | 1 +
net/bpf/test_run.c | 27 +++++++++++++++++++++++++++
3 files changed, 31 insertions(+)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index b4825d3cdb29..e25338e67ec4 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -2376,6 +2376,9 @@ int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog,
int bpf_prog_test_run_nf(struct bpf_prog *prog,
const union bpf_attr *kattr,
union bpf_attr __user *uattr);
+int bpf_prog_test_run_seccomp(struct bpf_prog *prog,
+ const union bpf_attr *kattr,
+ union bpf_attr __user *uattr);
bool btf_ctx_access(int off, int size, enum bpf_access_type type,
const struct bpf_prog *prog,
struct bpf_insn_access_aux *info);
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 5a6ed8630566..1fa2312654a5 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -2517,6 +2517,7 @@ int proc_pid_seccomp_cache(struct seq_file *m, struct pid_namespace *ns,
#if defined(CONFIG_SECCOMP_FILTER) && defined(CONFIG_BPF_SYSCALL)
const struct bpf_prog_ops seccomp_prog_ops = {
+ .test_run = bpf_prog_test_run_seccomp,
};
static bool seccomp_is_valid_access(int off, int size, enum bpf_access_type type,
diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c
index 0841f8d82419..db159b9c56ca 100644
--- a/net/bpf/test_run.c
+++ b/net/bpf/test_run.c
@@ -20,6 +20,7 @@
#include <linux/smp.h>
#include <linux/sock_diag.h>
#include <linux/netfilter.h>
+#include <linux/seccomp.h>
#include <net/netdev_rx_queue.h>
#include <net/xdp.h>
#include <net/netfilter/nf_bpf_link.h>
@@ -1665,6 +1666,32 @@ int bpf_prog_test_run_nf(struct bpf_prog *prog,
return ret;
}
+int bpf_prog_test_run_seccomp(struct bpf_prog *prog,
+ const union bpf_attr *kattr,
+ union bpf_attr __user *uattr)
+{
+ void __user *ctx_in = u64_to_user_ptr(kattr->test.ctx_in);
+ __u32 ctx_size_in = kattr->test.ctx_size_in;
+ struct seccomp_data ctx = {};
+ __u32 retval;
+
+ if (kattr->test.flags || kattr->test.cpu || kattr->test.batch_size)
+ return -EINVAL;
+
+ if (ctx_size_in && ctx_size_in < sizeof(ctx))
+ return -EINVAL;
+
+ if (ctx_size_in && copy_from_user(&ctx, ctx_in, sizeof(ctx)))
+ return -EFAULT;
+
+ retval = bpf_prog_run_pin_on_cpu(prog, &ctx);
+
+ if (copy_to_user(&uattr->test.retval, &retval, sizeof(retval)))
+ return -EFAULT;
+
+ return 0;
+}
+
static const struct btf_kfunc_id_set bpf_prog_test_kfunc_set = {
.owner = THIS_MODULE,
.set = &test_sk_check_kfunc_ids,
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH bpf-next 3/6] seccomp: Refactor filter copy/create for reuse
2023-10-31 1:24 [PATCH bpf-next 0/6] bpf: Add seccomp program type Hengqi Chen
2023-10-31 1:24 ` [PATCH bpf-next 1/6] bpf: Introduce BPF_PROG_TYPE_SECCOMP Hengqi Chen
2023-10-31 1:24 ` [PATCH bpf-next 2/6] bpf: Add test_run support for seccomp program type Hengqi Chen
@ 2023-10-31 1:24 ` Hengqi Chen
2023-10-31 1:24 ` [PATCH bpf-next 4/6] seccomp: Support attaching BPF_PROG_TYPE_SECCOMP progs Hengqi Chen
` (2 subsequent siblings)
5 siblings, 0 replies; 14+ messages in thread
From: Hengqi Chen @ 2023-10-31 1:24 UTC (permalink / raw)
To: bpf; +Cc: ast, daniel, andrii, keescook, luto, wad, hengqi.chen
This refactors seccomp_prepare_filter() for reuse in
subsequent additions. No functional change intended.
Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
---
kernel/seccomp.c | 50 +++++++++++++++++++++++++++++++++---------------
1 file changed, 35 insertions(+), 15 deletions(-)
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 1fa2312654a5..2a724690a627 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -641,14 +641,14 @@ static inline void seccomp_sync_threads(unsigned long flags)
}
/**
- * seccomp_prepare_filter: Prepares a seccomp filter for use.
- * @fprog: BPF program to install
+ * seccomp_prepare_prog - prepares a JITed BPF filter for use.
+ * @pfp: the unattached filter that is created
+ * @fprog: the filter program
*
- * Returns filter on success or an ERR_PTR on failure.
+ * Returns 0 on success and non-zero otherwise.
*/
-static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog)
+static int seccomp_prepare_prog(struct bpf_prog **pfp, struct sock_fprog *fprog)
{
- struct seccomp_filter *sfilter;
int ret;
const bool save_orig =
#if defined(CONFIG_CHECKPOINT_RESTORE) || defined(SECCOMP_ARCH_NATIVE)
@@ -658,10 +658,27 @@ static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog)
#endif
if (fprog->len == 0 || fprog->len > BPF_MAXINSNS)
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
BUG_ON(INT_MAX / fprog->len < sizeof(struct sock_filter));
+ ret = bpf_prog_create_from_user(pfp, fprog, seccomp_check_filter, save_orig);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+/**
+ * seccomp_prepare_filter: Prepares a seccomp filter for use.
+ * @prog: BPF program to install
+ *
+ * Returns filter on success or an ERR_PTR on failure.
+ */
+static struct seccomp_filter *seccomp_prepare_filter(struct bpf_prog *prog)
+{
+ struct seccomp_filter *sfilter;
+
/*
* Installing a seccomp filter requires that the task has
* CAP_SYS_ADMIN in its namespace or be running with no_new_privs.
@@ -678,13 +695,7 @@ static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog)
return ERR_PTR(-ENOMEM);
mutex_init(&sfilter->notify_lock);
- ret = bpf_prog_create_from_user(&sfilter->prog, fprog,
- seccomp_check_filter, save_orig);
- if (ret < 0) {
- kfree(sfilter);
- return ERR_PTR(ret);
- }
-
+ sfilter->prog = prog;
refcount_set(&sfilter->refs, 1);
refcount_set(&sfilter->users, 1);
init_waitqueue_head(&sfilter->wqh);
@@ -701,8 +712,10 @@ static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog)
static struct seccomp_filter *
seccomp_prepare_user_filter(const char __user *user_filter)
{
- struct sock_fprog fprog;
struct seccomp_filter *filter = ERR_PTR(-EFAULT);
+ struct sock_fprog fprog;
+ struct bpf_prog *prog;
+ int ret;
#ifdef CONFIG_COMPAT
if (in_compat_syscall()) {
@@ -715,7 +728,14 @@ seccomp_prepare_user_filter(const char __user *user_filter)
#endif
if (copy_from_user(&fprog, user_filter, sizeof(fprog)))
goto out;
- filter = seccomp_prepare_filter(&fprog);
+
+ ret = seccomp_prepare_prog(&prog, &fprog);
+ if (ret)
+ return ERR_PTR(ret);
+
+ filter = seccomp_prepare_filter(prog);
+ if (IS_ERR(filter))
+ bpf_prog_destroy(prog);
out:
return filter;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH bpf-next 4/6] seccomp: Support attaching BPF_PROG_TYPE_SECCOMP progs
2023-10-31 1:24 [PATCH bpf-next 0/6] bpf: Add seccomp program type Hengqi Chen
` (2 preceding siblings ...)
2023-10-31 1:24 ` [PATCH bpf-next 3/6] seccomp: Refactor filter copy/create for reuse Hengqi Chen
@ 2023-10-31 1:24 ` Hengqi Chen
2023-10-31 1:24 ` [PATCH bpf-next 5/6] selftests/bpf: Add seccomp verifier tests Hengqi Chen
2023-10-31 1:24 ` [PATCH bpf-next 6/6] selftests/bpf: Test BPF_PROG_TYPE_SECCOMP Hengqi Chen
5 siblings, 0 replies; 14+ messages in thread
From: Hengqi Chen @ 2023-10-31 1:24 UTC (permalink / raw)
To: bpf; +Cc: ast, daniel, andrii, keescook, luto, wad, hengqi.chen
Add a new flag SECCOMP_FILTER_FLAG_BPF_PROG_FD for
SECCOMP_SET_MODE_FILTER, which indicates the seccomp filter
is a seccomp bpf prog fd, not a sock_fprog. This allows
us to attach seccomp filter that is previously loaded via
bpf syscall.
Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
---
include/linux/seccomp.h | 3 ++-
include/uapi/linux/seccomp.h | 2 ++
kernel/seccomp.c | 37 ++++++++++++++++++++++++++++++++++--
3 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index 175079552f68..7caa53b629d9 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -9,7 +9,8 @@
SECCOMP_FILTER_FLAG_SPEC_ALLOW | \
SECCOMP_FILTER_FLAG_NEW_LISTENER | \
SECCOMP_FILTER_FLAG_TSYNC_ESRCH | \
- SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV)
+ SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV | \
+ SECCOMP_FILTER_FLAG_BPF_PROG_FD)
/* sizeof() the first published struct seccomp_notif_addfd */
#define SECCOMP_NOTIFY_ADDFD_SIZE_VER0 24
diff --git a/include/uapi/linux/seccomp.h b/include/uapi/linux/seccomp.h
index dbfc9b37fcae..db792dc96b5a 100644
--- a/include/uapi/linux/seccomp.h
+++ b/include/uapi/linux/seccomp.h
@@ -25,6 +25,8 @@
#define SECCOMP_FILTER_FLAG_TSYNC_ESRCH (1UL << 4)
/* Received notifications wait in killable state (only respond to fatal signals) */
#define SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV (1UL << 5)
+/* Indicates that the filter is in form of bpf prog fd */
+#define SECCOMP_FILTER_FLAG_BPF_PROG_FD (1UL << 6)
/*
* All BPF programs must return a 32-bit value.
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 2a724690a627..f88dc7880cfa 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -524,7 +524,10 @@ static inline pid_t seccomp_can_sync_threads(void)
static inline void seccomp_filter_free(struct seccomp_filter *filter)
{
if (filter) {
- bpf_prog_destroy(filter->prog);
+ if (filter->prog->type == BPF_PROG_TYPE_SECCOMP)
+ bpf_prog_put(filter->prog);
+ else
+ bpf_prog_destroy(filter->prog);
kfree(filter);
}
}
@@ -740,6 +743,33 @@ seccomp_prepare_user_filter(const char __user *user_filter)
return filter;
}
+/**
+ * seccomp_prepare_filter_from_fd - prepares filter from a user-supplied fd
+ * @ufd: pointer to fd that refers to a seccomp bpf prog.
+ *
+ * Returns filter on success or an ERR_PTR on failure.
+ */
+static struct seccomp_filter *
+seccomp_prepare_filter_from_fd(const char __user *ufd)
+{
+ struct seccomp_filter *sfilter;
+ struct bpf_prog *prog;
+ int fd;
+
+ if (copy_from_user(&fd, ufd, sizeof(fd)))
+ return ERR_PTR(-EFAULT);
+
+ prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_SECCOMP);
+ if (IS_ERR(prog))
+ return ERR_PTR(-EBADF);
+
+ sfilter = seccomp_prepare_filter(prog);
+ if (IS_ERR(sfilter))
+ bpf_prog_put(prog);
+
+ return sfilter;
+}
+
#ifdef SECCOMP_ARCH_NATIVE
/**
* seccomp_is_const_allow - check if filter is constant allow with given data
@@ -1953,7 +1983,10 @@ static long seccomp_set_mode_filter(unsigned int flags,
return -EINVAL;
/* Prepare the new filter before holding any locks. */
- prepared = seccomp_prepare_user_filter(filter);
+ if (flags & SECCOMP_FILTER_FLAG_BPF_PROG_FD)
+ prepared = seccomp_prepare_filter_from_fd(filter);
+ else
+ prepared = seccomp_prepare_user_filter(filter);
if (IS_ERR(prepared))
return PTR_ERR(prepared);
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH bpf-next 5/6] selftests/bpf: Add seccomp verifier tests
2023-10-31 1:24 [PATCH bpf-next 0/6] bpf: Add seccomp program type Hengqi Chen
` (3 preceding siblings ...)
2023-10-31 1:24 ` [PATCH bpf-next 4/6] seccomp: Support attaching BPF_PROG_TYPE_SECCOMP progs Hengqi Chen
@ 2023-10-31 1:24 ` Hengqi Chen
2023-10-31 1:24 ` [PATCH bpf-next 6/6] selftests/bpf: Test BPF_PROG_TYPE_SECCOMP Hengqi Chen
5 siblings, 0 replies; 14+ messages in thread
From: Hengqi Chen @ 2023-10-31 1:24 UTC (permalink / raw)
To: bpf; +Cc: ast, daniel, andrii, keescook, luto, wad, hengqi.chen
This tests seccomp context access and helper call
restriction.
# ./test_progs -t verifier_seccomp
#375/1 verifier_seccomp/seccomp no helper call:OK
#375/2 verifier_seccomp/seccomp invalid ctx access, write:OK
#375/3 verifier_seccomp/seccomp invalid ctx access, out of range:OK
#375/4 verifier_seccomp/seccomp invalid ctx access, size too short:OK
#375/5 verifier_seccomp/seccomp invalid ctx access, size too short:OK
#375/6 verifier_seccomp/seccomp invalid ctx access, size too short:OK
#375/7 verifier_seccomp/seccomp invalid ctx access, size too short:OK
#375/8 verifier_seccomp/seccomp invalid ctx access, size too large:OK
#375/9 verifier_seccomp/seccomp ctx access, valid:OK
#375 verifier_seccomp:OK
Summary: 1/9 PASSED, 0 SKIPPED, 0 FAILED
Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
---
.../selftests/bpf/prog_tests/verifier.c | 2 +
.../selftests/bpf/progs/verifier_seccomp.c | 154 ++++++++++++++++++
2 files changed, 156 insertions(+)
create mode 100644 tools/testing/selftests/bpf/progs/verifier_seccomp.c
diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c
index e3e68c97b40c..dfb40a11939e 100644
--- a/tools/testing/selftests/bpf/prog_tests/verifier.c
+++ b/tools/testing/selftests/bpf/prog_tests/verifier.c
@@ -57,6 +57,7 @@
#include "verifier_scalar_ids.skel.h"
#include "verifier_sdiv.skel.h"
#include "verifier_search_pruning.skel.h"
+#include "verifier_seccomp.skel.h"
#include "verifier_sock.skel.h"
#include "verifier_spill_fill.skel.h"
#include "verifier_spin_lock.skel.h"
@@ -164,6 +165,7 @@ void test_verifier_runtime_jit(void) { RUN(verifier_runtime_jit); }
void test_verifier_scalar_ids(void) { RUN(verifier_scalar_ids); }
void test_verifier_sdiv(void) { RUN(verifier_sdiv); }
void test_verifier_search_pruning(void) { RUN(verifier_search_pruning); }
+void test_verifier_seccomp(void) { RUN(verifier_seccomp); }
void test_verifier_sock(void) { RUN(verifier_sock); }
void test_verifier_spill_fill(void) { RUN(verifier_spill_fill); }
void test_verifier_spin_lock(void) { RUN(verifier_spin_lock); }
diff --git a/tools/testing/selftests/bpf/progs/verifier_seccomp.c b/tools/testing/selftests/bpf/progs/verifier_seccomp.c
new file mode 100644
index 000000000000..d3984a0cdae0
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/verifier_seccomp.c
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2023 Hengqi Chen */
+
+#include "vmlinux.h"
+#include "bpf_misc.h"
+
+#include <bpf/bpf_endian.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_helpers.h>
+
+SEC("seccomp")
+__description("seccomp no helper call")
+__failure __msg("unknown func bpf_get_prandom_u32")
+__naked void seccomp_no_helper_call(void)
+{
+ asm volatile (" \
+ call %[bpf_get_prandom_u32]; \
+ r0 = 0; \
+ exit;" \
+ :
+ : __imm(bpf_get_prandom_u32)
+ : __clobber_all);
+}
+
+SEC("seccomp")
+__description("seccomp invalid ctx access, write")
+__failure __msg("invalid bpf_context access")
+__naked void seccomp_ctx_write(void)
+{
+ asm volatile (" \
+ r2 = r1; \
+ *(u64*)(r2 + 8) = r1; \
+ r0 = 0; \
+ exit;" \
+ :
+ :
+ : __clobber_all);
+}
+
+SEC("seccomp")
+__description("seccomp invalid ctx access, out of range")
+__failure __msg("invalid bpf_context access")
+__naked void seccomp_ctx_read_out_of_range(void)
+{
+ asm volatile (" \
+ r2 = *(u64*)(r1 + %[__bpf_seccomp_ctx_size]); \
+ r0 = 0; \
+ exit;" \
+ :
+ : __imm_const(__bpf_seccomp_ctx_size, sizeof(struct seccomp_data))
+ : __clobber_all);
+}
+
+SEC("seccomp")
+__description("seccomp invalid ctx access, size too short")
+__failure __msg("invalid bpf_context access")
+__naked void seccomp_ctx_read_too_short1(void)
+{
+ asm volatile (" \
+ r2 = *(u8*)(r1 + %[__bpf_seccomp_ctx_nr]); \
+ r0 = 0; \
+ exit;" \
+ :
+ : __imm_const(__bpf_seccomp_ctx_nr, offsetof(struct seccomp_data, nr))
+ : __clobber_all);
+}
+
+SEC("seccomp")
+__description("seccomp invalid ctx access, size too short")
+__failure __msg("invalid bpf_context access")
+__naked void seccomp_ctx_read_too_short2(void)
+{
+ asm volatile (" \
+ r2 = *(u16*)(r1 + %[__bpf_seccomp_ctx_arch]); \
+ r0 = 0; \
+ exit;" \
+ :
+ : __imm_const(__bpf_seccomp_ctx_arch, offsetof(struct seccomp_data, arch))
+ : __clobber_all);
+}
+
+SEC("seccomp")
+__description("seccomp invalid ctx access, size too short")
+__failure __msg("invalid bpf_context access")
+__naked void seccomp_ctx_read_too_short3(void)
+{
+ asm volatile (" \
+ r2 = *(u32*)(r1 + %[__bpf_seccomp_ctx_ip]); \
+ r0 = 0; \
+ exit;" \
+ :
+ : __imm_const(__bpf_seccomp_ctx_ip, offsetof(struct seccomp_data, instruction_pointer))
+ : __clobber_all);
+}
+
+SEC("seccomp")
+__description("seccomp invalid ctx access, size too short")
+__failure __msg("invalid bpf_context access")
+__naked void seccomp_ctx_read_too_short4(void)
+{
+ asm volatile (" \
+ r2 = *(u32*)(r1 + %[__bpf_seccomp_ctx_arg1]); \
+ r0 = 0; \
+ exit;" \
+ :
+ : __imm_const(__bpf_seccomp_ctx_arg1, offsetof(struct seccomp_data, args[1]))
+ : __clobber_all);
+}
+
+SEC("seccomp")
+__description("seccomp invalid ctx access, size too large")
+__failure __msg("invalid bpf_context access")
+__naked void seccomp_ctx_read_too_large(void)
+{
+ asm volatile (" \
+ r2 = *(u64*)(r1 + %[__bpf_seccomp_ctx_nr]); \
+ r0 = 0; \
+ exit;" \
+ :
+ : __imm_const(__bpf_seccomp_ctx_nr, offsetof(struct seccomp_data, nr))
+ : __clobber_all);
+}
+
+SEC("seccomp")
+__description("seccomp ctx access, valid")
+__success __retval(0x5ecc0779)
+__naked void seccomp_ctx_read_ok(void)
+{
+ asm volatile (" \
+ r2 = *(u32*)(r1 + %[__bpf_seccomp_ctx_nr]); \
+ r2 = *(u32*)(r1 + %[__bpf_seccomp_ctx_arch]); \
+ r2 = *(u64*)(r1 + %[__bpf_seccomp_ctx_ip]); \
+ r2 = *(u64*)(r1 + %[__bpf_seccomp_ctx_arg0]); \
+ r2 = *(u64*)(r1 + %[__bpf_seccomp_ctx_arg1]); \
+ r2 = *(u64*)(r1 + %[__bpf_seccomp_ctx_arg2]); \
+ r2 = *(u64*)(r1 + %[__bpf_seccomp_ctx_arg3]); \
+ r2 = *(u64*)(r1 + %[__bpf_seccomp_ctx_arg4]); \
+ r2 = *(u64*)(r1 + %[__bpf_seccomp_ctx_arg5]); \
+ r0 = 0x5ecc0779; \
+ exit;" \
+ :
+ : __imm_const(__bpf_seccomp_ctx_nr, offsetof(struct seccomp_data, nr)),
+ __imm_const(__bpf_seccomp_ctx_arch, offsetof(struct seccomp_data, arch)),
+ __imm_const(__bpf_seccomp_ctx_ip, offsetof(struct seccomp_data, instruction_pointer)),
+ __imm_const(__bpf_seccomp_ctx_arg0, offsetof(struct seccomp_data, args[0])),
+ __imm_const(__bpf_seccomp_ctx_arg1, offsetof(struct seccomp_data, args[1])),
+ __imm_const(__bpf_seccomp_ctx_arg2, offsetof(struct seccomp_data, args[2])),
+ __imm_const(__bpf_seccomp_ctx_arg3, offsetof(struct seccomp_data, args[3])),
+ __imm_const(__bpf_seccomp_ctx_arg4, offsetof(struct seccomp_data, args[4])),
+ __imm_const(__bpf_seccomp_ctx_arg5, offsetof(struct seccomp_data, args[5]))
+ : __clobber_all);
+}
+
+char _license[] SEC("license") = "GPL";
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH bpf-next 6/6] selftests/bpf: Test BPF_PROG_TYPE_SECCOMP
2023-10-31 1:24 [PATCH bpf-next 0/6] bpf: Add seccomp program type Hengqi Chen
` (4 preceding siblings ...)
2023-10-31 1:24 ` [PATCH bpf-next 5/6] selftests/bpf: Add seccomp verifier tests Hengqi Chen
@ 2023-10-31 1:24 ` Hengqi Chen
5 siblings, 0 replies; 14+ messages in thread
From: Hengqi Chen @ 2023-10-31 1:24 UTC (permalink / raw)
To: bpf; +Cc: ast, daniel, andrii, keescook, luto, wad, hengqi.chen
Add a testcase to exercise BPF_PROG_TYPE_SECCOMP.
# ./test_progs -n 194
#194 seccomp:OK
Summary: 1/0 PASSED, 0 SKIPPED, 0 FAILED
Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
---
tools/include/uapi/linux/bpf.h | 1 +
tools/include/uapi/linux/seccomp.h | 2 +
.../selftests/bpf/prog_tests/seccomp.c | 40 +++++++++++++++++++
.../selftests/bpf/progs/test_seccomp.c | 24 +++++++++++
4 files changed, 67 insertions(+)
create mode 100644 tools/testing/selftests/bpf/prog_tests/seccomp.c
create mode 100644 tools/testing/selftests/bpf/progs/test_seccomp.c
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 0f6cdf52b1da..f0fcfe0ccb2e 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/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/tools/include/uapi/linux/seccomp.h b/tools/include/uapi/linux/seccomp.h
index dbfc9b37fcae..db792dc96b5a 100644
--- a/tools/include/uapi/linux/seccomp.h
+++ b/tools/include/uapi/linux/seccomp.h
@@ -25,6 +25,8 @@
#define SECCOMP_FILTER_FLAG_TSYNC_ESRCH (1UL << 4)
/* Received notifications wait in killable state (only respond to fatal signals) */
#define SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV (1UL << 5)
+/* Indicates that the filter is in form of bpf prog fd */
+#define SECCOMP_FILTER_FLAG_BPF_PROG_FD (1UL << 6)
/*
* All BPF programs must return a 32-bit value.
diff --git a/tools/testing/selftests/bpf/prog_tests/seccomp.c b/tools/testing/selftests/bpf/prog_tests/seccomp.c
new file mode 100644
index 000000000000..fc7db6af7d64
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/seccomp.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2023 Hengqi Chen */
+
+#include <test_progs.h>
+#include <linux/seccomp.h>
+#include "test_seccomp.skel.h"
+
+static int seccomp(unsigned int op, unsigned int flags, void *args)
+{
+ errno = 0;
+ return syscall(__NR_seccomp, op, flags, args);
+}
+
+void test_seccomp(void)
+{
+ struct test_seccomp *skel;
+ int fd, flags, ret;
+
+ skel = test_seccomp__open();
+ if (!ASSERT_OK_PTR(skel, "skel_open"))
+ return;
+
+ skel->rodata->seccomp_syscall_nr = __NR_seccomp;
+ skel->rodata->seccomp_errno = 99;
+
+ ret = test_seccomp__load(skel);
+ if (!ASSERT_OK(ret, "skel_load"))
+ goto cleanup;
+
+ fd = bpf_program__fd(skel->progs.seccomp_prog);
+ flags = SECCOMP_FILTER_FLAG_BPF_PROG_FD;
+ ret = seccomp(SECCOMP_SET_MODE_FILTER, flags, &fd);
+ ASSERT_OK(ret, "seccomp_set_bpf_prog");
+ ret = seccomp(SECCOMP_SET_MODE_FILTER, flags, &fd);
+ ASSERT_EQ(ret, -1, "seccomp should fail");
+ ASSERT_EQ(errno, 99, "errno not equal to 99");
+
+cleanup:
+ test_seccomp__destroy(skel);
+}
diff --git a/tools/testing/selftests/bpf/progs/test_seccomp.c b/tools/testing/selftests/bpf/progs/test_seccomp.c
new file mode 100644
index 000000000000..c53e75b8c0ec
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_seccomp.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2023 Hengqi Chen */
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+#define SECCOMP_RET_ERRNO 0x00050000U
+#define SECCOMP_RET_ALLOW 0x7fff0000U
+#define SECCOMP_RET_DATA 0x0000ffffU
+
+const volatile int seccomp_syscall_nr = 0;
+const volatile __u32 seccomp_errno = 0;
+
+SEC("seccomp")
+int seccomp_prog(struct seccomp_data *ctx)
+{
+ if (ctx->nr != seccomp_syscall_nr)
+ return SECCOMP_RET_ALLOW;
+
+ return SECCOMP_RET_ERRNO | (seccomp_errno & SECCOMP_RET_DATA);
+}
+
+char _license[] SEC("license") = "GPL";
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 1/6] bpf: Introduce BPF_PROG_TYPE_SECCOMP
2023-10-31 1:24 ` [PATCH bpf-next 1/6] bpf: Introduce BPF_PROG_TYPE_SECCOMP Hengqi Chen
@ 2023-11-02 17:30 ` Andrii Nakryiko
2023-11-02 19:49 ` Kees Cook
1 sibling, 0 replies; 14+ messages in thread
From: Andrii Nakryiko @ 2023-11-02 17:30 UTC (permalink / raw)
To: Hengqi Chen; +Cc: bpf, ast, daniel, andrii, keescook, luto, wad
On Mon, Oct 30, 2023 at 11:00 PM Hengqi Chen <hengqi.chen@gmail.com> 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@gmail.com>
> ---
> 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
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 2/6] bpf: Add test_run support for seccomp program type
2023-10-31 1:24 ` [PATCH bpf-next 2/6] bpf: Add test_run support for seccomp program type Hengqi Chen
@ 2023-11-02 17:32 ` Andrii Nakryiko
0 siblings, 0 replies; 14+ messages in thread
From: Andrii Nakryiko @ 2023-11-02 17:32 UTC (permalink / raw)
To: Hengqi Chen; +Cc: bpf, ast, daniel, andrii, keescook, luto, wad
On Mon, Oct 30, 2023 at 11:00 PM Hengqi Chen <hengqi.chen@gmail.com> wrote:
>
> Implement test_run for seccomp program type. Default
> is to use an empty struct seccomp_data as bpf_context,
> but can be overridden by userspace. This will be used
> in selftests.
>
> Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
> ---
> include/linux/bpf.h | 3 +++
> kernel/seccomp.c | 1 +
> net/bpf/test_run.c | 27 +++++++++++++++++++++++++++
> 3 files changed, 31 insertions(+)
>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index b4825d3cdb29..e25338e67ec4 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -2376,6 +2376,9 @@ int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog,
> int bpf_prog_test_run_nf(struct bpf_prog *prog,
> const union bpf_attr *kattr,
> union bpf_attr __user *uattr);
> +int bpf_prog_test_run_seccomp(struct bpf_prog *prog,
> + const union bpf_attr *kattr,
> + union bpf_attr __user *uattr);
> bool btf_ctx_access(int off, int size, enum bpf_access_type type,
> const struct bpf_prog *prog,
> struct bpf_insn_access_aux *info);
> diff --git a/kernel/seccomp.c b/kernel/seccomp.c
> index 5a6ed8630566..1fa2312654a5 100644
> --- a/kernel/seccomp.c
> +++ b/kernel/seccomp.c
> @@ -2517,6 +2517,7 @@ int proc_pid_seccomp_cache(struct seq_file *m, struct pid_namespace *ns,
>
> #if defined(CONFIG_SECCOMP_FILTER) && defined(CONFIG_BPF_SYSCALL)
> const struct bpf_prog_ops seccomp_prog_ops = {
> + .test_run = bpf_prog_test_run_seccomp,
> };
>
> static bool seccomp_is_valid_access(int off, int size, enum bpf_access_type type,
> diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c
> index 0841f8d82419..db159b9c56ca 100644
> --- a/net/bpf/test_run.c
> +++ b/net/bpf/test_run.c
> @@ -20,6 +20,7 @@
> #include <linux/smp.h>
> #include <linux/sock_diag.h>
> #include <linux/netfilter.h>
> +#include <linux/seccomp.h>
> #include <net/netdev_rx_queue.h>
> #include <net/xdp.h>
> #include <net/netfilter/nf_bpf_link.h>
> @@ -1665,6 +1666,32 @@ int bpf_prog_test_run_nf(struct bpf_prog *prog,
> return ret;
> }
>
> +int bpf_prog_test_run_seccomp(struct bpf_prog *prog,
> + const union bpf_attr *kattr,
> + union bpf_attr __user *uattr)
> +{
> + void __user *ctx_in = u64_to_user_ptr(kattr->test.ctx_in);
> + __u32 ctx_size_in = kattr->test.ctx_size_in;
> + struct seccomp_data ctx = {};
> + __u32 retval;
> +
> + if (kattr->test.flags || kattr->test.cpu || kattr->test.batch_size)
> + return -EINVAL;
> +
what about ctx_out, ctx_size_out, data_size_in/data_size_out, etc,
etc. Should we enforce that they all stay zero? Similar questions to
repeat and duration.
> + if (ctx_size_in && ctx_size_in < sizeof(ctx))
> + return -EINVAL;
> +
> + if (ctx_size_in && copy_from_user(&ctx, ctx_in, sizeof(ctx)))
> + return -EFAULT;
> +
> + retval = bpf_prog_run_pin_on_cpu(prog, &ctx);
> +
> + if (copy_to_user(&uattr->test.retval, &retval, sizeof(retval)))
> + return -EFAULT;
> +
> + return 0;
> +}
> +
> static const struct btf_kfunc_id_set bpf_prog_test_kfunc_set = {
> .owner = THIS_MODULE,
> .set = &test_sk_check_kfunc_ids,
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 1/6] bpf: Introduce BPF_PROG_TYPE_SECCOMP
2023-10-31 1:24 ` [PATCH bpf-next 1/6] bpf: Introduce BPF_PROG_TYPE_SECCOMP Hengqi Chen
2023-11-02 17:30 ` Andrii Nakryiko
@ 2023-11-02 19:49 ` Kees Cook
2023-11-02 19:53 ` Alexei Starovoitov
2023-11-03 5:46 ` Hengqi Chen
1 sibling, 2 replies; 14+ messages in thread
From: Kees Cook @ 2023-11-02 19:49 UTC (permalink / raw)
To: Hengqi Chen, bpf; +Cc: ast, daniel, andrii, keescook, luto, wad, hengqi.chen
On October 30, 2023 6:24:02 PM PDT, Hengqi Chen <hengqi.chen@gmail.com> 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.
I think this is bypassing the seccomp bitmap generation pass, so this will break (at least) performance.
I continue to prefer sticking to only cBPF for seccomp, so let's just use the seccomp syscall to generate the fds.
-Kees
--
Kees Cook
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 1/6] bpf: Introduce BPF_PROG_TYPE_SECCOMP
2023-11-02 19:49 ` Kees Cook
@ 2023-11-02 19:53 ` Alexei Starovoitov
2023-11-03 20:44 ` Kees Cook
2023-11-03 5:46 ` Hengqi Chen
1 sibling, 1 reply; 14+ messages in thread
From: Alexei Starovoitov @ 2023-11-02 19:53 UTC (permalink / raw)
To: Kees Cook
Cc: Hengqi Chen, bpf, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Kees Cook, Andy Lutomirski, Will Drewry
On Thu, Nov 2, 2023 at 12:49 PM Kees Cook <kees@kernel.org> wrote:
>
>
>
> On October 30, 2023 6:24:02 PM PDT, Hengqi Chen <hengqi.chen@gmail.com> 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.
>
> I think this is bypassing the seccomp bitmap generation pass, so this will break (at least) performance.
>
> I continue to prefer sticking to only cBPF for seccomp, so let's just use the seccomp syscall to generate the fds.
That's fine, but let's not mix old things with bpffs, bpftool, etc.
If you want an anon_fd then go ahead and allocate it standalone.
It shouldn't be confused with eBPF fd-s.
No bpffs treatment and no bpftool visibility.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 1/6] bpf: Introduce BPF_PROG_TYPE_SECCOMP
2023-11-02 19:49 ` Kees Cook
2023-11-02 19:53 ` Alexei Starovoitov
@ 2023-11-03 5:46 ` Hengqi Chen
2023-11-03 8:47 ` Hengqi Chen
1 sibling, 1 reply; 14+ messages in thread
From: Hengqi Chen @ 2023-11-03 5:46 UTC (permalink / raw)
To: Kees Cook; +Cc: bpf, ast, daniel, andrii, keescook, luto, wad
Hi, Kees:
On Fri, Nov 3, 2023 at 3:49 AM Kees Cook <kees@kernel.org> wrote:
>
>
>
> On October 30, 2023 6:24:02 PM PDT, Hengqi Chen <hengqi.chen@gmail.com> 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.
>
> I think this is bypassing the seccomp bitmap generation pass, so this will break (at least) performance.
>
What if we did the same for eBPF, a bit harder though, does that
address your concerns ?
> I continue to prefer sticking to only cBPF for seccomp, so let's just use the seccomp syscall to generate the fds.
>
That's an alternative. But as Alexei said, there would be no more bpffs things.
AFAIK, we could only share the filter via UDS.
> -Kees
>
> --
> Kees Cook
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 1/6] bpf: Introduce BPF_PROG_TYPE_SECCOMP
2023-11-03 5:46 ` Hengqi Chen
@ 2023-11-03 8:47 ` Hengqi Chen
0 siblings, 0 replies; 14+ messages in thread
From: Hengqi Chen @ 2023-11-03 8:47 UTC (permalink / raw)
To: Kees Cook; +Cc: bpf, ast, daniel, andrii, keescook, luto, wad
On Fri, Nov 3, 2023 at 1:46 PM Hengqi Chen <hengqi.chen@gmail.com> wrote:
>
> Hi, Kees:
>
> On Fri, Nov 3, 2023 at 3:49 AM Kees Cook <kees@kernel.org> wrote:
> >
> >
> >
> > On October 30, 2023 6:24:02 PM PDT, Hengqi Chen <hengqi.chen@gmail.com> 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.
> >
> > I think this is bypassing the seccomp bitmap generation pass, so this will break (at least) performance.
> >
>
> What if we did the same for eBPF, a bit harder though, does that
> address your concerns ?
>
> > I continue to prefer sticking to only cBPF for seccomp, so let's just use the seccomp syscall to generate the fds.
> >
>
> That's an alternative. But as Alexei said, there would be no more bpffs things.
> AFAIK, we could only share the filter via UDS.
>
Just take a deeper look, there are too many
registers/instructions/states in eBPF,
stick to cBPF would be easier for now.
> > -Kees
> >
> > --
> > Kees Cook
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH bpf-next 1/6] bpf: Introduce BPF_PROG_TYPE_SECCOMP
2023-11-02 19:53 ` Alexei Starovoitov
@ 2023-11-03 20:44 ` Kees Cook
0 siblings, 0 replies; 14+ messages in thread
From: Kees Cook @ 2023-11-03 20:44 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Hengqi Chen, bpf, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Kees Cook, Andy Lutomirski, Will Drewry
On November 2, 2023 12:53:56 PM PDT, Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
>On Thu, Nov 2, 2023 at 12:49 PM Kees Cook <kees@kernel.org> wrote:
>>
>>
>>
>> On October 30, 2023 6:24:02 PM PDT, Hengqi Chen <hengqi.chen@gmail.com> 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.
>>
>> I think this is bypassing the seccomp bitmap generation pass, so this will break (at least) performance.
>>
>> I continue to prefer sticking to only cBPF for seccomp, so let's just use the seccomp syscall to generate the fds.
>
>That's fine, but let's not mix old things with bpffs, bpftool, etc.
>If you want an anon_fd then go ahead and allocate it standalone.
>It shouldn't be confused with eBPF fd-s.
>No bpffs treatment and no bpftool visibility.
Agreed. Let's just emit an anon_fd from the seccomp syscall.
--
Kees Cook
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2023-11-03 20:44 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-10-31 1:24 [PATCH bpf-next 0/6] bpf: Add seccomp program type Hengqi Chen
2023-10-31 1:24 ` [PATCH bpf-next 1/6] bpf: Introduce BPF_PROG_TYPE_SECCOMP Hengqi Chen
2023-11-02 17:30 ` Andrii Nakryiko
2023-11-02 19:49 ` Kees Cook
2023-11-02 19:53 ` Alexei Starovoitov
2023-11-03 20:44 ` Kees Cook
2023-11-03 5:46 ` Hengqi Chen
2023-11-03 8:47 ` Hengqi Chen
2023-10-31 1:24 ` [PATCH bpf-next 2/6] bpf: Add test_run support for seccomp program type Hengqi Chen
2023-11-02 17:32 ` Andrii Nakryiko
2023-10-31 1:24 ` [PATCH bpf-next 3/6] seccomp: Refactor filter copy/create for reuse Hengqi Chen
2023-10-31 1:24 ` [PATCH bpf-next 4/6] seccomp: Support attaching BPF_PROG_TYPE_SECCOMP progs Hengqi Chen
2023-10-31 1:24 ` [PATCH bpf-next 5/6] selftests/bpf: Add seccomp verifier tests Hengqi Chen
2023-10-31 1:24 ` [PATCH bpf-next 6/6] selftests/bpf: Test BPF_PROG_TYPE_SECCOMP Hengqi Chen
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.