rxrpc: Separate the packet length from the data length in rxrpc_txbuf
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>
This commit is contained in:
committed by
Jakub Kicinski
parent
eeaedc5449
commit
3d2bdf73ce
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -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);
|
||||
|
||||
|
||||
+24
-20
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+2
-5
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user