Skip to content

Commit 4f9218a

Browse files
Jakub Kicinskidavem330
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]>
1 parent 00176a3 commit 4f9218a

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
@@ -291,6 +291,9 @@ DECLARE_PER_CPU(int, bpf_prog_active);
291291
#undef BPF_PROG_TYPE
292292
#undef BPF_MAP_TYPE
293293

294+
extern const struct bpf_verifier_ops tc_cls_act_analyzer_ops;
295+
extern const struct bpf_verifier_ops xdp_analyzer_ops;
296+
294297
struct bpf_prog *bpf_prog_get(u32 ufd);
295298
struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type);
296299
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
@@ -822,36 +822,6 @@ static int check_packet_access(struct bpf_verifier_env *env, u32 regno, int off,
822822
return err;
823823
}
824824

825-
static bool analyzer_is_valid_access(struct bpf_verifier_env *env, int off,
826-
struct bpf_insn_access_aux *info)
827-
{
828-
switch (env->prog->type) {
829-
case BPF_PROG_TYPE_XDP:
830-
switch (off) {
831-
case offsetof(struct xdp_buff, data):
832-
info->reg_type = PTR_TO_PACKET;
833-
return true;
834-
case offsetof(struct xdp_buff, data_end):
835-
info->reg_type = PTR_TO_PACKET_END;
836-
return true;
837-
}
838-
return false;
839-
case BPF_PROG_TYPE_SCHED_CLS:
840-
switch (off) {
841-
case offsetof(struct sk_buff, data):
842-
info->reg_type = PTR_TO_PACKET;
843-
return true;
844-
case offsetof(struct sk_buff, cb) +
845-
offsetof(struct bpf_skb_data_end, data_end):
846-
info->reg_type = PTR_TO_PACKET_END;
847-
return true;
848-
}
849-
return false;
850-
default:
851-
return false;
852-
}
853-
}
854-
855825
/* check access to 'struct bpf_context' fields. Supports fixed offsets only */
856826
static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off, int size,
857827
enum bpf_access_type t, enum bpf_reg_type *reg_type)
@@ -860,23 +830,21 @@ static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off,
860830
.reg_type = *reg_type,
861831
};
862832

863-
if (env->analyzer_ops) {
864-
if (analyzer_is_valid_access(env, off, &info)) {
865-
*reg_type = info.reg_type;
866-
return 0;
867-
}
868-
} else if (env->ops->is_valid_access &&
869-
env->ops->is_valid_access(off, size, t, &info)) {
833+
if (env->ops->is_valid_access &&
834+
env->ops->is_valid_access(off, size, t, &info)) {
870835
/* A non zero info.ctx_field_size indicates that this field is a
871836
* candidate for later verifier transformation to load the whole
872837
* field and then apply a mask when accessed with a narrower
873838
* access than actual ctx access size. A zero info.ctx_field_size
874839
* will only allow for whole field access and rejects any other
875840
* type of narrower access.
876841
*/
877-
env->insn_aux_data[insn_idx].ctx_field_size = info.ctx_field_size;
878842
*reg_type = info.reg_type;
879843

844+
if (env->analyzer_ops)
845+
return 0;
846+
847+
env->insn_aux_data[insn_idx].ctx_field_size = info.ctx_field_size;
880848
/* remember the offset of last byte accessed in ctx */
881849
if (env->prog->aux->max_ctx_offset < off + size)
882850
env->prog->aux->max_ctx_offset = off + size;
@@ -4400,12 +4368,21 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr)
44004368
return ret;
44014369
}
44024370

