Skip to content

Commit 79a7f8b

Browse files
Alexei Starovoitovborkmann
Alexei Starovoitov
authored andcommitted
bpf: Introduce bpf_sys_bpf() helper and program type.
Add placeholders for bpf_sys_bpf() helper and new program type. Make sure to check that expected_attach_type is zero for future extensibility. Allow tracing helper functions to be used in this program type, since they will only execute from user context via bpf_prog_test_run. Signed-off-by: Alexei Starovoitov <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: John Fastabend <[email protected]> Acked-by: Andrii Nakryiko <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent fa7b83b commit 79a7f8b

File tree

7 files changed

+132
-0
lines changed

7 files changed

+132
-0
lines changed

include/linux/bpf.h

+10
Original file line numberDiff line numberDiff line change
@@ -1826,6 +1826,9 @@ static inline bool bpf_map_is_dev_bound(struct bpf_map *map)
18261826

18271827
struct bpf_map *bpf_map_offload_map_alloc(union bpf_attr *attr);
18281828
void bpf_map_offload_map_free(struct bpf_map *map);
1829+
int bpf_prog_test_run_syscall(struct bpf_prog *prog,
1830+
const union bpf_attr *kattr,
1831+
union bpf_attr __user *uattr);
18291832
#else
18301833
static inline int bpf_prog_offload_init(struct bpf_prog *prog,
18311834
union bpf_attr *attr)
@@ -1851,6 +1854,13 @@ static inline struct bpf_map *bpf_map_offload_map_alloc(union bpf_attr *attr)
18511854
static inline void bpf_map_offload_map_free(struct bpf_map *map)
18521855
{
18531856
}
1857+
1858+
static inline int bpf_prog_test_run_syscall(struct bpf_prog *prog,
1859+
const union bpf_attr *kattr,
1860+
union bpf_attr __user *uattr)
1861+
{
1862+
return -ENOTSUPP;
1863+
}
18541864
#endif /* CONFIG_NET && CONFIG_BPF_SYSCALL */
18551865

18561866
#if defined(CONFIG_INET) && defined(CONFIG_BPF_SYSCALL)

include/linux/bpf_types.h

+2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ BPF_PROG_TYPE(BPF_PROG_TYPE_LSM, lsm,
7777
void *, void *)
7878
#endif /* CONFIG_BPF_LSM */
7979
#endif
80+
BPF_PROG_TYPE(BPF_PROG_TYPE_SYSCALL, bpf_syscall,
81+
void *, void *)
8082

8183
BPF_MAP_TYPE(BPF_MAP_TYPE_ARRAY, array_map_ops)
8284
BPF_MAP_TYPE(BPF_MAP_TYPE_PERCPU_ARRAY, percpu_array_map_ops)

include/uapi/linux/bpf.h

+8
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,7 @@ enum bpf_prog_type {
937937
BPF_PROG_TYPE_EXT,
938938
BPF_PROG_TYPE_LSM,
939939
BPF_PROG_TYPE_SK_LOOKUP,
940+
BPF_PROG_TYPE_SYSCALL, /* a program that can execute syscalls */
940941
};
941942

