[RFC net-next 10/17] tls: use protocol ops via tls_context
From: Geliang Tang <geliang@kernel.org>
Date: 2026-06-22 10:45:09
Also in:
mptcp
Subsystem:
networking [general], networking [tls], the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, John Fastabend, Sabrina Dubroca, Linus Torvalds
From: Geliang Tang <redacted> Currently, TLS code directly calls TCP-specific functions (e.g., tcp_rate_check_app_limited, tcp_read_done, tcp_epollin_ready, etc.) and accesses TCP-specific fields (e.g., TCP_SKB_CB(skb)->seq). This makes it hard to support other protocols like MPTCP. Introduce a struct tls_prot_ops pointer in tls_context, which is initialized during tls_init based on the socket protocol (TCP or MPTCP). All protocol-dependent operations are now invoked via this ops pointer, allowing each protocol to provide its own implementation. Also add proper module reference counting for the ops owner. Co-developed-by: Gang Yan <redacted> Signed-off-by: Gang Yan <redacted> Co-developed-by: Zqiang <qiang.zhang@linux.dev> Signed-off-by: Zqiang <qiang.zhang@linux.dev> Signed-off-by: Geliang Tang <redacted> --- include/net/tls.h | 2 ++ net/tls/tls_main.c | 15 ++++++++++++++- net/tls/tls_strp.c | 26 ++++++++++++++++++-------- net/tls/tls_sw.c | 6 ++++-- 4 files changed, 38 insertions(+), 11 deletions(-)
diff --git a/include/net/tls.h b/include/net/tls.h
index 500fe87b50d2..9270de42787b 100644
--- a/include/net/tls.h
+++ b/include/net/tls.h@@ -280,6 +280,8 @@ struct tls_context { int (*sk_read_sock)(struct sock *sk, read_descriptor_t *desc, sk_read_actor_t recv_actor); + const struct tls_prot_ops *ops; + union tls_crypto_context crypto_send; union tls_crypto_context crypto_recv;
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index 296d133fa61f..b45890e75c9e 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c@@ -201,7 +201,7 @@ int tls_push_sg(struct sock *sk, ctx->splicing_pages = true; while (1) { /* is sending application-limited? */ - tcp_rate_check_app_limited(sk); + ctx->ops->check_app_limited(sk); p = sg_page(sg); retry: bvec_set_page(&bvec, p, size, offset);
@@ -340,6 +340,11 @@ void tls_ctx_free(struct sock *sk, struct tls_context *ctx) if (!ctx) return; + if (ctx->ops) { + module_put(ctx->ops->owner); + ctx->ops = NULL; + } + memzero_explicit(&ctx->crypto_send, sizeof(ctx->crypto_send)); memzero_explicit(&ctx->crypto_recv, sizeof(ctx->crypto_recv)); mutex_destroy(&ctx->tx_lock);
@@ -1079,6 +1084,7 @@ static struct tls_prot_ops *tls_prot_ops_find(int protocol) static int tls_init(struct sock *sk) { + struct tls_prot_ops *ops; struct tls_context *ctx; int rc = 0;
@@ -1101,10 +1107,17 @@ static int tls_init(struct sock *sk) goto out; } + ops = tls_prot_ops_find(sk->sk_protocol); + if (!ops || !try_module_get(ops->owner)) { + rc = -EINVAL; + goto out; + } + ctx->tx_conf = TLS_BASE; ctx->rx_conf = TLS_BASE; ctx->tx_max_payload_len = TLS_MAX_PAYLOAD_SIZE; ctx->sk_read_sock = sk->sk_socket->ops->read_sock; + ctx->ops = ops; update_sk_prot(sk, ctx); out: write_unlock_bh(&sk->sk_callback_lock);
diff --git a/net/tls/tls_strp.c b/net/tls/tls_strp.c
index 9945d17b2f8c..48eb4b692f47 100644
--- a/net/tls/tls_strp.c
+++ b/net/tls/tls_strp.c@@ -120,6 +120,7 @@ struct sk_buff *tls_strp_msg_detach(struct tls_sw_context_rx *ctx) int tls_strp_msg_cow(struct tls_sw_context_rx *ctx) { struct tls_strparser *strp = &ctx->strp; + struct tls_context *tls_ctx = tls_get_ctx(strp->sk); struct sk_buff *skb; if (strp->copy_mode)
@@ -132,7 +133,7 @@ int tls_strp_msg_cow(struct tls_sw_context_rx *ctx) tls_strp_anchor_free(strp); strp->anchor = skb; - tcp_read_done(strp->sk, strp->stm.full_len); + tls_ctx->ops->read_done(strp->sk, strp->stm.full_len); strp->copy_mode = 1; return 0;
@@ -390,6 +391,7 @@ static int tls_strp_read_copyin(struct tls_strparser *strp) static int tls_strp_read_copy(struct tls_strparser *strp, bool qshort) { + struct tls_context *ctx = tls_get_ctx(strp->sk); struct skb_shared_info *shinfo; struct page *page; int need_spc, len;
@@ -398,7 +400,7 @@ static int tls_strp_read_copy(struct tls_strparser *strp, bool qshort) * to read the data out. Otherwise the connection will stall. * Without pressure threshold of INT_MAX will never be ready. */ - if (likely(qshort && !tcp_epollin_ready(strp->sk, INT_MAX))) + if (likely(qshort && !ctx->ops->epollin_ready(strp->sk))) return 0; shinfo = skb_shinfo(strp->anchor);
@@ -434,12 +436,13 @@ static int tls_strp_read_copy(struct tls_strparser *strp, bool qshort) static bool tls_strp_check_queue_ok(struct tls_strparser *strp) { unsigned int len = strp->stm.offset + strp->stm.full_len; + struct tls_context *ctx = tls_get_ctx(strp->sk); struct sk_buff *first, *skb; u32 seq; first = skb_shinfo(strp->anchor)->frag_list; skb = first; - seq = TCP_SKB_CB(first)->seq; + seq = ctx->ops->get_skb_seq(first); /* Make sure there's no duplicate data in the queue, * and the decrypted status matches.
@@ -449,7 +452,7 @@ static bool tls_strp_check_queue_ok(struct tls_strparser *strp) len -= skb->len; skb = skb->next; - if (TCP_SKB_CB(skb)->seq != seq) + if (ctx->ops->get_skb_seq(skb) != seq) return false; if (skb_cmp_decrypted(first, skb)) return false;
@@ -460,11 +463,11 @@ static bool tls_strp_check_queue_ok(struct tls_strparser *strp) static void tls_strp_load_anchor_with_queue(struct tls_strparser *strp, int len) { - struct tcp_sock *tp = tcp_sk(strp->sk); + struct tls_context *ctx = tls_get_ctx(strp->sk); struct sk_buff *first; u32 offset; - first = tcp_recv_skb(strp->sk, tp->copied_seq, &offset); + first = ctx->ops->recv_skb(strp->sk, &offset); if (WARN_ON_ONCE(!first)) return;
@@ -565,6 +568,11 @@ void tls_strp_check_rcv(struct tls_strparser *strp, bool announce) /* Lower sock lock held */ void tls_strp_data_ready(struct tls_strparser *strp) { + struct tls_context *ctx = tls_get_ctx(strp->sk); + + if (!ctx) + return; + /* This check is needed to synchronize with do_tls_strp_work. * do_tls_strp_work acquires a process lock (lock_sock) whereas * the lock held here is bh_lock_sock. The two locks can be
@@ -572,7 +580,7 @@ void tls_strp_data_ready(struct tls_strparser *strp) * allows a thread in BH context to safely check if the process * lock is held. In this case, if the lock is held, queue work. */ - if (sock_owned_by_user_nocheck(strp->sk)) { + if (ctx->ops->lock_is_held(strp->sk)) { queue_work(tls_strp_wq, &strp->work); return; }
@@ -597,10 +605,12 @@ static void tls_strp_work(struct work_struct *w) */ void tls_strp_msg_consume(struct tls_strparser *strp) { + struct tls_context *ctx = tls_get_ctx(strp->sk); + WARN_ON(!strp->stm.full_len); if (likely(!strp->copy_mode)) - tcp_read_done(strp->sk, strp->stm.full_len); + ctx->ops->read_done(strp->sk, strp->stm.full_len); else tls_strp_flush_anchor_copy(strp);
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 35fb0c3c965a..71ab9763b1ed 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c@@ -2171,7 +2171,8 @@ int tls_rx_msg_size(struct tls_strparser *strp, struct sk_buff *skb) } /* Linearize header to local buffer */ - ret = skb_copy_bits(skb, strp->stm.offset, header, prot->prepend_size); + ret = tls_ctx->ops->skb_get_header(skb, strp->stm.offset, header, + prot->prepend_size); if (ret < 0) goto read_failure;
@@ -2202,7 +2203,8 @@ int tls_rx_msg_size(struct tls_strparser *strp, struct sk_buff *skb) } tls_device_rx_resync_new_rec(strp->sk, data_len + TLS_HEADER_SIZE, - TCP_SKB_CB(skb)->seq + strp->stm.offset); + tls_ctx->ops->get_skb_seq(skb) + + strp->stm.offset); return data_len + TLS_HEADER_SIZE; read_failure:
--
2.53.0