rxrpc: Miscellaneous fixes
Subsystems (4)
David Howells
maintainerv5 cover rxrpc: Miscellaneous fixes
Here are some fixes for rxrpc:
(1) Fix key quota calculation.
(2) Fix a memory leak.
(3) Fix rxrpc_new_client_call_for_sendmsg() to substitute NULL for an empty key.
Might want to remove this substitution entirely or handle it in rxrpc_init_client_call_security() instead.
(4) Fix deletion of call->link to be RCU safe.
(5) Fix missing bounds checks when parsing RxGK tickets.
(6) Fix use of wrong skbuff to get challenge serial number. Also actually substitute the newer response skbuff and release the older one.
(7) Fix unexpected RACK timer warning to report old mode.
(8) Fix call key refcount leak.
(9) Fix the interaction of jumbograms with Tx window space, setting the request-ack flag when the window space is getting low, typically because each jumbogram take a big bite out of the window and fewer UDP packets get traded.
(10) Don't call rxrpc_put_call() with a NULL pointer.
(11) Reject undecryptable rxkad response tickets by checking result of decryption.
(12) Fix buffer bounds calculation in the RESPONSE authenticator parser.
(13) Fix oversized response length check.
(14) Fix refcount leak on multiple setting of server keyring.
(15) Fix checks made by RXRPC_SECURITY_KEY and RXRPC_SECURITY_KEYRING (both should be allowed).
(16) Fix lack of result checking on calls to crypto_skcipher_en/decrypt().
(17) Fix token_len limit check in rxgk_verify_response().
(18) Fix rxgk context leak in rxgk_verify_response().
(19) Fix read beyond end of buffer in rxgk_do_verify_authenticator().
(20) Fix parsing of RESPONSE packet on a connection that has already been set from a prior response.
(21) Fix size of buffers used for rendering addresses into for procfiles.
David
The patches can be found here also:
http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=rxrpc-fixes
Changes
=======
ver #5)
- AI review[2]:
- Dropped patch to check rx->securities in rxrpc_setsockopt().
- Changed patch to check rx->securities in rxrpc_server_keyring() to return error -EINVAL.
- Added patch to check rx->key and rx->securities correctly.
- Added patch to check return of crypto_skcipher_en/decrypt().
- Added patch to check buf len in rxgk_do_verify_authenticator().
- Imported a patch to fix parsing of RESPONSE packet in wrong state.
- Imported a patch to fix size of address buffers in procfiles.
ver #4)
- Got rid of the on_list()/on_list_rcu() patch.
- Removed the list_del_init from rxrpc_destroy_all_calls().
- Made the list_del_rcu() in rxrpc_put_call() unconditional.
- Added four new patches.
ver #3)
- Rename the dwc2's on_list() to dwc2_on_list() to free up the name.
- Added a patch to fix the interaction of jumbograms with window space.
ver #2)
- AI review[1]:
- Added a patch to fix key quota calculation.
- Added a patch to fix a memory leak.
- Added a patch to use NULL instead of an empty key in rxrpc_sengmsg().
- Added a patch to use RCU-safe deletion on call->link.
- Modified the response packet selection patch to select the newer response when there's an older response - and to release the older response skbuff.
- Move on_list_rcu() and add on_list().
Alok Tiwari (2):
rxrpc: Fix use of wrong skb when comparing queued RESP challenge
serial
rxrpc: Fix rack timer warning to report unexpected mode
Anderson Nascimento (1):
rxrpc: Fix key reference count leak from call->key
David Howells (9):
rxrpc: Fix key quota calculation for multitoken keys
rxrpc: Fix key parsing memleak
rxrpc: Fix anonymous key handling
rxrpc: Fix call removal to use RCU safe deletion
rxrpc: Fix key/keyring checks in
setsockopt(RXRPC_SECURITY_KEY/KEYRING)
rxrpc: Fix missing error checks for rxkad encryption/decryption
failure
rxrpc: Fix integer overflow in rxgk_verify_response()
rxrpc: Fix leak of rxgk context in rxgk_verify_response()
rxrpc: Fix buffer overread in rxgk_do_verify_authenticator()
Douya Le (1):
rxrpc: Only put the call ref if one was acquired
Keenan Dong (2):
rxrpc: fix RESPONSE authenticator parser OOB read
rxrpc: fix oversized RESPONSE authenticator length check
Luxiao Xu (1):
rxrpc: fix reference count leak in rxrpc_server_keyring()
Marc Dionne (1):
rxrpc: Fix to request an ack if window is limited
Oleh Konko (1):
rxrpc: Fix RxGK token loading to check bounds
Pengpeng Hou (1):
rxrpc: proc: size address buffers for %pISpc output
Wang Jie (1):
rxrpc: only handle RESPONSE during service challenge
Yuqi Xu (1):
rxrpc: reject undecryptable rxkad response tickets
include/trace/events/rxrpc.h | 4 ++- net/rxrpc/af_rxrpc.c | 6 ---- net/rxrpc/ar-internal.h | 2 +- net/rxrpc/call_object.c | 25 ++++++-------- net/rxrpc/conn_event.c | 19 ++++++++--- net/rxrpc/input_rack.c | 2 +- net/rxrpc/io_thread.c | 3 +- net/rxrpc/key.c | 40 +++++++++++++---------- net/rxrpc/output.c | 2 ++ net/rxrpc/proc.c | 37 ++++++++++++--------- net/rxrpc/rxgk.c | 19 +++++++---- net/rxrpc/rxkad.c | 63 ++++++++++++++++++++++++------------ net/rxrpc/sendmsg.c | 2 +- net/rxrpc/server_key.c | 3 ++ 14 files changed, 138 insertions(+), 89 deletions(-)
David Howells
maintainerPATCH v5 1/21 rxrpc: Fix key quota calculation for multitoken keys
In the rxrpc key preparsing, every token extracted sets the proposed quota value, but for multitoken keys, this will overwrite the previous proposed quota, losing it.
Fix this by adding to the proposed quota instead.
--- net/rxrpc/key.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
net/rxrpc/key.c +4 -3
@@ -72,7 +72,7 @@ static int rxrpc_preparse_xdr_rxkad(struct key_preparsed_payload *prep,return -EKEYREJECTED ; plen =sizeof (*token) +sizeof (*token->kad) + tktlen; - prep->quotalen = datalen + plen; + prep->quotalen += datalen + plen; plen -=sizeof (*token); token =kzalloc_obj (*token);
@@ -199,7 +199,7 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep, } plen =sizeof (*token) +sizeof (*token->rxgk) + tktlen + keylen; - prep->quotalen = datalen + plen; + prep->quotalen += datalen + plen; plen -=sizeof (*token); token =kzalloc_obj (*token);
@@ -460,6 +460,7 @@ static int rxrpc_preparse(struct key_preparsed_payload *prep)memcpy (&kver, prep->data,sizeof (kver)); prep->data +=sizeof (kver); prep->datalen -=sizeof (kver); + prep->quotalen =0 ;_debug ("KEY I/F VERSION: %u" , kver);
@@ -497,7 +498,7 @@ static int rxrpc_preparse(struct key_preparsed_payload *prep) goto error; plen =sizeof (*token->kad) + v1->ticket_length; - prep->quotalen = plen +sizeof (*token); + prep->quotalen += plen +sizeof (*token); ret = -ENOMEM ; token =kzalloc_obj (*token);
David Howells
maintainerPATCH v5 2/21 rxrpc: Fix key parsing memleak
In reply to David HowellsIn rxrpc_preparse_xdr_yfs_rxgk(), the memory attached to token->rxgk can be leaked in a few error paths after it's allocated.
Fix this by freeing it in the "reject_token:" case.
--- net/rxrpc/key.c | 1 + 1 file changed, 1 insertion(+)
net/rxrpc/key.c +1 -0
@@ -274,6 +274,7 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep, nomem:return -ENOMEM ; reject_token: +kfree (token->rxgk);kfree (token); reject:return -EKEYREJECTED ;
David Howells
maintainerPATCH v5 3/21 rxrpc: Fix anonymous key handling
In reply to David HowellsIn rxrpc_new_client_call_for_sendmsg(), a key with no payload is meant to be substituted for a NULL key pointer, but the variable this is done with is subsequently not used.
Fix this by using "key" rather than "rx->key" when filling in the connection parameters.
Note that this only affects direct use of AF_RXRPC; the kAFS filesystem doesn't use sendmsg() directly and so bypasses the issue. Further, AF_RXRPC passes a NULL key in if no key is set, so using an anonymous key in that manner works. Since this hasn't been noticed to this point, it might be better just to remove the "key" variable and the code that sets it
- and, arguably, rxrpc_init_client_call_security() would be a better place to handle it.
--- net/rxrpc/sendmsg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/rxrpc/sendmsg.c +1 -1
@@ -637,7 +637,7 @@ rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg,memset (&cp,0 ,sizeof (cp)); cp.local = rx->local; cp.peer = peer; - cp.key = rx->key; + cp.key = key; cp.security_level = rx->min_sec_level; cp.exclusive = rx->exclusive | p->exclusive; cp.upgrade = p->upgrade;
David Howells
maintainerPATCH v5 4/21 rxrpc: Fix call removal to use RCU safe deletion
In reply to David HowellsFix rxrpc call removal from the rxnet->calls list to use list_del_rcu() rather than list_del_init() to prevent stuffing up reading /proc/net/rxrpc/calls from potentially getting into an infinite loop.
This, however, means that list_empty() no longer works on an entry that's been deleted from the list, making it harder to detect prior deletion. Fix this by:
Firstly, make rxrpc_destroy_all_calls() only dump the first ten calls that are unexpectedly still on the list. Limiting the number of steps means there's no need to call cond_resched() or to remove calls from the list here, thereby eliminating the need for rxrpc_put_call() to check for that.
rxrpc_put_call() can then be fixed to unconditionally delete the call from the list as it is the only place that the deletion occurs.
--- include/trace/events/rxrpc.h | 2 +- net/rxrpc/call_object.c | 24 +++++++++--------------- 2 files changed, 10 insertions(+), 16 deletions(-)
include/trace/events/rxrpc.h +1 -1
@@ -347,7 +347,7 @@ EM(rxrpc_call_see_release, "SEE release ") \ EM(rxrpc_call_see_userid_exists, "SEE u-exists") \ EM(rxrpc_call_see_waiting_call, "SEE q-conn ") \ - E_(rxrpc_call_see_zap, "SEE zap ") + E_(rxrpc_call_see_still_live, "SEE !still-l")#define rxrpc_txqueue_traces \ EM(rxrpc_txqueue_await_reply, "AWR") \
net/rxrpc/call_object.c +9 -15
@@ -654,11 +654,9 @@ void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace why)if (dead) { ASSERTCMP(__rxrpc_call_state(call), ==, RXRPC_CALL_COMPLETE); -if (!list_empty (&call->link)) { -spin_lock (&rxnet->call_lock); -list_del_init (&call->link); -spin_unlock (&rxnet->call_lock); - } +spin_lock (&rxnet->call_lock); +list_del_rcu (&call->link); +spin_unlock (&rxnet->call_lock);rxrpc_cleanup_call (call); }
@@ -730,24 +728,20 @@ void rxrpc_destroy_all_calls(struct rxrpc_net *rxnet)_enter ("" );if (!list_empty (&rxnet->calls)) { -spin_lock (&rxnet->call_lock); +int shown =0 ; -while (!list_empty (&rxnet->calls)) { - call =list_entry (rxnet->calls.next, - struct rxrpc_call, link); -_debug ("Zapping call %p" , call); +spin_lock (&rxnet->call_lock); -rxrpc_see_call (call, rxrpc_call_see_zap); -list_del_init (&call->link); +list_for_each_entry (call, &rxnet->calls, link) { +rxrpc_see_call (call, rxrpc_call_see_still_live);pr_err ("Call %p still in use (%d,%s,%lx,%lx)!\n" , call,refcount_read (&call->ref), rxrpc_call_states[__rxrpc_call_state (call)], call->flags, call->events); -spin_unlock (&rxnet->call_lock); -cond_resched (); -spin_lock (&rxnet->call_lock); +if (++shown >=10 ) +break ; }spin_unlock (&rxnet->call_lock);
David Howells
maintainerPATCH v5 5/21 rxrpc: Fix RxGK token loading to check bounds
In reply to David HowellsFrom: Oleh Konko <[email protected]>
rxrpc_preparse_xdr_yfs_rxgk() reads the raw key length and ticket length from the XDR token as u32 values and passes each through round_up(x, 4) before using the rounded value for validation and allocation. When the raw length is >= 0xfffffffd, round_up() wraps to 0, so the bounds check and kzalloc both use 0 while the subsequent memcpy still copies the original ~4 GiB value, producing a heap buffer overflow reachable from an unprivileged add_key() call.
Fix this by:
(1) Rejecting raw key lengths above AFSTOKEN_GK_KEY_MAX and raw ticket lengths above AFSTOKEN_GK_TOKEN_MAX before rounding, consistent with the caps that the RxKAD path already enforces via AFSTOKEN_RK_TIX_MAX.
(2) Sizing the flexible-array allocation from the validated raw key length via struct_size_t() instead of the rounded value.
(3) Caching the raw lengths so that the later field assignments and memcpy calls do not re-read from the token, eliminating a class of TOCTOU re-parse.
The control path (valid token with lengths within bounds) is unaffected.
--- net/rxrpc/key.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-)
net/rxrpc/key.c +17 -13
@@ -13,6 +13,7 @@#include <crypto/skcipher.h> #include <linux/module.h> #include <linux/net.h> +#include <linux/overflow.h> #include <linux/skbuff.h> #include <linux/key-type.h> #include <linux/ctype.h>
@@ -171,7 +172,7 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,size_t plen;const __be32 *ticket, *key;s64 tmp; -u32 tktlen, keylen; +size_t raw_keylen, raw_tktlen, keylen, tktlen; _enter(",{%x,%x,%x,%x},%x", ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
@@ -181,18 +182,22 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep, goto reject; key = xdr + (6 *2 +1 ); - keylen =ntohl (key[-1 ]); -_debug ("keylen: %x" , keylen); - keylen =round_up (keylen,4 ); + raw_keylen =ntohl (key[-1 ]); +_debug ("keylen: %zx" , raw_keylen); +if (raw_keylen >AFSTOKEN_GK_KEY_MAX ) + goto reject; + keylen =round_up (raw_keylen,4 );if ((6 *2 +2 ) *4 + keylen > toklen) goto reject; ticket = xdr + (6 *2 +1 + (keylen /4 ) +1 ); - tktlen =ntohl (ticket[-1 ]); -_debug ("tktlen: %x" , tktlen); - tktlen =round_up (tktlen,4 ); + raw_tktlen =ntohl (ticket[-1 ]); +_debug ("tktlen: %zx" , raw_tktlen); +if (raw_tktlen >AFSTOKEN_GK_TOKEN_MAX ) + goto reject; + tktlen =round_up (raw_tktlen,4 );if ((6 *2 +2 ) *4 + keylen + tktlen != toklen) { -kleave (" = -EKEYREJECTED [%x!=%x, %x,%x]" , +kleave (" = -EKEYREJECTED [%zx!=%x, %zx,%zx]" , (6 *2 +2 ) *4 + keylen + tktlen, toklen, keylen, tktlen); goto reject;
@@ -206,7 +211,7 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,if (!token) goto nomem; - token->rxgk =kzalloc (sizeof (*token->rxgk) + keylen,GFP_KERNEL ); + token->rxgk = kzalloc(struct_size_t(struct rxgk_key, _key, raw_keylen), GFP_KERNEL);if (!token->rxgk) goto nomem_token;
@@ -221,9 +226,9 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep, token->rxgk->enctype = tmp =xdr_dec64 (xdr +5 *2 );if (tmp <0 || tmp >UINT_MAX ) goto reject_token; - token->rxgk->key.len =ntohl (key[-1 ]); + token->rxgk->key.len = raw_keylen; token->rxgk->key.data = token->rxgk->_key; - token->rxgk->ticket.len =ntohl (ticket[-1 ]); + token->rxgk->ticket.len = raw_tktlen;if (token->rxgk->endtime !=0 ) { expiry =rxrpc_s64_to_time64 (token->rxgk->endtime);
@@ -236,8 +241,7 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,memcpy (token->rxgk->key.data, key, token->rxgk->key.len);/* Pad the ticket so that we can use it directly in XDR */ - token->rxgk->ticket.data =kzalloc (round_up (token->rxgk->ticket.len,4 ), -GFP_KERNEL ); + token->rxgk->ticket.data =kzalloc (tktlen,GFP_KERNEL );if (!token->rxgk->ticket.data) goto nomem_yrxgk;memcpy (token->rxgk->ticket.data, ticket, token->rxgk->ticket.len);
David Howells
maintainerPATCH v5 6/21 rxrpc: Fix use of wrong skb when comparing queued RESP challenge serial
In reply to David HowellsFrom: Alok Tiwari <[email protected]>
In rxrpc_post_response(), the code should be comparing the challenge serial number from the cached response before deciding to switch to a newer response, but looks at the newer packet private data instead, rendering the comparison always false.
Fix this by switching to look at the older packet.
Fix further[1] to substitute the new packet in place of the old one if newer and also to release whichever we don't use.
--- include/trace/events/rxrpc.h | 1 + net/rxrpc/conn_event.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-)
include/trace/events/rxrpc.h +1 -0
@@ -185,6 +185,7 @@ EM(rxrpc_skb_put_input, "PUT input ") \ EM(rxrpc_skb_put_jumbo_subpacket, "PUT jumbo-sub") \ EM(rxrpc_skb_put_oob, "PUT oob ") \ + EM(rxrpc_skb_put_old_response, "PUT old-resp ") \ EM(rxrpc_skb_put_purge, "PUT purge ") \ EM(rxrpc_skb_put_purge_oob, "PUT purge-oob") \EM (rxrpc_skb_put_response,"PUT response " ) \
net/rxrpc/conn_event.c +3 -2
@@ -557,11 +557,11 @@ void rxrpc_post_response(struct rxrpc_connection *conn, struct sk_buff *skb)spin_lock_irq (&local->lock); old = conn->tx_response;if (old) { -struct rxrpc_skb_priv *osp =rxrpc_skb (skb); +struct rxrpc_skb_priv *osp =rxrpc_skb (old);/* Always go with the response to the most recent challenge. */ if (after (sp->resp.challenge_serial, osp->resp.challenge_serial)) - conn->tx_response = old; + conn->tx_response = skb;else old = skb; }else {
@@ -569,4 +569,5 @@ void rxrpc_post_response(struct rxrpc_connection *conn, struct sk_buff *skb) }spin_unlock_irq (&local->lock);rxrpc_poke_conn (conn, rxrpc_conn_get_poke_response); +rxrpc_free_skb (old, rxrpc_skb_put_old_response); }
David Howells
maintainerPATCH v5 7/21 rxrpc: Fix rack timer warning to report unexpected mode
In reply to David HowellsFrom: Alok Tiwari <[email protected]>
rxrpc_rack_timer_expired() clears call->rack_timer_mode to OFF before the switch. The default case warning therefore always prints OFF and doesn't identify the unexpected timer mode.
Log the saved mode value instead so the warning reports the actual unexpected rack timer mode.
--- net/rxrpc/input_rack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/rxrpc/input_rack.c +1 -1
@@ -413,6 +413,6 @@ void rxrpc_rack_timer_expired(struct rxrpc_call *call, ktime_t overran_by)break ;//case RXRPC_CALL_RACKTIMER_ZEROWIN: default : -pr_warn ("Unexpected rack timer %u" , call->rack_timer_mode); +pr_warn ("Unexpected rack timer %u" , mode); } }
David Howells
maintainerPATCH v5 8/21 rxrpc: Fix key reference count leak from call->key
In reply to David HowellsFrom: Anderson Nascimento <[email protected]>
When creating a client call in rxrpc_alloc_client_call(), the code obtains a reference to the key. This is never cleaned up and gets leaked when the call is destroyed.
Fix this by freeing call->key in rxrpc_destroy_call().
Before the patch, it shows the key reference counter elevated:
$ cat /proc/keys | grep afs@54321 1bffe9cd I--Q--i 8053480 4169w 3b010000 1000 1000 rxrpc afs@54321: ka $
After the patch, the invalidated key is removed when the code exits:
$ cat /proc/keys | grep afs@54321 $
--- net/rxrpc/call_object.c | 1 + 1 file changed, 1 insertion(+)
net/rxrpc/call_object.c +1 -0
@@ -692,6 +692,7 @@ static void rxrpc_destroy_call(struct work_struct *work)rxrpc_put_bundle (call->bundle, rxrpc_bundle_put_call);rxrpc_put_peer (call->peer, rxrpc_peer_put_call);rxrpc_put_local (call->local, rxrpc_local_put_call); +key_put (call->key);call_rcu (&call->rcu, rxrpc_rcu_free_call); }
David Howells
maintainerPATCH v5 9/21 rxrpc: Fix to request an ack if window is limited
In reply to David HowellsFrom: Marc Dionne <[email protected]>
Peers may only send immediate acks for every 2 UDP packets received. When sending a jumbogram, it is important to check that there is sufficient window space to send another same sized jumbogram following the current one, and request an ack if there isn't. Failure to do so may cause the call to stall waiting for an ack until the resend timer fires.
Where jumbograms are in use this causes a very significant drop in performance.
--- include/trace/events/rxrpc.h | 1 + net/rxrpc/ar-internal.h | 2 +- net/rxrpc/output.c | 2 ++ net/rxrpc/proc.c | 5 +++-- 4 files changed, 7 insertions(+), 3 deletions(-)
include/trace/events/rxrpc.h +1 -0
@@ -521,6 +521,7 @@#define rxrpc_req_ack_traces \ EM(rxrpc_reqack_ack_lost, "ACK-LOST ") \ EM(rxrpc_reqack_app_stall, "APP-STALL ") \ + EM(rxrpc_reqack_jumbo_win, "JUMBO-WIN ") \ EM(rxrpc_reqack_more_rtt, "MORE-RTT ") \ EM(rxrpc_reqack_no_srv_last, "NO-SRVLAST") \ EM(rxrpc_reqack_old_rtt, "OLD-RTT ") \
net/rxrpc/ar-internal.h +1 -1
@@ -117,7 +117,7 @@ struct rxrpc_net {atomic_t stat_tx_jumbo[10 ];atomic_t stat_rx_jumbo[10 ]; -atomic_t stat_why_req_ack[8 ]; +atomic_t stat_why_req_ack[9 ];atomic_t stat_io_loop; };
net/rxrpc/output.c +2 -0
@@ -479,6 +479,8 @@ static size_t rxrpc_prepare_data_subpacket(struct rxrpc_call *call, why = rxrpc_reqack_old_rtt; else if (!last && !after(READ_ONCE(call->send_top), txb->seq)) why = rxrpc_reqack_app_stall; + else if (call->tx_winsize <= (2 * req->n) || call->cong_cwnd <= (2 * req->n)) + why = rxrpc_reqack_jumbo_win; else goto dont_set_request_ack;
net/rxrpc/proc.c +3 -2
@@ -518,11 +518,12 @@ int rxrpc_stats_show(struct seq_file *seq, void *v)atomic_read (&rxnet->stat_rx_acks[RXRPC_ACK_IDLE ]), atomic_read(&rxnet->stat_rx_acks[0]));seq_printf (seq, -"Why-Req-A: acklost=%u mrtt=%u ortt=%u stall=%u\n" , +"Why-Req-A: acklost=%u mrtt=%u ortt=%u stall=%u jwin=%u\n" ,atomic_read (&rxnet->stat_why_req_ack[rxrpc_reqack_ack_lost]),atomic_read (&rxnet->stat_why_req_ack[rxrpc_reqack_more_rtt]),atomic_read (&rxnet->stat_why_req_ack[rxrpc_reqack_old_rtt]), -atomic_read (&rxnet->stat_why_req_ack[rxrpc_reqack_app_stall])); +atomic_read (&rxnet->stat_why_req_ack[rxrpc_reqack_app_stall]), +atomic_read (&rxnet->stat_why_req_ack[rxrpc_reqack_jumbo_win])); seq_printf(seq, "Why-Req-A: nolast=%u retx=%u slows=%u smtxw=%u\n", atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_no_srv_last]),
David Howells
maintainerPATCH v5 10/21 rxrpc: Only put the call ref if one was acquired
In reply to David HowellsFrom: Douya Le <[email protected]>
rxrpc_input_packet_on_conn() can process a to-client packet after the current client call on the channel has already been torn down. In that case chan->call is NULL, rxrpc_try_get_call() returns NULL and there is no reference to drop.
The client-side implicit-end error path does not account for that and unconditionally calls rxrpc_put_call(). This turns a protocol error path into a kernel crash instead of rejecting the packet.
Only drop the call reference if one was actually acquired. Keep the existing protocol error handling unchanged.
--- net/rxrpc/io_thread.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/rxrpc/io_thread.c +2 -1
@@ -419,7 +419,8 @@ static int rxrpc_input_packet_on_conn(struct rxrpc_connection *conn,if (sp->hdr.callNumber > chan->call_id) {if (rxrpc_to_client (sp)) { -rxrpc_put_call (call, rxrpc_call_put_input); +if (call) +rxrpc_put_call (call, rxrpc_call_put_input);return rxrpc_protocol_error (skb, rxrpc_eproto_unexpected_implicit_end); }
David Howells
maintainerPATCH v5 11/21 rxrpc: reject undecryptable rxkad response tickets
In reply to David HowellsFrom: Yuqi Xu <[email protected]>
rxkad_decrypt_ticket() decrypts the RXKAD response ticket and then parses the buffer as plaintext without checking whether crypto_skcipher_decrypt() succeeded.
A malformed RESPONSE can therefore use a non-block-aligned ticket length, make the decrypt operation fail, and still drive the ticket parser with attacker-controlled bytes.
Check the decrypt result and abort the connection with RXKADBADTICKET when ticket decryption fails.
--- net/rxrpc/rxkad.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
net/rxrpc/rxkad.c +5 -1
@@ -958,6 +958,7 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,struct in_addr addr;unsigned int life;time64_t issue, now; +int ret;bool little_endian;u8 *p, *q, *name, *end;
@@ -977,8 +978,11 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,sg_init_one (&sg[0 ], ticket, ticket_len);skcipher_request_set_callback (req,0 ,NULL ,NULL );skcipher_request_set_crypt (req, sg, sg, ticket_len, iv.x); -crypto_skcipher_decrypt (req); + ret =crypto_skcipher_decrypt (req);skcipher_request_free (req); +if (ret <0 ) +return rxrpc_abort_conn (conn, skb,RXKADBADTICKET , -EPROTO , + rxkad_abort_resp_tkt_short); p = ticket; end = p + ticket_len;
David Howells
maintainerPATCH v5 12/21 rxrpc: fix RESPONSE authenticator parser OOB read
In reply to David HowellsFrom: Keenan Dong <[email protected]>
rxgk_verify_authenticator() copies auth_len bytes into a temporary buffer and then passes p + auth_len as the parser limit to rxgk_do_verify_authenticator(). Since p is a __be32 *, that inflates the parser end pointer by a factor of four and lets malformed RESPONSE authenticators read past the kmalloc() buffer.
Decoded from the original latest-net reproduction logs with scripts/decode_stacktrace.sh:
BUG: KASAN: slab-out-of-bounds in rxgk_verify_response()
Call Trace:
dump_stack_lvl() [lib/dump_stack.c:123]
print_report() [mm/kasan/report.c:379 mm/kasan/report.c:482]
kasan_report() [mm/kasan/report.c:597]
rxgk_verify_response()
[net/rxrpc/rxgk.c:1103 net/rxrpc/rxgk.c:1167
net/rxrpc/rxgk.c:1274]
rxrpc_process_connection()
[net/rxrpc/conn_event.c:266 net/rxrpc/conn_event.c:364
net/rxrpc/conn_event.c:386]
process_one_work() [kernel/workqueue.c:3281]
worker_thread()
[kernel/workqueue.c:3353 kernel/workqueue.c:3440]
kthread() [kernel/kthread.c:436]
ret_from_fork() [arch/x86/kernel/process.c:164]
Allocated by task 54:
rxgk_verify_response()
[include/linux/slab.h:954 net/rxrpc/rxgk.c:1155
net/rxrpc/rxgk.c:1274]
rxrpc_process_connection()
[net/rxrpc/conn_event.c:266 net/rxrpc/conn_event.c:364
net/rxrpc/conn_event.c:386]Convert the byte count to __be32 units before constructing the parser limit.
--- net/rxrpc/rxgk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/rxrpc/rxgk.c +2 -1
@@ -1164,7 +1164,8 @@ static int rxgk_verify_authenticator(struct rxrpc_connection *conn, } p = auth; - ret =rxgk_do_verify_authenticator (conn, krb5, skb, p, p + auth_len); + ret =rxgk_do_verify_authenticator (conn, krb5, skb, p, + p + auth_len /sizeof (*p)); error:kfree (auth);return ret;
David Howells
maintainerPATCH v5 13/21 rxrpc: fix oversized RESPONSE authenticator length check
In reply to David HowellsFrom: Keenan Dong <[email protected]>
rxgk_verify_response() decodes auth_len from the packet and is supposed to verify that it fits in the remaining bytes. The existing check is inverted, so oversized RESPONSE authenticators are accepted and passed to rxgk_decrypt_skb(), which can later reach skb_to_sgvec() with an impossible length and hit BUG_ON(len).
Decoded from the original latest-net reproduction logs with scripts/decode_stacktrace.sh:
RIP: __skb_to_sgvec()
[net/core/skbuff.c:5285 (discriminator 1)]
Call Trace:
skb_to_sgvec() [net/core/skbuff.c:5305]
rxgk_decrypt_skb() [net/rxrpc/rxgk_common.h:81]
rxgk_verify_response() [net/rxrpc/rxgk.c:1268]
rxrpc_process_connection()
[net/rxrpc/conn_event.c:266 net/rxrpc/conn_event.c:364
net/rxrpc/conn_event.c:386]
process_one_work() [kernel/workqueue.c:3281]
worker_thread()
[kernel/workqueue.c:3353 kernel/workqueue.c:3440]
kthread() [kernel/kthread.c:436]
ret_from_fork() [arch/x86/kernel/process.c:164]Reject authenticator lengths that exceed the remaining packet payload.
--- net/rxrpc/rxgk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/rxrpc/rxgk.c +1 -1
@@ -1224,7 +1224,7 @@ static int rxgk_verify_response(struct rxrpc_connection *conn, auth_offset = offset; auth_len =ntohl (xauth_len); -if (auth_len < len) +if (auth_len > len) goto short_packet;if (auth_len &3 ) goto inconsistent;
David Howells
maintainerPATCH v5 14/21 rxrpc: fix reference count leak in rxrpc_server_keyring()
In reply to David HowellsFrom: Luxiao Xu <[email protected]>
This patch fixes a reference count leak in rxrpc_server_keyring() by checking if rx->securities is already set.
--- net/rxrpc/server_key.c | 3 +++ 1 file changed, 3 insertions(+)
net/rxrpc/server_key.c +3 -0
@@ -125,6 +125,9 @@ int rxrpc_server_keyring(struct rxrpc_sock *rx, sockptr_t optval, int optlen)_enter ("" ); +if (rx->securities) +return -EINVAL ; +if (optlen <=0 || optlen >PAGE_SIZE -1 )return -EINVAL ;
David Howells
maintainerPATCH v5 15/21 rxrpc: Fix key/keyring checks in setsockopt(RXRPC_SECURITY_KEY/KEYRING)
In reply to David HowellsAn AF_RXRPC socket can be both client and server at the same time. When sending new calls (ie. it's acting as a client), it uses rx->key to set the security, and when accepting incoming calls (ie. it's acting as a server), it uses rx->securities.
setsockopt(RXRPC_SECURITY_KEY) sets rx->key to point to an rxrpc-type key and setsockopt(RXRPC_SECURITY_KEYRING) sets rx->securities to point to a keyring of rxrpc_s-type keys.
Now, it should be possible to use both rx->key and rx->securities on the same socket - but for userspace AF_RXRPC sockets rxrpc_setsockopt() prevents that.
Fix this by:
(1) Remove the incorrect check rxrpc_setsockopt(RXRPC_SECURITY_KEYRING)
makes on rx->key.
(2) Move the check that rxrpc_setsockopt(RXRPC_SECURITY_KEY) makes on
rx->key down into rxrpc_request_key().
(3) Remove rxrpc_request_key()'s check on rx->securities.
This (in combination with a previous patch) pushes the checks down into the functions that set those pointers and removes the cross-checks that prevent both key and keyring being set.
--- net/rxrpc/af_rxrpc.c | 6 ------ net/rxrpc/key.c | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-)
net/rxrpc/af_rxrpc.c +0 -6
@@ -654,9 +654,6 @@ static int rxrpc_setsockopt(struct socket *sock, int level, int optname, goto success;case RXRPC_SECURITY_KEY : - ret = -EINVAL ; -if (rx->key) - goto error; ret = -EISCONN ;if (rx->sk.sk_state !=RXRPC_UNBOUND ) goto error;
@@ -664,9 +661,6 @@ static int rxrpc_setsockopt(struct socket *sock, int level, int optname, goto error;case RXRPC_SECURITY_KEYRING : - ret = -EINVAL ; -if (rx->key) - goto error; ret = -EISCONN ;if (rx->sk.sk_state !=RXRPC_UNBOUND ) goto error;
net/rxrpc/key.c +1 -1
@@ -622,7 +622,7 @@ int rxrpc_request_key(struct rxrpc_sock *rx, sockptr_t optval, int optlen)_enter ("" ); -if (optlen <=0 || optlen >PAGE_SIZE -1 || rx->securities) +if (optlen <=0 || optlen >PAGE_SIZE -1 || rx->key)return -EINVAL ; description =memdup_sockptr_nul (optval, optlen);
David Howells
maintainerPATCH v5 16/21 rxrpc: Fix missing error checks for rxkad encryption/decryption failure
In reply to David HowellsAdd error checking for failure of crypto_skcipher_en/decrypt() to various rxkad function as the crypto functions can fail with ENOMEM at least.
--- net/rxrpc/rxkad.c | 57 +++++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 19 deletions(-)
net/rxrpc/rxkad.c +38 -19
@@ -197,6 +197,7 @@ static int rxkad_prime_packet_security(struct rxrpc_connection *conn,struct rxrpc_crypt iv;__be32 *tmpbuf;size_t tmpsize =4 *sizeof (__be32); +int ret;_enter ("" );
@@ -225,13 +226,13 @@ static int rxkad_prime_packet_security(struct rxrpc_connection *conn,skcipher_request_set_sync_tfm (req, ci);skcipher_request_set_callback (req,0 ,NULL ,NULL );skcipher_request_set_crypt (req, &sg, &sg, tmpsize, iv.x); -crypto_skcipher_encrypt (req); + ret =crypto_skcipher_encrypt (req);skcipher_request_free (req);memcpy (&conn->rxkad.csum_iv, tmpbuf +2 ,sizeof (conn->rxkad.csum_iv));kfree (tmpbuf); -_leave (" = 0" ); -return 0 ; +_leave (" = %d" , ret); +return ret; }/*
@@ -264,6 +265,7 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call,struct scatterlist sg;size_t pad;u16 check; +int ret;_enter ("" );
@@ -286,11 +288,11 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call,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,8 , iv.x); -crypto_skcipher_encrypt (req); + ret =crypto_skcipher_encrypt (req);skcipher_request_zero (req); -_leave (" = 0" ); -return 0 ; +_leave (" = %d" , ret); +return ret; }/*
@@ -345,7 +347,7 @@ static int rxkad_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)union {__be32 buf[2 ]; } crypto__aligned(8) ; -u32 x, y; +u32 x, y =0 ;int ret; _enter("{%d{%x}},{#%u},%u,",
@@ -376,8 +378,10 @@ static int rxkad_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)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,8 , iv.x); -crypto_skcipher_encrypt (req); + ret =crypto_skcipher_encrypt (req);skcipher_request_zero (req); +if (ret <0 ) + goto out; y =ntohl (crypto.buf[1 ]); y = (y >>16 ) &0xffff ;
@@ -413,6 +417,7 @@ static int rxkad_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)memset (p + txb->pkt_len,0 , gap); } +out:skcipher_request_free (req);_leave (" = %d [set %x]" , ret, y);return ret;
@@ -453,8 +458,10 @@ static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,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,8 , iv.x); -crypto_skcipher_decrypt (req); + ret =crypto_skcipher_decrypt (req);skcipher_request_zero (req); +if (ret <0 ) +return ret;/* Extract the decrypted packet length */ if (skb_copy_bits (skb, sp->offset, &sechdr,sizeof (sechdr)) <0 )
@@ -531,10 +538,14 @@ static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,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, sp->len, iv.x); -crypto_skcipher_decrypt (req); + ret =crypto_skcipher_decrypt (req);skcipher_request_zero (req);if (sg != _sg)kfree (sg); +if (ret <0 ) { +WARN_ON_ONCE (ret != -ENOMEM ); +return ret; + }/* Extract the decrypted packet length */ if (skb_copy_bits (skb, sp->offset, &sechdr,sizeof (sechdr)) <0 )
@@ -602,8 +613,10 @@ static int rxkad_verify_packet(struct rxrpc_call *call, struct sk_buff *skb)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,8 , iv.x); -crypto_skcipher_encrypt (req); + ret =crypto_skcipher_encrypt (req);skcipher_request_zero (req); +if (ret <0 ) + goto out; y =ntohl (crypto.buf[1 ]); cksum = (y >>16 ) &0xffff ;
@@ -1077,21 +1090,23 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,/* * decrypt the response packet */ -static void rxkad_decrypt_response (struct rxrpc_connection *conn, -struct rxkad_response *resp, -const struct rxrpc_crypt *session_key) +static int rxkad_decrypt_response (struct rxrpc_connection *conn, +struct rxkad_response *resp, +const struct rxrpc_crypt *session_key) {struct skcipher_request *req = rxkad_ci_req;struct scatterlist sg[1 ];struct rxrpc_crypt iv; +int ret;_enter (",,%08x%08x" ,ntohl (session_key->n[0 ]),ntohl (session_key->n[1 ]));mutex_lock (&rxkad_ci_mutex); -if (crypto_sync_skcipher_setkey (rxkad_ci, session_key->x, -sizeof (*session_key)) <0 ) -BUG (); + ret =crypto_sync_skcipher_setkey (rxkad_ci, session_key->x, +sizeof (*session_key)); +if (ret <0 ) + goto unlock;memcpy (&iv, session_key,sizeof (iv));
@@ -1100,12 +1115,14 @@ static void rxkad_decrypt_response(struct rxrpc_connection *conn,skcipher_request_set_sync_tfm (req, rxkad_ci);skcipher_request_set_callback (req,0 ,NULL ,NULL );skcipher_request_set_crypt (req, sg, sg,sizeof (resp->encrypted), iv.x); -crypto_skcipher_decrypt (req); + ret =crypto_skcipher_decrypt (req);skcipher_request_zero (req); +unlock:mutex_unlock (&rxkad_ci_mutex);_leave ("" ); +return ret; }/*
@@ -1198,7 +1215,9 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,/* use the session key from inside the ticket to decrypt the * response */ -rxkad_decrypt_response (conn, response, &session_key); + ret =rxkad_decrypt_response (conn, response, &session_key); +if (ret <0 ) + goto temporary_error_free_ticket; if (ntohl(response->encrypted.epoch) != conn->proto.epoch || ntohl(response->encrypted.cid) != conn->proto.cid ||
David Howells
maintainerPATCH v5 17/21 rxrpc: Fix integer overflow in rxgk_verify_response()
In reply to David HowellsIn rxgk_verify_response(), there's a potential integer overflow due to rounding up token_len before checking it, thereby allowing the length check to be bypassed.
Fix this by checking the unrounded value against len too (len is limited as the response must fit in a single UDP packet).
--- net/rxrpc/rxgk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/rxrpc/rxgk.c +2 -1
@@ -1209,7 +1209,8 @@ static int rxgk_verify_response(struct rxrpc_connection *conn, token_offset = offset; token_len =ntohl (rhdr.token_len); -if (xdr_round_up (token_len) +sizeof (__be32) > len) +if (token_len > len || +xdr_round_up (token_len) +sizeof (__be32) > len) goto short_packet;trace_rxrpc_rx_response (conn, sp->hdr.serial,0 , sp->hdr.cksum, token_len);
David Howells
maintainerPATCH v5 18/21 rxrpc: Fix leak of rxgk context in rxgk_verify_response()
In reply to David HowellsFix rxgk_verify_response() to clean up the rxgk context it creates.
--- net/rxrpc/rxgk.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
net/rxrpc/rxgk.c +4 -2
@@ -1270,16 +1270,18 @@ static int rxgk_verify_response(struct rxrpc_connection *conn,if (ret <0 ) {rxrpc_abort_conn (conn, skb,RXGK_SEALEDINCON , ret, rxgk_abort_resp_auth_dec); - goto out; + goto out_gk; } ret =rxgk_verify_authenticator (conn, krb5, skb, auth_offset, auth_len);if (ret <0 ) - goto out; + goto out_gk; conn->key = key; key =NULL ; ret =0 ; +out_gk: +rxgk_put (gk); out:key_put (key);_leave (" = %d" , ret);
David Howells
maintainerPATCH v5 19/21 rxrpc: Fix buffer overread in rxgk_do_verify_authenticator()
In reply to David HowellsFix rxgk_do_verify_authenticator() to check the buffer size before checking the nonce.
--- net/rxrpc/rxgk.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
net/rxrpc/rxgk.c +4 -1
@@ -1085,6 +1085,9 @@ static int rxgk_do_verify_authenticator(struct rxrpc_connection *conn,_enter ("" ); +if ((end - p) *sizeof (__be32) <24 ) +return rxrpc_abort_conn (conn, skb,RXGK_NOTAUTH , -EPROTO , + rxgk_abort_resp_short_auth);if (memcmp (p, conn->rxgk.nonce,20 ) !=0 )return rxrpc_abort_conn (conn, skb,RXGK_NOTAUTH , -EPROTO , rxgk_abort_resp_bad_nonce);
@@ -1098,7 +1101,7 @@ static int rxgk_do_verify_authenticator(struct rxrpc_connection *conn, p +=xdr_round_up (app_len) /sizeof (__be32);if (end - p <4 )return rxrpc_abort_conn (conn, skb,RXGK_NOTAUTH , -EPROTO , - rxgk_abort_resp_short_applen); + rxgk_abort_resp_short_auth); level =ntohl (*p++); epoch =ntohl (*p++);
David Howells
maintainerPATCH v5 20/21 rxrpc: only handle RESPONSE during service challenge
In reply to David HowellsFrom: Wang Jie <[email protected]>
Only process RESPONSE packets while the service connection is still in RXRPC_CONN_SERVICE_CHALLENGING. Check that state under state_lock before running response verification and security initialization, then use a local secured flag to decide whether to queue the secured-connection work after the state transition. This keeps duplicate or late RESPONSE packets from re-running the setup path and removes the unlocked post-transition state test.
--- net/rxrpc/conn_event.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
net/rxrpc/conn_event.c +12 -2
@@ -247,6 +247,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn, struct sk_buff *skb) {struct rxrpc_skb_priv *sp =rxrpc_skb (skb); +bool secured = false;int ret;if (conn->state ==RXRPC_CONN_ABORTED )
@@ -262,6 +263,13 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,return ret;case RXRPC_PACKET_TYPE_RESPONSE : +spin_lock_irq (&conn->state_lock); +if (conn->state !=RXRPC_CONN_SERVICE_CHALLENGING ) { +spin_unlock_irq (&conn->state_lock); +return 0 ; + } +spin_unlock_irq (&conn->state_lock); + ret = conn->security->verify_response (conn, skb);if (ret <0 )return ret;
@@ -272,11 +280,13 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,return ret;spin_lock_irq (&conn->state_lock); -if (conn->state ==RXRPC_CONN_SERVICE_CHALLENGING ) +if (conn->state ==RXRPC_CONN_SERVICE_CHALLENGING ) { conn->state =RXRPC_CONN_SERVICE ; + secured = true; + }spin_unlock_irq (&conn->state_lock); -if (conn->state ==RXRPC_CONN_SERVICE ) { +if (secured) {/* Offload call state flipping to the I/O thread. As * we've already received the packet, put it on the * front of the queue.
David Howells
maintainerPATCH v5 21/21 rxrpc: proc: size address buffers for %pISpc output
In reply to David HowellsFrom: Pengpeng Hou <[email protected]>
The AF_RXRPC procfs helpers format local and remote socket addresses into fixed 50-byte stack buffers with "%pISpc".
That is too small for the longest current-tree IPv6-with-port form the formatter can produce. In lib/vsprintf.c, the compressed IPv6 path uses a dotted-quad tail not only for v4mapped addresses, but also for ISATAP addresses via ipv6_addr_is_isatap().
As a result, a case such as
[ffff:ffff:ffff:ffff:0:5efe:255.255.255.255]:65535
is possible with the current formatter. That is 50 visible characters, so 51 bytes including the trailing NUL, which does not fit in the existing char[50] buffers used by net/rxrpc/proc.c.
Size the buffers from the formatter's maximum textual form and switch the call sites to scnprintf().
Changes since v1:
- correct the changelog to cite the actual maximum current-tree case explicitly
- frame the proof around the ISATAP formatting path instead of the earlier mapped-v4 example
--- net/rxrpc/proc.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-)
net/rxrpc/proc.c +18 -14
@@ -10,6 +10,10 @@#include <net/af_rxrpc.h> #include "ar-internal.h" +#define RXRPC_PROC_ADDRBUF_SIZE \ + (sizeof("[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255]") + \ + sizeof(":12345")) +static const char *const rxrpc_conn_states[RXRPC_CONN__NR_STATES ] = { [RXRPC_CONN_UNUSED ] ="Unused " , [RXRPC_CONN_CLIENT_UNSECURED ] ="ClUnsec " ,
@@ -53,7 +57,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)struct rxrpc_net *rxnet =rxrpc_net (seq_file_net (seq));enum rxrpc_call_state state;rxrpc_seq_t tx_bottom; -char lbuff[50 ], rbuff[50 ]; +char lbuff[RXRPC_PROC_ADDRBUF_SIZE ], rbuff[RXRPC_PROC_ADDRBUF_SIZE ];long timeout =0 ;if (v == &rxnet->calls) {
@@ -69,11 +73,11 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) local = call->local;if (local) -sprintf (lbuff,"%pISpc" , &local->srx.transport); +scnprintf (lbuff,sizeof (lbuff),"%pISpc" , &local->srx.transport);else strcpy (lbuff,"no_local" ); -sprintf (rbuff,"%pISpc" , &call->dest_srx.transport); +scnprintf (rbuff,sizeof (rbuff),"%pISpc" , &call->dest_srx.transport); state =rxrpc_call_state (call);if (state !=RXRPC_CALL_SERVER_PREALLOC )
@@ -142,7 +146,7 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v)struct rxrpc_connection *conn;struct rxrpc_net *rxnet =rxrpc_net (seq_file_net (seq));const char *state; -char lbuff[50 ], rbuff[50 ]; +char lbuff[RXRPC_PROC_ADDRBUF_SIZE ], rbuff[RXRPC_PROC_ADDRBUF_SIZE ];if (v == &rxnet->conn_proc_list) { seq_puts(seq,
@@ -161,8 +165,8 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v) goto print; } -sprintf (lbuff,"%pISpc" , &conn->local->srx.transport); -sprintf (rbuff,"%pISpc" , &conn->peer->srx.transport); +scnprintf (lbuff,sizeof (lbuff),"%pISpc" , &conn->local->srx.transport); +scnprintf (rbuff,sizeof (rbuff),"%pISpc" , &conn->peer->srx.transport); print: state =rxrpc_is_conn_aborted (conn) ? rxrpc_call_completions[conn->completion] :
@@ -228,7 +232,7 @@ static int rxrpc_bundle_seq_show(struct seq_file *seq, void *v) {struct rxrpc_bundle *bundle;struct rxrpc_net *rxnet =rxrpc_net (seq_file_net (seq)); -char lbuff[50 ], rbuff[50 ]; +char lbuff[RXRPC_PROC_ADDRBUF_SIZE ], rbuff[RXRPC_PROC_ADDRBUF_SIZE ];if (v == &rxnet->bundle_proc_list) { seq_puts(seq,
@@ -242,8 +246,8 @@ static int rxrpc_bundle_seq_show(struct seq_file *seq, void *v) bundle = list_entry(v, struct rxrpc_bundle, proc_link); -sprintf (lbuff,"%pISpc" , &bundle->local->srx.transport); -sprintf (rbuff,"%pISpc" , &bundle->peer->srx.transport); +scnprintf (lbuff,sizeof (lbuff),"%pISpc" , &bundle->local->srx.transport); +scnprintf (rbuff,sizeof (rbuff),"%pISpc" , &bundle->peer->srx.transport); seq_printf(seq, "UDP %-47.47s %-47.47s %4x %3u %3d" " %c%c%c %08x | %08x %08x %08x %08x %08x\n",
@@ -279,7 +283,7 @@ static int rxrpc_peer_seq_show(struct seq_file *seq, void *v) {struct rxrpc_peer *peer;time64_t now; -char lbuff[50 ], rbuff[50 ]; +char lbuff[RXRPC_PROC_ADDRBUF_SIZE ], rbuff[RXRPC_PROC_ADDRBUF_SIZE ];if (v ==SEQ_START_TOKEN ) { seq_puts(seq,
@@ -290,9 +294,9 @@ static int rxrpc_peer_seq_show(struct seq_file *seq, void *v) peer = list_entry(v, struct rxrpc_peer, hash_link); -sprintf (lbuff,"%pISpc" , &peer->local->srx.transport); +scnprintf (lbuff,sizeof (lbuff),"%pISpc" , &peer->local->srx.transport); -sprintf (rbuff,"%pISpc" , &peer->srx.transport); +scnprintf (rbuff,sizeof (rbuff),"%pISpc" , &peer->srx.transport); now =ktime_get_seconds (); seq_printf(seq,
@@ -401,7 +405,7 @@ const struct seq_operations rxrpc_peer_seq_ops = {static int rxrpc_local_seq_show (struct seq_file *seq,void *v) {struct rxrpc_local *local; -char lbuff[50 ]; +char lbuff[RXRPC_PROC_ADDRBUF_SIZE ];if (v ==SEQ_START_TOKEN ) { seq_puts(seq,
@@ -412,7 +416,7 @@ static int rxrpc_local_seq_show(struct seq_file *seq, void *v) local = hlist_entry(v, struct rxrpc_local, link); -sprintf (lbuff,"%pISpc" , &local->srx.transport); +scnprintf (lbuff,sizeof (lbuff),"%pISpc" , &local->srx.transport); seq_printf(seq, "UDP %-47.47s %3u %3u %3u\n",
This series was applied to netdev/net.git (main) by Jakub Kicinski <[email protected]>:
Hello:
This series was applied to netdev/net.git (main)
by Jakub Kicinski <[email protected]>:
Quoted 10 lines · On Wed, 8 Apr 2026 13:12:28 +0100 you wrote:
Here are some fixes for rxrpc:
(1) Fix key quota calculation.
(2) Fix a memory leak.
(3) Fix
rxrpc_new_client_call_for_sendmsg()to substitute NULL for an empty key.[...]
Here is the summary with links:
- [net,v5,01/21] rxrpc: Fix key quota calculation for multitoken keys
https://git.kernel.org/netdev/net/c/bdbfead6d389 - [net,v5,02/21] rxrpc: Fix key parsing memleak https://git.kernel.org/netdev/net/c/b555912b9b21 - [net,v5,03/21] rxrpc: Fix anonymous key handling https://git.kernel.org/netdev/net/c/6a59d84b4fc2 - [net,v5,04/21] rxrpc: Fix call removal to use RCU safe deletion https://git.kernel.org/netdev/net/c/146d4ab94cf1 - [net,v5,05/21] rxrpc: Fix RxGK token loading to check bounds https://git.kernel.org/netdev/net/c/d179a868dd75 - [net,v5,06/21] rxrpc: Fix use of wrong skb when comparing queued RESP challenge serial https://git.kernel.org/netdev/net/c/b33f5741bb18 - [net,v5,07/21] rxrpc: Fix rack timer warning to report unexpected mode https://git.kernel.org/netdev/net/c/65b3ffe0972e - [net,v5,08/21] rxrpc: Fix key reference count leak from call->key https://git.kernel.org/netdev/net/c/d666540d217e - [net,v5,09/21] rxrpc: Fix to request an ack if window is limited https://git.kernel.org/netdev/net/c/0cd3e3f3f2ec - [net,v5,10/21] rxrpc: Only put the call ref if one was acquired https://git.kernel.org/netdev/net/c/6331f1b24a3e - [net,v5,11/21] rxrpc: reject undecryptable rxkad response tickets https://git.kernel.org/netdev/net/c/fe4447cd9562 - [net,v5,12/21] rxrpc: fix RESPONSE authenticator parser OOB read https://git.kernel.org/netdev/net/c/3e3138007887 - [net,v5,13/21] rxrpc: fix oversized RESPONSE authenticator length check https://git.kernel.org/netdev/net/c/a2567217ade9 - [net,v5,14/21] rxrpc: fix reference count leak in rxrpc_server_keyring() https://git.kernel.org/netdev/net/c/f125846ee79f - [net,v5,15/21] rxrpc: Fix key/keyring checks in setsockopt(RXRPC_SECURITY_KEY/KEYRING) https://git.kernel.org/netdev/net/c/2afd86ccbb20 - [net,v5,16/21] rxrpc: Fix missing error checks for rxkad encryption/decryption failure https://git.kernel.org/netdev/net/c/f93af41b9f5f - [net,v5,17/21] rxrpc: Fix integer overflow in rxgk_verify_response() https://git.kernel.org/netdev/net/c/699e52180f42 - [net,v5,18/21] rxrpc: Fix leak of rxgk context in rxgk_verify_response() https://git.kernel.org/netdev/net/c/7e1876caa836 - [net,v5,19/21] rxrpc: Fix buffer overread in rxgk_do_verify_authenticator() https://git.kernel.org/netdev/net/c/f564af387c8c - [net,v5,20/21] rxrpc: only handle RESPONSE during service challenge https://git.kernel.org/netdev/net/c/c43ffdcfdbb5 - [net,v5,21/21] rxrpc: proc: size address buffers for %pISpc output https://git.kernel.org/netdev/net/c/a44ce6aa2efb
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html