@@ -2532,7 +2532,7 @@ static void find_good_pkt_pointers(struct bpf_verifier_state *state,
2532
2532
continue ;
2533
2533
reg = & state -> stack [i ].spilled_ptr ;
2534
2534
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 );
2536
2536
}
2537
2537
}
2538
2538
@@ -2787,6 +2787,99 @@ static void mark_map_regs(struct bpf_verifier_state *state, u32 regno,
2787
2787
}
2788
2788
}
2789
2789
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
+
2790
2883
static int check_cond_jmp_op (struct bpf_verifier_env * env ,
2791
2884
struct bpf_insn * insn , int * insn_idx )
2792
2885
{
@@ -2893,75 +2986,9 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
2893
2986
*/
2894
2987
mark_map_regs (this_branch , insn -> dst_reg , opcode == BPF_JNE );
2895
2988
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 )) {
2965
2992
verbose (env , "R%d pointer comparison prohibited\n" ,
2966
2993
insn -> dst_reg );
2967
2994
return - EACCES ;
0 commit comments