@@ -3278,8 +3278,16 @@ static const struct bpf_func_proto *
3278
3278
static const struct bpf_func_proto * sk_skb_func_proto (enum bpf_func_id func_id )
3279
3279
{
3280
3280
switch (func_id ) {
3281
+ case BPF_FUNC_skb_store_bytes :
3282
+ return & bpf_skb_store_bytes_proto ;
3281
3283
case BPF_FUNC_skb_load_bytes :
3282
3284
return & bpf_skb_load_bytes_proto ;
3285
+ case BPF_FUNC_skb_pull_data :
3286
+ return & bpf_skb_pull_data_proto ;
3287
+ case BPF_FUNC_skb_change_tail :
3288
+ return & bpf_skb_change_tail_proto ;
3289
+ case BPF_FUNC_skb_change_head :
3290
+ return & bpf_skb_change_head_proto ;
3283
3291
case BPF_FUNC_get_socket_cookie :
3284
3292
return & bpf_get_socket_cookie_proto ;
3285
3293
case BPF_FUNC_get_socket_uid :
@@ -3343,6 +3351,10 @@ static bool bpf_skb_is_valid_access(int off, int size, enum bpf_access_type type
3343
3351
if (off + size > offsetofend (struct __sk_buff , cb [4 ]))
3344
3352
return false;
3345
3353
break ;
3354
+ case bpf_ctx_range_till (struct __sk_buff , remote_ip6 [0 ], remote_ip6 [3 ]):
3355
+ case bpf_ctx_range_till (struct __sk_buff , local_ip6 [0 ], local_ip6 [3 ]):
3356
+ case bpf_ctx_range_till (struct __sk_buff , remote_ip4 , remote_ip4 ):
3357
+ case bpf_ctx_range_till (struct __sk_buff , local_ip4 , local_ip4 ):
3346
3358
case bpf_ctx_range (struct __sk_buff , data ):
3347
3359
case bpf_ctx_range (struct __sk_buff , data_end ):
3348
3360
if (size != size_default )
@@ -3371,6 +3383,7 @@ static bool sk_filter_is_valid_access(int off, int size,
3371
3383
case bpf_ctx_range (struct __sk_buff , tc_classid ):
3372
3384
case bpf_ctx_range (struct __sk_buff , data ):
3373
3385
case bpf_ctx_range (struct __sk_buff , data_end ):
3386
+ case bpf_ctx_range_till (struct __sk_buff , family , local_port ):
3374
3387
return false;
3375
3388
}
3376
3389
@@ -3392,6 +3405,7 @@ static bool lwt_is_valid_access(int off, int size,
3392
3405
{
3393
3406
switch (off ) {
3394
3407
case bpf_ctx_range (struct __sk_buff , tc_classid ):
3408
+ case bpf_ctx_range_till (struct __sk_buff , family , local_port ):
3395
3409
return false;
3396
3410
}
3397
3411
@@ -3505,6 +3519,8 @@ static bool tc_cls_act_is_valid_access(int off, int size,
3505
3519
case bpf_ctx_range (struct __sk_buff , data_end ):
3506
3520
info -> reg_type = PTR_TO_PACKET_END ;
3507
3521
break ;
3522
+ case bpf_ctx_range_till (struct __sk_buff , family , local_port ):
3523
+ return false;
3508
3524
}
3509
3525
3510
3526
return bpf_skb_is_valid_access (off , size , type , info );
@@ -3582,11 +3598,63 @@ static bool sock_ops_is_valid_access(int off, int size,
3582
3598
return __is_valid_sock_ops_access (off , size );
3583
3599
}
3584
3600
3601
+ static int sk_skb_prologue (struct bpf_insn * insn_buf , bool direct_write ,
3602
+ const struct bpf_prog * prog )
3603
+ {
3604
+ struct bpf_insn * insn = insn_buf ;
3605
+
3606
+ if (!direct_write )
3607
+ return 0 ;
3608
+
3609
+ /* if (!skb->cloned)
3610
+ * goto start;
3611
+ *
3612
+ * (Fast-path, otherwise approximation that we might be
3613
+ * a clone, do the rest in helper.)
3614
+ */
3615
+ * insn ++ = BPF_LDX_MEM (BPF_B , BPF_REG_6 , BPF_REG_1 , CLONED_OFFSET ());
3616
+ * insn ++ = BPF_ALU32_IMM (BPF_AND , BPF_REG_6 , CLONED_MASK );
3617
+ * insn ++ = BPF_JMP_IMM (BPF_JEQ , BPF_REG_6 , 0 , 7 );
3618
+
3619
+ /* ret = bpf_skb_pull_data(skb, 0); */
3620
+ * insn ++ = BPF_MOV64_REG (BPF_REG_6 , BPF_REG_1 );
3621
+ * insn ++ = BPF_ALU64_REG (BPF_XOR , BPF_REG_2 , BPF_REG_2 );
3622
+ * insn ++ = BPF_RAW_INSN (BPF_JMP | BPF_CALL , 0 , 0 , 0 ,
3623
+ BPF_FUNC_skb_pull_data );
3624
+ /* if (!ret)
3625
+ * goto restore;
3626
+ * return SK_DROP;
3627
+ */
3628
+ * insn ++ = BPF_JMP_IMM (BPF_JEQ , BPF_REG_0 , 0 , 2 );
3629
+ * insn ++ = BPF_ALU32_IMM (BPF_MOV , BPF_REG_0 , SK_DROP );
3630
+ * insn ++ = BPF_EXIT_INSN ();
3631
+
3632
+ /* restore: */
3633
+ * insn ++ = BPF_MOV64_REG (BPF_REG_1 , BPF_REG_6 );
3634
+ /* start: */
3635
+ * insn ++ = prog -> insnsi [0 ];
3636
+
3637
+ return insn - insn_buf ;
3638
+ }
3639
+
3585
3640
static bool sk_skb_is_valid_access (int off , int size ,
3586
3641
enum bpf_access_type type ,
3587
3642
struct bpf_insn_access_aux * info )
3588
3643
{
3644
+ if (type == BPF_WRITE ) {
3645
+ switch (off ) {
3646
+ case bpf_ctx_range (struct __sk_buff , mark ):
3647
+ case bpf_ctx_range (struct __sk_buff , tc_index ):
3648
+ case bpf_ctx_range (struct __sk_buff , priority ):
3649
+ break ;
3650
+ default :
3651
+ return false;
3652
+ }
3653
+ }
3654
+
3589
3655
switch (off ) {
3656
+ case bpf_ctx_range (struct __sk_buff , tc_classid ):
3657
+ return false;
3590
3658
case bpf_ctx_range (struct __sk_buff , data ):
3591
3659
info -> reg_type = PTR_TO_PACKET ;
3592
3660
break ;
@@ -3783,6 +3851,106 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
3783
3851
* insn ++ = BPF_MOV64_IMM (si -> dst_reg , 0 );
3784
3852
#endif
3785
3853
break ;
3854
+ case offsetof(struct __sk_buff , family ):
3855
+ BUILD_BUG_ON (FIELD_SIZEOF (struct sock_common , skc_family ) != 2 );
3856
+
3857
+ * insn ++ = BPF_LDX_MEM (BPF_FIELD_SIZEOF (struct sk_buff , sk ),
3858
+ si -> dst_reg , si -> src_reg ,
3859
+ offsetof(struct sk_buff , sk ));
3860
+ * insn ++ = BPF_LDX_MEM (BPF_H , si -> dst_reg , si -> dst_reg ,
3861
+ bpf_target_off (struct sock_common ,
3862
+ skc_family ,
3863
+ 2 , target_size ));
3864
+ break ;
3865
+ case offsetof(struct __sk_buff , remote_ip4 ):
3866
+ BUILD_BUG_ON (FIELD_SIZEOF (struct sock_common , skc_daddr ) != 4 );
3867
+
3868
+ * insn ++ = BPF_LDX_MEM (BPF_FIELD_SIZEOF (struct sk_buff , sk ),
3869
+ si -> dst_reg , si -> src_reg ,
3870
+ offsetof(struct sk_buff , sk ));
3871
+ * insn ++ = BPF_LDX_MEM (BPF_W , si -> dst_reg , si -> dst_reg ,
3872
+ bpf_target_off (struct sock_common ,
3873
+ skc_daddr ,
3874
+ 4 , target_size ));
3875
+ break ;
3876
+ case offsetof(struct __sk_buff , local_ip4 ):
3877
+ BUILD_BUG_ON (FIELD_SIZEOF (struct sock_common ,
3878
+ skc_rcv_saddr ) != 4 );
3879
+
3880
+ * insn ++ = BPF_LDX_MEM (BPF_FIELD_SIZEOF (struct sk_buff , sk ),
3881
+ si -> dst_reg , si -> src_reg ,
3882
+ offsetof(struct sk_buff , sk ));
3883
+ * insn ++ = BPF_LDX_MEM (BPF_W , si -> dst_reg , si -> dst_reg ,
3884
+ bpf_target_off (struct sock_common ,
3885
+ skc_rcv_saddr ,
3886
+ 4 , target_size ));
3887
+ break ;
3888
+ case offsetof(struct __sk_buff , remote_ip6 [0 ]) ...
3889
+ offsetof(struct __sk_buff , remote_ip6 [3 ]):
3890
+ #if IS_ENABLED (CONFIG_IPV6 )
3891
+ BUILD_BUG_ON (FIELD_SIZEOF (struct sock_common ,
3892
+ skc_v6_daddr .s6_addr32 [0 ]) != 4 );
3893
+
3894
+ off = si -> off ;
3895
+ off -= offsetof(struct __sk_buff , remote_ip6 [0 ]);
3896
+
3897
+ * insn ++ = BPF_LDX_MEM (BPF_FIELD_SIZEOF (struct sk_buff , sk ),
3898
+ si -> dst_reg , si -> src_reg ,
3899
+ offsetof(struct sk_buff , sk ));
3900
+ * insn ++ = BPF_LDX_MEM (BPF_W , si -> dst_reg , si -> dst_reg ,
3901
+ offsetof(struct sock_common ,
3902
+ skc_v6_daddr .s6_addr32 [0 ]) +
3903
+ off );
3904
+ #else
3905
+ * insn ++ = BPF_MOV32_IMM (si -> dst_reg , 0 );
3906
+ #endif
3907
+ break ;
3908
+ case offsetof(struct __sk_buff , local_ip6 [0 ]) ...
3909
+ offsetof(struct __sk_buff , local_ip6 [3 ]):
3910
+ #if IS_ENABLED (CONFIG_IPV6 )
3911
+ BUILD_BUG_ON (FIELD_SIZEOF (struct sock_common ,
3912
+ skc_v6_rcv_saddr .s6_addr32 [0 ]) != 4 );
3913
+
3914
+ off = si -> off ;
3915
+ off -= offsetof(struct __sk_buff , local_ip6 [0 ]);
3916
+
3917
+ * insn ++ = BPF_LDX_MEM (BPF_FIELD_SIZEOF (struct sk_buff , sk ),
3918
+ si -> dst_reg , si -> src_reg ,
3919
+ offsetof(struct sk_buff , sk ));
3920
+ * insn ++ = BPF_LDX_MEM (BPF_W , si -> dst_reg , si -> dst_reg ,
3921
+ offsetof(struct sock_common ,
3922
+ skc_v6_rcv_saddr .s6_addr32 [0 ]) +
3923
+ off );
3924
+ #else
3925
+ * insn ++ = BPF_MOV32_IMM (si -> dst_reg , 0 );
3926
+ #endif
3927
+ break ;
3928
+
3929
+ case offsetof(struct __sk_buff , remote_port ):
3930
+ BUILD_BUG_ON (FIELD_SIZEOF (struct sock_common , skc_dport ) != 2 );
3931
+
3932
+ * insn ++ = BPF_LDX_MEM (BPF_FIELD_SIZEOF (struct sk_buff , sk ),
3933
+ si -> dst_reg , si -> src_reg ,
3934
+ offsetof(struct sk_buff , sk ));
3935
+ * insn ++ = BPF_LDX_MEM (BPF_H , si -> dst_reg , si -> dst_reg ,
3936
+ bpf_target_off (struct sock_common ,
3937
+ skc_dport ,
3938
+ 2 , target_size ));
3939
+ #ifndef __BIG_ENDIAN_BITFIELD
3940
+ * insn ++ = BPF_ALU32_IMM (BPF_LSH , si -> dst_reg , 16 );
3941
+ #endif
3942
+ break ;
3943
+
3944
+ case offsetof(struct __sk_buff , local_port ):
3945
+ BUILD_BUG_ON (FIELD_SIZEOF (struct sock_common , skc_num ) != 2 );
3946
+
3947
+ * insn ++ = BPF_LDX_MEM (BPF_FIELD_SIZEOF (struct sk_buff , sk ),
3948
+ si -> dst_reg , si -> src_reg ,
3949
+ offsetof(struct sk_buff , sk ));
3950
+ * insn ++ = BPF_LDX_MEM (BPF_H , si -> dst_reg , si -> dst_reg ,
3951
+ bpf_target_off (struct sock_common ,
3952
+ skc_num , 2 , target_size ));
3953
+ break ;
3786
3954
}
3787
3955
3788
3956
return insn - insn_buf ;
@@ -4071,6 +4239,7 @@ const struct bpf_verifier_ops sk_skb_prog_ops = {
4071
4239
.get_func_proto = sk_skb_func_proto ,
4072
4240
.is_valid_access = sk_skb_is_valid_access ,
4073
4241
.convert_ctx_access = bpf_convert_ctx_access ,
4242
+ .gen_prologue = sk_skb_prologue ,
4074
4243
};
4075
4244
4076
4245
int sk_detach_filter (struct sock * sk )
0 commit comments