Skip to content

Commit 73e1353

Browse files
Jakub KicinskiSomasundaram Krishnasamy
authored andcommitted
bpf: move knowledge about post-translation offsets out of verifier
Use the fact that verifier ops are now separate from program ops to define a separate set of callbacks for verification of already translated programs. Since we expect the analyzer ops to be defined only for a small subset of all program types initialize their array by hand (don't use linux/bpf_types.h). Signed-off-by: Jakub Kicinski <[email protected]> Acked-by: Daniel Borkmann <[email protected]> Acked-by: Alexei Starovoitov <[email protected]> Signed-off-by: David S. Miller <[email protected]> (cherry picked from commit 4f9218a) Orabug: 31667601 Signed-off-by: Alan Maguire <[email protected]> Reviewed-by: Mark Haywood <[email protected]> Signed-off-by: Somasundaram Krishnasamy <[email protected]>
1 parent 9f70688 commit 73e1353

File tree

3 files changed

+59
-39
lines changed

3 files changed

+59
-39
lines changed

include/linux/bpf.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,9 @@ DECLARE_PER_CPU(int, bpf_prog_active);
303303
#undef BPF_PROG_TYPE
304304
#undef BPF_MAP_TYPE
305305

306+
extern const struct bpf_verifier_ops tc_cls_act_analyzer_ops;
307+
extern const struct bpf_verifier_ops xdp_analyzer_ops;
308+
306309
struct bpf_prog *bpf_prog_get(u32 ufd);
307310
struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type);
308311
struct bpf_prog * __must_check bpf_prog_add(struct bpf_prog *prog, int i);

kernel/bpf/verifier.c

Lines changed: 16 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,36 +1111,6 @@ static int check_packet_access(struct bpf_verifier_env *env, u32 regno, int off,
11111111
return err;
11121112
}
11131113

1114-
static bool analyzer_is_valid_access(struct bpf_verifier_env *env, int off,
1115-
struct bpf_insn_access_aux *info)
1116-
{
1117-
switch (env->prog->type) {
1118-
case BPF_PROG_TYPE_XDP:
1119-
switch (off) {
1120-
case offsetof(struct xdp_buff, data):
1121-
info->reg_type = PTR_TO_PACKET;
1122-
return true;
1123-
case offsetof(struct xdp_buff, data_end):
1124-
info->reg_type = PTR_TO_PACKET_END;
1125-
return true;
1126-
}
1127-
return false;
1128-
case BPF_PROG_TYPE_SCHED_CLS:
1129-
switch (off) {
1130-
case offsetof(struct sk_buff, data):
1131-
info->reg_type = PTR_TO_PACKET;
1132-
return true;
1133-
case offsetof(struct sk_buff, cb) +
1134-
offsetof(struct bpf_skb_data_end, data_end):
1135-
info->reg_type = PTR_TO_PACKET_END;
1136-
return true;
1137-
}
1138-
return false;
1139-
default:
1140-
return false;
1141-
}
1142-
}
1143-
11441114
/* check access to 'struct bpf_context' fields. Supports fixed offsets only */
11451115
static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off, int size,
11461116
enum bpf_access_type t, enum bpf_reg_type *reg_type)
@@ -1149,23 +1119,21 @@ static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off,
11491119
.reg_type = *reg_type,
11501120
};
11511121

1152-
if (env->analyzer_ops) {
1153-
if (analyzer_is_valid_access(env, off, &info)) {
1154-
*reg_type = info.reg_type;
1155-
return 0;
1156-
}
1157-
} else if (env->ops->is_valid_access &&
1158-
env->ops->is_valid_access(off, size, t, &info)) {
1122+
if (env->ops->is_valid_access &&
1123+
env->ops->is_valid_access(off, size, t, &info)) {
11591124
/* A non zero info.ctx_field_size indicates that this field is a
11601125
* candidate for later verifier transformation to load the whole
11611126
* field and then apply a mask when accessed with a narrower
11621127
* access than actual ctx access size. A zero info.ctx_field_size
11631128
* will only allow for whole field access and rejects any other
11641129
* type of narrower access.
11651130
*/
1166-
env->insn_aux_data[insn_idx].ctx_field_size = info.ctx_field_size;
11671131
*reg_type = info.reg_type;
11681132

1133+
if (env->analyzer_ops)
1134+
return 0;
1135+
1136+
env->insn_aux_data[insn_idx].ctx_field_size = info.ctx_field_size;
11691137
/* remember the offset of last byte accessed in ctx */
11701138
if (env->prog->aux->max_ctx_offset < off + size)
11711139
env->prog->aux->max_ctx_offset = off + size;
@@ -5122,12 +5090,21 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr)
51225090
return ret;
51235091
}
51245092

