hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I7DNAP CVE: N/A
----------------------------------------------------
Add the local_skb parameter to struct sk_buff to identify the local connection. Currently, this function is used only on BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB and BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB to help the sockops bpf program check whether the current connection is a local connection. Updating the local_skb variable only when the ACK packet is sent is sufficient for this function to work.
Run the following command to confirm that the newly added parameter is in the struct hole and does not cause substantial KABI changes. pahole -C sk_buff net/core/skbuff.o __u8 from_ingress:1; /* 132: 0 1 */ __u8 decrypted:1; /* 132: 1 1 */ __u8 local_skb:1; /* 132: 2 1 */
/* XXX 5 bits hole, try to pack */ /* XXX 1 byte hole, try to pack */
__u16 tc_index; /* 134 2 */
Signed-off-by: Liu Jian liujian56@huawei.com --- include/linux/filter.h | 1 + include/linux/skbuff.h | 3 +++ include/uapi/linux/bpf.h | 1 + net/core/filter.c | 7 +++++++ net/ipv4/tcp_input.c | 4 +++- net/ipv4/tcp_output.c | 5 +++++ tools/include/uapi/linux/bpf.h | 1 + 7 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/include/linux/filter.h b/include/linux/filter.h index a2c9ca9626e9..4479a49a4f7c 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -1284,6 +1284,7 @@ struct bpf_sock_ops_kern { u8 op; u8 is_fullsock; u8 remaining_opt_len; + u8 local_skb; u64 temp; /* temp and everything after is not * initialized to 0 before calling * the BPF program. New fields that diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index d16c8bd085f3..0eb7f5217169 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -868,6 +868,9 @@ struct sk_buff { #ifdef CONFIG_TLS_DEVICE __u8 decrypted:1; #endif +#ifndef __GENKSYMS__ + __u8 local_skb:1; +#endif
#ifdef CONFIG_NET_SCHED __u16 tc_index; /* traffic control index */ diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 79d5e5850bf6..2f9e57e99bda 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -4707,6 +4707,7 @@ struct bpf_sock_ops { * the outgoing header has not * been written yet. */ + __u32 local_skb; };
/* Definitions for bpf_sock_ops_cb_flags */ diff --git a/net/core/filter.c b/net/core/filter.c index 6268ef7c8735..18d17598fcee 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -9670,6 +9670,13 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type, tcp_flags), si->dst_reg, si->dst_reg, off); break; + case offsetof(struct bpf_sock_ops, local_skb): + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_sock_ops_kern, + local_skb), + si->dst_reg, si->src_reg, + offsetof(struct bpf_sock_ops_kern, + local_skb)); + break; } return insn - insn_buf; } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 58a8f211b997..c18a0300abde 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -185,8 +185,10 @@ static void bpf_skops_established(struct sock *sk, int bpf_op, sock_ops.is_fullsock = 1; sock_ops.sk = sk; /* sk with TCP_REPAIR_ON does not have skb in tcp_finish_connect */ - if (skb) + if (skb) { bpf_skops_init_skb(&sock_ops, skb, tcp_hdrlen(skb)); + sock_ops.local_skb = skb->local_skb; + }
BPF_CGROUP_RUN_PROG_SOCK_OPS(&sock_ops); } diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 680d7f06a51c..45c4d8c2f2d0 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -3671,6 +3671,8 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst, rcu_read_unlock(); #endif
+ skb->local_skb = 1; + bpf_skops_write_hdr_opt((struct sock *)sk, skb, req, syn_skb, synack_type, &opts);
@@ -3910,6 +3912,7 @@ int tcp_connect(struct sock *sk) if (unlikely(!buff)) return -ENOBUFS;
+ buff->local_skb = 1; tcp_init_nondata_skb(buff, tp->write_seq++, TCPHDR_SYN); tcp_mstamp_refresh(tp); tp->retrans_stamp = tcp_time_stamp(tp); @@ -4028,6 +4031,7 @@ void __tcp_send_ack(struct sock *sk, u32 rcv_nxt)
/* Reserve space for headers and prepare control bits. */ skb_reserve(buff, MAX_TCP_HEADER); + buff->local_skb = 1; tcp_init_nondata_skb(buff, tcp_acceptable_seq(sk), TCPHDR_ACK);
/* We do not want pure acks influencing TCP Small Queues or fq/pacing @@ -4036,6 +4040,7 @@ void __tcp_send_ack(struct sock *sk, u32 rcv_nxt) */ skb_set_tcp_pure_ack(buff);
+ /* Send it off, this clears delayed acks for us. */ __tcp_transmit_skb(sk, buff, 0, (__force gfp_t)0, rcv_nxt); } diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 807232f0c7e0..96554988d8a8 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -4707,6 +4707,7 @@ struct bpf_sock_ops { * the outgoing header has not * been written yet. */ + __u32 local_skb; };
/* Definitions for bpf_sock_ops_cb_flags */