942943
enum bpf_attach_type {
@@ -4735,6 +4736,12 @@ union bpf_attr {
47354736
* be zero-terminated except when **str_size** is 0.
47364737
*
47374738
* Or **-EBUSY** if the per-CPU memory copy buffer is busy.
4739+
*
4740+
* long bpf_sys_bpf(u32 cmd, void *attr, u32 attr_size)
4741+
* Description
4742+
* Execute bpf syscall with given arguments.
4743+
* Return
4744+
* A syscall result.
47384745
*/
47394746
#define __BPF_FUNC_MAPPER(FN) \
47404747
FN(unspec), \
@@ -4903,6 +4910,7 @@ union bpf_attr {
49034910
FN(check_mtu), \
49044911
FN(for_each_map_elem), \
49054912
FN(snprintf), \
4913+
FN(sys_bpf), \
49064914
/* */
49074915

49084916
/* integer value in 'imm' field of BPF_CALL instruction selects which helper

kernel/bpf/syscall.c

+53
Original file line numberDiff line numberDiff line change
@@ -2014,6 +2014,7 @@ bpf_prog_load_check_attach(enum bpf_prog_type prog_type,
20142014
if (expected_attach_type == BPF_SK_LOOKUP)
20152015
return 0;
20162016
return -EINVAL;
2017+
case BPF_PROG_TYPE_SYSCALL:
20172018
case BPF_PROG_TYPE_EXT:
20182019
if (expected_attach_type)
20192020
return -EINVAL;
@@ -4508,3 +4509,55 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
45084509

45094510
return err;
45104511
}
4512+
4513+
static bool syscall_prog_is_valid_access(int off, int size,
4514+
enum bpf_access_type type,
4515+
const struct bpf_prog *prog,
4516+
struct bpf_insn_access_aux *info)
4517+
{
4518+
if (off < 0 || off >= U16_MAX)
4519+
return false;
4520+
if (off % size != 0)
4521+
return false;
4522+
return true;
4523+
}
4524+
4525+
BPF_CALL_3(bpf_sys_bpf, int, cmd, void *, attr, u32, attr_size)
4526+
{
4527+
return -EINVAL;
4528+
}
4529+
4530+
const struct bpf_func_proto bpf_sys_bpf_proto = {
4531+
.func = bpf_sys_bpf,
4532+
.gpl_only = false,
4533+
.ret_type = RET_INTEGER,
4534+
.arg1_type = ARG_ANYTHING,
4535+
.arg2_type = ARG_PTR_TO_MEM,
4536+
.arg3_type = ARG_CONST_SIZE,
4537+
};
4538+
4539+
const struct bpf_func_proto * __weak
4540+
tracing_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
4541+
{
4542+
return bpf_base_func_proto(func_id);
4543+
}
4544+
4545+
static const struct bpf_func_proto *
4546+
syscall_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
4547+
{
4548+
switch (func_id) {
4549+
case BPF_FUNC_sys_bpf:
4550+
return &bpf_sys_bpf_proto;
4551+
default:
4552+
return tracing_prog_func_proto(func_id, prog);
4553+
}
4554+
}
4555+
4556+
const struct bpf_verifier_ops bpf_syscall_verifier_ops = {
4557+
.get_func_proto = syscall_prog_func_proto,
4558+
.is_valid_access = syscall_prog_is_valid_access,
4559+
};
4560+
4561+
const struct bpf_prog_ops bpf_syscall_prog_ops = {
4562+
.test_run = bpf_prog_test_run_syscall,
4563+
};

kernel/bpf/verifier.c

+8
Original file line numberDiff line numberDiff line change
@@ -13196,6 +13196,14 @@ static int check_attach_btf_id(struct bpf_verifier_env *env)
1319613196
int ret;
1319713197
u64 key;
1319813198

13199+
if (prog->type == BPF_PROG_TYPE_SYSCALL) {
13200+
if (prog->aux->sleepable)
13201+
/* attach_btf_id checked to be zero already */
13202+
return 0;
13203+
verbose(env, "Syscall programs can only be sleepable\n");
13204+
return -EINVAL;
13205+
}
13206+
1319913207
if (prog->aux->sleepable && prog->type != BPF_PROG_TYPE_TRACING &&
1320013208
prog->type != BPF_PROG_TYPE_LSM) {
1320113209
verbose(env, "Only fentry/fexit/fmod_ret and lsm programs can be sleepable\n");

net/bpf/test_run.c

+43
Original file line numberDiff line numberDiff line change
@@ -918,3 +918,46 @@ int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog, const union bpf_attr *kat
918918
kfree(user_ctx);
919919
return ret;
920920
}
921+
922+
int bpf_prog_test_run_syscall(struct bpf_prog *prog,
923+
const union bpf_attr *kattr,
924+
union bpf_attr __user *uattr)
925+
{
926+
void __user *ctx_in = u64_to_user_ptr(kattr->test.ctx_in);
927+
__u32 ctx_size_in = kattr->test.ctx_size_in;
928+
void *ctx = NULL;
929+
u32 retval;
930+
int err = 0;
931+
932+
/* doesn't support data_in/out, ctx_out, duration, or repeat or flags */
933+
if (kattr->test.data_in || kattr->test.data_out ||
934+
kattr->test.ctx_out || kattr->test.duration ||
935+
kattr->test.repeat || kattr->test.flags)
936+
return -EINVAL;
937+
938+
if (ctx_size_in < prog->aux->max_ctx_offset ||
939+
ctx_size_in > U16_MAX)
940+
return -EINVAL;
941+
942+
if (ctx_size_in) {
943+
ctx = kzalloc(ctx_size_in, GFP_USER);
944+
if (!ctx)
945+
return -ENOMEM;
946+
if (copy_from_user(ctx, ctx_in, ctx_size_in)) {
947+
err = -EFAULT;
948+
goto out;
949+
}
950+
}
951+
retval = bpf_prog_run_pin_on_cpu(prog, ctx);
952+
953+
if (copy_to_user(&uattr->test.retval, &retval, sizeof(u32))) {
954+
err = -EFAULT;
955+
goto out;
956+
}
957+
if (ctx_size_in)
958+
if (copy_to_user(ctx_in, ctx, ctx_size_in))
959+
err = -EFAULT;
960+
out:
961+
kfree(ctx);
962+
return err;
963+
}

tools/include/uapi/linux/bpf.h

+8
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,7 @@ enum bpf_prog_type {
937937
BPF_PROG_TYPE_EXT,
938938
BPF_PROG_TYPE_LSM,
939939
BPF_PROG_TYPE_SK_LOOKUP,
940+
BPF_PROG_TYPE_SYSCALL, /* a program that can execute syscalls */
940941
};
941942

942943
enum bpf_attach_type {
@@ -4735,6 +4736,12 @@ union bpf_attr {
47354736
* be zero-terminated except when **str_size** is 0.
47364737
*
47374738
* Or **-EBUSY** if the per-CPU memory copy buffer is busy.
4739+
*
4740+
* long bpf_sys_bpf(u32 cmd, void *attr, u32 attr_size)
4741+
* Description
4742+
* Execute bpf syscall with given arguments.
4743+
* Return
4744+
* A syscall result.
47384745
*/
47394746
#define __BPF_FUNC_MAPPER(FN) \
47404747
FN(unspec), \
@@ -4903,6 +4910,7 @@ union bpf_attr {
49034910
FN(check_mtu), \
49044911
FN(for_each_map_elem), \
49054912
FN(snprintf), \
4913+
FN(sys_bpf), \
49064914
/* */
49074915

49084916
/* integer value in 'imm' field of BPF_CALL instruction selects which helper

0 commit comments

Comments
 (0)