From: Greg Kroah-Hartman Date: Fri, 1 May 2026 12:05:46 +0000 (+0200) Subject: 7.0-stable patches X-Git-Tag: v6.12.86~51 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ca8f1f33d00ae3724e45c31034a826ef764c314a;p=thirdparty%2Fkernel%2Fstable-queue.git 7.0-stable patches added patches: edac-versalnet-fix-memory-leak-in-remove-and-probe-error-paths.patch net-txgbe-fix-rtnl-assertion-warning-when-remove-module.patch rxrpc-fix-conn-level-packet-handling-to-unshare-response-packets.patch rxrpc-fix-error-handling-in-rxgk_extract_token.patch rxrpc-fix-memory-leaks-in-rxkad_verify_response.patch rxrpc-fix-potential-uaf-after-skb_unshare-failure.patch rxrpc-fix-re-decryption-of-response-packets.patch rxrpc-fix-rxkad-crypto-unalignment-handling.patch rxrpc-fix-rxrpc_input_call_event-to-only-unshare-data-packets.patch tools-accounting-handle-truncated-taskstats-netlink-messages.patch --- diff --git a/queue-7.0/edac-versalnet-fix-memory-leak-in-remove-and-probe-error-paths.patch b/queue-7.0/edac-versalnet-fix-memory-leak-in-remove-and-probe-error-paths.patch new file mode 100644 index 0000000000..406f436f2d --- /dev/null +++ b/queue-7.0/edac-versalnet-fix-memory-leak-in-remove-and-probe-error-paths.patch @@ -0,0 +1,41 @@ +From 1b6f292cb94d95c9bc22e1efe592daf62c60bc2e Mon Sep 17 00:00:00 2001 +From: Prasanna Kumar T S M +Date: Sun, 22 Mar 2026 06:11:39 -0700 +Subject: EDAC/versalnet: Fix memory leak in remove and probe error paths + +From: Prasanna Kumar T S M + +commit 1b6f292cb94d95c9bc22e1efe592daf62c60bc2e upstream. + +The mcdi object allocated using kzalloc() in the setup_mcdi() is not freed in +the remove path or in probe's error handling path leading to a memory leak. +Fix it by freeing the allocated memory. + +Fixes: d5fe2fec6c40d ("EDAC: Add a driver for the AMD Versal NET DDR controller") +Signed-off-by: Prasanna Kumar T S M +Signed-off-by: Borislav Petkov (AMD) +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260322131139.1684716-1-ptsm@linux.microsoft.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/edac/versalnet_edac.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/edac/versalnet_edac.c ++++ b/drivers/edac/versalnet_edac.c +@@ -917,6 +917,7 @@ static int mc_probe(struct platform_devi + + err_init: + cdx_mcdi_finish(priv->mcdi); ++ kfree(priv->mcdi); + + err_unreg: + unregister_rpmsg_driver(&amd_rpmsg_driver); +@@ -938,6 +939,7 @@ static void mc_remove(struct platform_de + remove_versalnet(priv); + rproc_shutdown(priv->mcdi->r5_rproc); + cdx_mcdi_finish(priv->mcdi); ++ kfree(priv->mcdi); + } + + static const struct of_device_id amd_edac_match[] = { diff --git a/queue-7.0/net-txgbe-fix-rtnl-assertion-warning-when-remove-module.patch b/queue-7.0/net-txgbe-fix-rtnl-assertion-warning-when-remove-module.patch new file mode 100644 index 0000000000..ebba2946ef --- /dev/null +++ b/queue-7.0/net-txgbe-fix-rtnl-assertion-warning-when-remove-module.patch @@ -0,0 +1,97 @@ +From e159f05e12cc1111a3103b99375ddf0dfd0e7d63 Mon Sep 17 00:00:00 2001 +From: Jiawen Wu +Date: Tue, 7 Apr 2026 17:40:41 +0800 +Subject: net: txgbe: fix RTNL assertion warning when remove module + +From: Jiawen Wu + +commit e159f05e12cc1111a3103b99375ddf0dfd0e7d63 upstream. + +For the copper NIC with external PHY, the driver called +phylink_connect_phy() during probe and phylink_disconnect_phy() during +remove. It caused an RTNL assertion warning in phylink_disconnect_phy() +upon module remove. + +To fix this, add rtnl_lock() and rtnl_unlock() around the +phylink_disconnect_phy() in remove function. + + ------------[ cut here ]------------ + RTNL: assertion failed at drivers/net/phy/phylink.c (2351) + WARNING: drivers/net/phy/phylink.c:2351 at +phylink_disconnect_phy+0xd8/0xf0 [phylink], CPU#0: rmmod/4464 + Modules linked in: ... + CPU: 0 UID: 0 PID: 4464 Comm: rmmod Kdump: loaded Not tainted 7.0.0-rc4+ + Hardware name: Micro-Star International Co., Ltd. MS-7E16/X670E GAMING +PLUS WIFI (MS-7E16), BIOS 1.90 12/31/2024 + RIP: 0010:phylink_disconnect_phy+0xe4/0xf0 [phylink] + Code: 5b 41 5c 41 5d 41 5e 41 5f 5d 31 c0 31 d2 31 f6 31 ff e9 3a 38 8f e7 +48 8d 3d 48 87 e2 ff ba 2f 09 00 00 48 c7 c6 c1 22 24 c0 <67> 48 0f b9 3a +e9 34 ff ff ff 66 90 90 90 90 90 90 90 90 90 90 90 + RSP: 0018:ffffce7288363ac0 EFLAGS: 00010246 + RAX: 0000000000000000 RBX: ffff89654b2a1a00 RCX: 0000000000000000 + RDX: 000000000000092f RSI: ffffffffc02422c1 RDI: ffffffffc0239020 + RBP: ffffce7288363ae8 R08: 0000000000000000 R09: 0000000000000000 + R10: 0000000000000000 R11: 0000000000000000 R12: ffff8964c4022000 + R13: ffff89654fce3028 R14: ffff89654ebb4000 R15: ffffffffc0226348 + FS: 0000795e80d93780(0000) GS:ffff896c52857000(0000) +knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00005b528b592000 CR3: 0000000170d0f000 CR4: 0000000000f50ef0 + PKRU: 55555554 + Call Trace: + + txgbe_remove_phy+0xbb/0xd0 [txgbe] + txgbe_remove+0x4c/0xb0 [txgbe] + pci_device_remove+0x41/0xb0 + device_remove+0x43/0x80 + device_release_driver_internal+0x206/0x270 + driver_detach+0x4a/0xa0 + bus_remove_driver+0x83/0x120 + driver_unregister+0x2f/0x60 + pci_unregister_driver+0x40/0x90 + txgbe_driver_exit+0x10/0x850 [txgbe] + __do_sys_delete_module.isra.0+0x1c3/0x2f0 + __x64_sys_delete_module+0x12/0x20 + x64_sys_call+0x20c3/0x2390 + do_syscall_64+0x11c/0x1500 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? do_syscall_64+0x15a/0x1500 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? do_fault+0x312/0x580 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? __handle_mm_fault+0x9d5/0x1040 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? count_memcg_events+0x101/0x1d0 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? handle_mm_fault+0x1e8/0x2f0 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? do_user_addr_fault+0x2f8/0x820 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? irqentry_exit+0xb2/0x600 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? exc_page_fault+0x92/0x1c0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +Fixes: 02b2a6f91b90 ("net: txgbe: support copper NIC with external PHY") +Cc: stable@vger.kernel.org +Signed-off-by: Jiawen Wu +Reviewed-by: Russell King (Oracle) +Link: https://patch.msgid.link/8B47A5872884147D+20260407094041.4646-1-jiawenwu@trustnetic.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c ++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +@@ -657,7 +657,9 @@ void txgbe_remove_phy(struct txgbe *txgb + return; + case wx_mac_sp: + if (txgbe->wx->media_type == wx_media_copper) { ++ rtnl_lock(); + phylink_disconnect_phy(txgbe->wx->phylink); ++ rtnl_unlock(); + phylink_destroy(txgbe->wx->phylink); + return; + } diff --git a/queue-7.0/rxrpc-fix-conn-level-packet-handling-to-unshare-response-packets.patch b/queue-7.0/rxrpc-fix-conn-level-packet-handling-to-unshare-response-packets.patch new file mode 100644 index 0000000000..a87b2986a6 --- /dev/null +++ b/queue-7.0/rxrpc-fix-conn-level-packet-handling-to-unshare-response-packets.patch @@ -0,0 +1,77 @@ +From 24481a7f573305706054c59e275371f8d0fe919f Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 22 Apr 2026 17:14:33 +0100 +Subject: rxrpc: Fix conn-level packet handling to unshare RESPONSE packets + +From: David Howells + +commit 24481a7f573305706054c59e275371f8d0fe919f upstream. + +The security operations that verify the RESPONSE packets decrypt bits of it +in place - however, the sk_buff may be shared with a packet sniffer, which +would lead to the sniffer seeing an apparently corrupt packet (actually +decrypted). + +Fix this by handing a copy of the packet off to the specific security +handler if the packet was cloned. + +Fixes: 17926a79320a ("[AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both") +Closes: https://sashiko.dev/#/patchset/20260408121252.2249051-1-dhowells%40redhat.com +Signed-off-by: David Howells +cc: Marc Dionne +cc: Jeffrey Altman +cc: Simon Horman +cc: linux-afs@lists.infradead.org +cc: stable@kernel.org +Link: https://patch.msgid.link/20260422161438.2593376-5-dhowells@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/rxrpc/conn_event.c | 29 ++++++++++++++++++++++++++++- + 1 file changed, 28 insertions(+), 1 deletion(-) + +--- a/net/rxrpc/conn_event.c ++++ b/net/rxrpc/conn_event.c +@@ -240,6 +240,33 @@ static void rxrpc_call_is_secure(struct + rxrpc_notify_socket(call); + } + ++static int rxrpc_verify_response(struct rxrpc_connection *conn, ++ struct sk_buff *skb) ++{ ++ int ret; ++ ++ if (skb_cloned(skb)) { ++ /* Copy the packet if shared so that we can do in-place ++ * decryption. ++ */ ++ struct sk_buff *nskb = skb_copy(skb, GFP_NOFS); ++ ++ if (nskb) { ++ rxrpc_new_skb(nskb, rxrpc_skb_new_unshared); ++ ret = conn->security->verify_response(conn, nskb); ++ rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy); ++ } else { ++ /* OOM - Drop the packet. */ ++ rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem); ++ ret = -ENOMEM; ++ } ++ } else { ++ ret = conn->security->verify_response(conn, skb); ++ } ++ ++ return ret; ++} ++ + /* + * connection-level Rx packet processor + */ +@@ -270,7 +297,7 @@ static int rxrpc_process_event(struct rx + } + spin_unlock_irq(&conn->state_lock); + +- ret = conn->security->verify_response(conn, skb); ++ ret = rxrpc_verify_response(conn, skb); + if (ret < 0) + return ret; + diff --git a/queue-7.0/rxrpc-fix-error-handling-in-rxgk_extract_token.patch b/queue-7.0/rxrpc-fix-error-handling-in-rxgk_extract_token.patch new file mode 100644 index 0000000000..d9801b144a --- /dev/null +++ b/queue-7.0/rxrpc-fix-error-handling-in-rxgk_extract_token.patch @@ -0,0 +1,38 @@ +From 3476c8bb960f48e49355d6f93fb7673211e0163f Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 23 Apr 2026 21:09:08 +0100 +Subject: rxrpc: Fix error handling in rxgk_extract_token() + +From: David Howells + +commit 3476c8bb960f48e49355d6f93fb7673211e0163f upstream. + +Fix a missing bit of error handling in rxgk_extract_token(): in the event +that rxgk_decrypt_skb() returns -ENOMEM, it should just return that rather +than continuing on (for anything else, it generates an abort). + +Fixes: 64863f4ca494 ("rxrpc: Fix unhandled errors in rxgk_verify_packet_integrity()") +Closes: https://sashiko.dev/#/patchset/20260422161438.2593376-4-dhowells@redhat.com +Signed-off-by: David Howells +cc: Marc Dionne +cc: Jeffrey Altman +cc: Simon Horman +cc: linux-afs@lists.infradead.org +cc: stable@kernel.org +Link: https://patch.msgid.link/20260423200909.3049438-4-dhowells@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/rxrpc/rxgk_app.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/rxrpc/rxgk_app.c ++++ b/net/rxrpc/rxgk_app.c +@@ -245,6 +245,7 @@ int rxgk_extract_token(struct rxrpc_conn + if (ret != -ENOMEM) + return rxrpc_abort_conn(conn, skb, ec, ret, + rxgk_abort_resp_tok_dec); ++ return ret; + } + + ret = conn->security->default_decode_ticket(conn, skb, ticket_offset, diff --git a/queue-7.0/rxrpc-fix-memory-leaks-in-rxkad_verify_response.patch b/queue-7.0/rxrpc-fix-memory-leaks-in-rxkad_verify_response.patch new file mode 100644 index 0000000000..285a6bda9c --- /dev/null +++ b/queue-7.0/rxrpc-fix-memory-leaks-in-rxkad_verify_response.patch @@ -0,0 +1,231 @@ +From 34f61a07e0cdefaecd3ec03bb5fb22215643678f Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 22 Apr 2026 17:14:30 +0100 +Subject: rxrpc: Fix memory leaks in rxkad_verify_response() + +From: David Howells + +commit 34f61a07e0cdefaecd3ec03bb5fb22215643678f upstream. + +Fix rxkad_verify_response() to free the ticket and the server key under all +circumstances by initialising the ticket pointer to NULL and then making +all paths through the function after the first allocation has been done go +through a single common epilogue that just releases everything - where all +the releases skip on a NULL pointer. + +Fixes: 57af281e5389 ("rxrpc: Tidy up abort generation infrastructure") +Fixes: ec832bd06d6f ("rxrpc: Don't retain the server key in the connection") +Closes: https://sashiko.dev/#/patchset/20260408121252.2249051-1-dhowells%40redhat.com +Signed-off-by: David Howells +cc: Marc Dionne +cc: Jeffrey Altman +cc: Simon Horman +cc: linux-afs@lists.infradead.org +cc: stable@kernel.org +Link: https://patch.msgid.link/20260422161438.2593376-2-dhowells@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/rxrpc/rxkad.c | 103 ++++++++++++++++++++++-------------------------------- + 1 file changed, 42 insertions(+), 61 deletions(-) + +--- a/net/rxrpc/rxkad.c ++++ b/net/rxrpc/rxkad.c +@@ -1136,7 +1136,7 @@ static int rxkad_verify_response(struct + struct rxrpc_crypt session_key; + struct key *server_key; + time64_t expiry; +- void *ticket; ++ void *ticket = NULL; + u32 version, kvno, ticket_len, level; + __be32 csum; + int ret, i; +@@ -1162,13 +1162,13 @@ static int rxkad_verify_response(struct + ret = -ENOMEM; + response = kzalloc_obj(struct rxkad_response, GFP_NOFS); + if (!response) +- goto temporary_error; ++ goto error; + + if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), + response, sizeof(*response)) < 0) { +- rxrpc_abort_conn(conn, skb, RXKADPACKETSHORT, -EPROTO, +- rxkad_abort_resp_short); +- goto protocol_error; ++ ret = rxrpc_abort_conn(conn, skb, RXKADPACKETSHORT, -EPROTO, ++ rxkad_abort_resp_short); ++ goto error; + } + + version = ntohl(response->version); +@@ -1178,62 +1178,62 @@ static int rxkad_verify_response(struct + trace_rxrpc_rx_response(conn, sp->hdr.serial, version, kvno, ticket_len); + + if (version != RXKAD_VERSION) { +- rxrpc_abort_conn(conn, skb, RXKADINCONSISTENCY, -EPROTO, +- rxkad_abort_resp_version); +- goto protocol_error; ++ ret = rxrpc_abort_conn(conn, skb, RXKADINCONSISTENCY, -EPROTO, ++ rxkad_abort_resp_version); ++ goto error; + } + + if (ticket_len < 4 || ticket_len > MAXKRB5TICKETLEN) { +- rxrpc_abort_conn(conn, skb, RXKADTICKETLEN, -EPROTO, +- rxkad_abort_resp_tkt_len); +- goto protocol_error; ++ ret = rxrpc_abort_conn(conn, skb, RXKADTICKETLEN, -EPROTO, ++ rxkad_abort_resp_tkt_len); ++ goto error; + } + + if (kvno >= RXKAD_TKT_TYPE_KERBEROS_V5) { +- rxrpc_abort_conn(conn, skb, RXKADUNKNOWNKEY, -EPROTO, +- rxkad_abort_resp_unknown_tkt); +- goto protocol_error; ++ ret = rxrpc_abort_conn(conn, skb, RXKADUNKNOWNKEY, -EPROTO, ++ rxkad_abort_resp_unknown_tkt); ++ goto error; + } + + /* extract the kerberos ticket and decrypt and decode it */ + ret = -ENOMEM; + ticket = kmalloc(ticket_len, GFP_NOFS); + if (!ticket) +- goto temporary_error_free_resp; ++ goto error; + + if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header) + sizeof(*response), + ticket, ticket_len) < 0) { +- rxrpc_abort_conn(conn, skb, RXKADPACKETSHORT, -EPROTO, +- rxkad_abort_resp_short_tkt); +- goto protocol_error; ++ ret = rxrpc_abort_conn(conn, skb, RXKADPACKETSHORT, -EPROTO, ++ rxkad_abort_resp_short_tkt); ++ goto error; + } + + ret = rxkad_decrypt_ticket(conn, server_key, skb, ticket, ticket_len, + &session_key, &expiry); + if (ret < 0) +- goto temporary_error_free_ticket; ++ goto error; + + /* use the session key from inside the ticket to decrypt the + * response */ + ret = rxkad_decrypt_response(conn, response, &session_key); + if (ret < 0) +- goto temporary_error_free_ticket; ++ goto error; + + if (ntohl(response->encrypted.epoch) != conn->proto.epoch || + ntohl(response->encrypted.cid) != conn->proto.cid || + ntohl(response->encrypted.securityIndex) != conn->security_ix) { +- rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, +- rxkad_abort_resp_bad_param); +- goto protocol_error_free; ++ ret = rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, ++ rxkad_abort_resp_bad_param); ++ goto error; + } + + csum = response->encrypted.checksum; + response->encrypted.checksum = 0; + rxkad_calc_response_checksum(response); + if (response->encrypted.checksum != csum) { +- rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, +- rxkad_abort_resp_bad_checksum); +- goto protocol_error_free; ++ ret = rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, ++ rxkad_abort_resp_bad_checksum); ++ goto error; + } + + for (i = 0; i < RXRPC_MAXCALLS; i++) { +@@ -1241,38 +1241,38 @@ static int rxkad_verify_response(struct + u32 counter = READ_ONCE(conn->channels[i].call_counter); + + if (call_id > INT_MAX) { +- rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, +- rxkad_abort_resp_bad_callid); +- goto protocol_error_free; ++ ret = rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, ++ rxkad_abort_resp_bad_callid); ++ goto error; + } + + if (call_id < counter) { +- rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, +- rxkad_abort_resp_call_ctr); +- goto protocol_error_free; ++ ret = rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, ++ rxkad_abort_resp_call_ctr); ++ goto error; + } + + if (call_id > counter) { + if (conn->channels[i].call) { +- rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, ++ ret = rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, + rxkad_abort_resp_call_state); +- goto protocol_error_free; ++ goto error; + } + conn->channels[i].call_counter = call_id; + } + } + + if (ntohl(response->encrypted.inc_nonce) != conn->rxkad.nonce + 1) { +- rxrpc_abort_conn(conn, skb, RXKADOUTOFSEQUENCE, -EPROTO, +- rxkad_abort_resp_ooseq); +- goto protocol_error_free; ++ ret = rxrpc_abort_conn(conn, skb, RXKADOUTOFSEQUENCE, -EPROTO, ++ rxkad_abort_resp_ooseq); ++ goto error; + } + + level = ntohl(response->encrypted.level); + if (level > RXRPC_SECURITY_ENCRYPT) { +- rxrpc_abort_conn(conn, skb, RXKADLEVELFAIL, -EPROTO, +- rxkad_abort_resp_level); +- goto protocol_error_free; ++ ret = rxrpc_abort_conn(conn, skb, RXKADLEVELFAIL, -EPROTO, ++ rxkad_abort_resp_level); ++ goto error; + } + conn->security_level = level; + +@@ -1280,31 +1280,12 @@ static int rxkad_verify_response(struct + * this the connection security can be handled in exactly the same way + * as for a client connection */ + ret = rxrpc_get_server_data_key(conn, &session_key, expiry, kvno); +- if (ret < 0) +- goto temporary_error_free_ticket; +- +- kfree(ticket); +- kfree(response); +- _leave(" = 0"); +- return 0; +- +-protocol_error_free: +- kfree(ticket); +-protocol_error: +- kfree(response); +- key_put(server_key); +- return -EPROTO; + +-temporary_error_free_ticket: ++error: + kfree(ticket); +-temporary_error_free_resp: + kfree(response); +-temporary_error: +- /* Ignore the response packet if we got a temporary error such as +- * ENOMEM. We just want to send the challenge again. Note that we +- * also come out this way if the ticket decryption fails. +- */ + key_put(server_key); ++ _leave(" = %d", ret); + return ret; + } + diff --git a/queue-7.0/rxrpc-fix-potential-uaf-after-skb_unshare-failure.patch b/queue-7.0/rxrpc-fix-potential-uaf-after-skb_unshare-failure.patch new file mode 100644 index 0000000000..32e3ea48ff --- /dev/null +++ b/queue-7.0/rxrpc-fix-potential-uaf-after-skb_unshare-failure.patch @@ -0,0 +1,176 @@ +From 1f2740150f904bfa60e4bad74d65add3ccb5e7f8 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 22 Apr 2026 17:14:32 +0100 +Subject: rxrpc: Fix potential UAF after skb_unshare() failure + +From: David Howells + +commit 1f2740150f904bfa60e4bad74d65add3ccb5e7f8 upstream. + +If skb_unshare() fails to unshare a packet due to allocation failure in +rxrpc_input_packet(), the skb pointer in the parent (rxrpc_io_thread()) +will be NULL'd out. This will likely cause the call to +trace_rxrpc_rx_done() to oops. + +Fix this by moving the unsharing down to where rxrpc_input_call_event() +calls rxrpc_input_call_packet(). There are a number of places prior to +that where we ignore DATA packets for a variety of reasons (such as the +call already being complete) for which an unshare is then avoided. + +And with that, rxrpc_input_packet() doesn't need to take a pointer to the +pointer to the packet, so change that to just a pointer. + +Fixes: 2d1faf7a0ca3 ("rxrpc: Simplify skbuff accounting in receive path") +Closes: https://sashiko.dev/#/patchset/20260408121252.2249051-1-dhowells%40redhat.com +Signed-off-by: David Howells +cc: Marc Dionne +cc: Jeffrey Altman +cc: Simon Horman +cc: linux-afs@lists.infradead.org +cc: stable@kernel.org +Link: https://patch.msgid.link/20260422161438.2593376-4-dhowells@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + include/trace/events/rxrpc.h | 4 ++-- + net/rxrpc/ar-internal.h | 1 - + net/rxrpc/call_event.c | 19 ++++++++++++++++++- + net/rxrpc/io_thread.c | 24 ++---------------------- + net/rxrpc/skbuff.c | 9 --------- + 5 files changed, 22 insertions(+), 35 deletions(-) + +--- a/include/trace/events/rxrpc.h ++++ b/include/trace/events/rxrpc.h +@@ -161,8 +161,6 @@ + E_(rxrpc_call_poke_timer_now, "Timer-now") + + #define rxrpc_skb_traces \ +- EM(rxrpc_skb_eaten_by_unshare, "ETN unshare ") \ +- EM(rxrpc_skb_eaten_by_unshare_nomem, "ETN unshar-nm") \ + EM(rxrpc_skb_get_call_rx, "GET call-rx ") \ + EM(rxrpc_skb_get_conn_secured, "GET conn-secd") \ + EM(rxrpc_skb_get_conn_work, "GET conn-work") \ +@@ -189,6 +187,7 @@ + EM(rxrpc_skb_put_purge, "PUT purge ") \ + EM(rxrpc_skb_put_purge_oob, "PUT purge-oob") \ + EM(rxrpc_skb_put_response, "PUT response ") \ ++ EM(rxrpc_skb_put_response_copy, "PUT resp-cpy ") \ + EM(rxrpc_skb_put_rotate, "PUT rotate ") \ + EM(rxrpc_skb_put_unknown, "PUT unknown ") \ + EM(rxrpc_skb_see_conn_work, "SEE conn-work") \ +@@ -197,6 +196,7 @@ + EM(rxrpc_skb_see_recvmsg_oob, "SEE recvm-oob") \ + EM(rxrpc_skb_see_reject, "SEE reject ") \ + EM(rxrpc_skb_see_rotate, "SEE rotate ") \ ++ EM(rxrpc_skb_see_unshare_nomem, "SEE unshar-nm") \ + E_(rxrpc_skb_see_version, "SEE version ") + + #define rxrpc_local_traces \ +--- a/net/rxrpc/ar-internal.h ++++ b/net/rxrpc/ar-internal.h +@@ -1486,7 +1486,6 @@ int rxrpc_server_keyring(struct rxrpc_so + void rxrpc_kernel_data_consumed(struct rxrpc_call *, struct sk_buff *); + void rxrpc_new_skb(struct sk_buff *, enum rxrpc_skb_trace); + void rxrpc_see_skb(struct sk_buff *, enum rxrpc_skb_trace); +-void rxrpc_eaten_skb(struct sk_buff *, enum rxrpc_skb_trace); + void rxrpc_get_skb(struct sk_buff *, enum rxrpc_skb_trace); + void rxrpc_free_skb(struct sk_buff *, enum rxrpc_skb_trace); + void rxrpc_purge_queue(struct sk_buff_head *); +--- a/net/rxrpc/call_event.c ++++ b/net/rxrpc/call_event.c +@@ -332,7 +332,24 @@ bool rxrpc_input_call_event(struct rxrpc + + saw_ack |= sp->hdr.type == RXRPC_PACKET_TYPE_ACK; + +- rxrpc_input_call_packet(call, skb); ++ if (sp->hdr.securityIndex != 0 && ++ skb_cloned(skb)) { ++ /* Unshare the packet so that it can be ++ * modified by in-place decryption. ++ */ ++ struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC); ++ ++ if (nskb) { ++ rxrpc_new_skb(nskb, rxrpc_skb_new_unshared); ++ rxrpc_input_call_packet(call, nskb); ++ rxrpc_free_skb(nskb, rxrpc_skb_put_call_rx); ++ } else { ++ /* OOM - Drop the packet. */ ++ rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem); ++ } ++ } else { ++ rxrpc_input_call_packet(call, skb); ++ } + rxrpc_free_skb(skb, rxrpc_skb_put_call_rx); + did_receive = true; + } +--- a/net/rxrpc/io_thread.c ++++ b/net/rxrpc/io_thread.c +@@ -192,13 +192,12 @@ static bool rxrpc_extract_abort(struct s + /* + * Process packets received on the local endpoint + */ +-static bool rxrpc_input_packet(struct rxrpc_local *local, struct sk_buff **_skb) ++static bool rxrpc_input_packet(struct rxrpc_local *local, struct sk_buff *skb) + { + struct rxrpc_connection *conn; + struct sockaddr_rxrpc peer_srx; + struct rxrpc_skb_priv *sp; + struct rxrpc_peer *peer = NULL; +- struct sk_buff *skb = *_skb; + bool ret = false; + + skb_pull(skb, sizeof(struct udphdr)); +@@ -244,25 +243,6 @@ static bool rxrpc_input_packet(struct rx + return rxrpc_bad_message(skb, rxrpc_badmsg_zero_call); + if (sp->hdr.seq == 0) + return rxrpc_bad_message(skb, rxrpc_badmsg_zero_seq); +- +- /* Unshare the packet so that it can be modified for in-place +- * decryption. +- */ +- if (sp->hdr.securityIndex != 0) { +- skb = skb_unshare(skb, GFP_ATOMIC); +- if (!skb) { +- rxrpc_eaten_skb(*_skb, rxrpc_skb_eaten_by_unshare_nomem); +- *_skb = NULL; +- return just_discard; +- } +- +- if (skb != *_skb) { +- rxrpc_eaten_skb(*_skb, rxrpc_skb_eaten_by_unshare); +- *_skb = skb; +- rxrpc_new_skb(skb, rxrpc_skb_new_unshared); +- sp = rxrpc_skb(skb); +- } +- } + break; + + case RXRPC_PACKET_TYPE_CHALLENGE: +@@ -494,7 +474,7 @@ int rxrpc_io_thread(void *data) + switch (skb->mark) { + case RXRPC_SKB_MARK_PACKET: + skb->priority = 0; +- if (!rxrpc_input_packet(local, &skb)) ++ if (!rxrpc_input_packet(local, skb)) + rxrpc_reject_packet(local, skb); + trace_rxrpc_rx_done(skb->mark, skb->priority); + rxrpc_free_skb(skb, rxrpc_skb_put_input); +--- a/net/rxrpc/skbuff.c ++++ b/net/rxrpc/skbuff.c +@@ -47,15 +47,6 @@ void rxrpc_get_skb(struct sk_buff *skb, + } + + /* +- * Note the dropping of a ref on a socket buffer by the core. +- */ +-void rxrpc_eaten_skb(struct sk_buff *skb, enum rxrpc_skb_trace why) +-{ +- int n = atomic_inc_return(&rxrpc_n_rx_skbs); +- trace_rxrpc_skb(skb, 0, n, why); +-} +- +-/* + * Note the destruction of a socket buffer. + */ + void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace why) diff --git a/queue-7.0/rxrpc-fix-re-decryption-of-response-packets.patch b/queue-7.0/rxrpc-fix-re-decryption-of-response-packets.patch new file mode 100644 index 0000000000..7be5d299b7 --- /dev/null +++ b/queue-7.0/rxrpc-fix-re-decryption-of-response-packets.patch @@ -0,0 +1,73 @@ +From 0422e7a4883f25101903f3e8105c0808aa5f4ce9 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 23 Apr 2026 21:09:07 +0100 +Subject: rxrpc: Fix re-decryption of RESPONSE packets + +From: David Howells + +commit 0422e7a4883f25101903f3e8105c0808aa5f4ce9 upstream. + +If a RESPONSE packet gets a temporary failure during processing, it may end +up in a partially decrypted state - and then get requeued for a retry. + +Fix this by just discarding the packet; we will send another CHALLENGE +packet and thereby elicit a further response. Similarly, discard an +incoming CHALLENGE packet if we get an error whilst generating a RESPONSE; +the server will send another CHALLENGE. + +Fixes: 17926a79320a ("[AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both") +Closes: https://sashiko.dev/#/patchset/20260422161438.2593376-4-dhowells@redhat.com +Signed-off-by: David Howells +cc: Marc Dionne +cc: Jeffrey Altman +cc: Simon Horman +cc: linux-afs@lists.infradead.org +cc: stable@kernel.org +Link: https://patch.msgid.link/20260423200909.3049438-3-dhowells@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + include/trace/events/rxrpc.h | 1 - + net/rxrpc/conn_event.c | 14 ++------------ + 2 files changed, 2 insertions(+), 13 deletions(-) + +--- a/include/trace/events/rxrpc.h ++++ b/include/trace/events/rxrpc.h +@@ -285,7 +285,6 @@ + EM(rxrpc_conn_put_unidle, "PUT unidle ") \ + EM(rxrpc_conn_put_work, "PUT work ") \ + EM(rxrpc_conn_queue_challenge, "QUE chall ") \ +- EM(rxrpc_conn_queue_retry_work, "QUE retry-wk") \ + EM(rxrpc_conn_queue_rx_work, "QUE rx-work ") \ + EM(rxrpc_conn_see_new_service_conn, "SEE new-svc ") \ + EM(rxrpc_conn_see_reap_service, "SEE reap-svc") \ +--- a/net/rxrpc/conn_event.c ++++ b/net/rxrpc/conn_event.c +@@ -389,7 +389,6 @@ again: + static void rxrpc_do_process_connection(struct rxrpc_connection *conn) + { + struct sk_buff *skb; +- int ret; + + if (test_and_clear_bit(RXRPC_CONN_EV_CHALLENGE, &conn->events)) + rxrpc_secure_connection(conn); +@@ -398,17 +397,8 @@ static void rxrpc_do_process_connection( + * connection that each one has when we've finished with it */ + while ((skb = skb_dequeue(&conn->rx_queue))) { + rxrpc_see_skb(skb, rxrpc_skb_see_conn_work); +- ret = rxrpc_process_event(conn, skb); +- switch (ret) { +- case -ENOMEM: +- case -EAGAIN: +- skb_queue_head(&conn->rx_queue, skb); +- rxrpc_queue_conn(conn, rxrpc_conn_queue_retry_work); +- break; +- default: +- rxrpc_free_skb(skb, rxrpc_skb_put_conn_work); +- break; +- } ++ rxrpc_process_event(conn, skb); ++ rxrpc_free_skb(skb, rxrpc_skb_put_conn_work); + } + } + diff --git a/queue-7.0/rxrpc-fix-rxkad-crypto-unalignment-handling.patch b/queue-7.0/rxrpc-fix-rxkad-crypto-unalignment-handling.patch new file mode 100644 index 0000000000..b1f1ec89d4 --- /dev/null +++ b/queue-7.0/rxrpc-fix-rxkad-crypto-unalignment-handling.patch @@ -0,0 +1,65 @@ +From def304aae2edf321d2671fd6ca766a93c21f877e Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 22 Apr 2026 17:14:31 +0100 +Subject: rxrpc: Fix rxkad crypto unalignment handling + +From: David Howells + +commit def304aae2edf321d2671fd6ca766a93c21f877e upstream. + +Fix handling of a packet with a misaligned crypto length. Also handle +non-ENOMEM errors from decryption by aborting. Further, remove the +WARN_ON_ONCE() so that it can't be remotely triggered (a trace line can +still be emitted). + +Fixes: f93af41b9f5f ("rxrpc: Fix missing error checks for rxkad encryption/decryption failure") +Closes: https://sashiko.dev/#/patchset/20260408121252.2249051-1-dhowells%40redhat.com +Signed-off-by: David Howells +cc: Marc Dionne +cc: Jeffrey Altman +cc: Simon Horman +cc: linux-afs@lists.infradead.org +cc: stable@kernel.org +Link: https://patch.msgid.link/20260422161438.2593376-3-dhowells@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + include/trace/events/rxrpc.h | 1 + + net/rxrpc/rxkad.c | 9 +++++++-- + 2 files changed, 8 insertions(+), 2 deletions(-) + +--- a/include/trace/events/rxrpc.h ++++ b/include/trace/events/rxrpc.h +@@ -37,6 +37,7 @@ + EM(rxkad_abort_1_short_encdata, "rxkad1-short-encdata") \ + EM(rxkad_abort_1_short_header, "rxkad1-short-hdr") \ + EM(rxkad_abort_2_short_check, "rxkad2-short-check") \ ++ EM(rxkad_abort_2_crypto_unaligned, "rxkad2-crypto-unaligned") \ + EM(rxkad_abort_2_short_data, "rxkad2-short-data") \ + EM(rxkad_abort_2_short_header, "rxkad2-short-hdr") \ + EM(rxkad_abort_2_short_len, "rxkad2-short-len") \ +--- a/net/rxrpc/rxkad.c ++++ b/net/rxrpc/rxkad.c +@@ -510,6 +510,9 @@ static int rxkad_verify_packet_2(struct + return rxrpc_abort_eproto(call, skb, RXKADSEALEDINCON, + rxkad_abort_2_short_header); + ++ /* Don't let the crypto algo see a misaligned length. */ ++ sp->len = round_down(sp->len, 8); ++ + /* Decrypt the skbuff in-place. TODO: We really want to decrypt + * directly into the target buffer. + */ +@@ -543,8 +546,10 @@ static int rxkad_verify_packet_2(struct + if (sg != _sg) + kfree(sg); + if (ret < 0) { +- WARN_ON_ONCE(ret != -ENOMEM); +- return ret; ++ if (ret == -ENOMEM) ++ return ret; ++ return rxrpc_abort_eproto(call, skb, RXKADSEALEDINCON, ++ rxkad_abort_2_crypto_unaligned); + } + + /* Extract the decrypted packet length */ diff --git a/queue-7.0/rxrpc-fix-rxrpc_input_call_event-to-only-unshare-data-packets.patch b/queue-7.0/rxrpc-fix-rxrpc_input_call_event-to-only-unshare-data-packets.patch new file mode 100644 index 0000000000..899276ef93 --- /dev/null +++ b/queue-7.0/rxrpc-fix-rxrpc_input_call_event-to-only-unshare-data-packets.patch @@ -0,0 +1,42 @@ +From 55b2984c96c37f909bbfe8851f13152693951382 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 23 Apr 2026 21:09:06 +0100 +Subject: rxrpc: Fix rxrpc_input_call_event() to only unshare DATA packets + +From: David Howells + +commit 55b2984c96c37f909bbfe8851f13152693951382 upstream. + +Fix rxrpc_input_call_event() to only unshare DATA packets and not ACK, +ABORT, etc.. + +And with that, rxrpc_input_packet() doesn't need to take a pointer to the +pointer to the packet, so change that to just a pointer. + +Fixes: 1f2740150f90 ("rxrpc: Fix potential UAF after skb_unshare() failure") +Closes: https://sashiko.dev/#/patchset/20260422161438.2593376-4-dhowells@redhat.com +Signed-off-by: David Howells +cc: Marc Dionne +cc: Jeffrey Altman +cc: Simon Horman +cc: linux-afs@lists.infradead.org +cc: stable@kernel.org +Link: https://patch.msgid.link/20260423200909.3049438-2-dhowells@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/rxrpc/call_event.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/net/rxrpc/call_event.c ++++ b/net/rxrpc/call_event.c +@@ -332,7 +332,8 @@ bool rxrpc_input_call_event(struct rxrpc + + saw_ack |= sp->hdr.type == RXRPC_PACKET_TYPE_ACK; + +- if (sp->hdr.securityIndex != 0 && ++ if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA && ++ sp->hdr.securityIndex != 0 && + skb_cloned(skb)) { + /* Unshare the packet so that it can be + * modified by in-place decryption. diff --git a/queue-7.0/series b/queue-7.0/series index 38a88ea668..920faec8f0 100644 --- a/queue-7.0/series +++ b/queue-7.0/series @@ -123,3 +123,13 @@ alsa-pcmtest-fix-reference-leak-on-failed-device-registration.patch alsa-pcmtest-fix-resource-leaks-in-module-init-error-paths.patch iio-adc-ad7768-1-fix-one-shot-mode-data-acquisition.patch iio-adc-ad7768-1-remove-switch-to-one-shot-mode.patch +rxrpc-fix-potential-uaf-after-skb_unshare-failure.patch +rxrpc-fix-memory-leaks-in-rxkad_verify_response.patch +rxrpc-fix-conn-level-packet-handling-to-unshare-response-packets.patch +rxrpc-fix-rxkad-crypto-unalignment-handling.patch +rxrpc-fix-error-handling-in-rxgk_extract_token.patch +rxrpc-fix-re-decryption-of-response-packets.patch +rxrpc-fix-rxrpc_input_call_event-to-only-unshare-data-packets.patch +edac-versalnet-fix-memory-leak-in-remove-and-probe-error-paths.patch +tools-accounting-handle-truncated-taskstats-netlink-messages.patch +net-txgbe-fix-rtnl-assertion-warning-when-remove-module.patch diff --git a/queue-7.0/tools-accounting-handle-truncated-taskstats-netlink-messages.patch b/queue-7.0/tools-accounting-handle-truncated-taskstats-netlink-messages.patch new file mode 100644 index 0000000000..1689bea50c --- /dev/null +++ b/queue-7.0/tools-accounting-handle-truncated-taskstats-netlink-messages.patch @@ -0,0 +1,181 @@ +From cc82b3dcc6a8fa259fbda12ab00d6fc00908a49e Mon Sep 17 00:00:00 2001 +From: Yiyang Chen +Date: Mon, 30 Mar 2026 03:00:41 +0800 +Subject: tools/accounting: handle truncated taskstats netlink messages + +From: Yiyang Chen + +commit cc82b3dcc6a8fa259fbda12ab00d6fc00908a49e upstream. + +procacct and getdelays use a fixed receive buffer for taskstats generic +netlink messages. A multi-threaded process exit can emit a single +PID+TGID notification large enough to exceed that buffer on newer kernels. + +Switch to recvmsg() so MSG_TRUNC is detected explicitly, increase the +message buffer size, and report truncated datagrams clearly instead of +misparsing them as fatal netlink errors. + +Also print the taskstats version in debug output to make version +mismatches easier to diagnose while inspecting taskstats traffic. + +Link: https://lkml.kernel.org/r/520308bb4cbbaf8dc2c7296b5f60f11e12fb30a5.1774810498.git.cyyzero16@gmail.com +Signed-off-by: Yiyang Chen +Cc: Balbir Singh +Cc: Dr. Thomas Orgis +Cc: Fan Yu +Cc: Wang Yaxin +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + tools/accounting/getdelays.c | 41 +++++++++++++++++++++++++++++++++++++---- + tools/accounting/procacct.c | 40 ++++++++++++++++++++++++++++++++++++---- + 2 files changed, 73 insertions(+), 8 deletions(-) + +--- a/tools/accounting/getdelays.c ++++ b/tools/accounting/getdelays.c +@@ -60,7 +60,7 @@ int print_task_context_switch_counts; + } + + /* Maximum size of response requested or message sent */ +-#define MAX_MSG_SIZE 1024 ++#define MAX_MSG_SIZE 2048 + /* Maximum number of cpus expected to be specified in a cpumask */ + #define MAX_CPUS 32 + +@@ -115,6 +115,32 @@ error: + return -1; + } + ++static int recv_taskstats_msg(int sd, struct msgtemplate *msg) ++{ ++ struct sockaddr_nl nladdr; ++ struct iovec iov = { ++ .iov_base = msg, ++ .iov_len = sizeof(*msg), ++ }; ++ struct msghdr hdr = { ++ .msg_name = &nladdr, ++ .msg_namelen = sizeof(nladdr), ++ .msg_iov = &iov, ++ .msg_iovlen = 1, ++ }; ++ int ret; ++ ++ ret = recvmsg(sd, &hdr, 0); ++ if (ret < 0) ++ return -1; ++ if (hdr.msg_flags & MSG_TRUNC) { ++ errno = EMSGSIZE; ++ return -1; ++ } ++ ++ return ret; ++} ++ + + static int send_cmd(int sd, __u16 nlmsg_type, __u32 nlmsg_pid, + __u8 genl_cmd, __u16 nla_type, +@@ -633,12 +659,16 @@ int main(int argc, char *argv[]) + } + + do { +- rep_len = recv(nl_sd, &msg, sizeof(msg), 0); ++ rep_len = recv_taskstats_msg(nl_sd, &msg); + PRINTF("received %d bytes\n", rep_len); + + if (rep_len < 0) { +- fprintf(stderr, "nonfatal reply error: errno %d\n", +- errno); ++ if (errno == EMSGSIZE) ++ fprintf(stderr, ++ "dropped truncated taskstats netlink message, please increase MAX_MSG_SIZE\n"); ++ else ++ fprintf(stderr, "nonfatal reply error: errno %d\n", ++ errno); + continue; + } + if (msg.n.nlmsg_type == NLMSG_ERROR || +@@ -680,6 +710,9 @@ int main(int argc, char *argv[]) + printf("TGID\t%d\n", rtid); + break; + case TASKSTATS_TYPE_STATS: ++ PRINTF("version %u\n", ++ ((struct taskstats *) ++ NLA_DATA(na))->version); + if (print_delays) + print_delayacct((struct taskstats *) NLA_DATA(na)); + if (print_io_accounting) +--- a/tools/accounting/procacct.c ++++ b/tools/accounting/procacct.c +@@ -71,7 +71,7 @@ int print_task_context_switch_counts; + } + + /* Maximum size of response requested or message sent */ +-#define MAX_MSG_SIZE 1024 ++#define MAX_MSG_SIZE 2048 + /* Maximum number of cpus expected to be specified in a cpumask */ + #define MAX_CPUS 32 + +@@ -121,6 +121,32 @@ error: + return -1; + } + ++static int recv_taskstats_msg(int sd, struct msgtemplate *msg) ++{ ++ struct sockaddr_nl nladdr; ++ struct iovec iov = { ++ .iov_base = msg, ++ .iov_len = sizeof(*msg), ++ }; ++ struct msghdr hdr = { ++ .msg_name = &nladdr, ++ .msg_namelen = sizeof(nladdr), ++ .msg_iov = &iov, ++ .msg_iovlen = 1, ++ }; ++ int ret; ++ ++ ret = recvmsg(sd, &hdr, 0); ++ if (ret < 0) ++ return -1; ++ if (hdr.msg_flags & MSG_TRUNC) { ++ errno = EMSGSIZE; ++ return -1; ++ } ++ ++ return ret; ++} ++ + + static int send_cmd(int sd, __u16 nlmsg_type, __u32 nlmsg_pid, + __u8 genl_cmd, __u16 nla_type, +@@ -239,6 +265,8 @@ void handle_aggr(int mother, struct nlat + PRINTF("TGID\t%d\n", rtid); + break; + case TASKSTATS_TYPE_STATS: ++ PRINTF("version %u\n", ++ ((struct taskstats *)NLA_DATA(na))->version); + if (mother == TASKSTATS_TYPE_AGGR_PID) + print_procacct((struct taskstats *) NLA_DATA(na)); + if (fd) { +@@ -347,12 +375,16 @@ int main(int argc, char *argv[]) + } + + do { +- rep_len = recv(nl_sd, &msg, sizeof(msg), 0); ++ rep_len = recv_taskstats_msg(nl_sd, &msg); + PRINTF("received %d bytes\n", rep_len); + + if (rep_len < 0) { +- fprintf(stderr, "nonfatal reply error: errno %d\n", +- errno); ++ if (errno == EMSGSIZE) ++ fprintf(stderr, ++ "dropped truncated taskstats netlink message, please increase MAX_MSG_SIZE\n"); ++ else ++ fprintf(stderr, "nonfatal reply error: errno %d\n", ++ errno); + continue; + } + if (msg.n.nlmsg_type == NLMSG_ERROR ||