Commit dea034b9 authored by Chuck Lever's avatar Chuck Lever Committed by Trond Myklebust

SUNRPC: Capture CMSG metadata on client-side receive

kTLS sockets use CMSG to report decryption errors and the need
for session re-keying.

For RPC-with-TLS, an "application data" message contains a ULP
payload, and that is passed along to the RPC client. An "alert"
message triggers connection reset. Everything else is discarded.
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent 0d3ca07f
...@@ -47,6 +47,8 @@ ...@@ -47,6 +47,8 @@
#include <net/checksum.h> #include <net/checksum.h>
#include <net/udp.h> #include <net/udp.h>
#include <net/tcp.h> #include <net/tcp.h>
#include <net/tls.h>
#include <linux/bvec.h> #include <linux/bvec.h>
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/uio.h> #include <linux/uio.h>
...@@ -347,13 +349,56 @@ xs_alloc_sparse_pages(struct xdr_buf *buf, size_t want, gfp_t gfp) ...@@ -347,13 +349,56 @@ xs_alloc_sparse_pages(struct xdr_buf *buf, size_t want, gfp_t gfp)
return want; return want;
} }
static int
xs_sock_process_cmsg(struct socket *sock, struct msghdr *msg,
struct cmsghdr *cmsg, int ret)
{
if (cmsg->cmsg_level == SOL_TLS &&
cmsg->cmsg_type == TLS_GET_RECORD_TYPE) {
u8 content_type = *((u8 *)CMSG_DATA(cmsg));
switch (content_type) {
case TLS_RECORD_TYPE_DATA:
/* TLS sets EOR at the end of each application data
* record, even though there might be more frames
* waiting to be decrypted.
*/
msg->msg_flags &= ~MSG_EOR;
break;
case TLS_RECORD_TYPE_ALERT:
ret = -ENOTCONN;
break;
default:
ret = -EAGAIN;
}
}
return ret;
}
static int
xs_sock_recv_cmsg(struct socket *sock, struct msghdr *msg, int flags)
{
union {
struct cmsghdr cmsg;
u8 buf[CMSG_SPACE(sizeof(u8))];
} u;
int ret;
msg->msg_control = &u;
msg->msg_controllen = sizeof(u);
ret = sock_recvmsg(sock, msg, flags);
if (msg->msg_controllen != sizeof(u))
ret = xs_sock_process_cmsg(sock, msg, &u.cmsg, ret);
return ret;
}
static ssize_t static ssize_t
xs_sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags, size_t seek) xs_sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags, size_t seek)
{ {
ssize_t ret; ssize_t ret;
if (seek != 0) if (seek != 0)
iov_iter_advance(&msg->msg_iter, seek); iov_iter_advance(&msg->msg_iter, seek);
ret = sock_recvmsg(sock, msg, flags); ret = xs_sock_recv_cmsg(sock, msg, flags);
return ret > 0 ? ret + seek : ret; return ret > 0 ? ret + seek : ret;
} }
...@@ -379,7 +424,7 @@ xs_read_discard(struct socket *sock, struct msghdr *msg, int flags, ...@@ -379,7 +424,7 @@ xs_read_discard(struct socket *sock, struct msghdr *msg, int flags,
size_t count) size_t count)
{ {
iov_iter_discard(&msg->msg_iter, ITER_DEST, count); iov_iter_discard(&msg->msg_iter, ITER_DEST, count);
return sock_recvmsg(sock, msg, flags); return xs_sock_recv_cmsg(sock, msg, flags);
} }
#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment