Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rxrpc: Fix untrusted unsigned subtract

Fix the following Smatch static checker warning:

net/rxrpc/rxgk_app.c:65 rxgk_yfs_decode_ticket()
warn: untrusted unsigned subtract. 'ticket_len - 10 * 4'

by prechecking the length of what we're trying to extract in two places in
the token and decoding for a response packet.

Also use sizeof() on the struct we're extracting rather specifying the size
numerically to be consistent with the other related statements.

Fixes: 9d1d2b59341f ("rxrpc: rxgk: Implement the yfs-rxgk security class (GSSAPI)")
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Closes: https://lists.infradead.org/pipermail/linux-afs/2025-September/010135.html
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/2039268.1757631977@warthog.procyon.org.uk
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

David Howells and committed by
Jakub Kicinski
2429a197 64863f4c

+14 -5
+14 -5
net/rxrpc/rxgk_app.c
··· 54 54 55 55 _enter(""); 56 56 57 + if (ticket_len < 10 * sizeof(__be32)) 58 + return rxrpc_abort_conn(conn, skb, RXGK_INCONSISTENCY, -EPROTO, 59 + rxgk_abort_resp_short_yfs_tkt); 60 + 57 61 /* Get the session key length */ 58 62 ret = skb_copy_bits(skb, ticket_offset, tmp, sizeof(tmp)); 59 63 if (ret < 0) ··· 199 195 __be32 token_len; 200 196 } container; 201 197 198 + if (token_len < sizeof(container)) 199 + goto short_packet; 200 + 202 201 /* Decode the RXGK_TokenContainer object. This tells us which server 203 202 * key we should be using. We can then fetch the key, get the secret 204 203 * and set up the crypto to extract the token. 205 204 */ 206 205 if (skb_copy_bits(skb, token_offset, &container, sizeof(container)) < 0) 207 - return rxrpc_abort_conn(conn, skb, RXGK_PACKETSHORT, -EPROTO, 208 - rxgk_abort_resp_tok_short); 206 + goto short_packet; 209 207 210 208 kvno = ntohl(container.kvno); 211 209 enctype = ntohl(container.enctype); 212 210 ticket_len = ntohl(container.token_len); 213 211 ticket_offset = token_offset + sizeof(container); 214 212 215 - if (xdr_round_up(ticket_len) > token_len - 3 * 4) 216 - return rxrpc_abort_conn(conn, skb, RXGK_PACKETSHORT, -EPROTO, 217 - rxgk_abort_resp_tok_short); 213 + if (xdr_round_up(ticket_len) > token_len - sizeof(container)) 214 + goto short_packet; 218 215 219 216 _debug("KVNO %u", kvno); 220 217 _debug("ENC %u", enctype); ··· 290 285 * also come out this way if the ticket decryption fails. 291 286 */ 292 287 return ret; 288 + 289 + short_packet: 290 + return rxrpc_abort_conn(conn, skb, RXGK_PACKETSHORT, -EPROTO, 291 + rxgk_abort_resp_tok_short); 293 292 }