@@ -1689,6 +1689,12 @@ static int __bpf_redirect_no_mac(struct sk_buff *skb, struct net_device *dev,
1689
1689
static int __bpf_redirect_common (struct sk_buff * skb , struct net_device * dev ,
1690
1690
u32 flags )
1691
1691
{
1692
+ /* Verify that a link layer header is carried */
1693
+ if (unlikely (skb -> mac_header >= skb -> network_header )) {
1694
+ kfree_skb (skb );
1695
+ return - ERANGE ;
1696
+ }
1697
+
1692
1698
bpf_push_mac_rcsum (skb );
1693
1699
return flags & BPF_F_INGRESS ?
1694
1700
__bpf_rx_skb (dev , skb ) : __bpf_tx_skb (dev , skb );
@@ -2188,12 +2194,53 @@ static const struct bpf_func_proto bpf_skb_change_tail_proto = {
2188
2194
.arg3_type = ARG_ANYTHING ,
2189
2195
};
2190
2196
2197
+ BPF_CALL_3 (bpf_skb_change_head , struct sk_buff * , skb , u32 , head_room ,
2198
+ u64 , flags )
2199
+ {
2200
+ u32 max_len = __bpf_skb_max_len (skb );
2201
+ u32 new_len = skb -> len + head_room ;
2202
+ int ret ;
2203
+
2204
+ if (unlikely (flags || (!skb_is_gso (skb ) && new_len > max_len ) ||
2205
+ new_len < skb -> len ))
2206
+ return - EINVAL ;
2207
+
2208
+ ret = skb_cow (skb , head_room );
2209
+ if (likely (!ret )) {
2210
+ /* Idea for this helper is that we currently only
2211
+ * allow to expand on mac header. This means that
2212
+ * skb->protocol network header, etc, stay as is.
2213
+ * Compared to bpf_skb_change_tail(), we're more
2214
+ * flexible due to not needing to linearize or
2215
+ * reset GSO. Intention for this helper is to be
2216
+ * used by an L3 skb that needs to push mac header
2217
+ * for redirection into L2 device.
2218
+ */
2219
+ __skb_push (skb , head_room );
2220
+ memset (skb -> data , 0 , head_room );
2221
+ skb_reset_mac_header (skb );
2222
+ }
2223
+
2224
+ bpf_compute_data_end (skb );
2225
+ return 0 ;
2226
+ }
2227
+
2228
+ static const struct bpf_func_proto bpf_skb_change_head_proto = {
2229
+ .func = bpf_skb_change_head ,
2230
+ .gpl_only = false,
2231
+ .ret_type = RET_INTEGER ,
2232
+ .arg1_type = ARG_PTR_TO_CTX ,
2233
+ .arg2_type = ARG_ANYTHING ,
2234
+ .arg3_type = ARG_ANYTHING ,
2235
+ };
2236
+
2191
2237
bool bpf_helper_changes_skb_data (void * func )
2192
2238
{
2193
2239
if (func == bpf_skb_vlan_push ||
2194
2240
func == bpf_skb_vlan_pop ||
2195
2241
func == bpf_skb_store_bytes ||
2196
2242
func == bpf_skb_change_proto ||
2243
+ func == bpf_skb_change_head ||
2197
2244
func == bpf_skb_change_tail ||
2198
2245
func == bpf_skb_pull_data ||
2199
2246
func == bpf_l3_csum_replace ||
@@ -2639,6 +2686,68 @@ cg_skb_func_proto(enum bpf_func_id func_id)
2639
2686
}
2640
2687
}
2641
2688
2689
+ static const struct bpf_func_proto *
2690
+ lwt_inout_func_proto (enum bpf_func_id func_id )
2691
+ {
2692
+ switch (func_id ) {
2693
+ case BPF_FUNC_skb_load_bytes :
2694
+ return & bpf_skb_load_bytes_proto ;
2695
+ case BPF_FUNC_skb_pull_data :
2696
+ return & bpf_skb_pull_data_proto ;
2697
+ case BPF_FUNC_csum_diff :
2698
+ return & bpf_csum_diff_proto ;
2699
+ case BPF_FUNC_get_cgroup_classid :
2700
+ return & bpf_get_cgroup_classid_proto ;
2701
+ case BPF_FUNC_get_route_realm :
2702
+ return & bpf_get_route_realm_proto ;
2703
+ case BPF_FUNC_get_hash_recalc :
2704
+ return & bpf_get_hash_recalc_proto ;
2705
+ case BPF_FUNC_perf_event_output :
2706
+ return & bpf_skb_event_output_proto ;
2707
+ case BPF_FUNC_get_smp_processor_id :
2708
+ return & bpf_get_smp_processor_id_proto ;
2709
+ case BPF_FUNC_skb_under_cgroup :
2710
+ return & bpf_skb_under_cgroup_proto ;
2711
+ default :
2712
+ return sk_filter_func_proto (func_id );
2713
+ }
2714
+ }
2715
+
2716
+ static const struct bpf_func_proto *
2717
+ lwt_xmit_func_proto (enum bpf_func_id func_id )
2718
+ {
2719
+ switch (func_id ) {
2720
+ case BPF_FUNC_skb_get_tunnel_key :
2721
+ return & bpf_skb_get_tunnel_key_proto ;
2722
+ case BPF_FUNC_skb_set_tunnel_key :
2723
+ return bpf_get_skb_set_tunnel_proto (func_id );
2724
+ case BPF_FUNC_skb_get_tunnel_opt :
2725
+ return & bpf_skb_get_tunnel_opt_proto ;
2726
+ case BPF_FUNC_skb_set_tunnel_opt :
2727
+ return bpf_get_skb_set_tunnel_proto (func_id );
2728
+ case BPF_FUNC_redirect :
2729
+ return & bpf_redirect_proto ;
2730
+ case BPF_FUNC_clone_redirect :
2731
+ return & bpf_clone_redirect_proto ;
2732
+ case BPF_FUNC_skb_change_tail :
2733
+ return & bpf_skb_change_tail_proto ;
2734
+ case BPF_FUNC_skb_change_head :
2735
+ return & bpf_skb_change_head_proto ;
2736
+ case BPF_FUNC_skb_store_bytes :
2737
+ return & bpf_skb_store_bytes_proto ;
2738
+ case BPF_FUNC_csum_update :
2739
+ return & bpf_csum_update_proto ;
2740
+ case BPF_FUNC_l3_csum_replace :
2741
+ return & bpf_l3_csum_replace_proto ;
2742
+ case BPF_FUNC_l4_csum_replace :
2743
+ return & bpf_l4_csum_replace_proto ;
2744
+ case BPF_FUNC_set_hash_invalid :
2745
+ return & bpf_set_hash_invalid_proto ;
2746
+ default :
2747
+ return lwt_inout_func_proto (func_id );
2748
+ }
2749
+ }
2750
+
2642
2751
static bool __is_valid_access (int off , int size , enum bpf_access_type type )
2643
2752
{
2644
2753
if (off < 0 || off >= sizeof (struct __sk_buff ))
@@ -2676,6 +2785,39 @@ static bool sk_filter_is_valid_access(int off, int size,
2676
2785
return __is_valid_access (off , size , type );
2677
2786
}
2678
2787
2788
+ static bool lwt_is_valid_access (int off , int size ,
2789
+ enum bpf_access_type type ,
2790
+ enum bpf_reg_type * reg_type )
2791
+ {
2792
+ switch (off ) {
2793
+ case offsetof(struct __sk_buff , tc_classid ):
2794
+ return false;
2795
+ }
2796
+
2797
+ if (type == BPF_WRITE ) {
2798
+ switch (off ) {
2799
+ case offsetof(struct __sk_buff , mark ):
2800
+ case offsetof(struct __sk_buff , priority ):
2801
+ case offsetof(struct __sk_buff , cb [0 ]) ...
2802
+ offsetof(struct __sk_buff , cb [4 ]):
2803
+ break ;
2804
+ default :
2805
+ return false;
2806
+ }
2807
+ }
2808
+
2809
+ switch (off ) {
2810
+ case offsetof(struct __sk_buff , data ):
2811
+ * reg_type = PTR_TO_PACKET ;
2812
+ break ;
2813
+ case offsetof(struct __sk_buff , data_end ):
2814
+ * reg_type = PTR_TO_PACKET_END ;
2815
+ break ;
2816
+ }
2817
+
2818
+ return __is_valid_access (off , size , type );
2819
+ }
2820
+
2679
2821
static int tc_cls_act_prologue (struct bpf_insn * insn_buf , bool direct_write ,
2680
2822
const struct bpf_prog * prog )
2681
2823
{
@@ -3007,6 +3149,19 @@ static const struct bpf_verifier_ops cg_skb_ops = {
3007
3149
.convert_ctx_access = sk_filter_convert_ctx_access ,
3008
3150
};
3009
3151
3152
+ static const struct bpf_verifier_ops lwt_inout_ops = {
3153
+ .get_func_proto = lwt_inout_func_proto ,
3154
+ .is_valid_access = lwt_is_valid_access ,
3155
+ .convert_ctx_access = sk_filter_convert_ctx_access ,
3156
+ };
3157
+
3158
+ static const struct bpf_verifier_ops lwt_xmit_ops = {
3159
+ .get_func_proto = lwt_xmit_func_proto ,
3160
+ .is_valid_access = lwt_is_valid_access ,
3161
+ .convert_ctx_access = sk_filter_convert_ctx_access ,
3162
+ .gen_prologue = tc_cls_act_prologue ,
3163
+ };
3164
+
3010
3165
static struct bpf_prog_type_list sk_filter_type __read_mostly = {
3011
3166
.ops = & sk_filter_ops ,
3012
3167
.type = BPF_PROG_TYPE_SOCKET_FILTER ,
@@ -3032,13 +3187,31 @@ static struct bpf_prog_type_list cg_skb_type __read_mostly = {
3032
3187
.type = BPF_PROG_TYPE_CGROUP_SKB ,
3033
3188
};
3034
3189
3190
+ static struct bpf_prog_type_list lwt_in_type __read_mostly = {
3191
+ .ops = & lwt_inout_ops ,
3192
+ .type = BPF_PROG_TYPE_LWT_IN ,
3193
+ };
3194
+
3195
+ static struct bpf_prog_type_list lwt_out_type __read_mostly = {
3196
+ .ops = & lwt_inout_ops ,
3197
+ .type = BPF_PROG_TYPE_LWT_OUT ,
3198
+ };
3199
+
3200
+ static struct bpf_prog_type_list lwt_xmit_type __read_mostly = {
3201
+ .ops = & lwt_xmit_ops ,
3202
+ .type = BPF_PROG_TYPE_LWT_XMIT ,
3203
+ };
3204
+
3035
3205
static int __init register_sk_filter_ops (void )
3036
3206
{
3037
3207
bpf_register_prog_type (& sk_filter_type );
3038
3208
bpf_register_prog_type (& sched_cls_type );
3039
3209
bpf_register_prog_type (& sched_act_type );
3040
3210
bpf_register_prog_type (& xdp_type );
3041
3211
bpf_register_prog_type (& cg_skb_type );
3212
+ bpf_register_prog_type (& lwt_in_type );
3213
+ bpf_register_prog_type (& lwt_out_type );
3214
+ bpf_register_prog_type (& lwt_xmit_type );
3042
3215
3043
3216
return 0 ;
3044
3217
}
0 commit comments