From: Chuck Lever <chuck.lever@oracle.com>
To: netdev@vger.kernel.org, linux-nfs@vger.kernel.org,
linux-nvme@lists.infradead.org, linux-cifs@vger.kernel.org,
linux-fsdevel@vger.kernel.org
Cc: ak@tempesta-tech.com, borisp@nvidia.com, simo@redhat.com
Subject: [PATCH RFC 11/15] SUNRPC: Add infrastructure for async RPC_AUTH_TLS probe
Date: Mon, 18 Apr 2022 12:52:22 -0400 [thread overview]
Message-ID: <165030074244.5246.8728494438187879593.stgit@oracle-102.nfsv4.dev> (raw)
In-Reply-To: <165030062272.5246.16956092606399079004.stgit@oracle-102.nfsv4.dev>
Introduce helpers for sending an RPC_AUTH_TLS probe, waiting for
it, and then parsing the reply. These will be used to handle the
reconnect case.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
include/linux/sunrpc/clnt.h | 1 +
include/linux/sunrpc/xprt.h | 13 ++++++++++
net/sunrpc/clnt.c | 58 +++++++++++++++++++++++++++++++++++++++++++
net/sunrpc/xprt.c | 1 +
net/sunrpc/xprtsock.c | 56 ++++++++++++++++++++++++++++++++++++++++++
5 files changed, 129 insertions(+)
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index e10a19d136ca..15fd84e4c321 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -209,6 +209,7 @@ int rpc_call_sync(struct rpc_clnt *clnt,
unsigned int flags);
struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred,
int flags);
+void rpc_starttls_async(struct rpc_task *task);
int rpc_restart_call_prepare(struct rpc_task *);
int rpc_restart_call(struct rpc_task *);
void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 8d654bc35dce..cbb0fe738d97 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -159,6 +159,7 @@ struct rpc_xprt_ops {
void (*disable_swap)(struct rpc_xprt *xprt);
void (*inject_disconnect)(struct rpc_xprt *xprt);
int (*tls_handshake_sync)(struct rpc_xprt *xprt);
+ int (*tls_handshake_async)(struct rpc_xprt *xprt);
int (*bc_setup)(struct rpc_xprt *xprt,
unsigned int min_reqs);
size_t (*bc_maxpayload)(struct rpc_xprt *xprt);
@@ -204,6 +205,7 @@ struct rpc_xprt {
size_t max_payload; /* largest RPC payload size,
in bytes */
+ struct rpc_wait_queue probing; /* requests waiting on TLS probe */
struct rpc_wait_queue binding; /* requests waiting on rpcbind */
struct rpc_wait_queue sending; /* requests waiting to send */
struct rpc_wait_queue pending; /* requests in flight */
@@ -436,6 +438,7 @@ void xprt_release_write(struct rpc_xprt *, struct rpc_task *);
#define XPRT_CWND_WAIT (10)
#define XPRT_WRITE_SPACE (11)
#define XPRT_SND_IS_COOKIE (12)
+#define XPRT_PROBING (13)
static inline void xprt_set_connected(struct rpc_xprt *xprt)
{
@@ -506,4 +509,14 @@ static inline int xprt_test_and_set_binding(struct rpc_xprt *xprt)
return test_and_set_bit(XPRT_BINDING, &xprt->state);
}
+static inline void xprt_clear_probing(struct rpc_xprt *xprt)
+{
+ clear_bit(XPRT_PROBING, &xprt->state);
+}
+
+static inline int xprt_test_and_set_probing(struct rpc_xprt *xprt)
+{
+ return test_and_set_bit(XPRT_PROBING, &xprt->state);
+}
+
#endif /* _LINUX_SUNRPC_XPRT_H */
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 1601a06deaf5..e9a6622dba68 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -2829,6 +2829,64 @@ static int rpc_starttls_sync(struct rpc_clnt *clnt)
return err;
}
+static void rpc_probe_tls_done(struct rpc_task *task, void *data)
+{
+ struct rpc_xprt *xprt = data;
+
+ if (task->tk_status < 0) {
+ trace_rpc_tls_unavailable(task->tk_client, xprt);
+ xprt_clear_probing(xprt);
+ rpc_wake_up_status(&xprt->probing, task->tk_status);
+ return;
+ }
+
+ /* Send ClientHello; a second callback will wake the waiting task */
+ if (xprt->ops->tls_handshake_async(xprt)) {
+ trace_rpc_tls_not_started(task->tk_client, xprt);
+ xprt_clear_probing(xprt);
+ rpc_wake_up_status(&xprt->probing, -EACCES);
+ }
+}
+
+static void rpc_probe_tls_release(void *data)
+{
+ struct rpc_xprt *xprt = data;
+
+ xprt_put(xprt);
+}
+
+static const struct rpc_call_ops rpc_ops_probe_tls = {
+ .rpc_call_done = rpc_probe_tls_done,
+ .rpc_release = rpc_probe_tls_release,
+};
+
+/**
+ * rpc_starttls_async - Asynchronously establish a TLS session
+ * @task: an RPC task waiting for a TLS session
+ *
+ */
+void rpc_starttls_async(struct rpc_task *task)
+{
+ struct rpc_xprt *xprt = xprt_get(task->tk_xprt);
+
+ rpc_sleep_on_timeout(&xprt->probing, task, NULL,
+ jiffies + xprt->connect_timeout);
+ if (xprt_test_and_set_probing(xprt)) {
+ xprt_put(xprt);
+ return;
+ }
+
+ /*
+ * RPC_TASK_TLSCRED: use an RPC_AUTH_TLS cred instead of AUTH_NULL
+ * RPC_TASK_SWAPPER: insert the task at the head of the transmit queue
+ * RPC_TASK_CORK: stop sending after this Call is transmitted
+ */
+ rpc_put_task(rpc_call_null_helper(task->tk_client, xprt, NULL,
+ RPC_TASK_TLSCRED | RPC_TASK_SWAPPER | RPC_TASK_CORK,
+ &rpc_ops_probe_tls, xprt));
+}
+EXPORT_SYMBOL_GPL(rpc_starttls_async);
+
struct rpc_cb_add_xprt_calldata {
struct rpc_xprt_switch *xps;
struct rpc_xprt *xprt;
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 4b303b945b51..762281dba077 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -2016,6 +2016,7 @@ static void xprt_init(struct rpc_xprt *xprt, struct net *net)
xprt->cwnd = RPC_INITCWND;
xprt->bind_index = 0;
+ rpc_init_wait_queue(&xprt->probing, "xprt_probing");
rpc_init_wait_queue(&xprt->binding, "xprt_binding");
rpc_init_wait_queue(&xprt->pending, "xprt_pending");
rpc_init_wait_queue(&xprt->sending, "xprt_sending");
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index bbba9747f68d..bb8c32002ce7 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -2378,6 +2378,46 @@ static int xs_tcp_tls_handshake_sync(struct rpc_xprt *xprt)
return rc;
}
+/**
+ * xs_tcp_tls_handshake_wake - TLS handshake completion handler
+ * @data: address of xprt to wake
+ * @status: status of handshake
+ *
+ */
+static void xs_tcp_tls_handshake_wake(void *data, int status)
+{
+ struct rpc_xprt *xprt = data;
+ struct sock_xprt *transport =
+ container_of(xprt, struct sock_xprt, xprt);
+
+ xs_tcp_clear_discard(transport);
+ xprt_clear_probing(xprt);
+ rpc_wake_up_status(&xprt->probing, status < 0 ? -EACCES : 0);
+ xprt_put(xprt);
+}
+
+/**
+ * xs_tcp_tls_handshake_async - Start a TLS handshake
+ * @xprt: transport on which to perform handshake
+ *
+ * Caller ensures there will be no other traffic on this transport.
+ *
+ * Return values:
+ * %0: Handshake initiated; @xprt will be awoken when it's done.
+ * Negative errno: handshake was not started.
+ */
+static int xs_tcp_tls_handshake_async(struct rpc_xprt *xprt)
+{
+ struct sock_xprt *transport =
+ container_of(xprt, struct sock_xprt, xprt);
+
+ WRITE_ONCE(transport->recv.ignore_dr, true);
+ return tls_client_hello_x509(transport->sock,
+ xs_tcp_tls_handshake_wake, xprt_get(xprt),
+ TLSH_DEFAULT_PRIORITIES, TLSH_NO_PEERID,
+ TLSH_NO_CERT);
+}
+
#else /* CONFIG_TLS */
/**
@@ -2394,6 +2434,21 @@ static int xs_tcp_tls_handshake_sync(struct rpc_xprt *xprt)
return -EACCES;
}
+/**
+ * xs_tcp_tls_handshake_async - Start a TLS handshake
+ * @xprt: transport on which to perform handshake
+ *
+ * Caller ensures there will be no other traffic on this transport.
+ *
+ * Return values:
+ * %0: Handshake initiated; @xprt will be awoken when it's done.
+ * Negative errno: handshake was not started.
+ */
+static int xs_tcp_tls_handshake_async(struct rpc_xprt *xprt)
+{
+ return -EACCES;
+}
+
#endif /*CONFIG_TLS */
/**
@@ -2845,6 +2900,7 @@ static const struct rpc_xprt_ops xs_tcp_ops = {
.disable_swap = xs_disable_swap,
.inject_disconnect = xs_inject_disconnect,
.tls_handshake_sync = xs_tcp_tls_handshake_sync,
+ .tls_handshake_async = xs_tcp_tls_handshake_async,
#ifdef CONFIG_SUNRPC_BACKCHANNEL
.bc_setup = xprt_setup_bc,
.bc_maxpayload = xs_tcp_bc_maxpayload,
next prev parent reply other threads:[~2022-04-18 16:54 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-18 16:51 [PATCH RFC 00/15] Prototype implementation of RPC-with-TLS Chuck Lever
2022-04-18 16:51 ` [PATCH RFC 01/15] SUNRPC: Replace dprintk() call site in xs_data_ready Chuck Lever
2022-04-18 16:51 ` [PATCH RFC 02/15] SUNRPC: Ignore data_ready callbacks during TLS handshakes Chuck Lever
2022-04-18 16:51 ` [PATCH RFC 03/15] SUNRPC: Capture cmsg metadata on client-side receive Chuck Lever
2022-04-18 16:51 ` [PATCH RFC 04/15] SUNRPC: Fail faster on bad verifier Chuck Lever
2022-04-18 16:51 ` [PATCH RFC 05/15] SUNRPC: Widen rpc_task::tk_flags Chuck Lever
2022-04-18 16:51 ` [PATCH RFC 06/15] SUNRPC: Add RPC client support for the RPC_AUTH_TLS authentication flavor Chuck Lever
2022-04-18 16:51 ` [PATCH RFC 07/15] SUNRPC: Refactor rpc_call_null_helper() Chuck Lever
2022-04-18 16:52 ` [PATCH RFC 08/15] SUNRPC: Add RPC_TASK_CORK flag Chuck Lever
2022-04-19 2:57 ` Trond Myklebust
2022-04-19 18:16 ` Chuck Lever III
2022-04-19 19:04 ` Trond Myklebust
2022-04-19 19:40 ` Chuck Lever III
2022-04-19 22:08 ` Trond Myklebust
2022-04-20 0:34 ` Chuck Lever III
2022-04-18 16:52 ` [PATCH RFC 09/15] SUNRPC: Add a cl_xprtsec_policy field Chuck Lever
2022-04-18 16:52 ` [PATCH RFC 10/15] SUNRPC: Expose TLS policy via the rpc_create() API Chuck Lever
2022-04-18 16:52 ` Chuck Lever [this message]
2022-04-18 16:52 ` [PATCH RFC 12/15] SUNRPC: Add FSM machinery to handle RPC_AUTH_TLS on reconnect Chuck Lever
2022-04-18 16:52 ` [PATCH RFC 13/15] NFS: Replace fs_context-related dprintk() call sites with tracepoints Chuck Lever
2022-04-18 16:52 ` [PATCH RFC 14/15] NFS: Have struct nfs_client carry a TLS policy field Chuck Lever
2022-04-18 16:52 ` [PATCH RFC 15/15] NFS: Add an "xprtsec=" NFS mount option Chuck Lever
2022-04-19 3:31 ` [PATCH RFC 00/15] Prototype implementation of RPC-with-TLS Trond Myklebust
2022-04-19 16:00 ` Chuck Lever III
2022-04-19 18:48 ` Trond Myklebust
2022-04-19 18:53 ` Chuck Lever III
2022-04-19 20:49 ` Rick Macklem
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=165030074244.5246.8728494438187879593.stgit@oracle-102.nfsv4.dev \
--to=chuck.lever@oracle.com \
--cc=ak@tempesta-tech.com \
--cc=borisp@nvidia.com \
--cc=linux-cifs@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=linux-nvme@lists.infradead.org \
--cc=netdev@vger.kernel.org \
--cc=simo@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).