-
Notifications
You must be signed in to change notification settings - Fork 54.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bpf: Introduce BPF_PROG_TYPE_STRUCT_OPS
This patch allows the kernel's struct ops (i.e. func ptr) to be implemented in BPF. The first use case in this series is the "struct tcp_congestion_ops" which will be introduced in a latter patch. This patch introduces a new prog type BPF_PROG_TYPE_STRUCT_OPS. The BPF_PROG_TYPE_STRUCT_OPS prog is verified against a particular func ptr of a kernel struct. The attr->attach_btf_id is the btf id of a kernel struct. The attr->expected_attach_type is the member "index" of that kernel struct. The first member of a struct starts with member index 0. That will avoid ambiguity when a kernel struct has multiple func ptrs with the same func signature. For example, a BPF_PROG_TYPE_STRUCT_OPS prog is written to implement the "init" func ptr of the "struct tcp_congestion_ops". The attr->attach_btf_id is the btf id of the "struct tcp_congestion_ops" of the _running_ kernel. The attr->expected_attach_type is 3. The ctx of BPF_PROG_TYPE_STRUCT_OPS is an array of u64 args saved by arch_prepare_bpf_trampoline that will be done in the next patch when introducing BPF_MAP_TYPE_STRUCT_OPS. "struct bpf_struct_ops" is introduced as a common interface for the kernel struct that supports BPF_PROG_TYPE_STRUCT_OPS prog. The supporting kernel struct will need to implement an instance of the "struct bpf_struct_ops". The supporting kernel struct also needs to implement a bpf_verifier_ops. During BPF_PROG_LOAD, bpf_struct_ops_find() will find the right bpf_verifier_ops by searching the attr->attach_btf_id. A new "btf_struct_access" is also added to the bpf_verifier_ops such that the supporting kernel struct can optionally provide its own specific check on accessing the func arg (e.g. provide limited write access). After btf_vmlinux is parsed, the new bpf_struct_ops_init() is called to initialize some values (e.g. the btf id of the supporting kernel struct) and it can only be done once the btf_vmlinux is available. The R0 checks at BPF_EXIT is excluded for the BPF_PROG_TYPE_STRUCT_OPS prog if the return type of the prog->aux->attach_func_proto is "void". Signed-off-by: Martin KaFai Lau <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Acked-by: Andrii Nakryiko <[email protected]> Acked-by: Yonghong Song <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
- Loading branch information
Showing
10 changed files
with
373 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
// SPDX-License-Identifier: GPL-2.0-only | ||
/* Copyright (c) 2019 Facebook */ | ||
|
||
#include <linux/bpf.h> | ||
#include <linux/bpf_verifier.h> | ||
#include <linux/btf.h> | ||
#include <linux/filter.h> | ||
#include <linux/slab.h> | ||
#include <linux/numa.h> | ||
#include <linux/seq_file.h> | ||
#include <linux/refcount.h> | ||
|
||
#define BPF_STRUCT_OPS_TYPE(_name) \ | ||
extern struct bpf_struct_ops bpf_##_name; | ||
#include "bpf_struct_ops_types.h" | ||
#undef BPF_STRUCT_OPS_TYPE | ||
|
||
enum { | ||
#define BPF_STRUCT_OPS_TYPE(_name) BPF_STRUCT_OPS_TYPE_##_name, | ||
#include "bpf_struct_ops_types.h" | ||
#undef BPF_STRUCT_OPS_TYPE | ||
__NR_BPF_STRUCT_OPS_TYPE, | ||
}; | ||
|
||
static struct bpf_struct_ops * const bpf_struct_ops[] = { | ||
#define BPF_STRUCT_OPS_TYPE(_name) \ | ||
[BPF_STRUCT_OPS_TYPE_##_name] = &bpf_##_name, | ||
#include "bpf_struct_ops_types.h" | ||
#undef BPF_STRUCT_OPS_TYPE | ||
}; | ||
|
||
const struct bpf_verifier_ops bpf_struct_ops_verifier_ops = { | ||
}; | ||
|
||
const struct bpf_prog_ops bpf_struct_ops_prog_ops = { | ||
}; | ||
|
||
void bpf_struct_ops_init(struct btf *btf) | ||
{ | ||
const struct btf_member *member; | ||
struct bpf_struct_ops *st_ops; | ||
struct bpf_verifier_log log = {}; | ||
const struct btf_type *t; | ||
const char *mname; | ||
s32 type_id; | ||
u32 i, j; | ||
|
||
for (i = 0; i < ARRAY_SIZE(bpf_struct_ops); i++) { | ||
st_ops = bpf_struct_ops[i]; | ||
|
||
type_id = btf_find_by_name_kind(btf, st_ops->name, | ||
BTF_KIND_STRUCT); | ||
if (type_id < 0) { | ||
pr_warn("Cannot find struct %s in btf_vmlinux\n", | ||
st_ops->name); | ||
continue; | ||
} | ||
t = btf_type_by_id(btf, type_id); | ||
if (btf_type_vlen(t) > BPF_STRUCT_OPS_MAX_NR_MEMBERS) { | ||
pr_warn("Cannot support #%u members in struct %s\n", | ||
btf_type_vlen(t), st_ops->name); | ||
continue; | ||
} | ||
|
||
for_each_member(j, t, member) { | ||
const struct btf_type *func_proto; | ||
|
||
mname = btf_name_by_offset(btf, member->name_off); | ||
if (!*mname) { | ||
pr_warn("anon member in struct %s is not supported\n", | ||
st_ops->name); | ||
break; | ||
} | ||
|
||
if (btf_member_bitfield_size(t, member)) { | ||
pr_warn("bit field member %s in struct %s is not supported\n", | ||
mname, st_ops->name); | ||
break; | ||
} | ||
|
||
func_proto = btf_type_resolve_func_ptr(btf, | ||
member->type, | ||
NULL); | ||
if (func_proto && | ||
btf_distill_func_proto(&log, btf, | ||
func_proto, mname, | ||
&st_ops->func_models[j])) { | ||
pr_warn("Error in parsing func ptr %s in struct %s\n", | ||
mname, st_ops->name); | ||
break; | ||
} | ||
} | ||
|
||
if (j == btf_type_vlen(t)) { | ||
if (st_ops->init(btf)) { | ||
pr_warn("Error in init bpf_struct_ops %s\n", | ||
st_ops->name); | ||
} else { | ||
st_ops->type_id = type_id; | ||
st_ops->type = t; | ||
} | ||
} | ||
} | ||
} | ||
|
||
extern struct btf *btf_vmlinux; | ||
|
||
const struct bpf_struct_ops *bpf_struct_ops_find(u32 type_id) | ||
{ | ||
unsigned int i; | ||
|
||
if (!type_id || !btf_vmlinux) | ||
return NULL; | ||
|
||
for (i = 0; i < ARRAY_SIZE(bpf_struct_ops); i++) { | ||
if (bpf_struct_ops[i]->type_id == type_id) | ||
return bpf_struct_ops[i]; | ||
} | ||
|
||
return NULL; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
/* internal file - do not include directly */ | ||
|
||
/* To be filled in a later patch */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.