Skip to content

Commit 953d7af

Browse files
jrfastabkernel-patches-bot
authored andcommitted
bpf, sockmap: add skb_adjust_room to pop bytes off ingress payload
This implements a new helper skb_adjust_room() so users can push/pop extra bytes from a BPF_SK_SKB_STREAM_VERDICT program. Some protocols may include headers and other information that we may not want to include when doing a redirect from a BPF_SK_SKB_STREAM_VERDICT program. One use case is to redirect TLS packets into a receive socket that doesn't expect TLS data. In TLS case the first 13B or so contain the protocol header. With KTLS the payload is decrypted so we should be able to redirect this to a receiving socket, but the receiving socket may not be expecting to receive a TLS header and discard the data. Using the above helper we can pop the header off and put an appropriate header on the payload. This allows for creating a proxy between protocols without extra hops through the stack or userspace. So in order to fix this case add skb_adjust_room() so users can strip the header. After this the user can strip the header and an unmodified receiver thread will work correctly when data is redirected into the ingress path of a sock. Signed-off-by: John Fastabend <[email protected]>
1 parent 384bdac commit 953d7af

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

net/core/filter.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
#include <net/bpf_sk_storage.h>
7777
#include <net/transp_v6.h>
7878
#include <linux/btf_ids.h>
79+
#include <net/tls.h>
7980

8081
static const struct bpf_func_proto *
8182
bpf_sk_base_func_proto(enum bpf_func_id func_id);
@@ -3218,6 +3219,53 @@ static u32 __bpf_skb_max_len(const struct sk_buff *skb)
32183219
SKB_MAX_ALLOC;
32193220
}
32203221

3222+
BPF_CALL_4(sk_skb_adjust_room, struct sk_buff *, skb, s32, len_diff,
3223+
u32, mode, u64, flags)
3224+
{
3225+
unsigned int len_diff_abs = abs(len_diff);
3226+
bool shrink = len_diff < 0;
3227+
int ret = 0;
3228+
3229+
if (unlikely(flags))
3230+
return -EINVAL;
3231+
if (unlikely(len_diff_abs > 0xfffU))
3232+
return -EFAULT;
3233+
3234+
if (!shrink) {
3235+
unsigned int grow = len_diff;
3236+
3237+
ret = skb_cow(skb, grow);
3238+
if (likely(!ret)) {
3239+
__skb_push(skb, len_diff_abs);
3240+
memset(skb->data, 0, len_diff_abs);
3241+
}
3242+
} else {
3243+
/* skb_ensure_writable() is not needed here, as we're
3244+
* already working on an uncloned skb.
3245+
*/
3246+
if (unlikely(!pskb_may_pull(skb, len_diff_abs)))
3247+
return -ENOMEM;
3248+
__skb_pull(skb, len_diff_abs);
3249+
}
3250+
bpf_compute_data_end_sk_skb(skb);
3251+
if (tls_sw_has_ctx_rx(skb->sk)) {
3252+
struct strp_msg *rxm = strp_msg(skb);
3253+
3254+
rxm->full_len += len_diff;
3255+
}
3256+
return ret;
3257+
}
3258+
3259+
static const struct bpf_func_proto sk_skb_adjust_room_proto = {
3260+
.func = sk_skb_adjust_room,
3261+
.gpl_only = false,
3262+
.ret_type = RET_INTEGER,
3263+
.arg1_type = ARG_PTR_TO_CTX,
3264+
.arg2_type = ARG_ANYTHING,
3265+
.arg3_type = ARG_ANYTHING,
3266+
.arg4_type = ARG_ANYTHING,
3267+
};
3268+
32213269
BPF_CALL_4(bpf_skb_adjust_room, struct sk_buff *, skb, s32, len_diff,
32223270
u32, mode, u64, flags)
32233271
{
@@ -6484,6 +6532,7 @@ bool bpf_helper_changes_pkt_data(void *func)
64846532
func == bpf_skb_change_tail ||
64856533
func == sk_skb_change_tail ||
64866534
func == bpf_skb_adjust_room ||
6535+
func == sk_skb_adjust_room ||
64876536
func == bpf_skb_pull_data ||
64886537
func == sk_skb_pull_data ||
64896538
func == bpf_clone_redirect ||
@@ -6951,6 +7000,8 @@ sk_skb_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
69517000
return &sk_skb_change_tail_proto;
69527001
case BPF_FUNC_skb_change_head:
69537002
return &sk_skb_change_head_proto;
7003+
case BPF_FUNC_skb_adjust_room:
7004+
return &sk_skb_adjust_room_proto;
69547005
case BPF_FUNC_get_socket_cookie:
69557006
return &bpf_get_socket_cookie_proto;
69567007
case BPF_FUNC_get_socket_uid:

0 commit comments

Comments
 (0)