5093+
static const struct bpf_verifier_ops * const bpf_analyzer_ops[] = {
5094+
[BPF_PROG_TYPE_XDP] = &xdp_analyzer_ops,
5095+
[BPF_PROG_TYPE_SCHED_CLS] = &tc_cls_act_analyzer_ops,
5096+
};
5097+
51255098
int bpf_analyzer(struct bpf_prog *prog, const struct bpf_ext_analyzer_ops *ops,
51265099
void *priv)
51275100
{
51285101
struct bpf_verifier_env *env;
51295102
int ret;
51305103

5104+
if (prog->type >= ARRAY_SIZE(bpf_analyzer_ops) ||
5105+
!bpf_analyzer_ops[prog->type])
5106+
return -EOPNOTSUPP;
5107+
51315108
env = kzalloc(sizeof(struct bpf_verifier_env), GFP_KERNEL);
51325109
if (!env)
51335110
return -ENOMEM;
@@ -5138,7 +5115,7 @@ int bpf_analyzer(struct bpf_prog *prog, const struct bpf_ext_analyzer_ops *ops,
51385115
if (!env->insn_aux_data)
51395116
goto err_free_env;
51405117
env->prog = prog;
5141-
env->ops = bpf_verifier_ops[env->prog->type];
5118+
env->ops = bpf_analyzer_ops[env->prog->type];
51425119
env->analyzer_ops = ops;
51435120
env->analyzer_priv = priv;
51445121

net/core/filter.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3846,6 +3846,23 @@ static bool tc_cls_act_is_valid_access(int off, int size,
38463846
return bpf_skb_is_valid_access(off, size, type, info);
38473847
}
38483848

3849+
static bool
3850+
tc_cls_act_is_valid_access_analyzer(int off, int size,
3851+
enum bpf_access_type type,
3852+
struct bpf_insn_access_aux *info)
3853+
{
3854+
switch (off) {
3855+
case offsetof(struct sk_buff, data):
3856+
info->reg_type = PTR_TO_PACKET;
3857+
return true;
3858+
case offsetof(struct sk_buff, cb) +
3859+
offsetof(struct bpf_skb_data_end, data_end):
3860+
info->reg_type = PTR_TO_PACKET_END;
3861+
return true;
3862+
}
3863+
return false;
3864+
}
3865+
38493866
static bool __is_valid_xdp_access(int off, int size)
38503867
{
38513868
if (off < 0 || off >= sizeof(struct xdp_md))
@@ -3877,6 +3894,21 @@ static bool xdp_is_valid_access(int off, int size,
38773894
return __is_valid_xdp_access(off, size);
38783895
}
38793896

3897+
static bool xdp_is_valid_access_analyzer(int off, int size,
3898+
enum bpf_access_type type,
3899+
struct bpf_insn_access_aux *info)
3900+
{
3901+
switch (off) {
3902+
case offsetof(struct xdp_buff, data):
3903+
info->reg_type = PTR_TO_PACKET;
3904+
return true;
3905+
case offsetof(struct xdp_buff, data_end):
3906+
info->reg_type = PTR_TO_PACKET_END;
3907+
return true;
3908+
}
3909+
return false;
3910+
}
3911+
38803912
void bpf_warn_invalid_xdp_action(u32 act)
38813913
{
38823914
const u32 act_max = XDP_REDIRECT;
@@ -4744,6 +4776,10 @@ const struct bpf_verifier_ops tc_cls_act_verifier_ops = {
47444776
.gen_prologue = tc_cls_act_prologue,
47454777
};
47464778

4779+
const struct bpf_verifier_ops tc_cls_act_analyzer_ops = {
4780+
.is_valid_access = tc_cls_act_is_valid_access_analyzer,
4781+
};
4782+
47474783
const struct bpf_prog_ops tc_cls_act_prog_ops = {
47484784
.test_run = bpf_prog_test_run_skb,
47494785
};
@@ -4754,6 +4790,10 @@ const struct bpf_verifier_ops xdp_verifier_ops = {
47544790
.convert_ctx_access = xdp_convert_ctx_access,
47554791
};
47564792

4793+
const struct bpf_verifier_ops xdp_analyzer_ops = {
4794+
.is_valid_access = xdp_is_valid_access_analyzer,
4795+
};
4796+
47574797
const struct bpf_prog_ops xdp_prog_ops = {
47584798
.test_run = bpf_prog_test_run_xdp,
47594799
};

0 commit comments

Comments
 (0)