Commit fcefa42f authored by David S. Miller's avatar David S. Miller

Merge branch 'bpf-cb-access'

Daniel Borkmann says:

====================
More flexible BPF cb access

This patch improves BPF's cb access by allowing b/h/w/dw
access variants on it. For details, please see individual
patches.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f811b436 62c7989b
...@@ -161,9 +161,10 @@ struct bpf_verifier_ops { ...@@ -161,9 +161,10 @@ struct bpf_verifier_ops {
enum bpf_reg_type *reg_type); enum bpf_reg_type *reg_type);
int (*gen_prologue)(struct bpf_insn *insn, bool direct_write, int (*gen_prologue)(struct bpf_insn *insn, bool direct_write,
const struct bpf_prog *prog); const struct bpf_prog *prog);
u32 (*convert_ctx_access)(enum bpf_access_type type, int dst_reg, u32 (*convert_ctx_access)(enum bpf_access_type type,
int src_reg, int ctx_off, const struct bpf_insn *src,
struct bpf_insn *insn, struct bpf_prog *prog); struct bpf_insn *dst,
struct bpf_prog *prog);
}; };
struct bpf_prog_type_list { struct bpf_prog_type_list {
......
...@@ -3165,10 +3165,14 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) ...@@ -3165,10 +3165,14 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
insn = env->prog->insnsi + delta; insn = env->prog->insnsi + delta;
for (i = 0; i < insn_cnt; i++, insn++) { for (i = 0; i < insn_cnt; i++, insn++) {
if (insn->code == (BPF_LDX | BPF_MEM | BPF_W) || if (insn->code == (BPF_LDX | BPF_MEM | BPF_B) ||
insn->code == (BPF_LDX | BPF_MEM | BPF_H) ||
insn->code == (BPF_LDX | BPF_MEM | BPF_W) ||
insn->code == (BPF_LDX | BPF_MEM | BPF_DW)) insn->code == (BPF_LDX | BPF_MEM | BPF_DW))
type = BPF_READ; type = BPF_READ;
else if (insn->code == (BPF_STX | BPF_MEM | BPF_W) || else if (insn->code == (BPF_STX | BPF_MEM | BPF_B) ||
insn->code == (BPF_STX | BPF_MEM | BPF_H) ||
insn->code == (BPF_STX | BPF_MEM | BPF_W) ||
insn->code == (BPF_STX | BPF_MEM | BPF_DW)) insn->code == (BPF_STX | BPF_MEM | BPF_DW))
type = BPF_WRITE; type = BPF_WRITE;
else else
...@@ -3177,8 +3181,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) ...@@ -3177,8 +3181,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
if (env->insn_aux_data[i].ptr_type != PTR_TO_CTX) if (env->insn_aux_data[i].ptr_type != PTR_TO_CTX)
continue; continue;
cnt = ops->convert_ctx_access(type, insn->dst_reg, insn->src_reg, cnt = ops->convert_ctx_access(type, insn, insn_buf, env->prog);
insn->off, insn_buf, env->prog);
if (cnt == 0 || cnt >= ARRAY_SIZE(insn_buf)) { if (cnt == 0 || cnt >= ARRAY_SIZE(insn_buf)) {
verbose("bpf verifier is misconfigured\n"); verbose("bpf verifier is misconfigured\n");
return -EINVAL; return -EINVAL;
......
...@@ -572,28 +572,29 @@ static bool pe_prog_is_valid_access(int off, int size, enum bpf_access_type type ...@@ -572,28 +572,29 @@ static bool pe_prog_is_valid_access(int off, int size, enum bpf_access_type type
return true; return true;
} }
static u32 pe_prog_convert_ctx_access(enum bpf_access_type type, int dst_reg, static u32 pe_prog_convert_ctx_access(enum bpf_access_type type,
int src_reg, int ctx_off, const struct bpf_insn *si,
struct bpf_insn *insn_buf, struct bpf_insn *insn_buf,
struct bpf_prog *prog) struct bpf_prog *prog)
{ {
struct bpf_insn *insn = insn_buf; struct bpf_insn *insn = insn_buf;
switch (ctx_off) { switch (si->off) {
case offsetof(struct bpf_perf_event_data, sample_period): case offsetof(struct bpf_perf_event_data, sample_period):
BUILD_BUG_ON(FIELD_SIZEOF(struct perf_sample_data, period) != sizeof(u64)); BUILD_BUG_ON(FIELD_SIZEOF(struct perf_sample_data, period) != sizeof(u64));
*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_perf_event_data_kern, *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_perf_event_data_kern,
data), dst_reg, src_reg, data), si->dst_reg, si->src_reg,
offsetof(struct bpf_perf_event_data_kern, data)); offsetof(struct bpf_perf_event_data_kern, data));
*insn++ = BPF_LDX_MEM(BPF_DW, dst_reg, dst_reg, *insn++ = BPF_LDX_MEM(BPF_DW, si->dst_reg, si->dst_reg,
offsetof(struct perf_sample_data, period)); offsetof(struct perf_sample_data, period));
break; break;
default: default:
*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_perf_event_data_kern, *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_perf_event_data_kern,
regs), dst_reg, src_reg, regs), si->dst_reg, si->src_reg,
offsetof(struct bpf_perf_event_data_kern, regs)); offsetof(struct bpf_perf_event_data_kern, regs));
*insn++ = BPF_LDX_MEM(BPF_SIZEOF(long), dst_reg, dst_reg, ctx_off); *insn++ = BPF_LDX_MEM(BPF_SIZEOF(long), si->dst_reg, si->dst_reg,
si->off);
break; break;
} }
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment