Skip to content

Commit 74b200d

Browse files
committed
Merge branch 'BPF-range-marking-improvements-for-meta-data'
Daniel Borkmann says: ==================== BPF range marking improvements for meta data The set contains improvements for direct packet access range markings related to data_meta pointer and test cases for all such access patterns that the verifier matches on. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 1495dc9 + 634eab1 commit 74b200d

File tree

2 files changed

+594
-125
lines changed

2 files changed

+594
-125
lines changed

kernel/bpf/verifier.c

Lines changed: 97 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -2532,7 +2532,7 @@ static void find_good_pkt_pointers(struct bpf_verifier_state *state,
25322532
continue;
25332533
reg = &state->stack[i].spilled_ptr;
25342534
if (reg->type == type && reg->id == dst_reg->id)
2535-
reg->range = max_t(u16, reg->range, new_range);
2535+
reg->range = max(reg->range, new_range);
25362536
}
25372537
}
25382538

@@ -2787,6 +2787,99 @@ static void mark_map_regs(struct bpf_verifier_state *state, u32 regno,
27872787
}
27882788
}
27892789

2790+
static bool try_match_pkt_pointers(const struct bpf_insn *insn,
2791+
struct bpf_reg_state *dst_reg,
2792+
struct bpf_reg_state *src_reg,
2793+
struct bpf_verifier_state *this_branch,
2794+
struct bpf_verifier_state *other_branch)
2795+
{
2796+
if (BPF_SRC(insn->code) != BPF_X)
2797+
return false;
2798+
2799+
switch (BPF_OP(insn->code)) {
2800+
case BPF_JGT:
2801+
if ((dst_reg->type == PTR_TO_PACKET &&
2802+
src_reg->type == PTR_TO_PACKET_END) ||
2803+
(dst_reg->type == PTR_TO_PACKET_META &&
2804+
reg_is_init_pkt_pointer(src_reg, PTR_TO_PACKET))) {
2805+
/* pkt_data' > pkt_end, pkt_meta' > pkt_data */
2806+
find_good_pkt_pointers(this_branch, dst_reg,
2807+
dst_reg->type, false);
2808+
} else if ((dst_reg->type == PTR_TO_PACKET_END &&
2809+
src_reg->type == PTR_TO_PACKET) ||
2810+
(reg_is_init_pkt_pointer(dst_reg, PTR_TO_PACKET) &&
2811+
src_reg->type == PTR_TO_PACKET_META)) {
2812+
/* pkt_end > pkt_data', pkt_data > pkt_meta' */
2813+
find_good_pkt_pointers(other_branch, src_reg,
2814+
src_reg->type, true);
2815+
} else {
2816+
return false;
2817+
}
2818+
break;
2819+
case BPF_JLT:
2820+
if ((dst_reg->type == PTR_TO_PACKET &&
2821+
src_reg->type == PTR_TO_PACKET_END) ||
2822+
(dst_reg->type == PTR_TO_PACKET_META &&
2823+
reg_is_init_pkt_pointer(src_reg, PTR_TO_PACKET))) {
2824+
/* pkt_data' < pkt_end, pkt_meta' < pkt_data */
2825+
find_good_pkt_pointers(other_branch, dst_reg,
2826+
dst_reg->type, true);
2827+
} else if ((dst_reg->type == PTR_TO_PACKET_END &&
2828+
src_reg->type == PTR_TO_PACKET) ||
2829+
(reg_is_init_pkt_pointer(dst_reg, PTR_TO_PACKET) &&
2830+
src_reg->type == PTR_TO_PACKET_META)) {
2831+
/* pkt_end < pkt_data', pkt_data > pkt_meta' */
2832+
find_good_pkt_pointers(this_branch, src_reg,
2833+
src_reg->type, false);
2834+
} else {
2835+
return false;
2836+
}
2837+
break;
2838+
case BPF_JGE:
2839+
if ((dst_reg->type == PTR_TO_PACKET &&
2840+
src_reg->type == PTR_TO_PACKET_END) ||
2841+
(dst_reg->type == PTR_TO_PACKET_META &&
2842+
reg_is_init_pkt_pointer(src_reg, PTR_TO_PACKET))) {
2843+
/* pkt_data' >= pkt_end, pkt_meta' >= pkt_data */
2844+
find_good_pkt_pointers(this_branch, dst_reg,
2845+
dst_reg->type, true);
2846+
} else if ((dst_reg->type == PTR_TO_PACKET_END &&
2847+
src_reg->type == PTR_TO_PACKET) ||
2848+
(reg_is_init_pkt_pointer(dst_reg, PTR_TO_PACKET) &&
2849+
src_reg->type == PTR_TO_PACKET_META)) {
2850+
/* pkt_end >= pkt_data', pkt_data >= pkt_meta' */
2851+
find_good_pkt_pointers(other_branch, src_reg,
2852+
src_reg->type, false);
2853+
} else {
2854+
return false;
2855+
}
2856+
break;
2857+
case BPF_JLE:
2858+
if ((dst_reg->type == PTR_TO_PACKET &&
2859+
src_reg->type == PTR_TO_PACKET_END) ||
2860+
(dst_reg->type == PTR_TO_PACKET_META &&
2861+
reg_is_init_pkt_pointer(src_reg, PTR_TO_PACKET))) {
2862+
/* pkt_data' <= pkt_end, pkt_meta' <= pkt_data */
2863+
find_good_pkt_pointers(other_branch, dst_reg,
2864+
dst_reg->type, false);
2865+
} else if ((dst_reg->type == PTR_TO_PACKET_END &&
2866+
src_reg->type == PTR_TO_PACKET) ||
2867+
(reg_is_init_pkt_pointer(dst_reg, PTR_TO_PACKET) &&
2868+
src_reg->type == PTR_TO_PACKET_META)) {
2869+
/* pkt_end <= pkt_data', pkt_data <= pkt_meta' */
2870+
find_good_pkt_pointers(this_branch, src_reg,
2871+
src_reg->type, true);
2872+
} else {
2873+
return false;
2874+
}
2875+
break;
2876+
default:
2877+
return false;
2878+
}
2879+
2880+
return true;
2881+
}
2882+
27902883
static int check_cond_jmp_op(struct bpf_verifier_env *env,
27912884
struct bpf_insn *insn, int *insn_idx)
27922885
{
@@ -2893,75 +2986,9 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
28932986
*/
28942987
mark_map_regs(this_branch, insn->dst_reg, opcode == BPF_JNE);
28952988
mark_map_regs(other_branch, insn->dst_reg, opcode == BPF_JEQ);
2896-
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JGT &&
2897-
dst_reg->type == PTR_TO_PACKET &&
2898-
regs[insn->src_reg].type == PTR_TO_PACKET_END) {
2899-
/* pkt_data' > pkt_end */
2900-
find_good_pkt_pointers(this_branch, dst_reg,
2901-
PTR_TO_PACKET, false);
2902-
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JGT &&
2903-
dst_reg->type == PTR_TO_PACKET_END &&
2904-
regs[insn->src_reg].type == PTR_TO_PACKET) {
2905-
/* pkt_end > pkt_data' */
2906-
find_good_pkt_pointers(other_branch, &regs[insn->src_reg],
2907-
PTR_TO_PACKET, true);
2908-
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JLT &&
2909-
dst_reg->type == PTR_TO_PACKET &&
2910-
regs[insn->src_reg].type == PTR_TO_PACKET_END) {
2911-
/* pkt_data' < pkt_end */
2912-
find_good_pkt_pointers(other_branch, dst_reg, PTR_TO_PACKET,
2913-
true);
2914-
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JLT &&
2915-
dst_reg->type == PTR_TO_PACKET_END &&
2916-
regs[insn->src_reg].type == PTR_TO_PACKET) {
2917-
/* pkt_end < pkt_data' */
2918-
find_good_pkt_pointers(this_branch, &regs[insn->src_reg],
2919-
PTR_TO_PACKET, false);
2920-
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JGE &&
2921-
dst_reg->type == PTR_TO_PACKET &&
2922-
regs[insn->src_reg].type == PTR_TO_PACKET_END) {
2923-
/* pkt_data' >= pkt_end */
2924-
find_good_pkt_pointers(this_branch, dst_reg,
2925-
PTR_TO_PACKET, true);
2926-
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JGE &&
2927-
dst_reg->type == PTR_TO_PACKET_END &&
2928-
regs[insn->src_reg].type == PTR_TO_PACKET) {
2929-
/* pkt_end >= pkt_data' */
2930-
find_good_pkt_pointers(other_branch, &regs[insn->src_reg],
2931-
PTR_TO_PACKET, false);
2932-
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JLE &&
2933-
dst_reg->type == PTR_TO_PACKET &&
2934-
regs[insn->src_reg].type == PTR_TO_PACKET_END) {
2935-
/* pkt_data' <= pkt_end */
2936-
find_good_pkt_pointers(other_branch, dst_reg,
2937-
PTR_TO_PACKET, false);
2938-
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JLE &&
2939-
dst_reg->type == PTR_TO_PACKET_END &&
2940-
regs[insn->src_reg].type == PTR_TO_PACKET) {
2941-
/* pkt_end <= pkt_data' */
2942-
find_good_pkt_pointers(this_branch, &regs[insn->src_reg],
2943-
PTR_TO_PACKET, true);
2944-
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JGT &&
2945-
dst_reg->type == PTR_TO_PACKET_META &&
2946-
reg_is_init_pkt_pointer(&regs[insn->src_reg], PTR_TO_PACKET)) {
2947-
find_good_pkt_pointers(this_branch, dst_reg,
2948-
PTR_TO_PACKET_META, false);
2949-
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JLT &&
2950-
dst_reg->type == PTR_TO_PACKET_META &&
2951-
reg_is_init_pkt_pointer(&regs[insn->src_reg], PTR_TO_PACKET)) {
2952-
find_good_pkt_pointers(other_branch, dst_reg,
2953-
PTR_TO_PACKET_META, false);
2954-
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JGE &&
2955-
reg_is_init_pkt_pointer(dst_reg, PTR_TO_PACKET) &&
2956-
regs[insn->src_reg].type == PTR_TO_PACKET_META) {
2957-
find_good_pkt_pointers(other_branch, &regs[insn->src_reg],
2958-
PTR_TO_PACKET_META, false);
2959-
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JLE &&
2960-
reg_is_init_pkt_pointer(dst_reg, PTR_TO_PACKET) &&
2961-
regs[insn->src_reg].type == PTR_TO_PACKET_META) {
2962-
find_good_pkt_pointers(this_branch, &regs[insn->src_reg],
2963-
PTR_TO_PACKET_META, false);
2964-
} else if (is_pointer_value(env, insn->dst_reg)) {
2989+
} else if (!try_match_pkt_pointers(insn, dst_reg, &regs[insn->src_reg],
2990+
this_branch, other_branch) &&
2991+
is_pointer_value(env, insn->dst_reg)) {
29652992
verbose(env, "R%d pointer comparison prohibited\n",
29662993
insn->dst_reg);
29672994
return -EACCES;

0 commit comments

Comments
 (0)