tls: rx: make tls_wait_data() return an recvmsg retcode
[linux-2.6-microblaze.git] / net / tls / tls_sw.c
index 21c76db..09370f8 100644 (file)
@@ -44,6 +44,8 @@
 #include <net/strparser.h>
 #include <net/tls.h>
 
+#include "tls.h"
+
 struct tls_decrypt_arg {
        bool zc;
        bool async;
@@ -524,7 +526,8 @@ static int tls_do_encryption(struct sock *sk,
        memcpy(&rec->iv_data[iv_offset], tls_ctx->tx.iv,
               prot->iv_size + prot->salt_size);
 
-       xor_iv_with_seq(prot, rec->iv_data + iv_offset, tls_ctx->tx.rec_seq);
+       tls_xor_iv_with_seq(prot, rec->iv_data + iv_offset,
+                           tls_ctx->tx.rec_seq);
 
        sge->offset += prot->prepend_size;
        sge->length -= prot->prepend_size;
@@ -961,7 +964,7 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
        lock_sock(sk);
 
        if (unlikely(msg->msg_controllen)) {
-               ret = tls_proccess_cmsg(sk, msg, &record_type);
+               ret = tls_process_cmsg(sk, msg, &record_type);
                if (ret) {
                        if (ret == -EINPROGRESS)
                                num_async++;
@@ -1299,54 +1302,50 @@ int tls_sw_sendpage(struct sock *sk, struct page *page,
        return ret;
 }
 
-static struct sk_buff *tls_wait_data(struct sock *sk, struct sk_psock *psock,
-                                    bool nonblock, long timeo, int *err)
+static int
+tls_rx_rec_wait(struct sock *sk, struct sk_psock *psock, bool nonblock,
+               long timeo)
 {
        struct tls_context *tls_ctx = tls_get_ctx(sk);
        struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
-       struct sk_buff *skb;
        DEFINE_WAIT_FUNC(wait, woken_wake_function);
 
-       while (!(skb = ctx->recv_pkt) && sk_psock_queue_empty(psock)) {
-               if (sk->sk_err) {
-                       *err = sock_error(sk);
-                       return NULL;
-               }
+       while (!ctx->recv_pkt) {
+               if (!sk_psock_queue_empty(psock))
+                       return 0;
+
+               if (sk->sk_err)
+                       return sock_error(sk);
 
                if (!skb_queue_empty(&sk->sk_receive_queue)) {
                        __strp_unpause(&ctx->strp);
                        if (ctx->recv_pkt)
-                               return ctx->recv_pkt;
+                               break;
                }
 
                if (sk->sk_shutdown & RCV_SHUTDOWN)
-                       return NULL;
+                       return 0;
 
                if (sock_flag(sk, SOCK_DONE))
-                       return NULL;
+                       return 0;
 
-               if (nonblock || !timeo) {
-                       *err = -EAGAIN;
-                       return NULL;
-               }
+               if (nonblock || !timeo)
+                       return -EAGAIN;
 
                add_wait_queue(sk_sleep(sk), &wait);
                sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
                sk_wait_event(sk, &timeo,
-                             ctx->recv_pkt != skb ||
-                             !sk_psock_queue_empty(psock),
+                             ctx->recv_pkt || !sk_psock_queue_empty(psock),
                              &wait);
                sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
                remove_wait_queue(sk_sleep(sk), &wait);
 
                /* Handle signals */
-               if (signal_pending(current)) {
-                       *err = sock_intr_errno(timeo);
-                       return NULL;
-               }
+               if (signal_pending(current))
+                       return sock_intr_errno(timeo);
        }
 
-       return skb;
+       return 1;
 }
 
 static int tls_setup_from_iter(struct iov_iter *from,
@@ -1495,7 +1494,7 @@ static int decrypt_internal(struct sock *sk, struct sk_buff *skb,
                        goto exit_free;
                memcpy(&dctx->iv[iv_offset], tls_ctx->rx.iv, prot->salt_size);
        }
-       xor_iv_with_seq(prot, &dctx->iv[iv_offset], tls_ctx->rx.rec_seq);
+       tls_xor_iv_with_seq(prot, &dctx->iv[iv_offset], tls_ctx->rx.rec_seq);
 
        /* Prepare AAD */
        tls_make_aad(dctx->aad, rxm->full_len - prot->overhead_size +
@@ -1809,8 +1808,8 @@ int tls_sw_recvmsg(struct sock *sk,
                struct tls_decrypt_arg darg = {};
                int to_decrypt, chunk;
 
-               skb = tls_wait_data(sk, psock, flags & MSG_DONTWAIT, timeo, &err);
-               if (!skb) {
+               err = tls_rx_rec_wait(sk, psock, flags & MSG_DONTWAIT, timeo);
+               if (err <= 0) {
                        if (psock) {
                                chunk = sk_msg_recvmsg(sk, psock, msg, len,
                                                       flags);
@@ -1820,6 +1819,7 @@ int tls_sw_recvmsg(struct sock *sk,
                        goto recv_end;
                }
 
+               skb = ctx->recv_pkt;
                rxm = strp_msg(skb);
                tlm = tls_msg(skb);
 
@@ -1986,11 +1986,13 @@ ssize_t tls_sw_splice_read(struct socket *sock,  loff_t *ppos,
        } else {
                struct tls_decrypt_arg darg = {};
 
-               skb = tls_wait_data(sk, NULL, flags & SPLICE_F_NONBLOCK, timeo,
-                                   &err);
-               if (!skb)
+               err = tls_rx_rec_wait(sk, NULL, flags & SPLICE_F_NONBLOCK,
+                                     timeo);
+               if (err <= 0)
                        goto splice_read_end;
 
+               skb = ctx->recv_pkt;
+
                err = decrypt_skb_update(sk, skb, NULL, &darg);
                if (err < 0) {
                        tls_err_abort(sk, -EBADMSG);
@@ -2267,12 +2269,23 @@ static void tx_work_handler(struct work_struct *work)
        mutex_unlock(&tls_ctx->tx_lock);
 }
 
+static bool tls_is_tx_ready(struct tls_sw_context_tx *ctx)
+{
+       struct tls_rec *rec;
+
+       rec = list_first_entry(&ctx->tx_list, struct tls_rec, list);
+       if (!rec)
+               return false;
+
+       return READ_ONCE(rec->tx_ready);
+}
+
 void tls_sw_write_space(struct sock *sk, struct tls_context *ctx)
 {
        struct tls_sw_context_tx *tx_ctx = tls_sw_ctx_tx(ctx);
 
        /* Schedule the transmission if tx list is ready */
-       if (is_tx_ready(tx_ctx) &&
+       if (tls_is_tx_ready(tx_ctx) &&
            !test_and_set_bit(BIT_TX_SCHEDULED, &tx_ctx->tx_bitmask))
                schedule_delayed_work(&tx_ctx->tx_work.work, 0);
 }