Commit 39067dda authored by Chuck Lever's avatar Chuck Lever Committed by Jakub Kicinski
Browse files

SUNRPC: Use new helpers to handle TLS Alerts



Use the helpers to parse the level and description fields in
incoming alerts. "Warning" alerts are discarded, and "fatal"
alerts mean the session is no longer valid.

Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Link: https://lore.kernel.org/r/169047944747.5241.1974889594004407123.stgit@oracle-102.nfsv4bat.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 39d0e38d
Loading
Loading
Loading
Loading
+25 −22
Original line number Diff line number Diff line
@@ -43,7 +43,6 @@
#include <net/udp.h>
#include <net/tcp.h>
#include <net/tcp_states.h>
#include <net/tls.h>
#include <net/tls_prot.h>
#include <net/handshake.h>
#include <linux/uaccess.h>
@@ -227,14 +226,15 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining)
}

static int
svc_tcp_sock_process_cmsg(struct svc_sock *svsk, struct msghdr *msg,
svc_tcp_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));
	u8 content_type = tls_get_record_type(sock->sk, cmsg);
	u8 level, description;

	switch (content_type) {
	case 0:
		break;
	case TLS_RECORD_TYPE_DATA:
		/* TLS sets EOR at the end of each application data
		 * record, even though there might be more frames
@@ -243,12 +243,14 @@ svc_tcp_sock_process_cmsg(struct svc_sock *svsk, struct msghdr *msg,
		msg->msg_flags &= ~MSG_EOR;
		break;
	case TLS_RECORD_TYPE_ALERT:
			ret = -ENOTCONN;
		tls_alert_recv(sock->sk, msg, &level, &description);
		ret = (level == TLS_ALERT_LEVEL_FATAL) ?
			-ENOTCONN : -EAGAIN;
		break;
	default:
		/* discard this record type */
		ret = -EAGAIN;
	}
	}
	return ret;
}

@@ -259,13 +261,14 @@ svc_tcp_sock_recv_cmsg(struct svc_sock *svsk, struct msghdr *msg)
		struct cmsghdr	cmsg;
		u8		buf[CMSG_SPACE(sizeof(u8))];
	} u;
	struct socket *sock = svsk->sk_sock;
	int ret;

	msg->msg_control = &u;
	msg->msg_controllen = sizeof(u);
	ret = sock_recvmsg(svsk->sk_sock, msg, MSG_DONTWAIT);
	ret = sock_recvmsg(sock, msg, MSG_DONTWAIT);
	if (unlikely(msg->msg_controllen != sizeof(u)))
		ret = svc_tcp_sock_process_cmsg(svsk, msg, &u.cmsg, ret);
		ret = svc_tcp_sock_process_cmsg(sock, msg, &u.cmsg, ret);
	return ret;
}

+23 −19
Original line number Diff line number Diff line
@@ -47,7 +47,6 @@
#include <net/checksum.h>
#include <net/udp.h>
#include <net/tcp.h>
#include <net/tls.h>
#include <net/tls_prot.h>
#include <net/handshake.h>

@@ -361,11 +360,12 @@ 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));
	u8 content_type = tls_get_record_type(sock->sk, cmsg);
	u8 level, description;

	switch (content_type) {
	case 0:
		break;
	case TLS_RECORD_TYPE_DATA:
		/* TLS sets EOR at the end of each application data
		 * record, even though there might be more frames
@@ -374,12 +374,14 @@ xs_sock_process_cmsg(struct socket *sock, struct msghdr *msg,
		msg->msg_flags &= ~MSG_EOR;
		break;
	case TLS_RECORD_TYPE_ALERT:
			ret = -ENOTCONN;
		tls_alert_recv(sock->sk, msg, &level, &description);
		ret = (level == TLS_ALERT_LEVEL_FATAL) ?
			-EACCES : -EAGAIN;
		break;
	default:
		/* discard this record type */
		ret = -EAGAIN;
	}
	}
	return ret;
}

@@ -778,6 +780,8 @@ static void xs_stream_data_receive(struct sock_xprt *transport)
	}
	if (ret == -ESHUTDOWN)
		kernel_sock_shutdown(transport->sock, SHUT_RDWR);
	else if (ret == -EACCES)
		xprt_wake_pending_tasks(&transport->xprt, -EACCES);
	else
		xs_poll_check_readable(transport);
out: