mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 22:24:11 +08:00
Merge branch 'Add skb_adjust_room() for SK_SKB'
John Fastabend says: ==================== This implements the helper skb_adjust_room() for BPF_SKS_SK_STREAM_VERDICT programs so we can push/pop headers from the data on recieve. One use case is to pop TLS headers off kTLS packets. The first patch implements the helper and the second updates test_sockmap to use it removing some case handling we had to do earlier to account for the TLS headers in the kTLS tests. v1->v2: Fix error path for TLS case (Daniel) check mode input is 0 because we don't use it now (Daniel) Remove incorrect/misleading comment (Lorenz) Thanks, John Acked-by: Martin KaFai Lau <kafai@fb.com> --- ==================== Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
commit
fb91db01c6
@ -76,6 +76,7 @@
|
||||
#include <net/bpf_sk_storage.h>
|
||||
#include <net/transp_v6.h>
|
||||
#include <linux/btf_ids.h>
|
||||
#include <net/tls.h>
|
||||
|
||||
static const struct bpf_func_proto *
|
||||
bpf_sk_base_func_proto(enum bpf_func_id func_id);
|
||||
@ -3479,6 +3480,48 @@ static u32 __bpf_skb_max_len(const struct sk_buff *skb)
|
||||
SKB_MAX_ALLOC;
|
||||
}
|
||||
|
||||
BPF_CALL_4(sk_skb_adjust_room, struct sk_buff *, skb, s32, len_diff,
|
||||
u32, mode, u64, flags)
|
||||
{
|
||||
u32 len_diff_abs = abs(len_diff);
|
||||
bool shrink = len_diff < 0;
|
||||
int ret = 0;
|
||||
|
||||
if (unlikely(flags || mode))
|
||||
return -EINVAL;
|
||||
if (unlikely(len_diff_abs > 0xfffU))
|
||||
return -EFAULT;
|
||||
|
||||
if (!shrink) {
|
||||
ret = skb_cow(skb, len_diff);
|
||||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
__skb_push(skb, len_diff_abs);
|
||||
memset(skb->data, 0, len_diff_abs);
|
||||
} else {
|
||||
if (unlikely(!pskb_may_pull(skb, len_diff_abs)))
|
||||
return -ENOMEM;
|
||||
__skb_pull(skb, len_diff_abs);
|
||||
}
|
||||
bpf_compute_data_end_sk_skb(skb);
|
||||
if (tls_sw_has_ctx_rx(skb->sk)) {
|
||||
struct strp_msg *rxm = strp_msg(skb);
|
||||
|
||||
rxm->full_len += len_diff;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto sk_skb_adjust_room_proto = {
|
||||
.func = sk_skb_adjust_room,
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
BPF_CALL_4(bpf_skb_adjust_room, struct sk_buff *, skb, s32, len_diff,
|
||||
u32, mode, u64, flags)
|
||||
{
|
||||
@ -6745,6 +6788,7 @@ bool bpf_helper_changes_pkt_data(void *func)
|
||||
func == bpf_skb_change_tail ||
|
||||
func == sk_skb_change_tail ||
|
||||
func == bpf_skb_adjust_room ||
|
||||
func == sk_skb_adjust_room ||
|
||||
func == bpf_skb_pull_data ||
|
||||
func == sk_skb_pull_data ||
|
||||
func == bpf_clone_redirect ||
|
||||
@ -7218,6 +7262,8 @@ sk_skb_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
||||
return &sk_skb_change_tail_proto;
|
||||
case BPF_FUNC_skb_change_head:
|
||||
return &sk_skb_change_head_proto;
|
||||
case BPF_FUNC_skb_adjust_room:
|
||||
return &sk_skb_adjust_room_proto;
|
||||
case BPF_FUNC_get_socket_cookie:
|
||||
return &bpf_get_socket_cookie_proto;
|
||||
case BPF_FUNC_get_socket_uid:
|
||||
|
@ -131,39 +131,55 @@ int bpf_prog2(struct __sk_buff *skb)
|
||||
|
||||
}
|
||||
|
||||
SEC("sk_skb3")
|
||||
int bpf_prog3(struct __sk_buff *skb)
|
||||
static inline void bpf_write_pass(struct __sk_buff *skb, int offset)
|
||||
{
|
||||
const int one = 1;
|
||||
int err, *f, ret = SK_PASS;
|
||||
int err = bpf_skb_pull_data(skb, 6 + offset);
|
||||
void *data_end;
|
||||
char *c;
|
||||
|
||||
err = bpf_skb_pull_data(skb, 19);
|
||||
if (err)
|
||||
goto tls_out;
|
||||
return;
|
||||
|
||||
c = (char *)(long)skb->data;
|
||||
data_end = (void *)(long)skb->data_end;
|
||||
|
||||
if (c + 18 < data_end)
|
||||
memcpy(&c[13], "PASS", 4);
|
||||
if (c + 5 + offset < data_end)
|
||||
memcpy(c + offset, "PASS", 4);
|
||||
}
|
||||
|
||||
SEC("sk_skb3")
|
||||
int bpf_prog3(struct __sk_buff *skb)
|
||||
{
|
||||
int err, *f, ret = SK_PASS;
|
||||
const int one = 1;
|
||||
|
||||
f = bpf_map_lookup_elem(&sock_skb_opts, &one);
|
||||
if (f && *f) {
|
||||
__u64 flags = 0;
|
||||
|
||||
ret = 0;
|
||||
flags = *f;
|
||||
|
||||
err = bpf_skb_adjust_room(skb, -13, 0, 0);
|
||||
if (err)
|
||||
return SK_DROP;
|
||||
err = bpf_skb_adjust_room(skb, 4, 0, 0);
|
||||
if (err)
|
||||
return SK_DROP;
|
||||
bpf_write_pass(skb, 0);
|
||||
#ifdef SOCKMAP
|
||||
return bpf_sk_redirect_map(skb, &tls_sock_map, ret, flags);
|
||||
#else
|
||||
return bpf_sk_redirect_hash(skb, &tls_sock_map, &ret, flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
f = bpf_map_lookup_elem(&sock_skb_opts, &one);
|
||||
if (f && *f)
|
||||
ret = SK_DROP;
|
||||
err = bpf_skb_adjust_room(skb, 4, 0, 0);
|
||||
if (err)
|
||||
return SK_DROP;
|
||||
bpf_write_pass(skb, 13);
|
||||
tls_out:
|
||||
return ret;
|
||||
}
|
||||
|
@ -518,28 +518,13 @@ static int msg_verify_data(struct msghdr *msg, int size, int chunk_sz)
|
||||
if (i == 0 && txmsg_ktls_skb) {
|
||||
if (msg->msg_iov[i].iov_len < 4)
|
||||
return -EIO;
|
||||
if (txmsg_ktls_skb_redir) {
|
||||
if (memcmp(&d[13], "PASS", 4) != 0) {
|
||||
fprintf(stderr,
|
||||
"detected redirect ktls_skb data error with skb ingress update @iov[%i]:%i \"%02x %02x %02x %02x\" != \"PASS\"\n", i, 0, d[13], d[14], d[15], d[16]);
|
||||
return -EIO;
|
||||
}
|
||||
d[13] = 0;
|
||||
d[14] = 1;
|
||||
d[15] = 2;
|
||||
d[16] = 3;
|
||||
j = 13;
|
||||
} else if (txmsg_ktls_skb) {
|
||||
if (memcmp(d, "PASS", 4) != 0) {
|
||||
fprintf(stderr,
|
||||
"detected ktls_skb data error with skb ingress update @iov[%i]:%i \"%02x %02x %02x %02x\" != \"PASS\"\n", i, 0, d[0], d[1], d[2], d[3]);
|
||||
return -EIO;
|
||||
}
|
||||
d[0] = 0;
|
||||
d[1] = 1;
|
||||
d[2] = 2;
|
||||
d[3] = 3;
|
||||
if (memcmp(d, "PASS", 4) != 0) {
|
||||
fprintf(stderr,
|
||||
"detected skb data error with skb ingress update @iov[%i]:%i \"%02x %02x %02x %02x\" != \"PASS\"\n",
|
||||
i, 0, d[0], d[1], d[2], d[3]);
|
||||
return -EIO;
|
||||
}
|
||||
j = 4; /* advance index past PASS header */
|
||||
}
|
||||
|
||||
for (; j < msg->msg_iov[i].iov_len && size; j++) {
|
||||
|
Loading…
Reference in New Issue
Block a user