Skip to content

Commit 5e052dd

Browse files
committed
SUNRPC: Recognize control messages in server-side TCP socket code
To support kTLS, the server-side TCP socket receive path needs to watch for CMSGs. Acked-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
1 parent 6a0cdf5 commit 5e052dd

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

include/net/tls.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ extern const struct tls_cipher_size_desc tls_cipher_size_desc[];
6969

7070
#define TLS_CRYPTO_INFO_READY(info) ((info)->cipher_type)
7171

72+
#define TLS_RECORD_TYPE_ALERT 0x15
73+
#define TLS_RECORD_TYPE_HANDSHAKE 0x16
7274
#define TLS_RECORD_TYPE_DATA 0x17
7375

7476
#define TLS_AAD_SPACE_SIZE 13

net/sunrpc/svcsock.c

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include <net/udp.h>
4444
#include <net/tcp.h>
4545
#include <net/tcp_states.h>
46+
#include <net/tls.h>
4647
#include <linux/uaccess.h>
4748
#include <linux/highmem.h>
4849
#include <asm/ioctls.h>
@@ -216,6 +217,49 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining)
216217
return len;
217218
}
218219

220+
static int
221+
svc_tcp_sock_process_cmsg(struct svc_sock *svsk, struct msghdr *msg,
222+
struct cmsghdr *cmsg, int ret)
223+
{
224+
if (cmsg->cmsg_level == SOL_TLS &&
225+
cmsg->cmsg_type == TLS_GET_RECORD_TYPE) {
226+
u8 content_type = *((u8 *)CMSG_DATA(cmsg));
227+
228+
switch (content_type) {
229+
case TLS_RECORD_TYPE_DATA:
230+
/* TLS sets EOR at the end of each application data
231+
* record, even though there might be more frames
232+
* waiting to be decrypted.
233+
*/
234+
msg->msg_flags &= ~MSG_EOR;
235+
break;
236+
case TLS_RECORD_TYPE_ALERT:
237+
ret = -ENOTCONN;
238+
break;
239+
default:
240+
ret = -EAGAIN;
241+
}
242+
}
243+
return ret;
244+
}
245+
246+
static int
247+
svc_tcp_sock_recv_cmsg(struct svc_sock *svsk, struct msghdr *msg)
248+
{
249+
union {
250+
struct cmsghdr cmsg;
251+
u8 buf[CMSG_SPACE(sizeof(u8))];
252+
} u;
253+
int ret;
254+
255+
msg->msg_control = &u;
256+
msg->msg_controllen = sizeof(u);
257+
ret = sock_recvmsg(svsk->sk_sock, msg, MSG_DONTWAIT);
258+
if (unlikely(msg->msg_controllen != sizeof(u)))
259+
ret = svc_tcp_sock_process_cmsg(svsk, msg, &u.cmsg, ret);
260+
return ret;
261+
}
262+
219263
#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
220264
static void svc_flush_bvec(const struct bio_vec *bvec, size_t size, size_t seek)
221265
{
@@ -263,7 +307,7 @@ static ssize_t svc_tcp_read_msg(struct svc_rqst *rqstp, size_t buflen,
263307
iov_iter_advance(&msg.msg_iter, seek);
264308
buflen -= seek;
265309
}
266-
len = sock_recvmsg(svsk->sk_sock, &msg, MSG_DONTWAIT);
310+
len = svc_tcp_sock_recv_cmsg(svsk, &msg);
267311
if (len > 0)
268312
svc_flush_bvec(bvec, len, seek);
269313

@@ -877,7 +921,7 @@ static ssize_t svc_tcp_read_marker(struct svc_sock *svsk,
877921
iov.iov_base = ((char *)&svsk->sk_marker) + svsk->sk_tcplen;
878922
iov.iov_len = want;
879923
iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, want);
880-
len = sock_recvmsg(svsk->sk_sock, &msg, MSG_DONTWAIT);
924+
len = svc_tcp_sock_recv_cmsg(svsk, &msg);
881925
if (len < 0)
882926
return len;
883927
svsk->sk_tcplen += len;

0 commit comments

Comments
 (0)