Merge branch 'tls-fixes-for-record-type-handling-with-peek'
Sabrina Dubroca says: ==================== tls: fixes for record type handling with PEEK There are multiple bugs in tls_sw_recvmsg's handling of record types when MSG_PEEK flag is used, which can lead to incorrectly merging two records: - consecutive non-DATA records shouldn't be merged, even if they're the same type (partly handled by the test at the end of the main loop) - records of the same type (even DATA) shouldn't be merged if one record of a different type comes in between ==================== Link: https://lore.kernel.org/r/cover.1708007371.git.sd@queasysnail.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
f76d5f6580
@ -1772,7 +1772,8 @@ static int process_rx_list(struct tls_sw_context_rx *ctx,
|
||||
u8 *control,
|
||||
size_t skip,
|
||||
size_t len,
|
||||
bool is_peek)
|
||||
bool is_peek,
|
||||
bool *more)
|
||||
{
|
||||
struct sk_buff *skb = skb_peek(&ctx->rx_list);
|
||||
struct tls_msg *tlm;
|
||||
@ -1785,7 +1786,7 @@ static int process_rx_list(struct tls_sw_context_rx *ctx,
|
||||
|
||||
err = tls_record_content_type(msg, tlm, control);
|
||||
if (err <= 0)
|
||||
goto out;
|
||||
goto more;
|
||||
|
||||
if (skip < rxm->full_len)
|
||||
break;
|
||||
@ -1803,12 +1804,12 @@ static int process_rx_list(struct tls_sw_context_rx *ctx,
|
||||
|
||||
err = tls_record_content_type(msg, tlm, control);
|
||||
if (err <= 0)
|
||||
goto out;
|
||||
goto more;
|
||||
|
||||
err = skb_copy_datagram_msg(skb, rxm->offset + skip,
|
||||
msg, chunk);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
goto more;
|
||||
|
||||
len = len - chunk;
|
||||
copied = copied + chunk;
|
||||
@ -1844,6 +1845,10 @@ static int process_rx_list(struct tls_sw_context_rx *ctx,
|
||||
|
||||
out:
|
||||
return copied ? : err;
|
||||
more:
|
||||
if (more)
|
||||
*more = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -1947,6 +1952,7 @@ int tls_sw_recvmsg(struct sock *sk,
|
||||
int target, err;
|
||||
bool is_kvec = iov_iter_is_kvec(&msg->msg_iter);
|
||||
bool is_peek = flags & MSG_PEEK;
|
||||
bool rx_more = false;
|
||||
bool released = true;
|
||||
bool bpf_strp_enabled;
|
||||
bool zc_capable;
|
||||
@ -1966,12 +1972,12 @@ int tls_sw_recvmsg(struct sock *sk,
|
||||
goto end;
|
||||
|
||||
/* Process pending decrypted records. It must be non-zero-copy */
|
||||
err = process_rx_list(ctx, msg, &control, 0, len, is_peek);
|
||||
err = process_rx_list(ctx, msg, &control, 0, len, is_peek, &rx_more);
|
||||
if (err < 0)
|
||||
goto end;
|
||||
|
||||
copied = err;
|
||||
if (len <= copied)
|
||||
if (len <= copied || (copied && control != TLS_RECORD_TYPE_DATA) || rx_more)
|
||||
goto end;
|
||||
|
||||
target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
|
||||
@ -2064,6 +2070,8 @@ put_on_rx_list:
|
||||
decrypted += chunk;
|
||||
len -= chunk;
|
||||
__skb_queue_tail(&ctx->rx_list, skb);
|
||||
if (unlikely(control != TLS_RECORD_TYPE_DATA))
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -2128,10 +2136,10 @@ recv_end:
|
||||
/* Drain records from the rx_list & copy if required */
|
||||
if (is_peek || is_kvec)
|
||||
err = process_rx_list(ctx, msg, &control, copied,
|
||||
decrypted, is_peek);
|
||||
decrypted, is_peek, NULL);
|
||||
else
|
||||
err = process_rx_list(ctx, msg, &control, 0,
|
||||
async_copy_bytes, is_peek);
|
||||
async_copy_bytes, is_peek, NULL);
|
||||
}
|
||||
|
||||
copied += decrypted;
|
||||
|
@ -1485,6 +1485,51 @@ TEST_F(tls, control_msg)
|
||||
EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
|
||||
}
|
||||
|
||||
TEST_F(tls, control_msg_nomerge)
|
||||
{
|
||||
char *rec1 = "1111";
|
||||
char *rec2 = "2222";
|
||||
int send_len = 5;
|
||||
char buf[15];
|
||||
|
||||
if (self->notls)
|
||||
SKIP(return, "no TLS support");
|
||||
|
||||
EXPECT_EQ(tls_send_cmsg(self->fd, 100, rec1, send_len, 0), send_len);
|
||||
EXPECT_EQ(tls_send_cmsg(self->fd, 100, rec2, send_len, 0), send_len);
|
||||
|
||||
EXPECT_EQ(tls_recv_cmsg(_metadata, self->cfd, 100, buf, sizeof(buf), MSG_PEEK), send_len);
|
||||
EXPECT_EQ(memcmp(buf, rec1, send_len), 0);
|
||||
|
||||
EXPECT_EQ(tls_recv_cmsg(_metadata, self->cfd, 100, buf, sizeof(buf), MSG_PEEK), send_len);
|
||||
EXPECT_EQ(memcmp(buf, rec1, send_len), 0);
|
||||
|
||||
EXPECT_EQ(tls_recv_cmsg(_metadata, self->cfd, 100, buf, sizeof(buf), 0), send_len);
|
||||
EXPECT_EQ(memcmp(buf, rec1, send_len), 0);
|
||||
|
||||
EXPECT_EQ(tls_recv_cmsg(_metadata, self->cfd, 100, buf, sizeof(buf), 0), send_len);
|
||||
EXPECT_EQ(memcmp(buf, rec2, send_len), 0);
|
||||
}
|
||||
|
||||
TEST_F(tls, data_control_data)
|
||||
{
|
||||
char *rec1 = "1111";
|
||||
char *rec2 = "2222";
|
||||
char *rec3 = "3333";
|
||||
int send_len = 5;
|
||||
char buf[15];
|
||||
|
||||
if (self->notls)
|
||||
SKIP(return, "no TLS support");
|
||||
|
||||
EXPECT_EQ(send(self->fd, rec1, send_len, 0), send_len);
|
||||
EXPECT_EQ(tls_send_cmsg(self->fd, 100, rec2, send_len, 0), send_len);
|
||||
EXPECT_EQ(send(self->fd, rec3, send_len, 0), send_len);
|
||||
|
||||
EXPECT_EQ(recv(self->cfd, buf, sizeof(buf), MSG_PEEK), send_len);
|
||||
EXPECT_EQ(recv(self->cfd, buf, sizeof(buf), MSG_PEEK), send_len);
|
||||
}
|
||||
|
||||
TEST_F(tls, shutdown)
|
||||
{
|
||||
char const *test_str = "test_read";
|
||||
|
Loading…
Reference in New Issue
Block a user