tls: rx: factor out writing ContentType to cmsg

cmsg can be filled in during rx_list processing or normal
receive. Consolidate the code.

We don't need to keep the boolean to track if the cmsg was
created. 0 is an invalid content type.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Jakub Kicinski 2022-04-08 11:31:28 -07:00 committed by David S. Miller
parent 37943f047b
commit 06554f4ffc

View File

@ -1635,6 +1635,29 @@ static bool tls_sw_advance_skb(struct sock *sk, struct sk_buff *skb,
return true; return true;
} }
static int tls_record_content_type(struct msghdr *msg, struct tls_msg *tlm,
u8 *control)
{
int err;
if (!*control) {
*control = tlm->control;
if (!*control)
return -EBADMSG;
err = put_cmsg(msg, SOL_TLS, TLS_GET_RECORD_TYPE,
sizeof(*control), control);
if (*control != TLS_RECORD_TYPE_DATA) {
if (err || msg->msg_flags & MSG_CTRUNC)
return -EIO;
}
} else if (*control != tlm->control) {
return 0;
}
return 1;
}
/* This function traverses the rx_list in tls receive context to copies the /* This function traverses the rx_list in tls receive context to copies the
* decrypted records into the buffer provided by caller zero copy is not * decrypted records into the buffer provided by caller zero copy is not
* true. Further, the records are removed from the rx_list if it is not a peek * true. Further, the records are removed from the rx_list if it is not a peek
@ -1643,31 +1666,23 @@ static bool tls_sw_advance_skb(struct sock *sk, struct sk_buff *skb,
static int process_rx_list(struct tls_sw_context_rx *ctx, static int process_rx_list(struct tls_sw_context_rx *ctx,
struct msghdr *msg, struct msghdr *msg,
u8 *control, u8 *control,
bool *cmsg,
size_t skip, size_t skip,
size_t len, size_t len,
bool zc, bool zc,
bool is_peek) bool is_peek)
{ {
struct sk_buff *skb = skb_peek(&ctx->rx_list); struct sk_buff *skb = skb_peek(&ctx->rx_list);
u8 ctrl = *control;
u8 msgc = *cmsg;
struct tls_msg *tlm; struct tls_msg *tlm;
ssize_t copied = 0; ssize_t copied = 0;
int err;
/* Set the record type in 'control' if caller didn't pass it */
if (!ctrl && skb) {
tlm = tls_msg(skb);
ctrl = tlm->control;
}
while (skip && skb) { while (skip && skb) {
struct strp_msg *rxm = strp_msg(skb); struct strp_msg *rxm = strp_msg(skb);
tlm = tls_msg(skb); tlm = tls_msg(skb);
/* Cannot process a record of different type */ err = tls_record_content_type(msg, tlm, control);
if (ctrl != tlm->control) if (err <= 0)
return 0; return err;
if (skip < rxm->full_len) if (skip < rxm->full_len)
break; break;
@ -1683,27 +1698,12 @@ static int process_rx_list(struct tls_sw_context_rx *ctx,
tlm = tls_msg(skb); tlm = tls_msg(skb);
/* Cannot process a record of different type */ err = tls_record_content_type(msg, tlm, control);
if (ctrl != tlm->control) if (err <= 0)
return 0; return err;
/* Set record type if not already done. For a non-data record,
* do not proceed if record type could not be copied.
*/
if (!msgc) {
int cerr = put_cmsg(msg, SOL_TLS, TLS_GET_RECORD_TYPE,
sizeof(ctrl), &ctrl);
msgc = true;
if (ctrl != TLS_RECORD_TYPE_DATA) {
if (cerr || msg->msg_flags & MSG_CTRUNC)
return -EIO;
*cmsg = msgc;
}
}
if (!zc || (rxm->full_len - skip) > len) { if (!zc || (rxm->full_len - skip) > len) {
int err = skb_copy_datagram_msg(skb, rxm->offset + skip, err = skb_copy_datagram_msg(skb, rxm->offset + skip,
msg, chunk); msg, chunk);
if (err < 0) if (err < 0)
return err; return err;
@ -1740,7 +1740,6 @@ static int process_rx_list(struct tls_sw_context_rx *ctx,
skb = next_skb; skb = next_skb;
} }
*control = ctrl;
return copied; return copied;
} }
@ -1762,7 +1761,6 @@ int tls_sw_recvmsg(struct sock *sk,
struct tls_msg *tlm; struct tls_msg *tlm;
struct sk_buff *skb; struct sk_buff *skb;
ssize_t copied = 0; ssize_t copied = 0;
bool cmsg = false;
int target, err = 0; int target, err = 0;
long timeo; long timeo;
bool is_kvec = iov_iter_is_kvec(&msg->msg_iter); bool is_kvec = iov_iter_is_kvec(&msg->msg_iter);
@ -1779,8 +1777,7 @@ int tls_sw_recvmsg(struct sock *sk,
bpf_strp_enabled = sk_psock_strp_enabled(psock); bpf_strp_enabled = sk_psock_strp_enabled(psock);
/* Process pending decrypted records. It must be non-zero-copy */ /* Process pending decrypted records. It must be non-zero-copy */
err = process_rx_list(ctx, msg, &control, &cmsg, 0, len, false, err = process_rx_list(ctx, msg, &control, 0, len, false, is_peek);
is_peek);
if (err < 0) { if (err < 0) {
tls_err_abort(sk, err); tls_err_abort(sk, err);
goto end; goto end;
@ -1852,26 +1849,10 @@ int tls_sw_recvmsg(struct sock *sk,
* is known just after record is dequeued from stream parser. * is known just after record is dequeued from stream parser.
* For tls1.3, we disable async. * For tls1.3, we disable async.
*/ */
err = tls_record_content_type(msg, tlm, &control);
if (!control) if (err <= 0)
control = tlm->control;
else if (control != tlm->control)
goto recv_end; goto recv_end;
if (!cmsg) {
int cerr;
cerr = put_cmsg(msg, SOL_TLS, TLS_GET_RECORD_TYPE,
sizeof(control), &control);
cmsg = true;
if (control != TLS_RECORD_TYPE_DATA) {
if (cerr || msg->msg_flags & MSG_CTRUNC) {
err = -EIO;
goto recv_end;
}
}
}
if (async) { if (async) {
/* TLS 1.2-only, to_decrypt must be text length */ /* TLS 1.2-only, to_decrypt must be text length */
chunk = min_t(int, to_decrypt, len); chunk = min_t(int, to_decrypt, len);
@ -1953,10 +1934,10 @@ recv_end:
/* Drain records from the rx_list & copy if required */ /* Drain records from the rx_list & copy if required */
if (is_peek || is_kvec) if (is_peek || is_kvec)
err = process_rx_list(ctx, msg, &control, &cmsg, copied, err = process_rx_list(ctx, msg, &control, copied,
decrypted, false, is_peek); decrypted, false, is_peek);
else else
err = process_rx_list(ctx, msg, &control, &cmsg, 0, err = process_rx_list(ctx, msg, &control, 0,
decrypted, true, is_peek); decrypted, true, is_peek);
if (err < 0) { if (err < 0) {
tls_err_abort(sk, err); tls_err_abort(sk, err);