4371+
static const struct bpf_verifier_ops * const bpf_analyzer_ops[] = {
4372+
[BPF_PROG_TYPE_XDP] = &xdp_analyzer_ops,
4373+
[BPF_PROG_TYPE_SCHED_CLS] = &tc_cls_act_analyzer_ops,
4374+
};
4375+
44034376
int bpf_analyzer(struct bpf_prog *prog, const struct bpf_ext_analyzer_ops *ops,
44044377
void *priv)
44054378
{
44064379
struct bpf_verifier_env *env;
44074380
int ret;
44084381

4382+
if (prog->type >= ARRAY_SIZE(bpf_analyzer_ops) ||
4383+
!bpf_analyzer_ops[prog->type])
4384+
return -EOPNOTSUPP;
4385+
44094386
env = kzalloc(sizeof(struct bpf_verifier_env), GFP_KERNEL);
44104387
if (!env)
44114388
return -ENOMEM;
@@ -4416,7 +4393,7 @@ int bpf_analyzer(struct bpf_prog *prog, const struct bpf_ext_analyzer_ops *ops,
44164393
if (!env->insn_aux_data)
44174394
goto err_free_env;
44184395
env->prog = prog;
4419-
env->ops = bpf_verifier_ops[env->prog->type];
4396+
env->ops = bpf_analyzer_ops[env->prog->type];
44204397
env->analyzer_ops = ops;
44214398
env->analyzer_priv = priv;
44224399

net/core/filter.c

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

3735+
static bool
3736+
tc_cls_act_is_valid_access_analyzer(int off, int size,
3737+
enum bpf_access_type type,
3738+
struct bpf_insn_access_aux *info)
3739+
{
3740+
switch (off) {
3741+
case offsetof(struct sk_buff, data):
3742+
info->reg_type = PTR_TO_PACKET;
3743+
return true;
3744+
case offsetof(struct sk_buff, cb) +
3745+
offsetof(struct bpf_skb_data_end, data_end):
3746+
info->reg_type = PTR_TO_PACKET_END;
3747+
return true;
3748+
}
3749+
return false;
3750+
}
3751+
37353752
static bool __is_valid_xdp_access(int off, int size)
37363753
{
37373754
if (off < 0 || off >= sizeof(struct xdp_md))
@@ -3766,6 +3783,21 @@ static bool xdp_is_valid_access(int off, int size,
37663783
return __is_valid_xdp_access(off, size);
37673784
}
37683785

3786+
static bool xdp_is_valid_access_analyzer(int off, int size,
3787+
enum bpf_access_type type,
3788+
struct bpf_insn_access_aux *info)
3789+
{
3790+
switch (off) {
3791+
case offsetof(struct xdp_buff, data):
3792+
info->reg_type = PTR_TO_PACKET;
3793+
return true;
3794+
case offsetof(struct xdp_buff, data_end):
3795+
info->reg_type = PTR_TO_PACKET_END;
3796+
return true;
3797+
}
3798+
return false;
3799+
}
3800+
37693801
void bpf_warn_invalid_xdp_action(u32 act)
37703802
{
37713803
const u32 act_max = XDP_REDIRECT;
@@ -4411,6 +4443,10 @@ const struct bpf_verifier_ops tc_cls_act_verifier_ops = {
44114443
.gen_prologue = tc_cls_act_prologue,
44124444
};
44134445

4446+
const struct bpf_verifier_ops tc_cls_act_analyzer_ops = {
4447+
.is_valid_access = tc_cls_act_is_valid_access_analyzer,
4448+
};
4449+
44144450
const struct bpf_prog_ops tc_cls_act_prog_ops = {
44154451
.test_run = bpf_prog_test_run_skb,
44164452
};
@@ -4421,6 +4457,10 @@ const struct bpf_verifier_ops xdp_verifier_ops = {
44214457
.convert_ctx_access = xdp_convert_ctx_access,
44224458
};
44234459

4460+
const struct bpf_verifier_ops xdp_analyzer_ops = {
4461+
.is_valid_access = xdp_is_valid_access_analyzer,
4462+
};
4463+
44244464
const struct bpf_prog_ops xdp_prog_ops = {
44254465
.test_run = bpf_prog_test_run_xdp,
44264466
};

0 commit comments

Comments
 (0)