]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
rxrpc: Separate the packet length from the data length in rxrpc_txbuf
authorDavid Howells <dhowells@redhat.com>
Wed, 4 Dec 2024 07:46:38 +0000 (07:46 +0000)
committerJakub Kicinski <kuba@kernel.org>
Mon, 9 Dec 2024 21:48:25 +0000 (13:48 -0800)
Separate the packet length from the data length (txb->len) stored in the
rxrpc_txbuf to make security calculations easier.  Also store the
allocation size as that's an upper bound on the size of the security
wrapper and change a number of fields to unsigned short as the amount of
data can't exceed the capacity of a UDP packet.

Also, whilst we're at it, use kzalloc() for txbufs.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
Link: https://patch.msgid.link/20241204074710.990092-11-dhowells@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/rxrpc/ar-internal.h
net/rxrpc/insecure.c
net/rxrpc/output.c
net/rxrpc/rxkad.c
net/rxrpc/sendmsg.c
net/rxrpc/txbuf.c

index 69e6f4b20bad3891fec41f2eaf9fea0a33e61b9d..a5c0bc917641601fcd23b2bb81af5e2b86c3fcae 100644 (file)
@@ -821,9 +821,11 @@ struct rxrpc_txbuf {
        rxrpc_serial_t          serial;         /* Last serial number transmitted with */
        unsigned int            call_debug_id;
        unsigned int            debug_id;
-       unsigned int            len;            /* Amount of data in buffer */
-       unsigned int            space;          /* Remaining data space */
-       unsigned int            offset;         /* Offset of fill point */
+       unsigned short          len;            /* Amount of data in buffer */
+       unsigned short          space;          /* Remaining data space */
+       unsigned short          offset;         /* Offset of fill point */
+       unsigned short          pkt_len;        /* Size of packet content */
+       unsigned short          alloc_size;     /* Amount of bufferage allocated */
        unsigned int            flags;
 #define RXRPC_TXBUF_WIRE_FLAGS 0xff            /* The wire protocol flags */
 #define RXRPC_TXBUF_RESENT     0x100           /* Set if has been resent */
index 751eb621021de16dc6fbc7c93d2aed69327623ae..d665f486be5faafd0b796429b6192b9188134253 100644 (file)
@@ -24,6 +24,7 @@ static struct rxrpc_txbuf *none_alloc_txbuf(struct rxrpc_call *call, size_t rema
 
 static int none_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
 {
+       txb->pkt_len = txb->len;
        return 0;
 }
 
index a91be871ad9639c8cb82ba4d493c71671e7c0e64..df9af4ad426094782116b922c8d4a0ac254293d0 100644 (file)
@@ -383,11 +383,11 @@ static size_t rxrpc_prepare_data_subpacket(struct rxrpc_call *call, struct rxrpc
        enum rxrpc_req_ack_trace why;
        struct rxrpc_connection *conn = call->conn;
        struct kvec *kv = &call->local->kvec[subpkt];
-       size_t len = txb->len;
+       size_t len = txb->pkt_len;
        bool last, more;
        u8 flags;
 
-       _enter("%x,{%d}", txb->seq, txb->len);
+       _enter("%x,%zd", txb->seq, len);
 
        txb->serial = serial;
 
@@ -441,6 +441,7 @@ dont_set_request_ack:
        whdr->cksum     = txb->cksum;
        whdr->serviceId = htons(conn->service_id);
        kv->iov_base    = whdr;
+       len += sizeof(*whdr);
        // TODO: Convert into a jumbo header for tail subpackets
 
        trace_rxrpc_tx_data(call, txb->seq, txb->serial, flags, false);
@@ -509,7 +510,7 @@ static int rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_txbuf *t
        size_t len;
        int ret;
 
-       _enter("%x,{%d}", txb->seq, txb->len);
+       _enter("%x,{%d}", txb->seq, txb->pkt_len);
 
        len = rxrpc_prepare_data_packet(call, txb);
 
index e3194d73dd846e18b3f9d8a7921b9b71ec79b60b..755897fab6265be9add67e5ad9f28c805af5f037 100644 (file)
@@ -148,14 +148,14 @@ error:
 static struct rxrpc_txbuf *rxkad_alloc_txbuf(struct rxrpc_call *call, size_t remain, gfp_t gfp)
 {
        struct rxrpc_txbuf *txb;
-       size_t shdr, space;
+       size_t shdr, alloc, limit, part;
 
        remain = umin(remain, 65535 - sizeof(struct rxrpc_wire_header));
 
        switch (call->conn->security_level) {
        default:
-               space = umin(remain, RXRPC_JUMBO_DATALEN);
-               return rxrpc_alloc_data_txbuf(call, space, 1, gfp);
+               alloc = umin(remain, RXRPC_JUMBO_DATALEN);
+               return rxrpc_alloc_data_txbuf(call, alloc, 1, gfp);
        case RXRPC_SECURITY_AUTH:
                shdr = sizeof(struct rxkad_level1_hdr);
                break;
@@ -164,15 +164,21 @@ static struct rxrpc_txbuf *rxkad_alloc_txbuf(struct rxrpc_call *call, size_t rem
                break;
        }
 
-       space = umin(round_down(RXRPC_JUMBO_DATALEN, RXKAD_ALIGN), remain + shdr);
-       space = round_up(space, RXKAD_ALIGN);
+       limit = round_down(RXRPC_JUMBO_DATALEN, RXKAD_ALIGN) - shdr;
+       if (remain < limit) {
+               part = remain;
+               alloc = round_up(shdr + part, RXKAD_ALIGN);
+       } else {
+               part = limit;
+               alloc = RXRPC_JUMBO_DATALEN;
+       }
 
-       txb = rxrpc_alloc_data_txbuf(call, space, RXKAD_ALIGN, gfp);
+       txb = rxrpc_alloc_data_txbuf(call, alloc, RXKAD_ALIGN, gfp);
        if (!txb)
                return NULL;
 
        txb->offset += shdr;
-       txb->space -= shdr;
+       txb->space = part;
        return txb;
 }
 
@@ -263,13 +269,13 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call,
        check = txb->seq ^ call->call_id;
        hdr->data_size = htonl((u32)check << 16 | txb->len);
 
-       txb->len += sizeof(struct rxkad_level1_hdr);
-       pad = txb->len;
+       txb->pkt_len = sizeof(struct rxkad_level1_hdr) + txb->len;
+       pad = txb->pkt_len;
        pad = RXKAD_ALIGN - pad;
        pad &= RXKAD_ALIGN - 1;
        if (pad) {
                memset(txb->kvec[0].iov_base + txb->offset, 0, pad);
-               txb->len += pad;
+               txb->pkt_len += pad;
        }
 
        /* start the encryption afresh */
@@ -298,7 +304,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
        struct rxkad_level2_hdr *rxkhdr = (void *)(whdr + 1);
        struct rxrpc_crypt iv;
        struct scatterlist sg;
-       size_t pad;
+       size_t content, pad;
        u16 check;
        int ret;
 
@@ -309,23 +315,20 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
        rxkhdr->data_size = htonl(txb->len | (u32)check << 16);
        rxkhdr->checksum = 0;
 
-       txb->len += sizeof(struct rxkad_level2_hdr);
-       pad = txb->len;
-       pad = RXKAD_ALIGN - pad;
-       pad &= RXKAD_ALIGN - 1;
-       if (pad) {
+       content = sizeof(struct rxkad_level2_hdr) + txb->len;
+       txb->pkt_len = round_up(content, RXKAD_ALIGN);
+       pad = txb->pkt_len - content;
+       if (pad)
                memset(txb->kvec[0].iov_base + txb->offset, 0, pad);
-               txb->len += pad;
-       }
 
        /* encrypt from the session key */
        token = call->conn->key->payload.data[0];
        memcpy(&iv, token->kad->session_key, sizeof(iv));
 
-       sg_init_one(&sg, rxkhdr, txb->len);
+       sg_init_one(&sg, rxkhdr, txb->pkt_len);
        skcipher_request_set_sync_tfm(req, call->conn->rxkad.cipher);
        skcipher_request_set_callback(req, 0, NULL, NULL);
-       skcipher_request_set_crypt(req, &sg, &sg, txb->len, iv.x);
+       skcipher_request_set_crypt(req, &sg, &sg, txb->pkt_len, iv.x);
        ret = crypto_skcipher_encrypt(req);
        skcipher_request_zero(req);
        return ret;
@@ -384,6 +387,7 @@ static int rxkad_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
 
        switch (call->conn->security_level) {
        case RXRPC_SECURITY_PLAIN:
+               txb->pkt_len = txb->len;
                ret = 0;
                break;
        case RXRPC_SECURITY_AUTH:
index 546abb463c3f9e492140457e46c3dc99de59a85f..786c1fb1369abe789114fb525035308c10f6274c 100644 (file)
@@ -391,7 +391,6 @@ reload:
                                goto out;
 
                        txb->kvec[0].iov_len += txb->len;
-                       txb->len = txb->kvec[0].iov_len;
                        rxrpc_queue_packet(rx, call, txb, notify_end_tx);
                        txb = NULL;
                }
index 2a4291617d40f2d9d85da9173f55d05de304b199..8b7c854ed3d7581bf7a39c3cbb398cc5194da900 100644 (file)
@@ -24,7 +24,7 @@ struct rxrpc_txbuf *rxrpc_alloc_data_txbuf(struct rxrpc_call *call, size_t data_
        size_t total, hoff;
        void *buf;
 
-       txb = kmalloc(sizeof(*txb), gfp);
+       txb = kzalloc(sizeof(*txb), gfp);
        if (!txb)
                return NULL;
 
@@ -49,14 +49,11 @@ struct rxrpc_txbuf *rxrpc_alloc_data_txbuf(struct rxrpc_call *call, size_t data_
        txb->last_sent          = KTIME_MIN;
        txb->call_debug_id      = call->debug_id;
        txb->debug_id           = atomic_inc_return(&rxrpc_txbuf_debug_ids);
+       txb->alloc_size         = data_size;
        txb->space              = data_size;
-       txb->len                = 0;
        txb->offset             = sizeof(*whdr);
        txb->flags              = call->conn->out_clientflag;
-       txb->ack_why            = 0;
        txb->seq                = call->tx_prepared + 1;
-       txb->serial             = 0;
-       txb->cksum              = 0;
        txb->nr_kvec            = 1;
        txb->kvec[0].iov_base   = whdr;
        txb->kvec[0].iov_len    = sizeof(*whdr);