Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Chuck Lever and committed by
Trond Myklebust
dea034b9 0d3ca07f

+47 -2
+47 -2
net/sunrpc/xprtsock.c
··· 47 47 #include <net/checksum.h> 48 48 #include <net/udp.h> 49 49 #include <net/tcp.h> 50 + #include <net/tls.h> 51 + 50 52 #include <linux/bvec.h> 51 53 #include <linux/highmem.h> 52 54 #include <linux/uio.h> ··· 349 347 return want; 350 348 } 351 349 350 + static int 351 + xs_sock_process_cmsg(struct socket *sock, struct msghdr *msg, 352 + struct cmsghdr *cmsg, int ret) 353 + { 354 + if (cmsg->cmsg_level == SOL_TLS && 355 + cmsg->cmsg_type == TLS_GET_RECORD_TYPE) { 356 + u8 content_type = *((u8 *)CMSG_DATA(cmsg)); 357 + 358 + switch (content_type) { 359 + case TLS_RECORD_TYPE_DATA: 360 + /* TLS sets EOR at the end of each application data 361 + * record, even though there might be more frames 362 + * waiting to be decrypted. 363 + */ 364 + msg->msg_flags &= ~MSG_EOR; 365 + break; 366 + case TLS_RECORD_TYPE_ALERT: 367 + ret = -ENOTCONN; 368 + break; 369 + default: 370 + ret = -EAGAIN; 371 + } 372 + } 373 + return ret; 374 + } 375 + 376 + static int 377 + xs_sock_recv_cmsg(struct socket *sock, struct msghdr *msg, int flags) 378 + { 379 + union { 380 + struct cmsghdr cmsg; 381 + u8 buf[CMSG_SPACE(sizeof(u8))]; 382 + } u; 383 + int ret; 384 + 385 + msg->msg_control = &u; 386 + msg->msg_controllen = sizeof(u); 387 + ret = sock_recvmsg(sock, msg, flags); 388 + if (msg->msg_controllen != sizeof(u)) 389 + ret = xs_sock_process_cmsg(sock, msg, &u.cmsg, ret); 390 + return ret; 391 + } 392 + 352 393 static ssize_t 353 394 xs_sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags, size_t seek) 354 395 { 355 396 ssize_t ret; 356 397 if (seek != 0) 357 398 iov_iter_advance(&msg->msg_iter, seek); 358 - ret = sock_recvmsg(sock, msg, flags); 399 + ret = xs_sock_recv_cmsg(sock, msg, flags); 359 400 return ret > 0 ? ret + seek : ret; 360 401 } 361 402 ··· 424 379 size_t count) 425 380 { 426 381 iov_iter_discard(&msg->msg_iter, ITER_DEST, count); 427 - return sock_recvmsg(sock, msg, flags); 382 + return xs_sock_recv_cmsg(sock, msg, flags); 428 383 } 429 384 430 385 #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE