Skip to content

Commit dea034b

Browse files
chuckleverTrond Myklebust
authored andcommitted
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: Chuck Lever <chuck.lever@oracle.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
1 parent 0d3ca07 commit dea034b

File tree

1 file changed

+47
-2
lines changed

1 file changed

+47
-2
lines changed

net/sunrpc/xprtsock.c

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
#include <net/checksum.h>
4848
#include <net/udp.h>
4949
#include <net/tcp.h>
50+
#include <net/tls.h>
51+
5052
#include <linux/bvec.h>
5153
#include <linux/highmem.h>
5254
#include <linux/uio.h>
@@ -347,13 +349,56 @@ xs_alloc_sparse_pages(struct xdr_buf *buf, size_t want, gfp_t gfp)
347349
return want;
348350
}
349351

352+
static int
353+
xs_sock_process_cmsg(struct socket *sock, struct msghdr *msg,
354+
struct cmsghdr *cmsg, int ret)
355+
{
356+
if (cmsg->cmsg_level == SOL_TLS &&
357+
cmsg->cmsg_type == TLS_GET_RECORD_TYPE) {
358+
u8 content_type = *((u8 *)CMSG_DATA(cmsg));
359+
360+
switch (content_type) {
361+
case TLS_RECORD_TYPE_DATA:
362+
/* TLS sets EOR at the end of each application data
363+
* record, even though there might be more frames
364+
* waiting to be decrypted.
365+
*/
366+
msg->msg_flags &= ~MSG_EOR;
367+
break;
368+
case TLS_RECORD_TYPE_ALERT:
369+
ret = -ENOTCONN;
370+
break;
371+
default:
372+
ret = -EAGAIN;
373+
}
374+
}
375+
return ret;
376+
}
377+
378+
static int
379+
xs_sock_recv_cmsg(struct socket *sock, struct msghdr *msg, int flags)
380+
{
381+
union {
382+
struct cmsghdr cmsg;
383+
u8 buf[CMSG_SPACE(sizeof(u8))];
384+
} u;
385+
int ret;
386+
387+
msg->msg_control = &u;
388+
msg->msg_controllen = sizeof(u);
389+
ret = sock_recvmsg(sock, msg, flags);
390+
if (msg->msg_controllen != sizeof(u))
391+
ret = xs_sock_process_cmsg(sock, msg, &u.cmsg, ret);
392+
return ret;
393+
}
394+
350395
static ssize_t
351396
xs_sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags, size_t seek)
352397
{
353398
ssize_t ret;
354399
if (seek != 0)
355400
iov_iter_advance(&msg->msg_iter, seek);
356-
ret = sock_recvmsg(sock, msg, flags);
401+
ret = xs_sock_recv_cmsg(sock, msg, flags);
357402
return ret > 0 ? ret + seek : ret;
358403
}
359404

@@ -379,7 +424,7 @@ xs_read_discard(struct socket *sock, struct msghdr *msg, int flags,
379424
size_t count)
380425
{
381426
iov_iter_discard(&msg->msg_iter, ITER_DEST, count);
382-
return sock_recvmsg(sock, msg, flags);
427+
return xs_sock_recv_cmsg(sock, msg, flags);
383428
}
384429

385430
#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE

0 commit comments

Comments
 (0)