@@ -3278,8 +3278,16 @@ static const struct bpf_func_proto *
32783278static const struct bpf_func_proto * sk_skb_func_proto (enum bpf_func_id func_id )
32793279{
32803280 switch (func_id ) {
3281+ case BPF_FUNC_skb_store_bytes :
3282+ return & bpf_skb_store_bytes_proto ;
32813283 case BPF_FUNC_skb_load_bytes :
32823284 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 ;
32833291 case BPF_FUNC_get_socket_cookie :
32843292 return & bpf_get_socket_cookie_proto ;
32853293 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
33433351 if (off + size > offsetofend (struct __sk_buff , cb [4 ]))
33443352 return false;
33453353 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 ):
33463358 case bpf_ctx_range (struct __sk_buff , data ):
33473359 case bpf_ctx_range (struct __sk_buff , data_end ):
33483360 if (size != size_default )
@@ -3371,6 +3383,7 @@ static bool sk_filter_is_valid_access(int off, int size,
33713383 case bpf_ctx_range (struct __sk_buff , tc_classid ):
33723384 case bpf_ctx_range (struct __sk_buff , data ):
33733385 case bpf_ctx_range (struct __sk_buff , data_end ):
3386+ case bpf_ctx_range_till (struct __sk_buff , family , local_port ):
33743387 return false;
33753388 }
33763389
@@ -3392,6 +3405,7 @@ static bool lwt_is_valid_access(int off, int size,
33923405{
33933406 switch (off ) {
33943407 case bpf_ctx_range (struct __sk_buff , tc_classid ):
3408+ case bpf_ctx_range_till (struct __sk_buff , family , local_port ):
33953409 return false;
33963410 }
33973411
@@ -3505,6 +3519,8 @@ static bool tc_cls_act_is_valid_access(int off, int size,
35053519 case bpf_ctx_range (struct __sk_buff , data_end ):
35063520 info -> reg_type = PTR_TO_PACKET_END ;
35073521 break ;
3522+ case bpf_ctx_range_till (struct __sk_buff , family , local_port ):
3523+ return false;
35083524 }
35093525
35103526 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,
35823598 return __is_valid_sock_ops_access (off , size );
35833599}
35843600
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+
35853640static bool sk_skb_is_valid_access (int off , int size ,
35863641 enum bpf_access_type type ,
35873642 struct bpf_insn_access_aux * info )
35883643{
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+
35893655 switch (off ) {
3656+ case bpf_ctx_range (struct __sk_buff , tc_classid ):
3657+ return false;
35903658 case bpf_ctx_range (struct __sk_buff , data ):
35913659 info -> reg_type = PTR_TO_PACKET ;
35923660 break ;
@@ -3783,6 +3851,106 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
37833851 * insn ++ = BPF_MOV64_IMM (si -> dst_reg , 0 );
37843852#endif
37853853 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 ;
37863954 }
37873955
37883956 return insn - insn_buf ;
@@ -4071,6 +4239,7 @@ const struct bpf_verifier_ops sk_skb_prog_ops = {
40714239 .get_func_proto = sk_skb_func_proto ,
40724240 .is_valid_access = sk_skb_is_valid_access ,
40734241 .convert_ctx_access = bpf_convert_ctx_access ,
4242+ .gen_prologue = sk_skb_prologue ,
40744243};
40754244
40764245int sk_detach_filter (struct sock * sk )
0 commit comments