tls_push_record can return -EAGAIN because of tcp layer. In that case open_rec is already in the tx_record list and should not be freed. Also the record size can be more than the size requested to write in tls_sw_do_sendpage(). That leads to overflow of copied variable and wrong return code.
Fixes: d10523d0b3d7 ("net/tls: free the record on encryption error") Signed-off-by: Vadim Fedorenko <vfedore...@novek.ru> --- net/tls/tls_sw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index e23f94a..d4acbd1 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -796,7 +796,7 @@ static int bpf_exec_tx_verdict(struct sk_msg *msg, struct sock *sk, psock = sk_psock_get(sk); if (!psock || !policy) { err = tls_push_record(sk, flags, record_type); - if (err && err != -EINPROGRESS) { + if (err && err != -EINPROGRESS && err != -EAGAIN) { *copied -= sk_msg_free(sk, msg); tls_free_open_rec(sk); } @@ -824,7 +824,7 @@ static int bpf_exec_tx_verdict(struct sk_msg *msg, struct sock *sk, switch (psock->eval) { case __SK_PASS: err = tls_push_record(sk, flags, record_type); - if (err && err != -EINPROGRESS) { + if (err && err != -EINPROGRESS && err != -EAGAIN) { *copied -= sk_msg_free(sk, msg); tls_free_open_rec(sk); goto out_err; @@ -1132,7 +1132,7 @@ static int tls_sw_do_sendpage(struct sock *sk, struct page *page, struct sk_msg *msg_pl; struct tls_rec *rec; int num_async = 0; - size_t copied = 0; + ssize_t copied = 0; bool full_record; int record_room; int ret = 0; @@ -1234,7 +1234,7 @@ static int tls_sw_do_sendpage(struct sock *sk, struct page *page, } sendpage_end: ret = sk_stream_error(sk, flags, ret); - return copied ? copied : ret; + return (copied > 0) ? copied : ret; } int tls_sw_sendpage_locked(struct sock *sk, struct page *page, -- 1.8.3.1