From: Sasha Levin Date: Mon, 20 Apr 2026 13:18:35 +0000 (-0400) Subject: Fixes for all trees X-Git-Tag: v6.12.83~35^2 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=f544e4d79d0a87c5cedea776f5765640e58b81f5;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for all trees Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/acpi-property-constify-stubs-for-config_acpi-n-case.patch b/queue-5.10/acpi-property-constify-stubs-for-config_acpi-n-case.patch new file mode 100644 index 0000000000..f171d87815 --- /dev/null +++ b/queue-5.10/acpi-property-constify-stubs-for-config_acpi-n-case.patch @@ -0,0 +1,54 @@ +From 9771a609321655a073152bc0b01cf07e927ea976 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 18 Apr 2026 16:07:04 -0700 +Subject: ACPI: property: Constify stubs for CONFIG_ACPI=n case + +From: Andy Shevchenko + +commit 5c1a72a0fbe1b02c3ce0537f85f92ea935e0beec upstream. + +There is a few stubs that left untouched during constification of +the fwnode related APIs. Constify three more stubs here. + +Fixes: 8b9d6802583a ("ACPI: Constify acpi_bus helper functions, switch to macros") +Reported-by: kernel test robot +Signed-off-by: Andy Shevchenko +[ rjw: Subject edit ] +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Nathan Chancellor +Signed-off-by: Sasha Levin +--- + include/linux/acpi.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/include/linux/acpi.h b/include/linux/acpi.h +index 9c184dbceba47..c5b51d8dcbe18 100644 +--- a/include/linux/acpi.h ++++ b/include/linux/acpi.h +@@ -753,7 +753,7 @@ static inline bool is_acpi_device_node(struct fwnode_handle *fwnode) + return false; + } + +-static inline struct acpi_device *to_acpi_device_node(struct fwnode_handle *fwnode) ++static inline struct acpi_device *to_acpi_device_node(const struct fwnode_handle *fwnode) + { + return NULL; + } +@@ -763,12 +763,12 @@ static inline bool is_acpi_data_node(struct fwnode_handle *fwnode) + return false; + } + +-static inline struct acpi_data_node *to_acpi_data_node(struct fwnode_handle *fwnode) ++static inline struct acpi_data_node *to_acpi_data_node(const struct fwnode_handle *fwnode) + { + return NULL; + } + +-static inline bool acpi_data_node_match(struct fwnode_handle *fwnode, ++static inline bool acpi_data_node_match(const struct fwnode_handle *fwnode, + const char *name) + { + return false; +-- +2.53.0 + diff --git a/queue-5.10/media-uvcvideo-allow-extra-entities.patch b/queue-5.10/media-uvcvideo-allow-extra-entities.patch new file mode 100644 index 0000000000..9a8a50c8a5 --- /dev/null +++ b/queue-5.10/media-uvcvideo-allow-extra-entities.patch @@ -0,0 +1,59 @@ +From 209371af2e13f4811b3a6013eae1b1c3876ed243 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Apr 2026 11:01:11 +0000 +Subject: media: uvcvideo: Allow extra entities + +From: Ricardo Ribalda + +[ Upstream commit cae79e50d1222010fde8c522410c315f74d35c40 ] + +Increase the size of the id, to avoid collisions with entities +implemented by the driver that are not part of the UVC device. + +Entities exposed by the UVC device use IDs 0-255, extra entities +implemented by the driver (such as the GPIO entity) use IDs 256 and +up. + +Signed-off-by: Ricardo Ribalda +Signed-off-by: Laurent Pinchart +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/usb/uvc/uvc_driver.c | 2 +- + drivers/media/usb/uvc/uvcvideo.h | 7 ++++++- + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c +index 419fbdbb7a3b8..c2adc6854c540 100644 +--- a/drivers/media/usb/uvc/uvc_driver.c ++++ b/drivers/media/usb/uvc/uvc_driver.c +@@ -1032,7 +1032,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, + return ret; + } + +-static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, ++static struct uvc_entity *uvc_alloc_entity(u16 type, u16 id, + unsigned int num_pads, unsigned int extra_size) + { + struct uvc_entity *entity; +diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h +index 60a8749c97a9d..a83995276170b 100644 +--- a/drivers/media/usb/uvc/uvcvideo.h ++++ b/drivers/media/usb/uvc/uvcvideo.h +@@ -302,7 +302,12 @@ struct uvc_entity { + * chain. */ + unsigned int flags; + +- u8 id; ++ /* ++ * Entities exposed by the UVC device use IDs 0-255, extra entities ++ * implemented by the driver (such as the GPIO entity) use IDs 256 and ++ * up. ++ */ ++ u16 id; + u16 type; + char name[64]; + +-- +2.53.0 + diff --git a/queue-5.10/media-uvcvideo-mark-invalid-entities-with-id-uvc_inv.patch b/queue-5.10/media-uvcvideo-mark-invalid-entities-with-id-uvc_inv.patch new file mode 100644 index 0000000000..70a195b22c --- /dev/null +++ b/queue-5.10/media-uvcvideo-mark-invalid-entities-with-id-uvc_inv.patch @@ -0,0 +1,302 @@ +From 0f72edd2379b50618a7a80d37194ad2afcceda5f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Apr 2026 11:01:12 +0000 +Subject: media: uvcvideo: Mark invalid entities with id UVC_INVALID_ENTITY_ID + +From: Thadeu Lima de Souza Cascardo + +[ Upstream commit 0e2ee70291e64a30fe36960c85294726d34a103e ] + +Per UVC 1.1+ specification 3.7.2, units and terminals must have a non-zero +unique ID. + +``` +Each Unit and Terminal within the video function is assigned a unique +identification number, the Unit ID (UID) or Terminal ID (TID), contained in +the bUnitID or bTerminalID field of the descriptor. The value 0x00 is +reserved for undefined ID, +``` + +If we add a new entity with id 0 or a duplicated ID, it will be marked +as UVC_INVALID_ENTITY_ID. + +In a previous attempt commit 3dd075fe8ebb ("media: uvcvideo: Require +entities to have a non-zero unique ID"), we ignored all the invalid units, +this broke a lot of non-compatible cameras. Hopefully we are more lucky +this time. + +This also prevents some syzkaller reproducers from triggering warnings due +to a chain of entities referring to themselves. In one particular case, an +Output Unit is connected to an Input Unit, both with the same ID of 1. But +when looking up for the source ID of the Output Unit, that same entity is +found instead of the input entity, which leads to such warnings. + +In another case, a backward chain was considered finished as the source ID +was 0. Later on, that entity was found, but its pads were not valid. + +Here is a sample stack trace for one of those cases. + +[ 20.650953] usb 1-1: new high-speed USB device number 2 using dummy_hcd +[ 20.830206] usb 1-1: Using ep0 maxpacket: 8 +[ 20.833501] usb 1-1: config 0 descriptor?? +[ 21.038518] usb 1-1: string descriptor 0 read error: -71 +[ 21.038893] usb 1-1: Found UVC 0.00 device (2833:0201) +[ 21.039299] uvcvideo 1-1:0.0: Entity type for entity Output 1 was not initialized! +[ 21.041583] uvcvideo 1-1:0.0: Entity type for entity Input 1 was not initialized! +[ 21.042218] ------------[ cut here ]------------ +[ 21.042536] WARNING: CPU: 0 PID: 9 at drivers/media/mc/mc-entity.c:1147 media_create_pad_link+0x2c4/0x2e0 +[ 21.043195] Modules linked in: +[ 21.043535] CPU: 0 UID: 0 PID: 9 Comm: kworker/0:1 Not tainted 6.11.0-rc7-00030-g3480e43aeccf #444 +[ 21.044101] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014 +[ 21.044639] Workqueue: usb_hub_wq hub_event +[ 21.045100] RIP: 0010:media_create_pad_link+0x2c4/0x2e0 +[ 21.045508] Code: fe e8 20 01 00 00 b8 f4 ff ff ff 48 83 c4 30 5b 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 0f 0b eb e9 0f 0b eb 0a 0f 0b eb 06 <0f> 0b eb 02 0f 0b b8 ea ff ff ff eb d4 66 2e 0f 1f 84 00 00 00 00 +[ 21.046801] RSP: 0018:ffffc9000004b318 EFLAGS: 00010246 +[ 21.047227] RAX: ffff888004e5d458 RBX: 0000000000000000 RCX: ffffffff818fccf1 +[ 21.047719] RDX: 000000000000007b RSI: 0000000000000000 RDI: ffff888004313290 +[ 21.048241] RBP: ffff888004313290 R08: 0001ffffffffffff R09: 0000000000000000 +[ 21.048701] R10: 0000000000000013 R11: 0001888004313290 R12: 0000000000000003 +[ 21.049138] R13: ffff888004313080 R14: ffff888004313080 R15: 0000000000000000 +[ 21.049648] FS: 0000000000000000(0000) GS:ffff88803ec00000(0000) knlGS:0000000000000000 +[ 21.050271] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 21.050688] CR2: 0000592cc27635b0 CR3: 000000000431c000 CR4: 0000000000750ef0 +[ 21.051136] PKRU: 55555554 +[ 21.051331] Call Trace: +[ 21.051480] +[ 21.051611] ? __warn+0xc4/0x210 +[ 21.051861] ? media_create_pad_link+0x2c4/0x2e0 +[ 21.052252] ? report_bug+0x11b/0x1a0 +[ 21.052540] ? trace_hardirqs_on+0x31/0x40 +[ 21.052901] ? handle_bug+0x3d/0x70 +[ 21.053197] ? exc_invalid_op+0x1a/0x50 +[ 21.053511] ? asm_exc_invalid_op+0x1a/0x20 +[ 21.053924] ? media_create_pad_link+0x91/0x2e0 +[ 21.054364] ? media_create_pad_link+0x2c4/0x2e0 +[ 21.054834] ? media_create_pad_link+0x91/0x2e0 +[ 21.055131] ? _raw_spin_unlock+0x1e/0x40 +[ 21.055441] ? __v4l2_device_register_subdev+0x202/0x210 +[ 21.055837] uvc_mc_register_entities+0x358/0x400 +[ 21.056144] uvc_register_chains+0x1fd/0x290 +[ 21.056413] uvc_probe+0x380e/0x3dc0 +[ 21.056676] ? __lock_acquire+0x5aa/0x26e0 +[ 21.056946] ? find_held_lock+0x33/0xa0 +[ 21.057196] ? kernfs_activate+0x70/0x80 +[ 21.057533] ? usb_match_dynamic_id+0x1b/0x70 +[ 21.057811] ? find_held_lock+0x33/0xa0 +[ 21.058047] ? usb_match_dynamic_id+0x55/0x70 +[ 21.058330] ? lock_release+0x124/0x260 +[ 21.058657] ? usb_match_one_id_intf+0xa2/0x100 +[ 21.058997] usb_probe_interface+0x1ba/0x330 +[ 21.059399] really_probe+0x1ba/0x4c0 +[ 21.059662] __driver_probe_device+0xb2/0x180 +[ 21.059944] driver_probe_device+0x5a/0x100 +[ 21.060170] __device_attach_driver+0xe9/0x160 +[ 21.060427] ? __pfx___device_attach_driver+0x10/0x10 +[ 21.060872] bus_for_each_drv+0xa9/0x100 +[ 21.061312] __device_attach+0xed/0x190 +[ 21.061812] device_initial_probe+0xe/0x20 +[ 21.062229] bus_probe_device+0x4d/0xd0 +[ 21.062590] device_add+0x308/0x590 +[ 21.062912] usb_set_configuration+0x7b6/0xaf0 +[ 21.063403] usb_generic_driver_probe+0x36/0x80 +[ 21.063714] usb_probe_device+0x7b/0x130 +[ 21.063936] really_probe+0x1ba/0x4c0 +[ 21.064111] __driver_probe_device+0xb2/0x180 +[ 21.064577] driver_probe_device+0x5a/0x100 +[ 21.065019] __device_attach_driver+0xe9/0x160 +[ 21.065403] ? __pfx___device_attach_driver+0x10/0x10 +[ 21.065820] bus_for_each_drv+0xa9/0x100 +[ 21.066094] __device_attach+0xed/0x190 +[ 21.066535] device_initial_probe+0xe/0x20 +[ 21.066992] bus_probe_device+0x4d/0xd0 +[ 21.067250] device_add+0x308/0x590 +[ 21.067501] usb_new_device+0x347/0x610 +[ 21.067817] hub_event+0x156b/0x1e30 +[ 21.068060] ? process_scheduled_works+0x48b/0xaf0 +[ 21.068337] process_scheduled_works+0x5a3/0xaf0 +[ 21.068668] worker_thread+0x3cf/0x560 +[ 21.068932] ? kthread+0x109/0x1b0 +[ 21.069133] kthread+0x197/0x1b0 +[ 21.069343] ? __pfx_worker_thread+0x10/0x10 +[ 21.069598] ? __pfx_kthread+0x10/0x10 +[ 21.069908] ret_from_fork+0x32/0x40 +[ 21.070169] ? __pfx_kthread+0x10/0x10 +[ 21.070424] ret_from_fork_asm+0x1a/0x30 +[ 21.070737] + +Reported-by: syzbot+0584f746fde3d52b4675@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=0584f746fde3d52b4675 +Reported-by: syzbot+dd320d114deb3f5bb79b@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=dd320d114deb3f5bb79b +Reported-by: Youngjun Lee +Fixes: a3fbc2e6bb05 ("media: mc-entity.c: use WARN_ON, validate link pads") +Cc: stable@vger.kernel.org +Signed-off-by: Thadeu Lima de Souza Cascardo +Co-developed-by: Ricardo Ribalda +Signed-off-by: Ricardo Ribalda +Reviewed-by: Laurent Pinchart +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Signed-off-by: Laurent Pinchart +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/usb/uvc/uvc_driver.c | 66 +++++++++++++++++++----------- + drivers/media/usb/uvc/uvcvideo.h | 2 + + 2 files changed, 44 insertions(+), 24 deletions(-) + +diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c +index c2adc6854c540..34e3f04340a23 100644 +--- a/drivers/media/usb/uvc/uvc_driver.c ++++ b/drivers/media/usb/uvc/uvc_driver.c +@@ -412,6 +412,9 @@ struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id) + { + struct uvc_entity *entity; + ++ if (id == UVC_INVALID_ENTITY_ID) ++ return NULL; ++ + list_for_each_entry(entity, &dev->entities, list) { + if (entity->id == id) + return entity; +@@ -1032,14 +1035,27 @@ static int uvc_parse_streaming(struct uvc_device *dev, + return ret; + } + +-static struct uvc_entity *uvc_alloc_entity(u16 type, u16 id, +- unsigned int num_pads, unsigned int extra_size) ++static struct uvc_entity *uvc_alloc_new_entity(struct uvc_device *dev, u16 type, ++ u16 id, unsigned int num_pads, ++ unsigned int extra_size) + { + struct uvc_entity *entity; + unsigned int num_inputs; + unsigned int size; + unsigned int i; + ++ /* Per UVC 1.1+ spec 3.7.2, the ID should be non-zero. */ ++ if (id == 0) { ++ dev_err(&dev->intf->dev, "Found Unit with invalid ID 0\n"); ++ id = UVC_INVALID_ENTITY_ID; ++ } ++ ++ /* Per UVC 1.1+ spec 3.7.2, the ID is unique. */ ++ if (uvc_entity_by_id(dev, id)) { ++ dev_err(&dev->intf->dev, "Found multiple Units with ID %u\n", id); ++ id = UVC_INVALID_ENTITY_ID; ++ } ++ + extra_size = roundup(extra_size, sizeof(*entity->pads)); + if (num_pads) + num_inputs = type & UVC_TERM_OUTPUT ? num_pads : num_pads - 1; +@@ -1049,7 +1065,7 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u16 id, + + num_inputs; + entity = kzalloc(size, GFP_KERNEL); + if (entity == NULL) +- return NULL; ++ return ERR_PTR(-ENOMEM); + + entity->id = id; + entity->type = type; +@@ -1120,10 +1136,10 @@ static int uvc_parse_vendor_control(struct uvc_device *dev, + break; + } + +- unit = uvc_alloc_entity(UVC_VC_EXTENSION_UNIT, buffer[3], +- p + 1, 2*n); +- if (unit == NULL) +- return -ENOMEM; ++ unit = uvc_alloc_new_entity(dev, UVC_VC_EXTENSION_UNIT, ++ buffer[3], p + 1, 2 * n); ++ if (IS_ERR(unit)) ++ return PTR_ERR(unit); + + memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); + unit->extension.bNumControls = buffer[20]; +@@ -1234,10 +1250,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev, + return -EINVAL; + } + +- term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3], +- 1, n + p); +- if (term == NULL) +- return -ENOMEM; ++ term = uvc_alloc_new_entity(dev, type | UVC_TERM_INPUT, ++ buffer[3], 1, n + p); ++ if (IS_ERR(term)) ++ return PTR_ERR(term); + + if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) { + term->camera.bControlSize = n; +@@ -1293,10 +1309,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev, + return 0; + } + +- term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3], +- 1, 0); +- if (term == NULL) +- return -ENOMEM; ++ term = uvc_alloc_new_entity(dev, type | UVC_TERM_OUTPUT, ++ buffer[3], 1, 0); ++ if (IS_ERR(term)) ++ return PTR_ERR(term); + + memcpy(term->baSourceID, &buffer[7], 1); + +@@ -1317,9 +1333,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev, + return -EINVAL; + } + +- unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0); +- if (unit == NULL) +- return -ENOMEM; ++ unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], ++ p + 1, 0); ++ if (IS_ERR(unit)) ++ return PTR_ERR(unit); + + memcpy(unit->baSourceID, &buffer[5], p); + +@@ -1341,9 +1358,9 @@ static int uvc_parse_standard_control(struct uvc_device *dev, + return -EINVAL; + } + +- unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n); +- if (unit == NULL) +- return -ENOMEM; ++ unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], 2, n); ++ if (IS_ERR(unit)) ++ return PTR_ERR(unit); + + memcpy(unit->baSourceID, &buffer[4], 1); + unit->processing.wMaxMultiplier = +@@ -1372,9 +1389,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev, + return -EINVAL; + } + +- unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n); +- if (unit == NULL) +- return -ENOMEM; ++ unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], ++ p + 1, n); ++ if (IS_ERR(unit)) ++ return PTR_ERR(unit); + + memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); + unit->extension.bNumControls = buffer[20]; +diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h +index a83995276170b..46ec07ef1ef5a 100644 +--- a/drivers/media/usb/uvc/uvcvideo.h ++++ b/drivers/media/usb/uvc/uvcvideo.h +@@ -170,6 +170,8 @@ + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} + + ++#define UVC_INVALID_ENTITY_ID 0xffff ++ + /* ------------------------------------------------------------------------ + * Driver specific constants. + */ +-- +2.53.0 + diff --git a/queue-5.10/media-uvcvideo-use-heuristic-to-find-stream-entity.patch b/queue-5.10/media-uvcvideo-use-heuristic-to-find-stream-entity.patch new file mode 100644 index 0000000000..37b3562e38 --- /dev/null +++ b/queue-5.10/media-uvcvideo-use-heuristic-to-find-stream-entity.patch @@ -0,0 +1,77 @@ +From dd8f8e5b1d5789d2f2b8ddd71cd77241a9cb831c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Apr 2026 11:01:13 +0000 +Subject: media: uvcvideo: Use heuristic to find stream entity + +From: Ricardo Ribalda + +[ Upstream commit 758dbc756aad429da11c569c0d067f7fd032bcf7 ] + +Some devices, like the Grandstream GUV3100 webcam, have an invalid UVC +descriptor where multiple entities share the same ID, this is invalid +and makes it impossible to make a proper entity tree without heuristics. + +We have recently introduced a change in the way that we handle invalid +entities that has caused a regression on broken devices. + +Implement a new heuristic to handle these devices properly. + +Reported-by: Angel4005 +Closes: https://lore.kernel.org/linux-media/CAOzBiVuS7ygUjjhCbyWg-KiNx+HFTYnqH5+GJhd6cYsNLT=DaA@mail.gmail.com/ +Fixes: 0e2ee70291e6 ("media: uvcvideo: Mark invalid entities with id UVC_INVALID_ENTITY_ID") +Cc: stable@vger.kernel.org +Signed-off-by: Ricardo Ribalda +Reviewed-by: Hans de Goede +Signed-off-by: Hans Verkuil +Tested-by: Ron Economos +Tested-by: Pavel Machek (CIP) +Tested-by: Brett A C Sheffield +Tested-by: Mark Brown +Tested-by: Barry K. Nathan +Tested-by: Peter Schneider +Tested-by: Francesco Dolcini +Tested-by: Shuah Khan +Tested-by: Jon Hunter +Tested-by: Florian Fainelli +Tested-by: Miguel Ojeda +Tested-by: Vijayendra Suman +Signed-off-by: Sasha Levin +--- + drivers/media/usb/uvc/uvc_driver.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c +index 34e3f04340a23..20a18caf77176 100644 +--- a/drivers/media/usb/uvc/uvc_driver.c ++++ b/drivers/media/usb/uvc/uvc_driver.c +@@ -442,13 +442,26 @@ static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev, + + static struct uvc_streaming *uvc_stream_by_id(struct uvc_device *dev, int id) + { +- struct uvc_streaming *stream; ++ struct uvc_streaming *stream, *last_stream; ++ unsigned int count = 0; + + list_for_each_entry(stream, &dev->streams, list) { ++ count += 1; ++ last_stream = stream; + if (stream->header.bTerminalLink == id) + return stream; + } + ++ /* ++ * If the streaming entity is referenced by an invalid ID, notify the ++ * user and use heuristics to guess the correct entity. ++ */ ++ if (count == 1 && id == UVC_INVALID_ENTITY_ID) { ++ dev_warn(&dev->intf->dev, ++ "UVC non compliance: Invalid USB header. The streaming entity has an invalid ID, guessing the correct one."); ++ return last_stream; ++ } ++ + return NULL; + } + +-- +2.53.0 + diff --git a/queue-5.10/revert-wifi-cfg80211-stop-nan-and-p2p-in-cfg80211_le.patch b/queue-5.10/revert-wifi-cfg80211-stop-nan-and-p2p-in-cfg80211_le.patch new file mode 100644 index 0000000000..206445241b --- /dev/null +++ b/queue-5.10/revert-wifi-cfg80211-stop-nan-and-p2p-in-cfg80211_le.patch @@ -0,0 +1,38 @@ +From ea54024c88214bd0bb1a19cebe70e49dce387907 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Apr 2026 12:03:49 +0800 +Subject: Revert "wifi: cfg80211: stop NAN and P2P in cfg80211_leave" + +From: Guocai He + +This reverts commit d91240f24e831d3bd36954599ada6b456fb1bd0a which is commit +e1696c8bd0056bc1a5f7766f58ac333adc203e8a upstream. + +The reverted patch introduced a deadlock. The locking situation in mainline is +totally different, so it is incorrect to directly backport the commit from mainline. + +Signed-off-by: Guocai He +Signed-off-by: Sasha Levin +--- + net/wireless/core.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 019f9767eda5f..c6c5dd4e35209 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -1208,10 +1208,8 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev, + /* must be handled by mac80211/driver, has no APIs */ + break; + case NL80211_IFTYPE_P2P_DEVICE: +- cfg80211_stop_p2p_device(rdev, wdev); +- break; + case NL80211_IFTYPE_NAN: +- cfg80211_stop_nan(rdev, wdev); ++ /* cannot happen, has no netdev */ + break; + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_MONITOR: +-- +2.53.0 + diff --git a/queue-5.10/rxrpc-fix-call-removal-to-use-rcu-safe-deletion.patch b/queue-5.10/rxrpc-fix-call-removal-to-use-rcu-safe-deletion.patch new file mode 100644 index 0000000000..65dba79bbc --- /dev/null +++ b/queue-5.10/rxrpc-fix-call-removal-to-use-rcu-safe-deletion.patch @@ -0,0 +1,94 @@ +From a73066cd0f40f18f65e1b415c723b003f7898710 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Apr 2026 07:22:02 -0400 +Subject: rxrpc: Fix call removal to use RCU safe deletion + +From: David Howells + +[ Upstream commit 146d4ab94cf129ee06cd467cb5c71368a6b5bad6 ] + +Fix 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. + +Fixes: 2baec2c3f854 ("rxrpc: Support network namespacing") +Closes: https://sashiko.dev/#/patchset/20260319150150.4189381-1-dhowells%40redhat.com +Signed-off-by: David Howells +cc: Marc Dionne +cc: Jeffrey Altman +cc: Linus Torvalds +cc: Simon Horman +cc: linux-afs@lists.infradead.org +cc: stable@kernel.org +Link: https://patch.msgid.link/20260408121252.2249051-5-dhowells@redhat.com +Signed-off-by: Jakub Kicinski +[ adapted spin_lock/spin_unlock to write_lock/write_unlock ] +Signed-off-by: Sasha Levin +--- + net/rxrpc/call_object.c | 22 ++++++++-------------- + 1 file changed, 8 insertions(+), 14 deletions(-) + +diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c +index 10dad2834d5b6..2240e93b0048a 100644 +--- a/net/rxrpc/call_object.c ++++ b/net/rxrpc/call_object.c +@@ -634,11 +634,9 @@ void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace op) + _debug("call %d dead", call->debug_id); + ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); + +- if (!list_empty(&call->link)) { +- write_lock(&rxnet->call_lock); +- list_del_init(&call->link); +- write_unlock(&rxnet->call_lock); +- } ++ write_lock(&rxnet->call_lock); ++ list_del_rcu(&call->link); ++ write_unlock(&rxnet->call_lock); + + rxrpc_cleanup_call(call); + } +@@ -709,24 +707,20 @@ void rxrpc_destroy_all_calls(struct rxrpc_net *rxnet) + _enter(""); + + if (!list_empty(&rxnet->calls)) { +- write_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); ++ write_lock(&rxnet->call_lock); + ++ list_for_each_entry(call, &rxnet->calls, link) { + rxrpc_see_call(call); +- list_del_init(&call->link); + + pr_err("Call %p still in use (%d,%s,%lx,%lx)!\n", + call, refcount_read(&call->ref), + rxrpc_call_states[call->state], + call->flags, call->events); + +- write_unlock(&rxnet->call_lock); +- cond_resched(); +- write_lock(&rxnet->call_lock); ++ if (++shown >= 10) ++ break; + } + + write_unlock(&rxnet->call_lock); +-- +2.53.0 + diff --git a/queue-5.10/rxrpc-proc-size-address-buffers-for-pispc-output.patch b/queue-5.10/rxrpc-proc-size-address-buffers-for-pispc-output.patch new file mode 100644 index 0000000000..bec5939ed3 --- /dev/null +++ b/queue-5.10/rxrpc-proc-size-address-buffers-for-pispc-output.patch @@ -0,0 +1,155 @@ +From 8d069ea2fb51b997545f0746ea0a3143f4cd734c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Apr 2026 11:26:31 -0400 +Subject: rxrpc: proc: size address buffers for %pISpc output + +From: Pengpeng Hou + +[ Upstream commit a44ce6aa2efb61fe44f2cfab72bb01544bbca272 ] + +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 + +Fixes: 75b54cb57ca3 ("rxrpc: Add IPv6 support") +Signed-off-by: Pengpeng Hou +Signed-off-by: David Howells +cc: Marc Dionne +cc: Anderson Nascimento +cc: Simon Horman +cc: linux-afs@lists.infradead.org +cc: stable@kernel.org +Link: https://patch.msgid.link/20260408121252.2249051-22-dhowells@redhat.com +Signed-off-by: Jakub Kicinski +[ adapted address accessors and variable declarations ] +Signed-off-by: Sasha Levin +--- + net/rxrpc/proc.c | 26 +++++++++++++++----------- + 1 file changed, 15 insertions(+), 11 deletions(-) + +diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c +index 8967201fd8e54..67553dfe6a3e4 100644 +--- a/net/rxrpc/proc.c ++++ b/net/rxrpc/proc.c +@@ -10,6 +10,10 @@ + #include + #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] = "Client ", +@@ -61,7 +65,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) + struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); + unsigned long timeout = 0; + rxrpc_seq_t tx_hard_ack, rx_hard_ack; +- char lbuff[50], rbuff[50]; ++ char lbuff[RXRPC_PROC_ADDRBUF_SIZE], rbuff[RXRPC_PROC_ADDRBUF_SIZE]; + + if (v == &rxnet->calls) { + seq_puts(seq, +@@ -78,7 +82,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) + if (rx) { + local = READ_ONCE(rx->local); + if (local) +- sprintf(lbuff, "%pISpc", &local->srx.transport); ++ scnprintf(lbuff, sizeof(lbuff), "%pISpc", &local->srx.transport); + else + strcpy(lbuff, "no_local"); + } else { +@@ -87,7 +91,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) + + peer = call->peer; + if (peer) +- sprintf(rbuff, "%pISpc", &peer->srx.transport); ++ scnprintf(rbuff, sizeof(rbuff), "%pISpc", &peer->srx.transport); + else + strcpy(rbuff, "no_connection"); + +@@ -158,7 +162,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)); +- 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, +@@ -177,9 +181,9 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v) + goto print; + } + +- sprintf(lbuff, "%pISpc", &conn->params.local->srx.transport); ++ scnprintf(lbuff, sizeof(lbuff), "%pISpc", &conn->params.local->srx.transport); + +- sprintf(rbuff, "%pISpc", &conn->params.peer->srx.transport); ++ scnprintf(rbuff, sizeof(rbuff), "%pISpc", &conn->params.peer->srx.transport); + print: + seq_printf(seq, + "UDP %-47.47s %-47.47s %4x %08x %s %3u" +@@ -216,7 +220,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, +@@ -229,9 +233,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, +@@ -341,7 +345,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, +@@ -352,7 +356,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\n", +-- +2.53.0 + diff --git a/queue-5.10/series b/queue-5.10/series index 6efebd16b7..1792d99f91 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -65,3 +65,10 @@ media-vidtv-fix-null-pointer-dereference-in-vidtv_channel_pmt_match_sections.pat ocfs2-fix-use-after-free-in-ocfs2_fault-when-vm_fault_retry.patch ocfs2-handle-invalid-dinode-in-ocfs2_group_extend.patch kvm-sev-drop-warn-on-large-size-for-kvm_memory_encrypt_reg_region.patch +acpi-property-constify-stubs-for-config_acpi-n-case.patch +rxrpc-fix-call-removal-to-use-rcu-safe-deletion.patch +rxrpc-proc-size-address-buffers-for-pispc-output.patch +revert-wifi-cfg80211-stop-nan-and-p2p-in-cfg80211_le.patch +media-uvcvideo-allow-extra-entities.patch +media-uvcvideo-mark-invalid-entities-with-id-uvc_inv.patch +media-uvcvideo-use-heuristic-to-find-stream-entity.patch diff --git a/queue-5.15/fsl-mc-use-driver_set_override-instead-of-open-codin.patch b/queue-5.15/fsl-mc-use-driver_set_override-instead-of-open-codin.patch new file mode 100644 index 0000000000..bb0fb2e70d --- /dev/null +++ b/queue-5.15/fsl-mc-use-driver_set_override-instead-of-open-codin.patch @@ -0,0 +1,89 @@ +From 31fb79362a0713e2056addc61df6760761a9e2af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Apr 2022 13:34:26 +0200 +Subject: fsl-mc: Use driver_set_override() instead of open-coding + +From: Krzysztof Kozlowski + +[ Upstream commit 5688f212e98a2469583a067fa5da4312ddc4e357 ] + +Use a helper to set driver_override to reduce the amount of duplicated +code. Make the driver_override field const char, because it is not +modified by the core and it matches other subsystems. + +Signed-off-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20220419113435.246203-4-krzysztof.kozlowski@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/bus/fsl-mc/fsl-mc-bus.c | 25 ++++--------------------- + include/linux/fsl/mc.h | 6 ++++-- + 2 files changed, 8 insertions(+), 23 deletions(-) + +diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c +index bd086f8c4faa4..f958d6cfe4793 100644 +--- a/drivers/bus/fsl-mc/fsl-mc-bus.c ++++ b/drivers/bus/fsl-mc/fsl-mc-bus.c +@@ -166,31 +166,14 @@ static ssize_t driver_override_store(struct device *dev, + const char *buf, size_t count) + { + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); +- char *driver_override, *old = mc_dev->driver_override; +- char *cp; ++ int ret; + + if (WARN_ON(dev->bus != &fsl_mc_bus_type)) + return -EINVAL; + +- if (count >= (PAGE_SIZE - 1)) +- return -EINVAL; +- +- driver_override = kstrndup(buf, count, GFP_KERNEL); +- if (!driver_override) +- return -ENOMEM; +- +- cp = strchr(driver_override, '\n'); +- if (cp) +- *cp = '\0'; +- +- if (strlen(driver_override)) { +- mc_dev->driver_override = driver_override; +- } else { +- kfree(driver_override); +- mc_dev->driver_override = NULL; +- } +- +- kfree(old); ++ ret = driver_set_override(dev, &mc_dev->driver_override, buf, count); ++ if (ret) ++ return ret; + + return count; + } +diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h +index 30ece3ae6df7b..bfc062ff8b42c 100644 +--- a/include/linux/fsl/mc.h ++++ b/include/linux/fsl/mc.h +@@ -170,7 +170,9 @@ struct fsl_mc_obj_desc { + * @regions: pointer to array of MMIO region entries + * @irqs: pointer to array of pointers to interrupts allocated to this device + * @resource: generic resource associated with this MC object device, if any. +- * @driver_override: driver name to force a match ++ * @driver_override: driver name to force a match; do not set directly, ++ * because core frees it; use driver_set_override() to ++ * set or clear it. + * + * Generic device object for MC object devices that are "attached" to a + * MC bus. +@@ -204,7 +206,7 @@ struct fsl_mc_device { + struct fsl_mc_device_irq **irqs; + struct fsl_mc_resource *resource; + struct device_link *consumer_link; +- char *driver_override; ++ const char *driver_override; + }; + + #define to_fsl_mc_device(_dev) \ +-- +2.53.0 + diff --git a/queue-5.15/nf_tables-nft_dynset-fix-possible-stateful-expressio.patch b/queue-5.15/nf_tables-nft_dynset-fix-possible-stateful-expressio.patch new file mode 100644 index 0000000000..9890f021af --- /dev/null +++ b/queue-5.15/nf_tables-nft_dynset-fix-possible-stateful-expressio.patch @@ -0,0 +1,109 @@ +From c334fb7b685f6cd2aea88b245d99bfd02bbabbf4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Apr 2026 16:22:42 +0800 +Subject: nf_tables: nft_dynset: fix possible stateful expression memleak in + error path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pablo Neira Ayuso + +[ Upstream commit 0548a13b5a145b16e4da0628b5936baf35f51b43 ] + +If cloning the second stateful expression in the element via GFP_ATOMIC +fails, then the first stateful expression remains in place without being +released. + +   unreferenced object (percpu) 0x607b97e9cab8 (size 16): +     comm "softirq", pid 0, jiffies 4294931867 +     hex dump (first 16 bytes on cpu 3): +       00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +     backtrace (crc 0): +       pcpu_alloc_noprof+0x453/0xd80 +       nft_counter_clone+0x9c/0x190 [nf_tables] +       nft_expr_clone+0x8f/0x1b0 [nf_tables] +       nft_dynset_new+0x2cb/0x5f0 [nf_tables] +       nft_rhash_update+0x236/0x11c0 [nf_tables] +       nft_dynset_eval+0x11f/0x670 [nf_tables] +       nft_do_chain+0x253/0x1700 [nf_tables] +       nft_do_chain_ipv4+0x18d/0x270 [nf_tables] +       nf_hook_slow+0xaa/0x1e0 +       ip_local_deliver+0x209/0x330 + +Fixes: 563125a73ac3 ("netfilter: nftables: generalize set extension to support for several expressions") +Reported-by: Gurpreet Shergill +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Florian Westphal +[ Minor conflict resolved. ] +Signed-off-by: Li hongliang <1468888505@139.com> +Signed-off-by: Sasha Levin +--- + include/net/netfilter/nf_tables.h | 2 ++ + net/netfilter/nf_tables_api.c | 4 ++-- + net/netfilter/nft_dynset.c | 10 +++++++++- + 3 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h +index 9f68155e054cf..2b977d5d6f30f 100644 +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -821,6 +821,8 @@ void *nft_set_elem_init(const struct nft_set *set, + u64 timeout, u64 expiration, gfp_t gfp); + int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set, + struct nft_expr *expr_array[]); ++void nft_set_elem_expr_destroy(const struct nft_ctx *ctx, ++ struct nft_set_elem_expr *elem_expr); + void nft_set_elem_destroy(const struct nft_set *set, void *elem, + bool destroy_expr); + void nf_tables_set_elem_destroy(const struct nft_ctx *ctx, +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 53d7dd39a95bc..623b776bf7926 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -5919,8 +5919,8 @@ static void __nft_set_elem_expr_destroy(const struct nft_ctx *ctx, + } + } + +-static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx, +- struct nft_set_elem_expr *elem_expr) ++void nft_set_elem_expr_destroy(const struct nft_ctx *ctx, ++ struct nft_set_elem_expr *elem_expr) + { + struct nft_expr *expr; + u32 size; +diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c +index ecdd4a60db9c5..673c5e6a3e8d6 100644 +--- a/net/netfilter/nft_dynset.c ++++ b/net/netfilter/nft_dynset.c +@@ -30,18 +30,26 @@ static int nft_dynset_expr_setup(const struct nft_dynset *priv, + const struct nft_set_ext *ext) + { + struct nft_set_elem_expr *elem_expr = nft_set_ext_expr(ext); ++ struct nft_ctx ctx = { ++ .net = read_pnet(&priv->set->net), ++ .family = priv->set->table->family, ++ }; + struct nft_expr *expr; + int i; + + for (i = 0; i < priv->num_exprs; i++) { + expr = nft_setelem_expr_at(elem_expr, elem_expr->size); + if (nft_expr_clone(expr, priv->expr_array[i], GFP_ATOMIC) < 0) +- return -1; ++ goto err_out; + + elem_expr->size += priv->expr_array[i]->ops->size; + } + + return 0; ++err_out: ++ nft_set_elem_expr_destroy(&ctx, elem_expr); ++ ++ return -1; + } + + static void *nft_dynset_new(struct nft_set *set, const struct nft_expr *expr, +-- +2.53.0 + diff --git a/queue-5.15/rxrpc-proc-size-address-buffers-for-pispc-output.patch b/queue-5.15/rxrpc-proc-size-address-buffers-for-pispc-output.patch new file mode 100644 index 0000000000..1340ada7e5 --- /dev/null +++ b/queue-5.15/rxrpc-proc-size-address-buffers-for-pispc-output.patch @@ -0,0 +1,155 @@ +From d18f5250b5d1dfc53fe76319c98875a7fcbb4853 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Apr 2026 11:11:03 -0400 +Subject: rxrpc: proc: size address buffers for %pISpc output + +From: Pengpeng Hou + +[ Upstream commit a44ce6aa2efb61fe44f2cfab72bb01544bbca272 ] + +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 + +Fixes: 75b54cb57ca3 ("rxrpc: Add IPv6 support") +Signed-off-by: Pengpeng Hou +Signed-off-by: David Howells +cc: Marc Dionne +cc: Anderson Nascimento +cc: Simon Horman +cc: linux-afs@lists.infradead.org +cc: stable@kernel.org +Link: https://patch.msgid.link/20260408121252.2249051-22-dhowells@redhat.com +Signed-off-by: Jakub Kicinski +[ adapted address accessors and variable declarations ] +Signed-off-by: Sasha Levin +--- + net/rxrpc/proc.c | 26 +++++++++++++++----------- + 1 file changed, 15 insertions(+), 11 deletions(-) + +diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c +index 245418943e01c..47d36554ad311 100644 +--- a/net/rxrpc/proc.c ++++ b/net/rxrpc/proc.c +@@ -10,6 +10,10 @@ + #include + #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] = "Client ", +@@ -55,7 +59,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) + struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); + unsigned long timeout = 0; + rxrpc_seq_t tx_hard_ack, rx_hard_ack; +- char lbuff[50], rbuff[50]; ++ char lbuff[RXRPC_PROC_ADDRBUF_SIZE], rbuff[RXRPC_PROC_ADDRBUF_SIZE]; + + if (v == &rxnet->calls) { + seq_puts(seq, +@@ -72,7 +76,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) + if (rx) { + local = READ_ONCE(rx->local); + if (local) +- sprintf(lbuff, "%pISpc", &local->srx.transport); ++ scnprintf(lbuff, sizeof(lbuff), "%pISpc", &local->srx.transport); + else + strcpy(lbuff, "no_local"); + } else { +@@ -81,7 +85,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) + + peer = call->peer; + if (peer) +- sprintf(rbuff, "%pISpc", &peer->srx.transport); ++ scnprintf(rbuff, sizeof(rbuff), "%pISpc", &peer->srx.transport); + else + strcpy(rbuff, "no_connection"); + +@@ -152,7 +156,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)); +- 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, +@@ -171,9 +175,9 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v) + goto print; + } + +- sprintf(lbuff, "%pISpc", &conn->params.local->srx.transport); ++ scnprintf(lbuff, sizeof(lbuff), "%pISpc", &conn->params.local->srx.transport); + +- sprintf(rbuff, "%pISpc", &conn->params.peer->srx.transport); ++ scnprintf(rbuff, sizeof(rbuff), "%pISpc", &conn->params.peer->srx.transport); + print: + seq_printf(seq, + "UDP %-47.47s %-47.47s %4x %08x %s %3u" +@@ -210,7 +214,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, +@@ -223,9 +227,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, +@@ -335,7 +339,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, +@@ -346,7 +350,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\n", +-- +2.53.0 + diff --git a/queue-5.15/series b/queue-5.15/series index 36b1c2b16a..58d4f32452 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -76,3 +76,7 @@ media-vidtv-fix-null-pointer-dereference-in-vidtv_channel_pmt_match_sections.pat ocfs2-fix-use-after-free-in-ocfs2_fault-when-vm_fault_retry.patch ocfs2-handle-invalid-dinode-in-ocfs2_group_extend.patch kvm-sev-drop-warn-on-large-size-for-kvm_memory_encrypt_reg_region.patch +fsl-mc-use-driver_set_override-instead-of-open-codin.patch +smb-client-fix-potential-uaf-in-smb2_is_valid_oplock.patch +nf_tables-nft_dynset-fix-possible-stateful-expressio.patch +rxrpc-proc-size-address-buffers-for-pispc-output.patch diff --git a/queue-5.15/smb-client-fix-potential-uaf-in-smb2_is_valid_oplock.patch b/queue-5.15/smb-client-fix-potential-uaf-in-smb2_is_valid_oplock.patch new file mode 100644 index 0000000000..1ab09125ec --- /dev/null +++ b/queue-5.15/smb-client-fix-potential-uaf-in-smb2_is_valid_oplock.patch @@ -0,0 +1,38 @@ +From 681a79a5250a188817d255cda1a4882088d942af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Apr 2026 14:34:26 +0800 +Subject: smb: client: fix potential UAF in smb2_is_valid_oplock_break() + +From: Paulo Alcantara + +[ Upstream commit 22863485a4626ec6ecf297f4cc0aef709bc862e4 ] + +Skip sessions that are being teared down (status == SES_EXITING) to +avoid UAF. + +Cc: stable@vger.kernel.org +Signed-off-by: Paulo Alcantara (Red Hat) +Signed-off-by: Steve French +[ Appropriate path used. ] +Signed-off-by: Robert Garcia +Signed-off-by: Sasha Levin +--- + fs/cifs/smb2misc.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c +index b84e682b4cae2..da32b3f6686bd 100644 +--- a/fs/cifs/smb2misc.c ++++ b/fs/cifs/smb2misc.c +@@ -679,6 +679,8 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) + /* look up tcon based on tid & uid */ + spin_lock(&cifs_tcp_ses_lock); + list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { ++ if (cifs_ses_exiting(ses)) ++ continue; + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { + + spin_lock(&tcon->open_file_lock); +-- +2.53.0 + diff --git a/queue-6.1/alsa-usb-audio-fix-race-condition-to-uaf-in-snd_usbm.patch b/queue-6.1/alsa-usb-audio-fix-race-condition-to-uaf-in-snd_usbm.patch new file mode 100644 index 0000000000..5125b846a4 --- /dev/null +++ b/queue-6.1/alsa-usb-audio-fix-race-condition-to-uaf-in-snd_usbm.patch @@ -0,0 +1,60 @@ +From 69f8917d03dc834987a00f2233eb490e1a7518a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Apr 2026 16:45:16 +0800 +Subject: ALSA: usb-audio: fix race condition to UAF in snd_usbmidi_free + +From: Jeongjun Park + +[ Upstream commit 9f2c0ac1423d5f267e7f1d1940780fc764b0fee3 ] + +The previous commit 0718a78f6a9f ("ALSA: usb-audio: Kill timer properly at +removal") patched a UAF issue caused by the error timer. + +However, because the error timer kill added in this patch occurs after the +endpoint delete, a race condition to UAF still occurs, albeit rarely. + +Additionally, since kill-cleanup for urb is also missing, freed memory can +be accessed in interrupt context related to urb, which can cause UAF. + +Therefore, to prevent this, error timer and urb must be killed before +freeing the heap memory. + +Cc: +Reported-by: syzbot+f02665daa2abeef4a947@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=f02665daa2abeef4a947 +Fixes: 0718a78f6a9f ("ALSA: usb-audio: Kill timer properly at removal") +Signed-off-by: Jeongjun Park +Signed-off-by: Takashi Iwai +Signed-off-by: Wenshan Lan +Signed-off-by: Sasha Levin +--- + sound/usb/midi.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/sound/usb/midi.c b/sound/usb/midi.c +index 08dd0f0b19a3f..49a11e517e785 100644 +--- a/sound/usb/midi.c ++++ b/sound/usb/midi.c +@@ -1522,15 +1522,14 @@ static void snd_usbmidi_free(struct snd_usb_midi *umidi) + { + int i; + ++ if (!umidi->disconnected) ++ snd_usbmidi_disconnect(&umidi->list); ++ + for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { + struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i]; +- if (ep->out) +- snd_usbmidi_out_endpoint_delete(ep->out); +- if (ep->in) +- snd_usbmidi_in_endpoint_delete(ep->in); ++ kfree(ep->out); + } + mutex_destroy(&umidi->mutex); +- timer_shutdown_sync(&umidi->error_timer); + kfree(umidi); + } + +-- +2.53.0 + diff --git a/queue-6.1/bonding-check-xdp-prog-when-set-bond-mode.patch b/queue-6.1/bonding-check-xdp-prog-when-set-bond-mode.patch new file mode 100644 index 0000000000..2ba93f052a --- /dev/null +++ b/queue-6.1/bonding-check-xdp-prog-when-set-bond-mode.patch @@ -0,0 +1,140 @@ +From 6c47345858e0aae8b098f3f7d82691d0fdc789a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Apr 2026 17:12:32 +0800 +Subject: bonding: check xdp prog when set bond mode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Wang Liang + +[ Upstream commit 094ee6017ea09c11d6af187935a949df32803ce0 ] + +Following operations can trigger a warning[1]: + + ip netns add ns1 + ip netns exec ns1 ip link add bond0 type bond mode balance-rr + ip netns exec ns1 ip link set dev bond0 xdp obj af_xdp_kern.o sec xdp + ip netns exec ns1 ip link set bond0 type bond mode broadcast + ip netns del ns1 + +When delete the namespace, dev_xdp_uninstall() is called to remove xdp +program on bond dev, and bond_xdp_set() will check the bond mode. If bond +mode is changed after attaching xdp program, the warning may occur. + +Some bond modes (broadcast, etc.) do not support native xdp. Set bond mode +with xdp program attached is not good. Add check for xdp program when set +bond mode. + + [1] + ------------[ cut here ]------------ + WARNING: CPU: 0 PID: 11 at net/core/dev.c:9912 unregister_netdevice_many_notify+0x8d9/0x930 + Modules linked in: + CPU: 0 UID: 0 PID: 11 Comm: kworker/u4:0 Not tainted 6.14.0-rc4 #107 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.15.0-0-g2dd4b9b3f840-prebuilt.qemu.org 04/01/2014 + Workqueue: netns cleanup_net + RIP: 0010:unregister_netdevice_many_notify+0x8d9/0x930 + Code: 00 00 48 c7 c6 6f e3 a2 82 48 c7 c7 d0 b3 96 82 e8 9c 10 3e ... + RSP: 0018:ffffc90000063d80 EFLAGS: 00000282 + RAX: 00000000ffffffa1 RBX: ffff888004959000 RCX: 00000000ffffdfff + RDX: 0000000000000000 RSI: 00000000ffffffea RDI: ffffc90000063b48 + RBP: ffffc90000063e28 R08: ffffffff82d39b28 R09: 0000000000009ffb + R10: 0000000000000175 R11: ffffffff82d09b40 R12: ffff8880049598e8 + R13: 0000000000000001 R14: dead000000000100 R15: ffffc90000045000 + FS: 0000000000000000(0000) GS:ffff888007a00000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 000000000d406b60 CR3: 000000000483e000 CR4: 00000000000006f0 + Call Trace: + + ? __warn+0x83/0x130 + ? unregister_netdevice_many_notify+0x8d9/0x930 + ? report_bug+0x18e/0x1a0 + ? handle_bug+0x54/0x90 + ? exc_invalid_op+0x18/0x70 + ? asm_exc_invalid_op+0x1a/0x20 + ? unregister_netdevice_many_notify+0x8d9/0x930 + ? bond_net_exit_batch_rtnl+0x5c/0x90 + cleanup_net+0x237/0x3d0 + process_one_work+0x163/0x390 + worker_thread+0x293/0x3b0 + ? __pfx_worker_thread+0x10/0x10 + kthread+0xec/0x1e0 + ? __pfx_kthread+0x10/0x10 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x2f/0x50 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + ---[ end trace 0000000000000000 ]--- + +Fixes: 9e2ee5c7e7c3 ("net, bonding: Add XDP support to the bonding driver") +Signed-off-by: Wang Liang +Acked-by: Jussi Maki +Reviewed-by: Nikolay Aleksandrov +Reviewed-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20250321044852.1086551-1-wangliang74@huawei.com +Signed-off-by: Jakub Kicinski +[ Ignore changes in bond_xdp_set_features(), it was introduced to kernel +in commit:cb9e6e584d58 ("bonding: add xdp_features support") since 6.4 ] +Signed-off-by: Rajani Kantha <681739313@139.com> +Signed-off-by: Sasha Levin +--- + drivers/net/bonding/bond_main.c | 6 +++--- + drivers/net/bonding/bond_options.c | 3 +++ + include/net/bonding.h | 1 + + 3 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index c6b4f681c70d1..14e7439717a3d 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -320,9 +320,9 @@ bool bond_sk_check(struct bonding *bond) + } + } + +-static bool bond_xdp_check(struct bonding *bond) ++bool bond_xdp_check(struct bonding *bond, int mode) + { +- switch (BOND_MODE(bond)) { ++ switch (mode) { + case BOND_MODE_ROUNDROBIN: + case BOND_MODE_ACTIVEBACKUP: + return true; +@@ -5636,7 +5636,7 @@ static int bond_xdp_set(struct net_device *dev, struct bpf_prog *prog, + + ASSERT_RTNL(); + +- if (!bond_xdp_check(bond)) { ++ if (!bond_xdp_check(bond, BOND_MODE(bond))) { + BOND_NL_ERR(dev, extack, + "No native XDP support for the current bonding mode"); + return -EOPNOTSUPP; +diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c +index 9473e76c6dc9d..62b5d29e6db6c 100644 +--- a/drivers/net/bonding/bond_options.c ++++ b/drivers/net/bonding/bond_options.c +@@ -881,6 +881,9 @@ static bool bond_set_tls_features(struct bonding *bond) + static int bond_option_mode_set(struct bonding *bond, + const struct bond_opt_value *newval) + { ++ if (bond->xdp_prog && !bond_xdp_check(bond, newval->value)) ++ return -EOPNOTSUPP; ++ + if (!bond_mode_uses_arp(newval->value)) { + if (bond->params.arp_interval) { + netdev_dbg(bond->dev, "%s mode is incompatible with arp monitoring, start mii monitoring\n", +diff --git a/include/net/bonding.h b/include/net/bonding.h +index bdfbe77c18420..0a84a63d5e324 100644 +--- a/include/net/bonding.h ++++ b/include/net/bonding.h +@@ -701,6 +701,7 @@ void bond_debug_register(struct bonding *bond); + void bond_debug_unregister(struct bonding *bond); + void bond_debug_reregister(struct bonding *bond); + const char *bond_mode_name(int mode); ++bool bond_xdp_check(struct bonding *bond, int mode); + void bond_setup(struct net_device *bond_dev); + unsigned int bond_get_num_tx_queues(void); + int bond_netlink_init(void); +-- +2.53.0 + diff --git a/queue-6.1/bonding-return-detailed-error-when-loading-native-xd.patch b/queue-6.1/bonding-return-detailed-error-when-loading-native-xd.patch new file mode 100644 index 0000000000..c8518d3783 --- /dev/null +++ b/queue-6.1/bonding-return-detailed-error-when-loading-native-xd.patch @@ -0,0 +1,49 @@ +From dffbddeef1002fef6c54aaa9642255f98470322c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Apr 2026 17:12:31 +0800 +Subject: bonding: return detailed error when loading native XDP fails +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Hangbin Liu + +[ Upstream commit 22ccb684c1cae37411450e6e86a379cd3c29cb8f ] + +Bonding only supports native XDP for specific modes, which can lead to +confusion for users regarding why XDP loads successfully at times and +fails at others. This patch enhances error handling by returning detailed +error messages, providing users with clearer insights into the specific +reasons for the failure when loading native XDP. + +Reviewed-by: Nikolay Aleksandrov +Reviewed-by: Toke Høiland-Jørgensen +Signed-off-by: Hangbin Liu +Link: https://patch.msgid.link/20241021031211.814-2-liuhangbin@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Rajani Kantha <681739313@139.com> +Signed-off-by: Sasha Levin +--- + drivers/net/bonding/bond_main.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 7fe7485fbb160..c6b4f681c70d1 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -5636,8 +5636,11 @@ static int bond_xdp_set(struct net_device *dev, struct bpf_prog *prog, + + ASSERT_RTNL(); + +- if (!bond_xdp_check(bond)) ++ if (!bond_xdp_check(bond)) { ++ BOND_NL_ERR(dev, extack, ++ "No native XDP support for the current bonding mode"); + return -EOPNOTSUPP; ++ } + + old_prog = bond->xdp_prog; + bond->xdp_prog = prog; +-- +2.53.0 + diff --git a/queue-6.1/drm-amdgpu-remove-two-invalid-bug_on-s.patch b/queue-6.1/drm-amdgpu-remove-two-invalid-bug_on-s.patch new file mode 100644 index 0000000000..469b69d7e7 --- /dev/null +++ b/queue-6.1/drm-amdgpu-remove-two-invalid-bug_on-s.patch @@ -0,0 +1,41 @@ +From 988116f568d6a664acdd180bdd48a0d545978604 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Apr 2026 15:40:10 +0800 +Subject: drm/amdgpu: remove two invalid BUG_ON()s +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Christian König + +[ Upstream commit 5d55ed19d4190d2c210ac05ac7a53f800a8c6fe5 ] + +Those can be triggered trivially by userspace. + +Signed-off-by: Christian König +Reviewed-by: Alex Deucher +Acked-by: Timur Kristóf +Signed-off-by: Alex Deucher +[ Modified to gfx_v11_0.c only. ] +Signed-off-by: Robert Garcia +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +index 37f793f7d4d24..6e3a32779168b 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +@@ -5380,8 +5380,6 @@ static void gfx_v11_0_ring_emit_ib_gfx(struct amdgpu_ring *ring, + unsigned vmid = AMDGPU_JOB_GET_VMID(job); + u32 header, control = 0; + +- BUG_ON(ib->flags & AMDGPU_IB_FLAG_CE); +- + header = PACKET3(PACKET3_INDIRECT_BUFFER, 2); + + control |= ib->length_dw | (vmid << 24); +-- +2.53.0 + diff --git a/queue-6.1/net-add-proper-rcu-protection-to-proc-net-ptype.patch b/queue-6.1/net-add-proper-rcu-protection-to-proc-net-ptype.patch new file mode 100644 index 0000000000..f002f45e82 --- /dev/null +++ b/queue-6.1/net-add-proper-rcu-protection-to-proc-net-ptype.patch @@ -0,0 +1,190 @@ +From 360cba4b85e5bfa4cf2ff2af0ca413956971f21c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Apr 2026 16:28:46 +0800 +Subject: net: add proper RCU protection to /proc/net/ptype + +From: Eric Dumazet + +[ Upstream commit f613e8b4afea0cd17c7168e8b00e25bc8d33175d ] + +Yin Fengwei reported an RCU stall in ptype_seq_show() and provided +a patch. + +Real issue is that ptype_seq_next() and ptype_seq_show() violate +RCU rules. + +ptype_seq_show() runs under rcu_read_lock(), and reads pt->dev +to get device name without any barrier. + +At the same time, concurrent writers can remove a packet_type structure +(which is correctly freed after an RCU grace period) and clear pt->dev +without an RCU grace period. + +Define ptype_iter_state to carry a dev pointer along seq_net_private: + +struct ptype_iter_state { + struct seq_net_private p; + struct net_device *dev; // added in this patch +}; + +We need to record the device pointer in ptype_get_idx() and +ptype_seq_next() so that ptype_seq_show() is safe against +concurrent pt->dev changes. + +We also need to add full RCU protection in ptype_seq_next(). +(Missing READ_ONCE() when reading list.next values) + +Many thanks to Dong Chenchen for providing a repro. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Fixes: 1d10f8a1f40b ("net-procfs: show net devices bound packet types") +Fixes: c353e8983e0d ("net: introduce per netns packet chains") +Reported-by: Yin Fengwei +Reported-by: Dong Chenchen +Closes: https://lore.kernel.org/netdev/CANn89iKRRKPnWjJmb-_3a=sq+9h6DvTQM4DBZHT5ZRGPMzQaiA@mail.gmail.com/T/#m7b80b9fc9b9267f90e0b7aad557595f686f9c50d + +Signed-off-by: Eric Dumazet +Reviewed-by: Willem de Bruijn +Tested-by: Yin Fengwei +Link: https://patch.msgid.link/20260202205217.2881198-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +[ Some adjustments have been made. ] +Signed-off-by: XiaoHua Wang <561399680@139.com> +Signed-off-by: Sasha Levin +--- + net/core/net-procfs.c | 49 +++++++++++++++++++++++++++++-------------- + 1 file changed, 33 insertions(+), 16 deletions(-) + +diff --git a/net/core/net-procfs.c b/net/core/net-procfs.c +index 1ec23bf8b05ca..2be3c1f6949bc 100644 +--- a/net/core/net-procfs.c ++++ b/net/core/net-procfs.c +@@ -192,8 +192,14 @@ static const struct seq_operations softnet_seq_ops = { + .show = softnet_seq_show, + }; + ++struct ptype_iter_state { ++ struct seq_net_private p; ++ struct net_device *dev; ++}; ++ + static void *ptype_get_idx(struct seq_file *seq, loff_t pos) + { ++ struct ptype_iter_state *iter = seq->private; + struct list_head *ptype_list = NULL; + struct packet_type *pt = NULL; + struct net_device *dev; +@@ -203,12 +209,16 @@ static void *ptype_get_idx(struct seq_file *seq, loff_t pos) + for_each_netdev_rcu(seq_file_net(seq), dev) { + ptype_list = &dev->ptype_all; + list_for_each_entry_rcu(pt, ptype_list, list) { +- if (i == pos) ++ if (i == pos) { ++ iter->dev = dev; + return pt; ++ } + ++i; + } + } + ++ iter->dev = NULL; ++ + list_for_each_entry_rcu(pt, &ptype_all, list) { + if (i == pos) + return pt; +@@ -234,6 +244,7 @@ static void *ptype_seq_start(struct seq_file *seq, loff_t *pos) + + static void *ptype_seq_next(struct seq_file *seq, void *v, loff_t *pos) + { ++ struct ptype_iter_state *iter = seq->private; + struct net_device *dev; + struct packet_type *pt; + struct list_head *nxt; +@@ -244,20 +255,21 @@ static void *ptype_seq_next(struct seq_file *seq, void *v, loff_t *pos) + return ptype_get_idx(seq, 0); + + pt = v; +- nxt = pt->list.next; +- if (pt->dev) { +- if (nxt != &pt->dev->ptype_all) ++ nxt = READ_ONCE(pt->list.next); ++ dev = iter->dev; ++ if (dev) { ++ if (nxt != &dev->ptype_all) + goto found; + +- dev = pt->dev; + for_each_netdev_continue_rcu(seq_file_net(seq), dev) { +- if (!list_empty(&dev->ptype_all)) { +- nxt = dev->ptype_all.next; ++ nxt = READ_ONCE(dev->ptype_all.next); ++ if (nxt != &dev->ptype_all) { ++ iter->dev = dev; + goto found; + } + } +- +- nxt = ptype_all.next; ++ iter->dev = NULL; ++ nxt = READ_ONCE(ptype_all.next); + goto ptype_all; + } + +@@ -266,14 +278,14 @@ static void *ptype_seq_next(struct seq_file *seq, void *v, loff_t *pos) + if (nxt != &ptype_all) + goto found; + hash = 0; +- nxt = ptype_base[0].next; ++ nxt = READ_ONCE(ptype_base[0].next); + } else + hash = ntohs(pt->type) & PTYPE_HASH_MASK; + + while (nxt == &ptype_base[hash]) { + if (++hash >= PTYPE_HASH_SIZE) + return NULL; +- nxt = ptype_base[hash].next; ++ nxt = READ_ONCE(ptype_base[hash].next); + } + found: + return list_entry(nxt, struct packet_type, list); +@@ -287,19 +299,24 @@ static void ptype_seq_stop(struct seq_file *seq, void *v) + + static int ptype_seq_show(struct seq_file *seq, void *v) + { ++ struct ptype_iter_state *iter = seq->private; + struct packet_type *pt = v; ++ struct net_device *dev; + +- if (v == SEQ_START_TOKEN) ++ if (v == SEQ_START_TOKEN) { + seq_puts(seq, "Type Device Function\n"); +- else if ((!pt->af_packet_net || net_eq(pt->af_packet_net, seq_file_net(seq))) && +- (!pt->dev || net_eq(dev_net(pt->dev), seq_file_net(seq)))) { ++ return 0; ++ } ++ dev = iter->dev; ++ if ((!pt->af_packet_net || net_eq(pt->af_packet_net, seq_file_net(seq))) && ++ (!dev || net_eq(dev_net(dev), seq_file_net(seq)))) { + if (pt->type == htons(ETH_P_ALL)) + seq_puts(seq, "ALL "); + else + seq_printf(seq, "%04x", ntohs(pt->type)); + + seq_printf(seq, " %-8s %ps\n", +- pt->dev ? pt->dev->name : "", pt->func); ++ dev ? dev->name : "", pt->func); + } + + return 0; +@@ -323,7 +340,7 @@ static int __net_init dev_proc_net_init(struct net *net) + &softnet_seq_ops)) + goto out_dev; + if (!proc_create_net("ptype", 0444, net->proc_net, &ptype_seq_ops, +- sizeof(struct seq_net_private))) ++ sizeof(struct ptype_iter_state))) + goto out_softnet; + + if (wext_proc_init(net)) +-- +2.53.0 + diff --git a/queue-6.1/net-sched-fix-tcf_layer_transport-handling-in-tcf_ge.patch b/queue-6.1/net-sched-fix-tcf_layer_transport-handling-in-tcf_ge.patch new file mode 100644 index 0000000000..eab1af1ae4 --- /dev/null +++ b/queue-6.1/net-sched-fix-tcf_layer_transport-handling-in-tcf_ge.patch @@ -0,0 +1,131 @@ +From e31c7475fd84a12a30d57cefc746042b58a00478 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Apr 2026 07:53:43 -0700 +Subject: net: sched: fix TCF_LAYER_TRANSPORT handling in tcf_get_base_ptr() + +From: Eric Dumazet + +[Upstream commit 4fe5a00ec70717a7f1002d8913ec6143582b3c8e] + +syzbot reported that tcf_get_base_ptr() can be called while transport +header is not set [1]. + +Instead of returning a dangling pointer, return NULL. + +Fix tcf_get_base_ptr() callers to handle this NULL value. + +[1] + WARNING: CPU: 1 PID: 6019 at ./include/linux/skbuff.h:3071 skb_transport_header include/linux/skbuff.h:3071 [inline] + WARNING: CPU: 1 PID: 6019 at ./include/linux/skbuff.h:3071 tcf_get_base_ptr include/net/pkt_cls.h:539 [inline] + WARNING: CPU: 1 PID: 6019 at ./include/linux/skbuff.h:3071 em_nbyte_match+0x2d8/0x3f0 net/sched/em_nbyte.c:43 +Modules linked in: +CPU: 1 UID: 0 PID: 6019 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full) +Call Trace: + + tcf_em_match net/sched/ematch.c:494 [inline] + __tcf_em_tree_match+0x1ac/0x770 net/sched/ematch.c:520 + tcf_em_tree_match include/net/pkt_cls.h:512 [inline] + basic_classify+0x115/0x2d0 net/sched/cls_basic.c:50 + tc_classify include/net/tc_wrapper.h:197 [inline] + __tcf_classify net/sched/cls_api.c:1764 [inline] + tcf_classify+0x4cf/0x1140 net/sched/cls_api.c:1860 + multiq_classify net/sched/sch_multiq.c:39 [inline] + multiq_enqueue+0xfd/0x4c0 net/sched/sch_multiq.c:66 + dev_qdisc_enqueue+0x4e/0x260 net/core/dev.c:4118 + __dev_xmit_skb net/core/dev.c:4214 [inline] + __dev_queue_xmit+0xe83/0x3b50 net/core/dev.c:4729 + packet_snd net/packet/af_packet.c:3076 [inline] + packet_sendmsg+0x3e33/0x5080 net/packet/af_packet.c:3108 + sock_sendmsg_nosec net/socket.c:727 [inline] + __sock_sendmsg+0x21c/0x270 net/socket.c:742 + ____sys_sendmsg+0x505/0x830 net/socket.c:2630 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+f3a497f02c389d86ef16@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/6920855a.a70a0220.2ea503.0058.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Reviewed-by: Jamal Hadi Salim +Link: https://patch.msgid.link/20251121154100.1616228-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Chelsy Ratnawat +Signed-off-by: Sasha Levin +--- + include/net/pkt_cls.h | 2 ++ + net/sched/em_cmp.c | 5 ++++- + net/sched/em_nbyte.c | 2 ++ + net/sched/em_text.c | 11 +++++++++-- + 4 files changed, 17 insertions(+), 3 deletions(-) + +diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h +index 4cabb32a2ad94..857d9ea60d469 100644 +--- a/include/net/pkt_cls.h ++++ b/include/net/pkt_cls.h +@@ -526,6 +526,8 @@ static inline unsigned char * tcf_get_base_ptr(struct sk_buff *skb, int layer) + case TCF_LAYER_NETWORK: + return skb_network_header(skb); + case TCF_LAYER_TRANSPORT: ++ if (!skb_transport_header_was_set(skb)) ++ break; + return skb_transport_header(skb); + } + +diff --git a/net/sched/em_cmp.c b/net/sched/em_cmp.c +index f17b049ea5309..71ce113f2d08e 100644 +--- a/net/sched/em_cmp.c ++++ b/net/sched/em_cmp.c +@@ -22,9 +22,12 @@ static int em_cmp_match(struct sk_buff *skb, struct tcf_ematch *em, + struct tcf_pkt_info *info) + { + struct tcf_em_cmp *cmp = (struct tcf_em_cmp *) em->data; +- unsigned char *ptr = tcf_get_base_ptr(skb, cmp->layer) + cmp->off; ++ unsigned char *ptr = tcf_get_base_ptr(skb, cmp->layer); + u32 val = 0; + ++ if (!ptr) ++ return 0; ++ ptr += cmp->off; + if (!tcf_valid_offset(skb, ptr, cmp->align)) + return 0; + +diff --git a/net/sched/em_nbyte.c b/net/sched/em_nbyte.c +index a83b237cbeb06..2e3c1d58d4563 100644 +--- a/net/sched/em_nbyte.c ++++ b/net/sched/em_nbyte.c +@@ -42,6 +42,8 @@ static int em_nbyte_match(struct sk_buff *skb, struct tcf_ematch *em, + struct nbyte_data *nbyte = (struct nbyte_data *) em->data; + unsigned char *ptr = tcf_get_base_ptr(skb, nbyte->hdr.layer); + ++ if (!ptr) ++ return 0; + ptr += nbyte->hdr.off; + + if (!tcf_valid_offset(skb, ptr, nbyte->hdr.len)) +diff --git a/net/sched/em_text.c b/net/sched/em_text.c +index f176afb70559e..32aae8a9dedaa 100644 +--- a/net/sched/em_text.c ++++ b/net/sched/em_text.c +@@ -29,12 +29,19 @@ static int em_text_match(struct sk_buff *skb, struct tcf_ematch *m, + struct tcf_pkt_info *info) + { + struct text_match *tm = EM_TEXT_PRIV(m); ++ unsigned char *ptr; + int from, to; + +- from = tcf_get_base_ptr(skb, tm->from_layer) - skb->data; ++ ptr = tcf_get_base_ptr(skb, tm->from_layer); ++ if (!ptr) ++ return 0; ++ from = ptr - skb->data; + from += tm->from_offset; + +- to = tcf_get_base_ptr(skb, tm->to_layer) - skb->data; ++ ptr = tcf_get_base_ptr(skb, tm->to_layer); ++ if (!ptr) ++ return 0; ++ to = ptr - skb->data; + to += tm->to_offset; + + return skb_find_text(skb, from, to, tm->config) != UINT_MAX; +-- +2.53.0 + diff --git a/queue-6.1/nf_tables-nft_dynset-fix-possible-stateful-expressio.patch b/queue-6.1/nf_tables-nft_dynset-fix-possible-stateful-expressio.patch new file mode 100644 index 0000000000..b49163b135 --- /dev/null +++ b/queue-6.1/nf_tables-nft_dynset-fix-possible-stateful-expressio.patch @@ -0,0 +1,109 @@ +From 32fa9f282c6d8dd29dfe6ea4a3c8dd6295374060 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Apr 2026 16:21:24 +0800 +Subject: nf_tables: nft_dynset: fix possible stateful expression memleak in + error path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pablo Neira Ayuso + +[ Upstream commit 0548a13b5a145b16e4da0628b5936baf35f51b43 ] + +If cloning the second stateful expression in the element via GFP_ATOMIC +fails, then the first stateful expression remains in place without being +released. + +   unreferenced object (percpu) 0x607b97e9cab8 (size 16): +     comm "softirq", pid 0, jiffies 4294931867 +     hex dump (first 16 bytes on cpu 3): +       00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +     backtrace (crc 0): +       pcpu_alloc_noprof+0x453/0xd80 +       nft_counter_clone+0x9c/0x190 [nf_tables] +       nft_expr_clone+0x8f/0x1b0 [nf_tables] +       nft_dynset_new+0x2cb/0x5f0 [nf_tables] +       nft_rhash_update+0x236/0x11c0 [nf_tables] +       nft_dynset_eval+0x11f/0x670 [nf_tables] +       nft_do_chain+0x253/0x1700 [nf_tables] +       nft_do_chain_ipv4+0x18d/0x270 [nf_tables] +       nf_hook_slow+0xaa/0x1e0 +       ip_local_deliver+0x209/0x330 + +Fixes: 563125a73ac3 ("netfilter: nftables: generalize set extension to support for several expressions") +Reported-by: Gurpreet Shergill +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Florian Westphal +[ Minor conflict resolved. ] +Signed-off-by: Li hongliang <1468888505@139.com> +Signed-off-by: Sasha Levin +--- + include/net/netfilter/nf_tables.h | 2 ++ + net/netfilter/nf_tables_api.c | 4 ++-- + net/netfilter/nft_dynset.c | 10 +++++++++- + 3 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h +index 38c74f9fcce22..dafa0a32e6e1d 100644 +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -838,6 +838,8 @@ void *nft_set_elem_init(const struct nft_set *set, + u64 timeout, u64 expiration, gfp_t gfp); + int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set, + struct nft_expr *expr_array[]); ++void nft_set_elem_expr_destroy(const struct nft_ctx *ctx, ++ struct nft_set_elem_expr *elem_expr); + void nft_set_elem_destroy(const struct nft_set *set, void *elem, + bool destroy_expr); + void nf_tables_set_elem_destroy(const struct nft_ctx *ctx, +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index fb3d529ebf5ab..0c42242826387 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -6025,8 +6025,8 @@ static void __nft_set_elem_expr_destroy(const struct nft_ctx *ctx, + } + } + +-static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx, +- struct nft_set_elem_expr *elem_expr) ++void nft_set_elem_expr_destroy(const struct nft_ctx *ctx, ++ struct nft_set_elem_expr *elem_expr) + { + struct nft_expr *expr; + u32 size; +diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c +index 953aba871f45c..5f58ac874005a 100644 +--- a/net/netfilter/nft_dynset.c ++++ b/net/netfilter/nft_dynset.c +@@ -30,18 +30,26 @@ static int nft_dynset_expr_setup(const struct nft_dynset *priv, + const struct nft_set_ext *ext) + { + struct nft_set_elem_expr *elem_expr = nft_set_ext_expr(ext); ++ struct nft_ctx ctx = { ++ .net = read_pnet(&priv->set->net), ++ .family = priv->set->table->family, ++ }; + struct nft_expr *expr; + int i; + + for (i = 0; i < priv->num_exprs; i++) { + expr = nft_setelem_expr_at(elem_expr, elem_expr->size); + if (nft_expr_clone(expr, priv->expr_array[i], GFP_ATOMIC) < 0) +- return -1; ++ goto err_out; + + elem_expr->size += priv->expr_array[i]->ops->size; + } + + return 0; ++err_out: ++ nft_set_elem_expr_destroy(&ctx, elem_expr); ++ ++ return -1; + } + + static void *nft_dynset_new(struct nft_set *set, const struct nft_expr *expr, +-- +2.53.0 + diff --git a/queue-6.1/revert-dmaengine-idxd-fix-not-releasing-workqueue-on.patch b/queue-6.1/revert-dmaengine-idxd-fix-not-releasing-workqueue-on.patch new file mode 100644 index 0000000000..4015d195a1 --- /dev/null +++ b/queue-6.1/revert-dmaengine-idxd-fix-not-releasing-workqueue-on.patch @@ -0,0 +1,27 @@ +From 4414269d0870fbbb45c5ee94b91af34feb53f855 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Apr 2026 00:01:51 -0400 +Subject: Revert "dmaengine: idxd: Fix not releasing workqueue on .release()" + +This reverts commit fd4cb61bbd0fc3a749a8da6145cbb56d8f6dba35. + +Signed-off-by: Sasha Levin +--- + drivers/dma/idxd/sysfs.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c +index ea222e1654ab9..0689464c4816a 100644 +--- a/drivers/dma/idxd/sysfs.c ++++ b/drivers/dma/idxd/sysfs.c +@@ -1663,7 +1663,6 @@ static void idxd_conf_device_release(struct device *dev) + { + struct idxd_device *idxd = confdev_to_idxd(dev); + +- destroy_workqueue(idxd->wq); + kfree(idxd->groups); + bitmap_free(idxd->wq_enable_map); + kfree(idxd->wqs); +-- +2.53.0 + diff --git a/queue-6.1/rxrpc-proc-size-address-buffers-for-pispc-output.patch b/queue-6.1/rxrpc-proc-size-address-buffers-for-pispc-output.patch new file mode 100644 index 0000000000..5b2a52dd49 --- /dev/null +++ b/queue-6.1/rxrpc-proc-size-address-buffers-for-pispc-output.patch @@ -0,0 +1,155 @@ +From 85796387d6f3fc3b777db4f7fcb86d71040861c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Apr 2026 10:26:20 -0400 +Subject: rxrpc: proc: size address buffers for %pISpc output + +From: Pengpeng Hou + +[ Upstream commit a44ce6aa2efb61fe44f2cfab72bb01544bbca272 ] + +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 + +Fixes: 75b54cb57ca3 ("rxrpc: Add IPv6 support") +Signed-off-by: Pengpeng Hou +Signed-off-by: David Howells +cc: Marc Dionne +cc: Anderson Nascimento +cc: Simon Horman +cc: linux-afs@lists.infradead.org +cc: stable@kernel.org +Link: https://patch.msgid.link/20260408121252.2249051-22-dhowells@redhat.com +Signed-off-by: Jakub Kicinski +[ adapted address accessors and variable declarations ] +Signed-off-by: Sasha Levin +--- + net/rxrpc/proc.c | 26 +++++++++++++++----------- + 1 file changed, 15 insertions(+), 11 deletions(-) + +diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c +index 245418943e01c..47d36554ad311 100644 +--- a/net/rxrpc/proc.c ++++ b/net/rxrpc/proc.c +@@ -10,6 +10,10 @@ + #include + #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] = "Client ", +@@ -55,7 +59,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) + struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); + unsigned long timeout = 0; + rxrpc_seq_t tx_hard_ack, rx_hard_ack; +- char lbuff[50], rbuff[50]; ++ char lbuff[RXRPC_PROC_ADDRBUF_SIZE], rbuff[RXRPC_PROC_ADDRBUF_SIZE]; + + if (v == &rxnet->calls) { + seq_puts(seq, +@@ -72,7 +76,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) + if (rx) { + local = READ_ONCE(rx->local); + if (local) +- sprintf(lbuff, "%pISpc", &local->srx.transport); ++ scnprintf(lbuff, sizeof(lbuff), "%pISpc", &local->srx.transport); + else + strcpy(lbuff, "no_local"); + } else { +@@ -81,7 +85,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) + + peer = call->peer; + if (peer) +- sprintf(rbuff, "%pISpc", &peer->srx.transport); ++ scnprintf(rbuff, sizeof(rbuff), "%pISpc", &peer->srx.transport); + else + strcpy(rbuff, "no_connection"); + +@@ -152,7 +156,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)); +- 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, +@@ -171,9 +175,9 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v) + goto print; + } + +- sprintf(lbuff, "%pISpc", &conn->params.local->srx.transport); ++ scnprintf(lbuff, sizeof(lbuff), "%pISpc", &conn->params.local->srx.transport); + +- sprintf(rbuff, "%pISpc", &conn->params.peer->srx.transport); ++ scnprintf(rbuff, sizeof(rbuff), "%pISpc", &conn->params.peer->srx.transport); + print: + seq_printf(seq, + "UDP %-47.47s %-47.47s %4x %08x %s %3u" +@@ -210,7 +214,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, +@@ -223,9 +227,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, +@@ -335,7 +339,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, +@@ -346,7 +350,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\n", +-- +2.53.0 + diff --git a/queue-6.1/series b/queue-6.1/series index b0ad5fc900..b7f57427c1 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -76,3 +76,12 @@ usbip-validate-number_of_packets-in-usbip_pack_ret_submit.patch usb-storage-expand-range-of-matched-versions-for-vl817-quirks-entry.patch usb-cdc-acm-add-quirks-for-yoga-book-9-14iah10-ingenic-touchscreen.patch usb-port-add-delay-after-usb_hub_set_port_power.patch +revert-dmaengine-idxd-fix-not-releasing-workqueue-on.patch +alsa-usb-audio-fix-race-condition-to-uaf-in-snd_usbm.patch +net-add-proper-rcu-protection-to-proc-net-ptype.patch +net-sched-fix-tcf_layer_transport-handling-in-tcf_ge.patch +bonding-return-detailed-error-when-loading-native-xd.patch +bonding-check-xdp-prog-when-set-bond-mode.patch +drm-amdgpu-remove-two-invalid-bug_on-s.patch +nf_tables-nft_dynset-fix-possible-stateful-expressio.patch +rxrpc-proc-size-address-buffers-for-pispc-output.patch diff --git a/queue-6.12/gpiolib-fix-race-condition-for-gdev-srcu.patch b/queue-6.12/gpiolib-fix-race-condition-for-gdev-srcu.patch new file mode 100644 index 0000000000..814a88de04 --- /dev/null +++ b/queue-6.12/gpiolib-fix-race-condition-for-gdev-srcu.patch @@ -0,0 +1,164 @@ +From 31754a572d46b350322ce6351ed69fb91b35f0e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Apr 2026 13:15:41 +0200 +Subject: gpiolib: fix race condition for gdev->srcu +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Paweł Narewski + +[ Upstream commit a7ac22d53d0990152b108c3f4fe30df45fcb0181 ] + +If two drivers were calling gpiochip_add_data_with_key(), one may be +traversing the srcu-protected list in gpio_name_to_desc(), meanwhile +other has just added its gdev in gpiodev_add_to_list_unlocked(). +This creates a non-mutexed and non-protected timeframe, when one +instance is dereferencing and using &gdev->srcu, before the other +has initialized it, resulting in crash: + +[ 4.935481] Unable to handle kernel paging request at virtual address ffff800272bcc000 +[ 4.943396] Mem abort info: +[ 4.943400] ESR = 0x0000000096000005 +[ 4.943403] EC = 0x25: DABT (current EL), IL = 32 bits +[ 4.943407] SET = 0, FnV = 0 +[ 4.943410] EA = 0, S1PTW = 0 +[ 4.943413] FSC = 0x05: level 1 translation fault +[ 4.943416] Data abort info: +[ 4.943418] ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000 +[ 4.946220] CM = 0, WnR = 0, TnD = 0, TagAccess = 0 +[ 4.955261] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 +[ 4.955268] swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000038e6c000 +[ 4.961449] [ffff800272bcc000] pgd=0000000000000000 +[ 4.969203] , p4d=1000000039739003 +[ 4.979730] , pud=0000000000000000 +[ 4.980210] phandle (CPU): 0x0000005e, phandle (BE): 0x5e000000 for node "reset" +[ 4.991736] Internal error: Oops: 0000000096000005 [#1] PREEMPT SMP +... +[ 5.121359] pc : __srcu_read_lock+0x44/0x98 +[ 5.131091] lr : gpio_name_to_desc+0x60/0x1a0 +[ 5.153671] sp : ffff8000833bb430 +[ 5.298440] +[ 5.298443] Call trace: +[ 5.298445] __srcu_read_lock+0x44/0x98 +[ 5.309484] gpio_name_to_desc+0x60/0x1a0 +[ 5.320692] gpiochip_add_data_with_key+0x488/0xf00 + 5.946419] ---[ end trace 0000000000000000 ]--- + +Move initialization code for gdev fields before it is added to +gpio_devices, with adjacent initialization code. +Adjust goto statements to reflect modified order of operations + +Fixes: 47d8b4c1d868 ("gpio: add SRCU infrastructure to struct gpio_device") +Reviewed-by: Jakub Lewalski +Signed-off-by: Paweł Narewski +[Bartosz: fixed a build issue, removed stray newline] +Link: https://lore.kernel.org/r/20251224082641.10769-1-bartosz.golaszewski@oss.qualcomm.com +Signed-off-by: Bartosz Golaszewski +[missing commit fcc8b637c542 ("gpiolib: switch the line state notifier + to atomic"), commit dcb73cbaaeb3 ("gpio: cdev: use raw notifier for + line state events") and commit d4f335b410dd ("gpiolib: rename GPIO chip + printk macros") in 6.12.y. + Both notifiers as well as both srcu inits are moved before the + scoped_guard, following same logic as in a7ac22d53d09. + Rest is changes to git context only.] +Cc: stable@vger.kernel.org # 6.12 +Signed-off-by: Quentin Schulz +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpiolib.c | 38 +++++++++++++++++++------------------- + 1 file changed, 19 insertions(+), 19 deletions(-) + +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index 3f9019cc832ac..5c8cd81656963 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -988,6 +988,17 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, + gdev->ngpio = gc->ngpio; + gdev->can_sleep = gc->can_sleep; + ++ BLOCKING_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier); ++ BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier); ++ ++ ret = init_srcu_struct(&gdev->srcu); ++ if (ret) ++ goto err_free_label; ++ ++ ret = init_srcu_struct(&gdev->desc_srcu); ++ if (ret) ++ goto err_cleanup_gdev_srcu; ++ + scoped_guard(mutex, &gpio_devices_lock) { + /* + * TODO: this allocates a Linux GPIO number base in the global +@@ -1002,7 +1013,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, + if (base < 0) { + ret = base; + base = 0; +- goto err_free_label; ++ goto err_cleanup_desc_srcu; + } + + /* +@@ -1022,21 +1033,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, + ret = gpiodev_add_to_list_unlocked(gdev); + if (ret) { + chip_err(gc, "GPIO integer space overlap, cannot add chip\n"); +- goto err_free_label; ++ goto err_cleanup_desc_srcu; + } + } + +- BLOCKING_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier); +- BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier); +- +- ret = init_srcu_struct(&gdev->srcu); +- if (ret) +- goto err_remove_from_list; +- +- ret = init_srcu_struct(&gdev->desc_srcu); +- if (ret) +- goto err_cleanup_gdev_srcu; +- + #ifdef CONFIG_PINCTRL + INIT_LIST_HEAD(&gdev->pin_ranges); + #endif +@@ -1046,11 +1046,11 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, + + ret = gpiochip_set_names(gc); + if (ret) +- goto err_cleanup_desc_srcu; ++ goto err_remove_from_list; + + ret = gpiochip_init_valid_mask(gc); + if (ret) +- goto err_cleanup_desc_srcu; ++ goto err_remove_from_list; + + for (desc_index = 0; desc_index < gc->ngpio; desc_index++) { + struct gpio_desc *desc = &gdev->descs[desc_index]; +@@ -1117,10 +1117,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, + of_gpiochip_remove(gc); + err_free_valid_mask: + gpiochip_free_valid_mask(gc); +-err_cleanup_desc_srcu: +- cleanup_srcu_struct(&gdev->desc_srcu); +-err_cleanup_gdev_srcu: +- cleanup_srcu_struct(&gdev->srcu); + err_remove_from_list: + scoped_guard(mutex, &gpio_devices_lock) + list_del_rcu(&gdev->list); +@@ -1130,6 +1126,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, + gpio_device_put(gdev); + goto err_print_message; + } ++err_cleanup_desc_srcu: ++ cleanup_srcu_struct(&gdev->desc_srcu); ++err_cleanup_gdev_srcu: ++ cleanup_srcu_struct(&gdev->srcu); + err_free_label: + kfree_const(gdev->label); + err_free_descs: +-- +2.53.0 + diff --git a/queue-6.12/gpiolib-unify-two-loops-initializing-gpio-descriptor.patch b/queue-6.12/gpiolib-unify-two-loops-initializing-gpio-descriptor.patch new file mode 100644 index 0000000000..8d97ca668a --- /dev/null +++ b/queue-6.12/gpiolib-unify-two-loops-initializing-gpio-descriptor.patch @@ -0,0 +1,50 @@ +From a4bc20e11a270c0ef9740b23b10294e5d06b065c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Apr 2026 13:15:40 +0200 +Subject: gpiolib: unify two loops initializing GPIO descriptors + +From: Bartosz Golaszewski + +[ Upstream commit fa17f749ee5bc6afdaa9e0ddbe6a816b490dad7d ] + +We currently iterate over the descriptors owned by the GPIO device we're +adding twice with the first loop just setting the gdev pointer. It's not +used anywhere between this and the second loop so just drop the first +one and move the assignment to the second. + +Reviewed-by: Kent Gibson +Link: https://lore.kernel.org/r/20241004-gpio-notify-in-kernel-events-v1-2-8ac29e1df4fe@linaro.org +Signed-off-by: Bartosz Golaszewski +Cc: stable@vger.kernel.org # 6.12 +Signed-off-by: Quentin Schulz +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpiolib.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index 967ff661e4c96..3f9019cc832ac 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -1026,9 +1026,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, + } + } + +- for (desc_index = 0; desc_index < gc->ngpio; desc_index++) +- gdev->descs[desc_index].gdev = gdev; +- + BLOCKING_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier); + BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier); + +@@ -1058,6 +1055,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, + for (desc_index = 0; desc_index < gc->ngpio; desc_index++) { + struct gpio_desc *desc = &gdev->descs[desc_index]; + ++ desc->gdev = gdev; ++ + if (gc->get_direction && gpiochip_line_is_valid(gc, desc_index)) { + assign_bit(FLAG_IS_OUT, + &desc->flags, !gc->get_direction(gc, desc_index)); +-- +2.53.0 + diff --git a/queue-6.12/kernel-be-more-careful-about-dup_mmap-failures-and-u.patch b/queue-6.12/kernel-be-more-careful-about-dup_mmap-failures-and-u.patch new file mode 100644 index 0000000000..e0208f44ca --- /dev/null +++ b/queue-6.12/kernel-be-more-careful-about-dup_mmap-failures-and-u.patch @@ -0,0 +1,120 @@ +From 7e9f46b2bf21945079677dc9dc9df05e1ca431de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Apr 2026 20:06:23 +0200 +Subject: kernel: be more careful about dup_mmap() failures and uprobe + registering + +From: Liam R. Howlett + +[ Upstream commit 64c37e134b120fb462fb4a80694bfb8e7be77b14 ] + +If a memory allocation fails during dup_mmap(), the maple tree can be left +in an unsafe state for other iterators besides the exit path. All the +locks are dropped before the exit_mmap() call (in mm/mmap.c), but the +incomplete mm_struct can be reached through (at least) the rmap finding +the vmas which have a pointer back to the mm_struct. + +Up to this point, there have been no issues with being able to find an +mm_struct that was only partially initialised. Syzbot was able to make +the incomplete mm_struct fail with recent forking changes, so it has been +proven unsafe to use the mm_struct that hasn't been initialised, as +referenced in the link below. + +Although 8ac662f5da19f ("fork: avoid inappropriate uprobe access to +invalid mm") fixed the uprobe access, it does not completely remove the +race. + +This patch sets the MMF_OOM_SKIP to avoid the iteration of the vmas on the +oom side (even though this is extremely unlikely to be selected as an oom +victim in the race window), and sets MMF_UNSTABLE to avoid other potential +users from using a partially initialised mm_struct. + +When registering vmas for uprobe, skip the vmas in an mm that is marked +unstable. Modifying a vma in an unstable mm may cause issues if the mm +isn't fully initialised. + +Link: https://lore.kernel.org/all/6756d273.050a0220.2477f.003d.GAE@google.com/ +Link: https://lkml.kernel.org/r/20250127170221.1761366-1-Liam.Howlett@oracle.com +Fixes: d24062914837 ("fork: use __mt_dup() to duplicate maple tree in dup_mmap()") +Signed-off-by: Liam R. Howlett +Reviewed-by: Lorenzo Stoakes +Cc: Oleg Nesterov +Cc: Masami Hiramatsu +Cc: Jann Horn +Cc: Peter Zijlstra +Cc: Michal Hocko +Cc: Peng Zhang +Cc: Matthew Wilcox +Signed-off-by: Andrew Morton +[resolved conflict from missing header includes: + - linux/workqueue.h missing, introduced by commit 2bf8e5aceff8 ("uprobes: + allow put_uprobe() from non-sleepable softirq context") + - linux/srcu.h missing, introduced by commit dd1a7567784e ("uprobes: + SRCU-protect uretprobe lifetime (with timeout)") ] +Signed-off-by: Heiko Stuebner +Signed-off-by: Sasha Levin +--- + kernel/events/uprobes.c | 4 ++++ + kernel/fork.c | 17 ++++++++++++++--- + 2 files changed, 18 insertions(+), 3 deletions(-) + +diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c +index 1ff26dc3bdb01..5059de5fcc230 100644 +--- a/kernel/events/uprobes.c ++++ b/kernel/events/uprobes.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include /* check_stable_address_space */ + + #include + +@@ -1106,6 +1107,9 @@ register_for_each_vma(struct uprobe *uprobe, struct uprobe_consumer *new) + * returns NULL in find_active_uprobe_rcu(). + */ + mmap_write_lock(mm); ++ if (check_stable_address_space(mm)) ++ goto unlock; ++ + vma = find_vma(mm, info->vaddr); + if (!vma || !valid_vma(vma, is_register) || + file_inode(vma->vm_file) != uprobe->inode) +diff --git a/kernel/fork.c b/kernel/fork.c +index 55086df4d24cb..a01cf3a904bfd 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -766,7 +766,8 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, + mt_set_in_rcu(vmi.mas.tree); + ksm_fork(mm, oldmm); + khugepaged_fork(mm, oldmm); +- } else if (mpnt) { ++ } else { ++ + /* + * The entire maple tree has already been duplicated. If the + * mmap duplication fails, mark the failure point with +@@ -774,8 +775,18 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, + * stop releasing VMAs that have not been duplicated after this + * point. + */ +- mas_set_range(&vmi.mas, mpnt->vm_start, mpnt->vm_end - 1); +- mas_store(&vmi.mas, XA_ZERO_ENTRY); ++ if (mpnt) { ++ mas_set_range(&vmi.mas, mpnt->vm_start, mpnt->vm_end - 1); ++ mas_store(&vmi.mas, XA_ZERO_ENTRY); ++ /* Avoid OOM iterating a broken tree */ ++ set_bit(MMF_OOM_SKIP, &mm->flags); ++ } ++ /* ++ * The mm_struct is going to exit, but the locks will be dropped ++ * first. Set the mm_struct as unstable is advisable as it is ++ * not fully initialised. ++ */ ++ set_bit(MMF_UNSTABLE, &mm->flags); + } + out: + mmap_write_unlock(mm); +-- +2.53.0 + diff --git a/queue-6.12/kvm-remove-subtle-struct-kvm_stats_desc-pseudo-overl.patch b/queue-6.12/kvm-remove-subtle-struct-kvm_stats_desc-pseudo-overl.patch new file mode 100644 index 0000000000..759576972b --- /dev/null +++ b/queue-6.12/kvm-remove-subtle-struct-kvm_stats_desc-pseudo-overl.patch @@ -0,0 +1,470 @@ +From 71ad3de8d96c11cc06c2fee360b691627d613e16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Dec 2025 15:26:55 -0800 +Subject: KVM: Remove subtle "struct kvm_stats_desc" pseudo-overlay + +From: Sean Christopherson + +[ Upstream commit da142f3d373a6ddaca0119615a8db2175ddc4121 ] + +Remove KVM's internal pseudo-overlay of kvm_stats_desc, which subtly +aliases the flexible name[] in the uAPI definition with a fixed-size array +of the same name. The unusual embedded structure results in compiler +warnings due to -Wflex-array-member-not-at-end, and also necessitates an +extra level of dereferencing in KVM. To avoid the "overlay", define the +uAPI structure to have a fixed-size name when building for the kernel. + +Opportunistically clean up the indentation for the stats macros, and +replace spaces with tabs. + +No functional change intended. + +Reported-by: Gustavo A. R. Silva +Closes: https://lore.kernel.org/all/aPfNKRpLfhmhYqfP@kspp +Acked-by: Marc Zyngier +Acked-by: Christian Borntraeger +[..] +Acked-by: Anup Patel +Reviewed-by: Bibo Mao +Acked-by: Gustavo A. R. Silva +Link: https://patch.msgid.link/20251205232655.445294-1-seanjc@google.com +Signed-off-by: Sean Christopherson +Signed-off-by: Sasha Levin +--- + arch/arm64/kvm/guest.c | 4 +- + arch/loongarch/kvm/vcpu.c | 2 +- + arch/loongarch/kvm/vm.c | 2 +- + arch/mips/kvm/mips.c | 4 +- + arch/powerpc/kvm/book3s.c | 4 +- + arch/powerpc/kvm/booke.c | 4 +- + arch/riscv/kvm/vcpu.c | 2 +- + arch/riscv/kvm/vm.c | 2 +- + arch/s390/kvm/kvm-s390.c | 4 +- + arch/x86/kvm/x86.c | 4 +- + include/linux/kvm_host.h | 83 +++++++++++++++++---------------------- + include/uapi/linux/kvm.h | 8 ++++ + virt/kvm/binary_stats.c | 2 +- + virt/kvm/kvm_main.c | 20 +++++----- + 14 files changed, 70 insertions(+), 75 deletions(-) + +diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c +index 962f985977c2d..e67109b54ae90 100644 +--- a/arch/arm64/kvm/guest.c ++++ b/arch/arm64/kvm/guest.c +@@ -29,7 +29,7 @@ + + #include "trace.h" + +-const struct _kvm_stats_desc kvm_vm_stats_desc[] = { ++const struct kvm_stats_desc kvm_vm_stats_desc[] = { + KVM_GENERIC_VM_STATS() + }; + +@@ -42,7 +42,7 @@ const struct kvm_stats_header kvm_vm_stats_header = { + sizeof(kvm_vm_stats_desc), + }; + +-const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { ++const struct kvm_stats_desc kvm_vcpu_stats_desc[] = { + KVM_GENERIC_VCPU_STATS(), + STATS_DESC_COUNTER(VCPU, hvc_exit_stat), + STATS_DESC_COUNTER(VCPU, wfe_exit_stat), +diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c +index 8579bddb544a7..38d3435d4fe0e 100644 +--- a/arch/loongarch/kvm/vcpu.c ++++ b/arch/loongarch/kvm/vcpu.c +@@ -14,7 +14,7 @@ + #define CREATE_TRACE_POINTS + #include "trace.h" + +-const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { ++const struct kvm_stats_desc kvm_vcpu_stats_desc[] = { + KVM_GENERIC_VCPU_STATS(), + STATS_DESC_COUNTER(VCPU, int_exits), + STATS_DESC_COUNTER(VCPU, idle_exits), +diff --git a/arch/loongarch/kvm/vm.c b/arch/loongarch/kvm/vm.c +index fe9e973912d44..06c3fbab8c6fb 100644 +--- a/arch/loongarch/kvm/vm.c ++++ b/arch/loongarch/kvm/vm.c +@@ -7,7 +7,7 @@ + #include + #include + +-const struct _kvm_stats_desc kvm_vm_stats_desc[] = { ++const struct kvm_stats_desc kvm_vm_stats_desc[] = { + KVM_GENERIC_VM_STATS(), + STATS_DESC_ICOUNTER(VM, pages), + STATS_DESC_ICOUNTER(VM, hugepages), +diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c +index 60b43ea85c125..3f8d5310bbd27 100644 +--- a/arch/mips/kvm/mips.c ++++ b/arch/mips/kvm/mips.c +@@ -38,7 +38,7 @@ + #define VECTORSPACING 0x100 /* for EI/VI mode */ + #endif + +-const struct _kvm_stats_desc kvm_vm_stats_desc[] = { ++const struct kvm_stats_desc kvm_vm_stats_desc[] = { + KVM_GENERIC_VM_STATS() + }; + +@@ -51,7 +51,7 @@ const struct kvm_stats_header kvm_vm_stats_header = { + sizeof(kvm_vm_stats_desc), + }; + +-const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { ++const struct kvm_stats_desc kvm_vcpu_stats_desc[] = { + KVM_GENERIC_VCPU_STATS(), + STATS_DESC_COUNTER(VCPU, wait_exits), + STATS_DESC_COUNTER(VCPU, cache_exits), +diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c +index ff6c383739575..b6c4c1490a9f8 100644 +--- a/arch/powerpc/kvm/book3s.c ++++ b/arch/powerpc/kvm/book3s.c +@@ -38,7 +38,7 @@ + + /* #define EXIT_DEBUG */ + +-const struct _kvm_stats_desc kvm_vm_stats_desc[] = { ++const struct kvm_stats_desc kvm_vm_stats_desc[] = { + KVM_GENERIC_VM_STATS(), + STATS_DESC_ICOUNTER(VM, num_2M_pages), + STATS_DESC_ICOUNTER(VM, num_1G_pages) +@@ -53,7 +53,7 @@ const struct kvm_stats_header kvm_vm_stats_header = { + sizeof(kvm_vm_stats_desc), + }; + +-const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { ++const struct kvm_stats_desc kvm_vcpu_stats_desc[] = { + KVM_GENERIC_VCPU_STATS(), + STATS_DESC_COUNTER(VCPU, sum_exits), + STATS_DESC_COUNTER(VCPU, mmio_exits), +diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c +index 6a5be025a8afb..368b4381fe6b0 100644 +--- a/arch/powerpc/kvm/booke.c ++++ b/arch/powerpc/kvm/booke.c +@@ -36,7 +36,7 @@ + + unsigned long kvmppc_booke_handlers; + +-const struct _kvm_stats_desc kvm_vm_stats_desc[] = { ++const struct kvm_stats_desc kvm_vm_stats_desc[] = { + KVM_GENERIC_VM_STATS(), + STATS_DESC_ICOUNTER(VM, num_2M_pages), + STATS_DESC_ICOUNTER(VM, num_1G_pages) +@@ -51,7 +51,7 @@ const struct kvm_stats_header kvm_vm_stats_header = { + sizeof(kvm_vm_stats_desc), + }; + +-const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { ++const struct kvm_stats_desc kvm_vcpu_stats_desc[] = { + KVM_GENERIC_VCPU_STATS(), + STATS_DESC_COUNTER(VCPU, sum_exits), + STATS_DESC_COUNTER(VCPU, mmio_exits), +diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c +index 8d7d381737ee5..da01c81bf4167 100644 +--- a/arch/riscv/kvm/vcpu.c ++++ b/arch/riscv/kvm/vcpu.c +@@ -24,7 +24,7 @@ + #define CREATE_TRACE_POINTS + #include "trace.h" + +-const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { ++const struct kvm_stats_desc kvm_vcpu_stats_desc[] = { + KVM_GENERIC_VCPU_STATS(), + STATS_DESC_COUNTER(VCPU, ecall_exit_stat), + STATS_DESC_COUNTER(VCPU, wfi_exit_stat), +diff --git a/arch/riscv/kvm/vm.c b/arch/riscv/kvm/vm.c +index 7396b8654f454..b7713ffe4c548 100644 +--- a/arch/riscv/kvm/vm.c ++++ b/arch/riscv/kvm/vm.c +@@ -12,7 +12,7 @@ + #include + #include + +-const struct _kvm_stats_desc kvm_vm_stats_desc[] = { ++const struct kvm_stats_desc kvm_vm_stats_desc[] = { + KVM_GENERIC_VM_STATS() + }; + static_assert(ARRAY_SIZE(kvm_vm_stats_desc) == +diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c +index 286a224c81ee4..70d7bbd62120d 100644 +--- a/arch/s390/kvm/kvm-s390.c ++++ b/arch/s390/kvm/kvm-s390.c +@@ -59,7 +59,7 @@ + #define VCPU_IRQS_MAX_BUF (sizeof(struct kvm_s390_irq) * \ + (KVM_MAX_VCPUS + LOCAL_IRQS)) + +-const struct _kvm_stats_desc kvm_vm_stats_desc[] = { ++const struct kvm_stats_desc kvm_vm_stats_desc[] = { + KVM_GENERIC_VM_STATS(), + STATS_DESC_COUNTER(VM, inject_io), + STATS_DESC_COUNTER(VM, inject_float_mchk), +@@ -85,7 +85,7 @@ const struct kvm_stats_header kvm_vm_stats_header = { + sizeof(kvm_vm_stats_desc), + }; + +-const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { ++const struct kvm_stats_desc kvm_vcpu_stats_desc[] = { + KVM_GENERIC_VCPU_STATS(), + STATS_DESC_COUNTER(VCPU, exit_userspace), + STATS_DESC_COUNTER(VCPU, exit_null), +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 8a52b7bb821a7..693a9961fbec1 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -229,7 +229,7 @@ EXPORT_SYMBOL_GPL(allow_smaller_maxphyaddr); + bool __read_mostly enable_apicv = true; + EXPORT_SYMBOL_GPL(enable_apicv); + +-const struct _kvm_stats_desc kvm_vm_stats_desc[] = { ++const struct kvm_stats_desc kvm_vm_stats_desc[] = { + KVM_GENERIC_VM_STATS(), + STATS_DESC_COUNTER(VM, mmu_shadow_zapped), + STATS_DESC_COUNTER(VM, mmu_pte_write), +@@ -255,7 +255,7 @@ const struct kvm_stats_header kvm_vm_stats_header = { + sizeof(kvm_vm_stats_desc), + }; + +-const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { ++const struct kvm_stats_desc kvm_vcpu_stats_desc[] = { + KVM_GENERIC_VCPU_STATS(), + STATS_DESC_COUNTER(VCPU, pf_taken), + STATS_DESC_COUNTER(VCPU, pf_fixed), +diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h +index a2ebc37a29ff4..966511b1e70fa 100644 +--- a/include/linux/kvm_host.h ++++ b/include/linux/kvm_host.h +@@ -1877,56 +1877,43 @@ enum kvm_stat_kind { + + struct kvm_stat_data { + struct kvm *kvm; +- const struct _kvm_stats_desc *desc; ++ const struct kvm_stats_desc *desc; + enum kvm_stat_kind kind; + }; + +-struct _kvm_stats_desc { +- struct kvm_stats_desc desc; +- char name[KVM_STATS_NAME_SIZE]; +-}; +- +-#define STATS_DESC_COMMON(type, unit, base, exp, sz, bsz) \ +- .flags = type | unit | base | \ +- BUILD_BUG_ON_ZERO(type & ~KVM_STATS_TYPE_MASK) | \ +- BUILD_BUG_ON_ZERO(unit & ~KVM_STATS_UNIT_MASK) | \ +- BUILD_BUG_ON_ZERO(base & ~KVM_STATS_BASE_MASK), \ +- .exponent = exp, \ +- .size = sz, \ ++#define STATS_DESC_COMMON(type, unit, base, exp, sz, bsz) \ ++ .flags = type | unit | base | \ ++ BUILD_BUG_ON_ZERO(type & ~KVM_STATS_TYPE_MASK) | \ ++ BUILD_BUG_ON_ZERO(unit & ~KVM_STATS_UNIT_MASK) | \ ++ BUILD_BUG_ON_ZERO(base & ~KVM_STATS_BASE_MASK), \ ++ .exponent = exp, \ ++ .size = sz, \ + .bucket_size = bsz + +-#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \ +- { \ +- { \ +- STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \ +- .offset = offsetof(struct kvm_vm_stat, generic.stat) \ +- }, \ +- .name = #stat, \ +- } +-#define VCPU_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \ +- { \ +- { \ +- STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \ +- .offset = offsetof(struct kvm_vcpu_stat, generic.stat) \ +- }, \ +- .name = #stat, \ +- } +-#define VM_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \ +- { \ +- { \ +- STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \ +- .offset = offsetof(struct kvm_vm_stat, stat) \ +- }, \ +- .name = #stat, \ +- } +-#define VCPU_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \ +- { \ +- { \ +- STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \ +- .offset = offsetof(struct kvm_vcpu_stat, stat) \ +- }, \ +- .name = #stat, \ +- } ++#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \ ++{ \ ++ STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \ ++ .offset = offsetof(struct kvm_vm_stat, generic.stat), \ ++ .name = #stat, \ ++} ++#define VCPU_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \ ++{ \ ++ STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \ ++ .offset = offsetof(struct kvm_vcpu_stat, generic.stat), \ ++ .name = #stat, \ ++} ++#define VM_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \ ++{ \ ++ STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \ ++ .offset = offsetof(struct kvm_vm_stat, stat), \ ++ .name = #stat, \ ++} ++#define VCPU_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \ ++{ \ ++ STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \ ++ .offset = offsetof(struct kvm_vcpu_stat, stat), \ ++ .name = #stat, \ ++} + /* SCOPE: VM, VM_GENERIC, VCPU, VCPU_GENERIC */ + #define STATS_DESC(SCOPE, stat, type, unit, base, exp, sz, bsz) \ + SCOPE##_STATS_DESC(stat, type, unit, base, exp, sz, bsz) +@@ -2003,7 +1990,7 @@ struct _kvm_stats_desc { + STATS_DESC_IBOOLEAN(VCPU_GENERIC, blocking) + + ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header, +- const struct _kvm_stats_desc *desc, ++ const struct kvm_stats_desc *desc, + void *stats, size_t size_stats, + char __user *user_buffer, size_t size, loff_t *offset); + +@@ -2048,9 +2035,9 @@ static inline void kvm_stats_log_hist_update(u64 *data, size_t size, u64 value) + + + extern const struct kvm_stats_header kvm_vm_stats_header; +-extern const struct _kvm_stats_desc kvm_vm_stats_desc[]; ++extern const struct kvm_stats_desc kvm_vm_stats_desc[]; + extern const struct kvm_stats_header kvm_vcpu_stats_header; +-extern const struct _kvm_stats_desc kvm_vcpu_stats_desc[]; ++extern const struct kvm_stats_desc kvm_vcpu_stats_desc[]; + + #ifdef CONFIG_KVM_GENERIC_MMU_NOTIFIER + static inline int mmu_invalidate_retry(struct kvm *kvm, unsigned long mmu_seq) +diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h +index 637efc0551453..03bbe12620e98 100644 +--- a/include/uapi/linux/kvm.h ++++ b/include/uapi/linux/kvm.h +@@ -14,6 +14,10 @@ + #include + #include + ++#ifdef __KERNEL__ ++#include ++#endif ++ + #define KVM_API_VERSION 12 + + /* +@@ -1526,7 +1530,11 @@ struct kvm_stats_desc { + __u16 size; + __u32 offset; + __u32 bucket_size; ++#ifdef __KERNEL__ ++ char name[KVM_STATS_NAME_SIZE]; ++#else + char name[]; ++#endif + }; + + #define KVM_GET_STATS_FD _IO(KVMIO, 0xce) +diff --git a/virt/kvm/binary_stats.c b/virt/kvm/binary_stats.c +index eefca6c69f519..76ce697c773bf 100644 +--- a/virt/kvm/binary_stats.c ++++ b/virt/kvm/binary_stats.c +@@ -50,7 +50,7 @@ + * Return: the number of bytes that has been successfully read + */ + ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header, +- const struct _kvm_stats_desc *desc, ++ const struct kvm_stats_desc *desc, + void *stats, size_t size_stats, + char __user *user_buffer, size_t size, loff_t *offset) + { +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index 16cb973741f42..833553e0f2cc5 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -1013,9 +1013,9 @@ static void kvm_free_memslots(struct kvm *kvm, struct kvm_memslots *slots) + kvm_free_memslot(kvm, memslot); + } + +-static umode_t kvm_stats_debugfs_mode(const struct _kvm_stats_desc *pdesc) ++static umode_t kvm_stats_debugfs_mode(const struct kvm_stats_desc *desc) + { +- switch (pdesc->desc.flags & KVM_STATS_TYPE_MASK) { ++ switch (desc->flags & KVM_STATS_TYPE_MASK) { + case KVM_STATS_TYPE_INSTANT: + return 0444; + case KVM_STATS_TYPE_CUMULATIVE: +@@ -1050,7 +1050,7 @@ static int kvm_create_vm_debugfs(struct kvm *kvm, const char *fdname) + struct dentry *dent; + char dir_name[ITOA_MAX_LEN * 2]; + struct kvm_stat_data *stat_data; +- const struct _kvm_stats_desc *pdesc; ++ const struct kvm_stats_desc *pdesc; + int i, ret = -ENOMEM; + int kvm_debugfs_num_entries = kvm_vm_stats_header.num_desc + + kvm_vcpu_stats_header.num_desc; +@@ -6164,11 +6164,11 @@ static int kvm_stat_data_get(void *data, u64 *val) + switch (stat_data->kind) { + case KVM_STAT_VM: + r = kvm_get_stat_per_vm(stat_data->kvm, +- stat_data->desc->desc.offset, val); ++ stat_data->desc->offset, val); + break; + case KVM_STAT_VCPU: + r = kvm_get_stat_per_vcpu(stat_data->kvm, +- stat_data->desc->desc.offset, val); ++ stat_data->desc->offset, val); + break; + } + +@@ -6186,11 +6186,11 @@ static int kvm_stat_data_clear(void *data, u64 val) + switch (stat_data->kind) { + case KVM_STAT_VM: + r = kvm_clear_stat_per_vm(stat_data->kvm, +- stat_data->desc->desc.offset); ++ stat_data->desc->offset); + break; + case KVM_STAT_VCPU: + r = kvm_clear_stat_per_vcpu(stat_data->kvm, +- stat_data->desc->desc.offset); ++ stat_data->desc->offset); + break; + } + +@@ -6338,7 +6338,7 @@ static void kvm_uevent_notify_change(unsigned int type, struct kvm *kvm) + static void kvm_init_debug(void) + { + const struct file_operations *fops; +- const struct _kvm_stats_desc *pdesc; ++ const struct kvm_stats_desc *pdesc; + int i; + + kvm_debugfs_dir = debugfs_create_dir("kvm", NULL); +@@ -6351,7 +6351,7 @@ static void kvm_init_debug(void) + fops = &vm_stat_readonly_fops; + debugfs_create_file(pdesc->name, kvm_stats_debugfs_mode(pdesc), + kvm_debugfs_dir, +- (void *)(long)pdesc->desc.offset, fops); ++ (void *)(long)pdesc->offset, fops); + } + + for (i = 0; i < kvm_vcpu_stats_header.num_desc; ++i) { +@@ -6362,7 +6362,7 @@ static void kvm_init_debug(void) + fops = &vcpu_stat_readonly_fops; + debugfs_create_file(pdesc->name, kvm_stats_debugfs_mode(pdesc), + kvm_debugfs_dir, +- (void *)(long)pdesc->desc.offset, fops); ++ (void *)(long)pdesc->offset, fops); + } + } + +-- +2.53.0 + diff --git a/queue-6.12/kvm-x86-use-__declare_flex_array-for-uapi-structures.patch b/queue-6.12/kvm-x86-use-__declare_flex_array-for-uapi-structures.patch new file mode 100644 index 0000000000..49a77ec805 --- /dev/null +++ b/queue-6.12/kvm-x86-use-__declare_flex_array-for-uapi-structures.patch @@ -0,0 +1,156 @@ +From 5bcd1314f8d8ba91a01e1ca3e6a8c8e42827305c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Mar 2026 20:49:55 +0100 +Subject: KVM: x86: Use __DECLARE_FLEX_ARRAY() for UAPI structures with VLAs + +From: David Woodhouse + +[ Upstream commit 2619da73bb2f10d88f7e1087125c40144fdf0987 ] + +Commit 94dfc73e7cf4 ("treewide: uapi: Replace zero-length arrays with +flexible-array members") broke the userspace API for C++. + +These structures ending in VLAs are typically a *header*, which can be +followed by an arbitrary number of entries. Userspace typically creates +a larger structure with some non-zero number of entries, for example in +QEMU's kvm_arch_get_supported_msr_feature(): + + struct { + struct kvm_msrs info; + struct kvm_msr_entry entries[1]; + } msr_data = {}; + +While that works in C, it fails in C++ with an error like: + flexible array member 'kvm_msrs::entries' not at end of 'struct msr_data' + +Fix this by using __DECLARE_FLEX_ARRAY() for the VLA, which uses [0] +for C++ compilation. + +Fixes: 94dfc73e7cf4 ("treewide: uapi: Replace zero-length arrays with flexible-array members") +Cc: stable@vger.kernel.org +Signed-off-by: David Woodhouse +Link: https://patch.msgid.link/3abaf6aefd6e5efeff3b860ac38421d9dec908db.camel@infradead.org +[sean: tag for stable@] +Signed-off-by: Sean Christopherson +Signed-off-by: Sasha Levin +--- + arch/x86/include/uapi/asm/kvm.h | 12 ++++++------ + include/uapi/linux/kvm.h | 11 ++++++----- + 2 files changed, 12 insertions(+), 11 deletions(-) + +diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h +index 64cdf9763c0e0..f1b0a28b3a36b 100644 +--- a/arch/x86/include/uapi/asm/kvm.h ++++ b/arch/x86/include/uapi/asm/kvm.h +@@ -192,13 +192,13 @@ struct kvm_msrs { + __u32 nmsrs; /* number of msrs in entries */ + __u32 pad; + +- struct kvm_msr_entry entries[]; ++ __DECLARE_FLEX_ARRAY(struct kvm_msr_entry, entries); + }; + + /* for KVM_GET_MSR_INDEX_LIST */ + struct kvm_msr_list { + __u32 nmsrs; /* number of msrs in entries */ +- __u32 indices[]; ++ __DECLARE_FLEX_ARRAY(__u32, indices); + }; + + /* Maximum size of any access bitmap in bytes */ +@@ -240,7 +240,7 @@ struct kvm_cpuid_entry { + struct kvm_cpuid { + __u32 nent; + __u32 padding; +- struct kvm_cpuid_entry entries[]; ++ __DECLARE_FLEX_ARRAY(struct kvm_cpuid_entry, entries); + }; + + struct kvm_cpuid_entry2 { +@@ -262,7 +262,7 @@ struct kvm_cpuid_entry2 { + struct kvm_cpuid2 { + __u32 nent; + __u32 padding; +- struct kvm_cpuid_entry2 entries[]; ++ __DECLARE_FLEX_ARRAY(struct kvm_cpuid_entry2, entries); + }; + + /* for KVM_GET_PIT and KVM_SET_PIT */ +@@ -393,7 +393,7 @@ struct kvm_xsave { + * the contents of CPUID leaf 0xD on the host. + */ + __u32 region[1024]; +- __u32 extra[]; ++ __DECLARE_FLEX_ARRAY(__u32, extra); + }; + + #define KVM_MAX_XCRS 16 +@@ -530,7 +530,7 @@ struct kvm_pmu_event_filter { + __u32 fixed_counter_bitmap; + __u32 flags; + __u32 pad[4]; +- __u64 events[]; ++ __DECLARE_FLEX_ARRAY(__u64, events); + }; + + #define KVM_PMU_EVENT_ALLOW 0 +diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h +index 03bbe12620e98..9222f5e3c59b9 100644 +--- a/include/uapi/linux/kvm.h ++++ b/include/uapi/linux/kvm.h +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -496,7 +497,7 @@ struct kvm_coalesced_mmio { + + struct kvm_coalesced_mmio_ring { + __u32 first, last; +- struct kvm_coalesced_mmio coalesced_mmio[]; ++ __DECLARE_FLEX_ARRAY(struct kvm_coalesced_mmio, coalesced_mmio); + }; + + #define KVM_COALESCED_MMIO_MAX \ +@@ -546,7 +547,7 @@ struct kvm_clear_dirty_log { + /* for KVM_SET_SIGNAL_MASK */ + struct kvm_signal_mask { + __u32 len; +- __u8 sigset[]; ++ __DECLARE_FLEX_ARRAY(__u8, sigset); + }; + + /* for KVM_TPR_ACCESS_REPORTING */ +@@ -999,7 +1000,7 @@ struct kvm_irq_routing_entry { + struct kvm_irq_routing { + __u32 nr; + __u32 flags; +- struct kvm_irq_routing_entry entries[]; ++ __DECLARE_FLEX_ARRAY(struct kvm_irq_routing_entry, entries); + }; + + #define KVM_IRQFD_FLAG_DEASSIGN (1 << 0) +@@ -1086,7 +1087,7 @@ struct kvm_dirty_tlb { + + struct kvm_reg_list { + __u64 n; /* number of regs */ +- __u64 reg[]; ++ __DECLARE_FLEX_ARRAY(__u64, reg); + }; + + struct kvm_one_reg { +@@ -1533,7 +1534,7 @@ struct kvm_stats_desc { + #ifdef __KERNEL__ + char name[KVM_STATS_NAME_SIZE]; + #else +- char name[]; ++ __DECLARE_FLEX_ARRAY(char, name); + #endif + }; + +-- +2.53.0 + diff --git a/queue-6.12/net-sched-fix-tcf_layer_transport-handling-in-tcf_ge.patch b/queue-6.12/net-sched-fix-tcf_layer_transport-handling-in-tcf_ge.patch new file mode 100644 index 0000000000..915d5c176d --- /dev/null +++ b/queue-6.12/net-sched-fix-tcf_layer_transport-handling-in-tcf_ge.patch @@ -0,0 +1,131 @@ +From d077949a44aad638d6cccead04108a0eaf802591 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Apr 2026 14:43:48 -0700 +Subject: net: sched: fix TCF_LAYER_TRANSPORT handling in tcf_get_base_ptr() + +From: Eric Dumazet + +[Upstream commit 4fe5a00ec70717a7f1002d8913ec6143582b3c8e] + +syzbot reported that tcf_get_base_ptr() can be called while transport +header is not set [1]. + +Instead of returning a dangling pointer, return NULL. + +Fix tcf_get_base_ptr() callers to handle this NULL value. + +[1] + WARNING: CPU: 1 PID: 6019 at ./include/linux/skbuff.h:3071 skb_transport_header include/linux/skbuff.h:3071 [inline] + WARNING: CPU: 1 PID: 6019 at ./include/linux/skbuff.h:3071 tcf_get_base_ptr include/net/pkt_cls.h:539 [inline] + WARNING: CPU: 1 PID: 6019 at ./include/linux/skbuff.h:3071 em_nbyte_match+0x2d8/0x3f0 net/sched/em_nbyte.c:43 +Modules linked in: +CPU: 1 UID: 0 PID: 6019 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full) +Call Trace: + + tcf_em_match net/sched/ematch.c:494 [inline] + __tcf_em_tree_match+0x1ac/0x770 net/sched/ematch.c:520 + tcf_em_tree_match include/net/pkt_cls.h:512 [inline] + basic_classify+0x115/0x2d0 net/sched/cls_basic.c:50 + tc_classify include/net/tc_wrapper.h:197 [inline] + __tcf_classify net/sched/cls_api.c:1764 [inline] + tcf_classify+0x4cf/0x1140 net/sched/cls_api.c:1860 + multiq_classify net/sched/sch_multiq.c:39 [inline] + multiq_enqueue+0xfd/0x4c0 net/sched/sch_multiq.c:66 + dev_qdisc_enqueue+0x4e/0x260 net/core/dev.c:4118 + __dev_xmit_skb net/core/dev.c:4214 [inline] + __dev_queue_xmit+0xe83/0x3b50 net/core/dev.c:4729 + packet_snd net/packet/af_packet.c:3076 [inline] + packet_sendmsg+0x3e33/0x5080 net/packet/af_packet.c:3108 + sock_sendmsg_nosec net/socket.c:727 [inline] + __sock_sendmsg+0x21c/0x270 net/socket.c:742 + ____sys_sendmsg+0x505/0x830 net/socket.c:2630 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+f3a497f02c389d86ef16@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/6920855a.a70a0220.2ea503.0058.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Reviewed-by: Jamal Hadi Salim +Link: https://patch.msgid.link/20251121154100.1616228-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Chelsy Ratnawat +Signed-off-by: Sasha Levin +--- + include/net/pkt_cls.h | 2 ++ + net/sched/em_cmp.c | 5 ++++- + net/sched/em_nbyte.c | 2 ++ + net/sched/em_text.c | 11 +++++++++-- + 4 files changed, 17 insertions(+), 3 deletions(-) + +diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h +index 4229e4fcd2a9e..ea2c69fdc8396 100644 +--- a/include/net/pkt_cls.h ++++ b/include/net/pkt_cls.h +@@ -536,6 +536,8 @@ static inline unsigned char * tcf_get_base_ptr(struct sk_buff *skb, int layer) + case TCF_LAYER_NETWORK: + return skb_network_header(skb); + case TCF_LAYER_TRANSPORT: ++ if (!skb_transport_header_was_set(skb)) ++ break; + return skb_transport_header(skb); + } + +diff --git a/net/sched/em_cmp.c b/net/sched/em_cmp.c +index 64b637f18bc7d..48c1bce74f498 100644 +--- a/net/sched/em_cmp.c ++++ b/net/sched/em_cmp.c +@@ -22,9 +22,12 @@ static int em_cmp_match(struct sk_buff *skb, struct tcf_ematch *em, + struct tcf_pkt_info *info) + { + struct tcf_em_cmp *cmp = (struct tcf_em_cmp *) em->data; +- unsigned char *ptr = tcf_get_base_ptr(skb, cmp->layer) + cmp->off; ++ unsigned char *ptr = tcf_get_base_ptr(skb, cmp->layer); + u32 val = 0; + ++ if (!ptr) ++ return 0; ++ ptr += cmp->off; + if (!tcf_valid_offset(skb, ptr, cmp->align)) + return 0; + +diff --git a/net/sched/em_nbyte.c b/net/sched/em_nbyte.c +index 4f9f21a05d5e4..c65ffa5fff946 100644 +--- a/net/sched/em_nbyte.c ++++ b/net/sched/em_nbyte.c +@@ -42,6 +42,8 @@ static int em_nbyte_match(struct sk_buff *skb, struct tcf_ematch *em, + struct nbyte_data *nbyte = (struct nbyte_data *) em->data; + unsigned char *ptr = tcf_get_base_ptr(skb, nbyte->hdr.layer); + ++ if (!ptr) ++ return 0; + ptr += nbyte->hdr.off; + + if (!tcf_valid_offset(skb, ptr, nbyte->hdr.len)) +diff --git a/net/sched/em_text.c b/net/sched/em_text.c +index 420c66203b177..8331f38eadc60 100644 +--- a/net/sched/em_text.c ++++ b/net/sched/em_text.c +@@ -29,12 +29,19 @@ static int em_text_match(struct sk_buff *skb, struct tcf_ematch *m, + struct tcf_pkt_info *info) + { + struct text_match *tm = EM_TEXT_PRIV(m); ++ unsigned char *ptr; + int from, to; + +- from = tcf_get_base_ptr(skb, tm->from_layer) - skb->data; ++ ptr = tcf_get_base_ptr(skb, tm->from_layer); ++ if (!ptr) ++ return 0; ++ from = ptr - skb->data; + from += tm->from_offset; + +- to = tcf_get_base_ptr(skb, tm->to_layer) - skb->data; ++ ptr = tcf_get_base_ptr(skb, tm->to_layer); ++ if (!ptr) ++ return 0; ++ to = ptr - skb->data; + to += tm->to_offset; + + return skb_find_text(skb, from, to, tm->config) != UINT_MAX; +-- +2.53.0 + diff --git a/queue-6.12/series b/queue-6.12/series index 9fa494015c..f18204c049 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -113,3 +113,9 @@ usb-storage-expand-range-of-matched-versions-for-vl817-quirks-entry.patch usb-cdc-acm-add-quirks-for-yoga-book-9-14iah10-ingenic-touchscreen.patch usb-gadget-f_hid-don-t-call-cdev_init-while-cdev-in-use.patch usb-port-add-delay-after-usb_hub_set_port_power.patch +gpiolib-unify-two-loops-initializing-gpio-descriptor.patch +gpiolib-fix-race-condition-for-gdev-srcu.patch +net-sched-fix-tcf_layer_transport-handling-in-tcf_ge.patch +kernel-be-more-careful-about-dup_mmap-failures-and-u.patch +kvm-remove-subtle-struct-kvm_stats_desc-pseudo-overl.patch +kvm-x86-use-__declare_flex_array-for-uapi-structures.patch diff --git a/queue-6.6/blktrace-fix-__this_cpu_read-write-in-preemptible-co.patch b/queue-6.6/blktrace-fix-__this_cpu_read-write-in-preemptible-co.patch new file mode 100644 index 0000000000..8c57217497 --- /dev/null +++ b/queue-6.6/blktrace-fix-__this_cpu_read-write-in-preemptible-co.patch @@ -0,0 +1,134 @@ +From ed757888aacc3bce2436687cb9805faba78b665f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Apr 2026 18:08:59 +0800 +Subject: blktrace: fix __this_cpu_read/write in preemptible context + +From: Chaitanya Kulkarni + +[ Upstream commit da46b5dfef48658d03347cda21532bcdbb521e67 ] + +tracing_record_cmdline() internally uses __this_cpu_read() and +__this_cpu_write() on the per-CPU variable trace_cmdline_save, and +trace_save_cmdline() explicitly asserts preemption is disabled via +lockdep_assert_preemption_disabled(). These operations are only safe +when preemption is off, as they were designed to be called from the +scheduler context (probe_wakeup_sched_switch() / probe_wakeup()). + +__blk_add_trace() was calling tracing_record_cmdline(current) early in +the blk_tracer path, before ring buffer reservation, from process +context where preemption is fully enabled. This triggers the following +using blktests/blktrace/002: + +blktrace/002 (blktrace ftrace corruption with sysfs trace) [failed] + runtime 0.367s ... 0.437s + something found in dmesg: + [ 81.211018] run blktests blktrace/002 at 2026-02-25 22:24:33 + [ 81.239580] null_blk: disk nullb1 created + [ 81.357294] BUG: using __this_cpu_read() in preemptible [00000000] code: dd/2516 + [ 81.362842] caller is tracing_record_cmdline+0x10/0x40 + [ 81.362872] CPU: 16 UID: 0 PID: 2516 Comm: dd Tainted: G N 7.0.0-rc1lblk+ #84 PREEMPT(full) + [ 81.362877] Tainted: [N]=TEST + [ 81.362878] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org 04/01/2014 + [ 81.362881] Call Trace: + [ 81.362884] + [ 81.362886] dump_stack_lvl+0x8d/0xb0 + ... + (See '/mnt/sda/blktests/results/nodev/blktrace/002.dmesg' for the entire message) + +[ 81.211018] run blktests blktrace/002 at 2026-02-25 22:24:33 +[ 81.239580] null_blk: disk nullb1 created +[ 81.357294] BUG: using __this_cpu_read() in preemptible [00000000] code: dd/2516 +[ 81.362842] caller is tracing_record_cmdline+0x10/0x40 +[ 81.362872] CPU: 16 UID: 0 PID: 2516 Comm: dd Tainted: G N 7.0.0-rc1lblk+ #84 PREEMPT(full) +[ 81.362877] Tainted: [N]=TEST +[ 81.362878] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org 04/01/2014 +[ 81.362881] Call Trace: +[ 81.362884] +[ 81.362886] dump_stack_lvl+0x8d/0xb0 +[ 81.362895] check_preemption_disabled+0xce/0xe0 +[ 81.362902] tracing_record_cmdline+0x10/0x40 +[ 81.362923] __blk_add_trace+0x307/0x5d0 +[ 81.362934] ? lock_acquire+0xe0/0x300 +[ 81.362940] ? iov_iter_extract_pages+0x101/0xa30 +[ 81.362959] blk_add_trace_bio+0x106/0x1e0 +[ 81.362968] submit_bio_noacct_nocheck+0x24b/0x3a0 +[ 81.362979] ? lockdep_init_map_type+0x58/0x260 +[ 81.362988] submit_bio_wait+0x56/0x90 +[ 81.363009] __blkdev_direct_IO_simple+0x16c/0x250 +[ 81.363026] ? __pfx_submit_bio_wait_endio+0x10/0x10 +[ 81.363038] ? rcu_read_lock_any_held+0x73/0xa0 +[ 81.363051] blkdev_read_iter+0xc1/0x140 +[ 81.363059] vfs_read+0x20b/0x330 +[ 81.363083] ksys_read+0x67/0xe0 +[ 81.363090] do_syscall_64+0xbf/0xf00 +[ 81.363102] entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 81.363106] RIP: 0033:0x7f281906029d +[ 81.363111] Code: 31 c0 e9 c6 fe ff ff 50 48 8d 3d 66 63 0a 00 e8 59 ff 01 00 66 0f 1f 84 00 00 00 00 00 80 3d 41 33 0e 00 00 74 17 31 c0 0f 05 <48> 3d 00 f0 ff ff 77 5b c3 66 2e 0f 1f 84 00 00 00 00 00 48 83 ec +[ 81.363113] RSP: 002b:00007ffca127dd48 EFLAGS: 00000246 ORIG_RAX: 0000000000000000 +[ 81.363120] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f281906029d +[ 81.363122] RDX: 0000000000001000 RSI: 0000559f8bfae000 RDI: 0000000000000000 +[ 81.363123] RBP: 0000000000001000 R08: 0000002863a10a81 R09: 00007f281915f000 +[ 81.363124] R10: 00007f2818f77b60 R11: 0000000000000246 R12: 0000559f8bfae000 +[ 81.363126] R13: 0000000000000000 R14: 0000000000000000 R15: 000000000000000a +[ 81.363142] + +The same BUG fires from blk_add_trace_plug(), blk_add_trace_unplug(), +and blk_add_trace_rq() paths as well. + +The purpose of tracing_record_cmdline() is to cache the task->comm for +a given PID so that the trace can later resolve it. It is only +meaningful when a trace event is actually being recorded. Ring buffer +reservation via ring_buffer_lock_reserve() disables preemption, and +preemption remains disabled until the event is committed :- + +__blk_add_trace() + __trace_buffer_lock_reserve() + __trace_buffer_lock_reserve() + ring_buffer_lock_reserve() + preempt_disable_notrace(); <--- + +With this fix blktests for blktrace pass: + + blktests (master) # ./check blktrace + blktrace/001 (blktrace zone management command tracing) [passed] + runtime 3.650s ... 3.647s + blktrace/002 (blktrace ftrace corruption with sysfs trace) [passed] + runtime 0.411s ... 0.384s + +Fixes: 7ffbd48d5cab ("tracing: Cache comms only after an event occurred") +Reported-by: Shinichiro Kawasaki +Suggested-by: Steven Rostedt +Signed-off-by: Chaitanya Kulkarni +Reviewed-by: Steven Rostedt (Google) +Signed-off-by: Jens Axboe +Signed-off-by: Rajani Kantha <681739313@139.com> +Signed-off-by: Sasha Levin +--- + kernel/trace/blktrace.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c +index d5d94510afd3f..ce797d8dd451c 100644 +--- a/kernel/trace/blktrace.c ++++ b/kernel/trace/blktrace.c +@@ -251,8 +251,6 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, + cpu = raw_smp_processor_id(); + + if (blk_tracer) { +- tracing_record_cmdline(current); +- + buffer = blk_tr->array_buffer.buffer; + trace_ctx = tracing_gen_ctx_flags(0); + event = trace_buffer_lock_reserve(buffer, TRACE_BLK, +@@ -260,6 +258,8 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, + trace_ctx); + if (!event) + return; ++ ++ tracing_record_cmdline(current); + t = ring_buffer_event_data(event); + goto record_it; + } +-- +2.53.0 + diff --git a/queue-6.6/btrfs-merge-btrfs_orig_bbio_end_io-into-btrfs_bio_en.patch b/queue-6.6/btrfs-merge-btrfs_orig_bbio_end_io-into-btrfs_bio_en.patch new file mode 100644 index 0000000000..dbed15ac35 --- /dev/null +++ b/queue-6.6/btrfs-merge-btrfs_orig_bbio_end_io-into-btrfs_bio_en.patch @@ -0,0 +1,152 @@ +From 0d511cd31c42e0af23c9cb2c4370ab25f4f24888 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Apr 2026 10:51:15 +0800 +Subject: btrfs: merge btrfs_orig_bbio_end_io() into btrfs_bio_end_io() + +From: Qu Wenruo + +[ Upstream commit 9ca0e58cb752b09816f56f7a3147a39773d5e831 ] + +There are only two differences between the two functions: + +- btrfs_orig_bbio_end_io() does extra error propagation + This is mostly to allow tolerance for write errors. + +- btrfs_orig_bbio_end_io() does extra pending_ios check + This check can handle both the original bio, or the cloned one. + (All accounting happens in the original one). + +This makes btrfs_orig_bbio_end_io() a much safer call. +In fact we already had a double freeing error due to usage of +btrfs_bio_end_io() in the error path of btrfs_submit_chunk(). + +So just move the whole content of btrfs_orig_bbio_end_io() into +btrfs_bio_end_io(). + +For normal paths this brings no change, because they are already calling +btrfs_orig_bbio_end_io() in the first place. + +For error paths (not only inside bio.c but also external callers), this +change will introduce extra checks, especially for external callers, as +they will error out without submitting the btrfs bio. + +But considering it's already in the error path, such slower but much +safer checks are still an overall win. + +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Ruohan Lan +Signed-off-by: Sasha Levin +--- + fs/btrfs/bio.c | 29 +++++++++++------------------ + 1 file changed, 11 insertions(+), 18 deletions(-) + +diff --git a/fs/btrfs/bio.c b/fs/btrfs/bio.c +index 6fa13be15f301..36b5ec9701d22 100644 +--- a/fs/btrfs/bio.c ++++ b/fs/btrfs/bio.c +@@ -122,12 +122,6 @@ static void __btrfs_bio_end_io(struct btrfs_bio *bbio) + } + } + +-void btrfs_bio_end_io(struct btrfs_bio *bbio, blk_status_t status) +-{ +- bbio->bio.bi_status = status; +- __btrfs_bio_end_io(bbio); +-} +- + static void btrfs_orig_write_end_io(struct bio *bio); + + static void btrfs_bbio_propagate_error(struct btrfs_bio *bbio, +@@ -149,8 +143,9 @@ static void btrfs_bbio_propagate_error(struct btrfs_bio *bbio, + } + } + +-static void btrfs_orig_bbio_end_io(struct btrfs_bio *bbio) ++void btrfs_bio_end_io(struct btrfs_bio *bbio, blk_status_t status) + { ++ bbio->bio.bi_status = status; + if (bbio->bio.bi_pool == &btrfs_clone_bioset) { + struct btrfs_bio *orig_bbio = bbio->private; + +@@ -181,7 +176,7 @@ static int prev_repair_mirror(struct btrfs_failed_bio *fbio, int cur_mirror) + static void btrfs_repair_done(struct btrfs_failed_bio *fbio) + { + if (atomic_dec_and_test(&fbio->repair_count)) { +- btrfs_orig_bbio_end_io(fbio->bbio); ++ btrfs_bio_end_io(fbio->bbio, fbio->bbio->bio.bi_status); + mempool_free(fbio, &btrfs_failed_bio_pool); + } + } +@@ -322,7 +317,7 @@ static void btrfs_check_read_bio(struct btrfs_bio *bbio, struct btrfs_device *de + if (fbio) + btrfs_repair_done(fbio); + else +- btrfs_orig_bbio_end_io(bbio); ++ btrfs_bio_end_io(bbio, bbio->bio.bi_status); + } + + static void btrfs_log_dev_io_error(struct bio *bio, struct btrfs_device *dev) +@@ -356,7 +351,7 @@ static void btrfs_end_bio_work(struct work_struct *work) + if (is_data_bbio(bbio)) + btrfs_check_read_bio(bbio, bbio->bio.bi_private); + else +- btrfs_orig_bbio_end_io(bbio); ++ btrfs_bio_end_io(bbio, bbio->bio.bi_status); + } + + static void btrfs_simple_end_io(struct bio *bio) +@@ -376,7 +371,7 @@ static void btrfs_simple_end_io(struct bio *bio) + } else { + if (bio_op(bio) == REQ_OP_ZONE_APPEND && !bio->bi_status) + btrfs_record_physical_zoned(bbio); +- btrfs_orig_bbio_end_io(bbio); ++ btrfs_bio_end_io(bbio, bbio->bio.bi_status); + } + } + +@@ -390,7 +385,7 @@ static void btrfs_raid56_end_io(struct bio *bio) + if (bio_op(bio) == REQ_OP_READ && is_data_bbio(bbio)) + btrfs_check_read_bio(bbio, NULL); + else +- btrfs_orig_bbio_end_io(bbio); ++ btrfs_bio_end_io(bbio, bbio->bio.bi_status); + + btrfs_put_bioc(bioc); + } +@@ -420,7 +415,7 @@ static void btrfs_orig_write_end_io(struct bio *bio) + if (bio_op(bio) == REQ_OP_ZONE_APPEND && !bio->bi_status) + stripe->physical = bio->bi_iter.bi_sector << SECTOR_SHIFT; + +- btrfs_orig_bbio_end_io(bbio); ++ btrfs_bio_end_io(bbio, bbio->bio.bi_status); + btrfs_put_bioc(bioc); + } + +@@ -586,7 +581,7 @@ static void run_one_async_done(struct btrfs_work *work) + + /* If an error occurred we just want to clean up the bio and move on. */ + if (bio->bi_status) { +- btrfs_orig_bbio_end_io(async->bbio); ++ btrfs_bio_end_io(async->bbio, async->bbio->bio.bi_status); + return; + } + +@@ -750,11 +745,9 @@ static bool btrfs_submit_chunk(struct btrfs_bio *bbio, int mirror_num) + ASSERT(bbio->bio.bi_pool == &btrfs_clone_bioset); + ASSERT(remaining); + +- remaining->bio.bi_status = ret; +- btrfs_orig_bbio_end_io(remaining); ++ btrfs_bio_end_io(remaining, ret); + } +- bbio->bio.bi_status = ret; +- btrfs_orig_bbio_end_io(bbio); ++ btrfs_bio_end_io(bbio, ret); + /* Do not submit another chunk */ + return true; + } +-- +2.53.0 + diff --git a/queue-6.6/ice-fix-memory-leak-in-ice_set_ringparam.patch b/queue-6.6/ice-fix-memory-leak-in-ice_set_ringparam.patch new file mode 100644 index 0000000000..4428eda274 --- /dev/null +++ b/queue-6.6/ice-fix-memory-leak-in-ice_set_ringparam.patch @@ -0,0 +1,74 @@ +From 1daf77241a1032468fd6c01ad83d725013f5ab3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Apr 2026 17:17:53 +0800 +Subject: ice: Fix memory leak in ice_set_ringparam() + +From: Zilin Guan + +[ Upstream commit fe868b499d16f55bbeea89992edb98043c9de416 ] + +In ice_set_ringparam, tx_rings and xdp_rings are allocated before +rx_rings. If the allocation of rx_rings fails, the code jumps to +the done label leaking both tx_rings and xdp_rings. Furthermore, if +the setup of an individual Rx ring fails during the loop, the code jumps +to the free_tx label which releases tx_rings but leaks xdp_rings. + +Fix this by introducing a free_xdp label and updating the error paths to +ensure both xdp_rings and tx_rings are properly freed if rx_rings +allocation or setup fails. + +Compile tested only. Issue found using a prototype static analysis tool +and code review. + +Fixes: fcea6f3da546 ("ice: Add stats and ethtool support") +Fixes: efc2214b6047 ("ice: Add support for XDP") +Signed-off-by: Zilin Guan +Reviewed-by: Paul Menzel +Reviewed-by: Aleksandr Loktionov +Tested-by: Rinitha S (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Rajani Kantha <681739313@139.com> +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_ethtool.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c +index 448ca855df901..c254484e9b6b2 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c +@@ -2847,7 +2847,7 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring, + rx_rings = kcalloc(vsi->num_rxq, sizeof(*rx_rings), GFP_KERNEL); + if (!rx_rings) { + err = -ENOMEM; +- goto done; ++ goto free_xdp; + } + + ice_for_each_rxq(vsi, i) { +@@ -2877,7 +2877,7 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring, + } + kfree(rx_rings); + err = -ENOMEM; +- goto free_tx; ++ goto free_xdp; + } + } + +@@ -2928,6 +2928,13 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring, + } + goto done; + ++free_xdp: ++ if (xdp_rings) { ++ ice_for_each_xdp_txq(vsi, i) ++ ice_free_tx_ring(&xdp_rings[i]); ++ kfree(xdp_rings); ++ } ++ + free_tx: + /* error cleanup if the Rx allocations failed after getting Tx */ + if (tx_rings) { +-- +2.53.0 + diff --git a/queue-6.6/iio-common-st_sensors-fix-use-of-uninitialize-device.patch b/queue-6.6/iio-common-st_sensors-fix-use-of-uninitialize-device.patch new file mode 100644 index 0000000000..d5bba9f93d --- /dev/null +++ b/queue-6.6/iio-common-st_sensors-fix-use-of-uninitialize-device.patch @@ -0,0 +1,292 @@ +From d8857c89bd89d712c0eae93fe3d21d6e4a9822e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Apr 2026 14:45:53 +0800 +Subject: iio: common: st_sensors: Fix use of uninitialize device structs + +From: Maud Spierings + +[ Upstream commit 9f92e93e257b33e73622640a9205f8642ec16ddd ] + +Throughout the various probe functions &indio_dev->dev is used before it +is initialized. This caused a kernel panic in st_sensors_power_enable() +when the call to devm_regulator_bulk_get_enable() fails and then calls +dev_err_probe() with the uninitialized device. + +This seems to only cause a panic with dev_err_probe(), dev_err(), +dev_warn() and dev_info() don't seem to cause a panic, but are fixed +as well. + +The issue is reported and traced here: [1] + +Link: https://lore.kernel.org/all/AM7P189MB100986A83D2F28AF3FFAF976E39EA@AM7P189MB1009.EURP189.PROD.OUTLOOK.COM/ [1] +Cc: stable@vger.kernel.org +Signed-off-by: Maud Spierings +Reviewed-by: Andy Shevchenko +Link: https://... [1] +Link: https://patch.msgid.link/20250527-st_iio_fix-v4-1-12d89801c761@gocontroll.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Fang Wang <32840572@qq.com> +Signed-off-by: Sasha Levin +--- + drivers/iio/accel/st_accel_core.c | 10 +++--- + .../iio/common/st_sensors/st_sensors_core.c | 36 +++++++++---------- + .../common/st_sensors/st_sensors_trigger.c | 20 +++++------ + 3 files changed, 31 insertions(+), 35 deletions(-) + +diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c +index 51d8de18e6d6d..45d2268e042ef 100644 +--- a/drivers/iio/accel/st_accel_core.c ++++ b/drivers/iio/accel/st_accel_core.c +@@ -1342,6 +1342,7 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev) + union acpi_object *ont; + union acpi_object *elements; + acpi_status status; ++ struct device *parent = indio_dev->dev.parent; + int ret = -EINVAL; + unsigned int val; + int i, j; +@@ -1360,7 +1361,7 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev) + }; + + +- adev = ACPI_COMPANION(indio_dev->dev.parent); ++ adev = ACPI_COMPANION(parent); + if (!adev) + return -ENXIO; + +@@ -1369,8 +1370,7 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev) + if (status == AE_NOT_FOUND) { + return -ENXIO; + } else if (ACPI_FAILURE(status)) { +- dev_warn(&indio_dev->dev, "failed to execute _ONT: %d\n", +- status); ++ dev_warn(parent, "failed to execute _ONT: %d\n", status); + return status; + } + +@@ -1446,12 +1446,12 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev) + } + + ret = 0; +- dev_info(&indio_dev->dev, "computed mount matrix from ACPI\n"); ++ dev_info(parent, "computed mount matrix from ACPI\n"); + + out: + kfree(buffer.pointer); + if (ret) +- dev_dbg(&indio_dev->dev, ++ dev_dbg(parent, + "failed to apply ACPI orientation data: %d\n", ret); + + return ret; +diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c +index c77d7bdcc1216..78f5728417d5b 100644 +--- a/drivers/iio/common/st_sensors/st_sensors_core.c ++++ b/drivers/iio/common/st_sensors/st_sensors_core.c +@@ -154,7 +154,7 @@ static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs) + return err; + + st_accel_set_fullscale_error: +- dev_err(&indio_dev->dev, "failed to set new fullscale.\n"); ++ dev_err(indio_dev->dev.parent, "failed to set new fullscale.\n"); + return err; + } + +@@ -231,8 +231,7 @@ int st_sensors_power_enable(struct iio_dev *indio_dev) + ARRAY_SIZE(regulator_names), + regulator_names); + if (err) +- return dev_err_probe(&indio_dev->dev, err, +- "unable to enable supplies\n"); ++ return dev_err_probe(parent, err, "unable to enable supplies\n"); + + return 0; + } +@@ -241,13 +240,14 @@ EXPORT_SYMBOL_NS(st_sensors_power_enable, IIO_ST_SENSORS); + static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev, + struct st_sensors_platform_data *pdata) + { ++ struct device *parent = indio_dev->dev.parent; + struct st_sensor_data *sdata = iio_priv(indio_dev); + + /* Sensor does not support interrupts */ + if (!sdata->sensor_settings->drdy_irq.int1.addr && + !sdata->sensor_settings->drdy_irq.int2.addr) { + if (pdata->drdy_int_pin) +- dev_info(&indio_dev->dev, ++ dev_info(parent, + "DRDY on pin INT%d specified, but sensor does not support interrupts\n", + pdata->drdy_int_pin); + return 0; +@@ -256,29 +256,27 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev, + switch (pdata->drdy_int_pin) { + case 1: + if (!sdata->sensor_settings->drdy_irq.int1.mask) { +- dev_err(&indio_dev->dev, +- "DRDY on INT1 not available.\n"); ++ dev_err(parent, "DRDY on INT1 not available.\n"); + return -EINVAL; + } + sdata->drdy_int_pin = 1; + break; + case 2: + if (!sdata->sensor_settings->drdy_irq.int2.mask) { +- dev_err(&indio_dev->dev, +- "DRDY on INT2 not available.\n"); ++ dev_err(parent, "DRDY on INT2 not available.\n"); + return -EINVAL; + } + sdata->drdy_int_pin = 2; + break; + default: +- dev_err(&indio_dev->dev, "DRDY on pdata not valid.\n"); ++ dev_err(parent, "DRDY on pdata not valid.\n"); + return -EINVAL; + } + + if (pdata->open_drain) { + if (!sdata->sensor_settings->drdy_irq.int1.addr_od && + !sdata->sensor_settings->drdy_irq.int2.addr_od) +- dev_err(&indio_dev->dev, ++ dev_err(parent, + "open drain requested but unsupported.\n"); + else + sdata->int_pin_open_drain = true; +@@ -336,6 +334,7 @@ EXPORT_SYMBOL_NS(st_sensors_dev_name_probe, IIO_ST_SENSORS); + int st_sensors_init_sensor(struct iio_dev *indio_dev, + struct st_sensors_platform_data *pdata) + { ++ struct device *parent = indio_dev->dev.parent; + struct st_sensor_data *sdata = iio_priv(indio_dev); + struct st_sensors_platform_data *of_pdata; + int err = 0; +@@ -343,7 +342,7 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev, + mutex_init(&sdata->odr_lock); + + /* If OF/DT pdata exists, it will take precedence of anything else */ +- of_pdata = st_sensors_dev_probe(indio_dev->dev.parent, pdata); ++ of_pdata = st_sensors_dev_probe(parent, pdata); + if (IS_ERR(of_pdata)) + return PTR_ERR(of_pdata); + if (of_pdata) +@@ -370,7 +369,7 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev, + if (err < 0) + return err; + } else +- dev_info(&indio_dev->dev, "Full-scale not possible\n"); ++ dev_info(parent, "Full-scale not possible\n"); + + err = st_sensors_set_odr(indio_dev, sdata->odr); + if (err < 0) +@@ -405,7 +404,7 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev, + mask = sdata->sensor_settings->drdy_irq.int2.mask_od; + } + +- dev_info(&indio_dev->dev, ++ dev_info(parent, + "set interrupt line to open drain mode on pin %d\n", + sdata->drdy_int_pin); + err = st_sensors_write_data_with_mask(indio_dev, addr, +@@ -594,21 +593,20 @@ EXPORT_SYMBOL_NS(st_sensors_get_settings_index, IIO_ST_SENSORS); + int st_sensors_verify_id(struct iio_dev *indio_dev) + { + struct st_sensor_data *sdata = iio_priv(indio_dev); ++ struct device *parent = indio_dev->dev.parent; + int wai, err; + + if (sdata->sensor_settings->wai_addr) { + err = regmap_read(sdata->regmap, + sdata->sensor_settings->wai_addr, &wai); + if (err < 0) { +- dev_err(&indio_dev->dev, +- "failed to read Who-Am-I register.\n"); +- return err; ++ return dev_err_probe(parent, err, ++ "failed to read Who-Am-I register.\n"); + } + + if (sdata->sensor_settings->wai != wai) { +- dev_err(&indio_dev->dev, +- "%s: WhoAmI mismatch (0x%x).\n", +- indio_dev->name, wai); ++ dev_warn(parent, "%s: WhoAmI mismatch (0x%x).\n", ++ indio_dev->name, wai); + return -EINVAL; + } + } +diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c +index a0df9250a69ff..b900acd471bd4 100644 +--- a/drivers/iio/common/st_sensors/st_sensors_trigger.c ++++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c +@@ -127,7 +127,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, + sdata->trig = devm_iio_trigger_alloc(parent, "%s-trigger", + indio_dev->name); + if (sdata->trig == NULL) { +- dev_err(&indio_dev->dev, "failed to allocate iio trigger.\n"); ++ dev_err(parent, "failed to allocate iio trigger.\n"); + return -ENOMEM; + } + +@@ -143,7 +143,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, + case IRQF_TRIGGER_FALLING: + case IRQF_TRIGGER_LOW: + if (!sdata->sensor_settings->drdy_irq.addr_ihl) { +- dev_err(&indio_dev->dev, ++ dev_err(parent, + "falling/low specified for IRQ but hardware supports only rising/high: will request rising/high\n"); + if (irq_trig == IRQF_TRIGGER_FALLING) + irq_trig = IRQF_TRIGGER_RISING; +@@ -156,21 +156,19 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, + sdata->sensor_settings->drdy_irq.mask_ihl, 1); + if (err < 0) + return err; +- dev_info(&indio_dev->dev, ++ dev_info(parent, + "interrupts on the falling edge or active low level\n"); + } + break; + case IRQF_TRIGGER_RISING: +- dev_info(&indio_dev->dev, +- "interrupts on the rising edge\n"); ++ dev_info(parent, "interrupts on the rising edge\n"); + break; + case IRQF_TRIGGER_HIGH: +- dev_info(&indio_dev->dev, +- "interrupts active high level\n"); ++ dev_info(parent, "interrupts active high level\n"); + break; + default: + /* This is the most preferred mode, if possible */ +- dev_err(&indio_dev->dev, ++ dev_err(parent, + "unsupported IRQ trigger specified (%lx), enforce rising edge\n", irq_trig); + irq_trig = IRQF_TRIGGER_RISING; + } +@@ -179,7 +177,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, + if (irq_trig == IRQF_TRIGGER_FALLING || + irq_trig == IRQF_TRIGGER_RISING) { + if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr) { +- dev_err(&indio_dev->dev, ++ dev_err(parent, + "edge IRQ not supported w/o stat register.\n"); + return -EOPNOTSUPP; + } +@@ -214,13 +212,13 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, + sdata->trig->name, + sdata->trig); + if (err) { +- dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n"); ++ dev_err(parent, "failed to request trigger IRQ.\n"); + return err; + } + + err = devm_iio_trigger_register(parent, sdata->trig); + if (err < 0) { +- dev_err(&indio_dev->dev, "failed to register iio trigger.\n"); ++ dev_err(parent, "failed to register iio trigger.\n"); + return err; + } + indio_dev->trig = iio_trigger_get(sdata->trig); +-- +2.53.0 + diff --git a/queue-6.6/kvm-nvmx-fold-requested-virtual-interrupt-check-into.patch b/queue-6.6/kvm-nvmx-fold-requested-virtual-interrupt-check-into.patch new file mode 100644 index 0000000000..e39c13faa4 --- /dev/null +++ b/queue-6.6/kvm-nvmx-fold-requested-virtual-interrupt-check-into.patch @@ -0,0 +1,145 @@ +From 3ba9031edb6005c9803b17be7b4ba25149e517f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Apr 2026 13:23:46 -0700 +Subject: KVM: nVMX: Fold requested virtual interrupt check into + has_nested_events() + +From: Sean Christopherson + +[ Upstream commit 321ef62b0c5f6f57bb8500a2ca5986052675abbf ] + +Check for a Requested Virtual Interrupt, i.e. a virtual interrupt that is +pending delivery, in vmx_has_nested_events() and drop the one-off +kvm_x86_ops.guest_apic_has_interrupt() hook. + +In addition to dropping a superfluous hook, this fixes a bug where KVM +would incorrectly treat virtual interrupts _for L2_ as always enabled due +to kvm_arch_interrupt_allowed(), by way of vmx_interrupt_blocked(), +treating IRQs as enabled if L2 is active and vmcs12 is configured to exit +on IRQs, i.e. KVM would treat a virtual interrupt for L2 as a valid wake +event based on L1's IRQ blocking status. + +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20240607172609.3205077-6-seanjc@google.com +Signed-off-by: Sean Christopherson +Cc: Taeyang Lee <0wn@theori.io> +[sean: deal with lack of vmx/main.c and vmx/x86_ops.h] +Signed-off-by: Sean Christopherson +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/kvm-x86-ops.h | 1 - + arch/x86/include/asm/kvm_host.h | 1 - + arch/x86/kvm/vmx/nested.c | 4 ++++ + arch/x86/kvm/vmx/vmx.c | 21 --------------------- + arch/x86/kvm/x86.c | 10 +--------- + 5 files changed, 5 insertions(+), 32 deletions(-) + +diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h +index a0a4fc684e63b..3d00c2444a757 100644 +--- a/arch/x86/include/asm/kvm-x86-ops.h ++++ b/arch/x86/include/asm/kvm-x86-ops.h +@@ -83,7 +83,6 @@ KVM_X86_OP_OPTIONAL(update_cr8_intercept) + KVM_X86_OP(refresh_apicv_exec_ctrl) + KVM_X86_OP_OPTIONAL(hwapic_irr_update) + KVM_X86_OP_OPTIONAL(hwapic_isr_update) +-KVM_X86_OP_OPTIONAL_RET0(guest_apic_has_interrupt) + KVM_X86_OP_OPTIONAL(load_eoi_exitmap) + KVM_X86_OP_OPTIONAL(set_virtual_apic_mode) + KVM_X86_OP_OPTIONAL(set_apic_access_page_addr) +diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h +index df950c184c597..d79b8f7a39913 100644 +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -1671,7 +1671,6 @@ struct kvm_x86_ops { + void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu); + void (*hwapic_irr_update)(struct kvm_vcpu *vcpu, int max_irr); + void (*hwapic_isr_update)(struct kvm_vcpu *vcpu, int isr); +- bool (*guest_apic_has_interrupt)(struct kvm_vcpu *vcpu); + void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap); + void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu); + void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu); +diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c +index fb274bae41e2c..377b30212c191 100644 +--- a/arch/x86/kvm/vmx/nested.c ++++ b/arch/x86/kvm/vmx/nested.c +@@ -4007,6 +4007,10 @@ static bool vmx_has_nested_events(struct kvm_vcpu *vcpu, bool for_injection) + + vppr = *((u32 *)(vapic + APIC_PROCPRI)); + ++ max_irr = vmx_get_rvi(); ++ if ((max_irr & 0xf0) > (vppr & 0xf0)) ++ return true; ++ + if (vmx->nested.pi_pending && vmx->nested.pi_desc && + pi_test_on(vmx->nested.pi_desc)) { + max_irr = pi_find_highest_vector(vmx->nested.pi_desc); +diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c +index b68fb5329a13e..4a45e86c5e2fc 100644 +--- a/arch/x86/kvm/vmx/vmx.c ++++ b/arch/x86/kvm/vmx/vmx.c +@@ -4127,26 +4127,6 @@ void pt_update_intercept_for_msr(struct kvm_vcpu *vcpu) + } + } + +-static bool vmx_guest_apic_has_interrupt(struct kvm_vcpu *vcpu) +-{ +- struct vcpu_vmx *vmx = to_vmx(vcpu); +- void *vapic_page; +- u32 vppr; +- int rvi; +- +- if (WARN_ON_ONCE(!is_guest_mode(vcpu)) || +- !nested_cpu_has_vid(get_vmcs12(vcpu)) || +- WARN_ON_ONCE(!vmx->nested.virtual_apic_map.gfn)) +- return false; +- +- rvi = vmx_get_rvi(); +- +- vapic_page = vmx->nested.virtual_apic_map.hva; +- vppr = *((u32 *)(vapic_page + APIC_PROCPRI)); +- +- return ((rvi & 0xf0) > (vppr & 0xf0)); +-} +- + static void vmx_msr_filter_changed(struct kvm_vcpu *vcpu) + { + struct vcpu_vmx *vmx = to_vmx(vcpu); +@@ -8390,7 +8370,6 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = { + .required_apicv_inhibits = VMX_REQUIRED_APICV_INHIBITS, + .hwapic_irr_update = vmx_hwapic_irr_update, + .hwapic_isr_update = vmx_hwapic_isr_update, +- .guest_apic_has_interrupt = vmx_guest_apic_has_interrupt, + .sync_pir_to_irr = vmx_sync_pir_to_irr, + .deliver_interrupt = vmx_deliver_interrupt, + .dy_apicv_has_pending_interrupt = pi_has_pending_interrupt, +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index ac0b458582c38..485c1820e65a9 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -12906,12 +12906,6 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, + kvm_arch_free_memslot(kvm, old); + } + +-static inline bool kvm_guest_apic_has_interrupt(struct kvm_vcpu *vcpu) +-{ +- return (is_guest_mode(vcpu) && +- static_call(kvm_x86_guest_apic_has_interrupt)(vcpu)); +-} +- + static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu) + { + if (!list_empty_careful(&vcpu->async_pf.done)) +@@ -12942,9 +12936,7 @@ static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu) + if (kvm_test_request(KVM_REQ_PMI, vcpu)) + return true; + +- if (kvm_arch_interrupt_allowed(vcpu) && +- (kvm_cpu_has_interrupt(vcpu) || +- kvm_guest_apic_has_interrupt(vcpu))) ++ if (kvm_arch_interrupt_allowed(vcpu) && kvm_cpu_has_interrupt(vcpu)) + return true; + + if (kvm_hv_has_stimer_pending(vcpu)) +-- +2.53.0 + diff --git a/queue-6.6/net-add-proper-rcu-protection-to-proc-net-ptype.patch b/queue-6.6/net-add-proper-rcu-protection-to-proc-net-ptype.patch new file mode 100644 index 0000000000..4be8c48823 --- /dev/null +++ b/queue-6.6/net-add-proper-rcu-protection-to-proc-net-ptype.patch @@ -0,0 +1,190 @@ +From 33204afa2c38ef238d3f681a147f5c6ce1e97cd9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Apr 2026 20:11:18 +0800 +Subject: net: add proper RCU protection to /proc/net/ptype + +From: Eric Dumazet + +[ Upstream commit f613e8b4afea0cd17c7168e8b00e25bc8d33175d ] + +Yin Fengwei reported an RCU stall in ptype_seq_show() and provided +a patch. + +Real issue is that ptype_seq_next() and ptype_seq_show() violate +RCU rules. + +ptype_seq_show() runs under rcu_read_lock(), and reads pt->dev +to get device name without any barrier. + +At the same time, concurrent writers can remove a packet_type structure +(which is correctly freed after an RCU grace period) and clear pt->dev +without an RCU grace period. + +Define ptype_iter_state to carry a dev pointer along seq_net_private: + +struct ptype_iter_state { + struct seq_net_private p; + struct net_device *dev; // added in this patch +}; + +We need to record the device pointer in ptype_get_idx() and +ptype_seq_next() so that ptype_seq_show() is safe against +concurrent pt->dev changes. + +We also need to add full RCU protection in ptype_seq_next(). +(Missing READ_ONCE() when reading list.next values) + +Many thanks to Dong Chenchen for providing a repro. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Fixes: 1d10f8a1f40b ("net-procfs: show net devices bound packet types") +Fixes: c353e8983e0d ("net: introduce per netns packet chains") +Reported-by: Yin Fengwei +Reported-by: Dong Chenchen +Closes: https://lore.kernel.org/netdev/CANn89iKRRKPnWjJmb-_3a=sq+9h6DvTQM4DBZHT5ZRGPMzQaiA@mail.gmail.com/T/#m7b80b9fc9b9267f90e0b7aad557595f686f9c50d + +Signed-off-by: Eric Dumazet +Reviewed-by: Willem de Bruijn +Tested-by: Yin Fengwei +Link: https://patch.msgid.link/20260202205217.2881198-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +[ Some adjustments have been made. ] +Signed-off-by: XiaoHua Wang <561399680@139.com> +Signed-off-by: Sasha Levin +--- + net/core/net-procfs.c | 49 +++++++++++++++++++++++++++++-------------- + 1 file changed, 33 insertions(+), 16 deletions(-) + +diff --git a/net/core/net-procfs.c b/net/core/net-procfs.c +index 09f7ed1a04e8a..d6d139b49384b 100644 +--- a/net/core/net-procfs.c ++++ b/net/core/net-procfs.c +@@ -200,8 +200,14 @@ static const struct seq_operations softnet_seq_ops = { + .show = softnet_seq_show, + }; + ++struct ptype_iter_state { ++ struct seq_net_private p; ++ struct net_device *dev; ++}; ++ + static void *ptype_get_idx(struct seq_file *seq, loff_t pos) + { ++ struct ptype_iter_state *iter = seq->private; + struct list_head *ptype_list = NULL; + struct packet_type *pt = NULL; + struct net_device *dev; +@@ -211,12 +217,16 @@ static void *ptype_get_idx(struct seq_file *seq, loff_t pos) + for_each_netdev_rcu(seq_file_net(seq), dev) { + ptype_list = &dev->ptype_all; + list_for_each_entry_rcu(pt, ptype_list, list) { +- if (i == pos) ++ if (i == pos) { ++ iter->dev = dev; + return pt; ++ } + ++i; + } + } + ++ iter->dev = NULL; ++ + list_for_each_entry_rcu(pt, &ptype_all, list) { + if (i == pos) + return pt; +@@ -242,6 +252,7 @@ static void *ptype_seq_start(struct seq_file *seq, loff_t *pos) + + static void *ptype_seq_next(struct seq_file *seq, void *v, loff_t *pos) + { ++ struct ptype_iter_state *iter = seq->private; + struct net_device *dev; + struct packet_type *pt; + struct list_head *nxt; +@@ -252,20 +263,21 @@ static void *ptype_seq_next(struct seq_file *seq, void *v, loff_t *pos) + return ptype_get_idx(seq, 0); + + pt = v; +- nxt = pt->list.next; +- if (pt->dev) { +- if (nxt != &pt->dev->ptype_all) ++ nxt = READ_ONCE(pt->list.next); ++ dev = iter->dev; ++ if (dev) { ++ if (nxt != &dev->ptype_all) + goto found; + +- dev = pt->dev; + for_each_netdev_continue_rcu(seq_file_net(seq), dev) { +- if (!list_empty(&dev->ptype_all)) { +- nxt = dev->ptype_all.next; ++ nxt = READ_ONCE(dev->ptype_all.next); ++ if (nxt != &dev->ptype_all) { ++ iter->dev = dev; + goto found; + } + } +- +- nxt = ptype_all.next; ++ iter->dev = NULL; ++ nxt = READ_ONCE(ptype_all.next); + goto ptype_all; + } + +@@ -274,14 +286,14 @@ static void *ptype_seq_next(struct seq_file *seq, void *v, loff_t *pos) + if (nxt != &ptype_all) + goto found; + hash = 0; +- nxt = ptype_base[0].next; ++ nxt = READ_ONCE(ptype_base[0].next); + } else + hash = ntohs(pt->type) & PTYPE_HASH_MASK; + + while (nxt == &ptype_base[hash]) { + if (++hash >= PTYPE_HASH_SIZE) + return NULL; +- nxt = ptype_base[hash].next; ++ nxt = READ_ONCE(ptype_base[hash].next); + } + found: + return list_entry(nxt, struct packet_type, list); +@@ -295,19 +307,24 @@ static void ptype_seq_stop(struct seq_file *seq, void *v) + + static int ptype_seq_show(struct seq_file *seq, void *v) + { ++ struct ptype_iter_state *iter = seq->private; + struct packet_type *pt = v; ++ struct net_device *dev; + +- if (v == SEQ_START_TOKEN) ++ if (v == SEQ_START_TOKEN) { + seq_puts(seq, "Type Device Function\n"); +- else if ((!pt->af_packet_net || net_eq(pt->af_packet_net, seq_file_net(seq))) && +- (!pt->dev || net_eq(dev_net(pt->dev), seq_file_net(seq)))) { ++ return 0; ++ } ++ dev = iter->dev; ++ if ((!pt->af_packet_net || net_eq(pt->af_packet_net, seq_file_net(seq))) && ++ (!dev || net_eq(dev_net(dev), seq_file_net(seq)))) { + if (pt->type == htons(ETH_P_ALL)) + seq_puts(seq, "ALL "); + else + seq_printf(seq, "%04x", ntohs(pt->type)); + + seq_printf(seq, " %-8s %ps\n", +- pt->dev ? pt->dev->name : "", pt->func); ++ dev ? dev->name : "", pt->func); + } + + return 0; +@@ -331,7 +348,7 @@ static int __net_init dev_proc_net_init(struct net *net) + &softnet_seq_ops)) + goto out_dev; + if (!proc_create_net("ptype", 0444, net->proc_net, &ptype_seq_ops, +- sizeof(struct seq_net_private))) ++ sizeof(struct ptype_iter_state))) + goto out_softnet; + + if (wext_proc_init(net)) +-- +2.53.0 + diff --git a/queue-6.6/net-sched-fix-tcf_layer_transport-handling-in-tcf_ge.patch b/queue-6.6/net-sched-fix-tcf_layer_transport-handling-in-tcf_ge.patch new file mode 100644 index 0000000000..79bef393ab --- /dev/null +++ b/queue-6.6/net-sched-fix-tcf_layer_transport-handling-in-tcf_ge.patch @@ -0,0 +1,131 @@ +From 3b39a0168890db46f62fe939a8c446a944a88ccc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Apr 2026 15:19:21 -0700 +Subject: net: sched: fix TCF_LAYER_TRANSPORT handling in tcf_get_base_ptr() + +From: Eric Dumazet + +[Upstream commit 4fe5a00ec70717a7f1002d8913ec6143582b3c8e] + +syzbot reported that tcf_get_base_ptr() can be called while transport +header is not set [1]. + +Instead of returning a dangling pointer, return NULL. + +Fix tcf_get_base_ptr() callers to handle this NULL value. + +[1] + WARNING: CPU: 1 PID: 6019 at ./include/linux/skbuff.h:3071 skb_transport_header include/linux/skbuff.h:3071 [inline] + WARNING: CPU: 1 PID: 6019 at ./include/linux/skbuff.h:3071 tcf_get_base_ptr include/net/pkt_cls.h:539 [inline] + WARNING: CPU: 1 PID: 6019 at ./include/linux/skbuff.h:3071 em_nbyte_match+0x2d8/0x3f0 net/sched/em_nbyte.c:43 +Modules linked in: +CPU: 1 UID: 0 PID: 6019 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full) +Call Trace: + + tcf_em_match net/sched/ematch.c:494 [inline] + __tcf_em_tree_match+0x1ac/0x770 net/sched/ematch.c:520 + tcf_em_tree_match include/net/pkt_cls.h:512 [inline] + basic_classify+0x115/0x2d0 net/sched/cls_basic.c:50 + tc_classify include/net/tc_wrapper.h:197 [inline] + __tcf_classify net/sched/cls_api.c:1764 [inline] + tcf_classify+0x4cf/0x1140 net/sched/cls_api.c:1860 + multiq_classify net/sched/sch_multiq.c:39 [inline] + multiq_enqueue+0xfd/0x4c0 net/sched/sch_multiq.c:66 + dev_qdisc_enqueue+0x4e/0x260 net/core/dev.c:4118 + __dev_xmit_skb net/core/dev.c:4214 [inline] + __dev_queue_xmit+0xe83/0x3b50 net/core/dev.c:4729 + packet_snd net/packet/af_packet.c:3076 [inline] + packet_sendmsg+0x3e33/0x5080 net/packet/af_packet.c:3108 + sock_sendmsg_nosec net/socket.c:727 [inline] + __sock_sendmsg+0x21c/0x270 net/socket.c:742 + ____sys_sendmsg+0x505/0x830 net/socket.c:2630 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+f3a497f02c389d86ef16@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/6920855a.a70a0220.2ea503.0058.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Reviewed-by: Jamal Hadi Salim +Link: https://patch.msgid.link/20251121154100.1616228-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Chelsy Ratnawat +Signed-off-by: Sasha Levin +--- + include/net/pkt_cls.h | 2 ++ + net/sched/em_cmp.c | 5 ++++- + net/sched/em_nbyte.c | 2 ++ + net/sched/em_text.c | 11 +++++++++-- + 4 files changed, 17 insertions(+), 3 deletions(-) + +diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h +index f308e8268651e..ccc1c698ed007 100644 +--- a/include/net/pkt_cls.h ++++ b/include/net/pkt_cls.h +@@ -525,6 +525,8 @@ static inline unsigned char * tcf_get_base_ptr(struct sk_buff *skb, int layer) + case TCF_LAYER_NETWORK: + return skb_network_header(skb); + case TCF_LAYER_TRANSPORT: ++ if (!skb_transport_header_was_set(skb)) ++ break; + return skb_transport_header(skb); + } + +diff --git a/net/sched/em_cmp.c b/net/sched/em_cmp.c +index f17b049ea5309..71ce113f2d08e 100644 +--- a/net/sched/em_cmp.c ++++ b/net/sched/em_cmp.c +@@ -22,9 +22,12 @@ static int em_cmp_match(struct sk_buff *skb, struct tcf_ematch *em, + struct tcf_pkt_info *info) + { + struct tcf_em_cmp *cmp = (struct tcf_em_cmp *) em->data; +- unsigned char *ptr = tcf_get_base_ptr(skb, cmp->layer) + cmp->off; ++ unsigned char *ptr = tcf_get_base_ptr(skb, cmp->layer); + u32 val = 0; + ++ if (!ptr) ++ return 0; ++ ptr += cmp->off; + if (!tcf_valid_offset(skb, ptr, cmp->align)) + return 0; + +diff --git a/net/sched/em_nbyte.c b/net/sched/em_nbyte.c +index a83b237cbeb06..2e3c1d58d4563 100644 +--- a/net/sched/em_nbyte.c ++++ b/net/sched/em_nbyte.c +@@ -42,6 +42,8 @@ static int em_nbyte_match(struct sk_buff *skb, struct tcf_ematch *em, + struct nbyte_data *nbyte = (struct nbyte_data *) em->data; + unsigned char *ptr = tcf_get_base_ptr(skb, nbyte->hdr.layer); + ++ if (!ptr) ++ return 0; + ptr += nbyte->hdr.off; + + if (!tcf_valid_offset(skb, ptr, nbyte->hdr.len)) +diff --git a/net/sched/em_text.c b/net/sched/em_text.c +index f176afb70559e..32aae8a9dedaa 100644 +--- a/net/sched/em_text.c ++++ b/net/sched/em_text.c +@@ -29,12 +29,19 @@ static int em_text_match(struct sk_buff *skb, struct tcf_ematch *m, + struct tcf_pkt_info *info) + { + struct text_match *tm = EM_TEXT_PRIV(m); ++ unsigned char *ptr; + int from, to; + +- from = tcf_get_base_ptr(skb, tm->from_layer) - skb->data; ++ ptr = tcf_get_base_ptr(skb, tm->from_layer); ++ if (!ptr) ++ return 0; ++ from = ptr - skb->data; + from += tm->from_offset; + +- to = tcf_get_base_ptr(skb, tm->to_layer) - skb->data; ++ ptr = tcf_get_base_ptr(skb, tm->to_layer); ++ if (!ptr) ++ return 0; ++ to = ptr - skb->data; + to += tm->to_offset; + + return skb_find_text(skb, from, to, tm->config) != UINT_MAX; +-- +2.53.0 + diff --git a/queue-6.6/net-skb-fix-cross-cache-free-of-kfence-allocated-skb.patch b/queue-6.6/net-skb-fix-cross-cache-free-of-kfence-allocated-skb.patch new file mode 100644 index 0000000000..b13b768b48 --- /dev/null +++ b/queue-6.6/net-skb-fix-cross-cache-free-of-kfence-allocated-skb.patch @@ -0,0 +1,64 @@ +From c15e2fa830b2c88acbf4de38f535507f20aa7a9c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Apr 2026 08:11:26 -0400 +Subject: net: skb: fix cross-cache free of KFENCE-allocated skb head + +From: Jiayuan Chen + +[ Upstream commit 0f42e3f4fe2a58394e37241d02d9ca6ab7b7d516 ] + +SKB_SMALL_HEAD_CACHE_SIZE is intentionally set to a non-power-of-2 +value (e.g. 704 on x86_64) to avoid collisions with generic kmalloc +bucket sizes. This ensures that skb_kfree_head() can reliably use +skb_end_offset to distinguish skb heads allocated from +skb_small_head_cache vs. generic kmalloc caches. + +However, when KFENCE is enabled, kfence_ksize() returns the exact +requested allocation size instead of the slab bucket size. If a caller +(e.g. bpf_test_init) allocates skb head data via kzalloc() and the +requested size happens to equal SKB_SMALL_HEAD_CACHE_SIZE, then +slab_build_skb() -> ksize() returns that exact value. After subtracting +skb_shared_info overhead, skb_end_offset ends up matching +SKB_SMALL_HEAD_HEADROOM, causing skb_kfree_head() to incorrectly free +the object to skb_small_head_cache instead of back to the original +kmalloc cache, resulting in a slab cross-cache free: + + kmem_cache_free(skbuff_small_head): Wrong slab cache. Expected + skbuff_small_head but got kmalloc-1k + +Fix this by always calling kfree(head) in skb_kfree_head(). This keeps +the free path generic and avoids allocator-specific misclassification +for KFENCE objects. + +Fixes: bf9f1baa279f ("net: add dedicated kmem_cache for typical/small skb->head") +Reported-by: Antonius +Closes: https://lore.kernel.org/netdev/CAK8a0jxC5L5N7hq-DT2_NhUyjBxrPocoiDazzsBk4TGgT1r4-A@mail.gmail.com/ +Signed-off-by: Jiayuan Chen +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20260403014517.142550-1-jiayuan.chen@linux.dev +Signed-off-by: Jakub Kicinski +[ adapted variable names ] +Signed-off-by: Sasha Levin +--- + net/core/skbuff.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index 4c28954f915fa..c81ef99d39b04 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -943,10 +943,7 @@ static bool skb_pp_recycle(struct sk_buff *skb, void *data, bool napi_safe) + + static void skb_kfree_head(void *head, unsigned int end_offset) + { +- if (end_offset == SKB_SMALL_HEAD_HEADROOM) +- kmem_cache_free(skb_small_head_cache, head); +- else +- kfree(head); ++ kfree(head); + } + + static void skb_free_head(struct sk_buff *skb, bool napi_safe) +-- +2.53.0 + diff --git a/queue-6.6/nf_tables-nft_dynset-fix-possible-stateful-expressio.patch b/queue-6.6/nf_tables-nft_dynset-fix-possible-stateful-expressio.patch new file mode 100644 index 0000000000..e9c60bd190 --- /dev/null +++ b/queue-6.6/nf_tables-nft_dynset-fix-possible-stateful-expressio.patch @@ -0,0 +1,109 @@ +From 7a7a81db528919cfb1cb28ac5e3a207144930391 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Apr 2026 16:18:55 +0800 +Subject: nf_tables: nft_dynset: fix possible stateful expression memleak in + error path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pablo Neira Ayuso + +[ Upstream commit 0548a13b5a145b16e4da0628b5936baf35f51b43 ] + +If cloning the second stateful expression in the element via GFP_ATOMIC +fails, then the first stateful expression remains in place without being +released. + +   unreferenced object (percpu) 0x607b97e9cab8 (size 16): +     comm "softirq", pid 0, jiffies 4294931867 +     hex dump (first 16 bytes on cpu 3): +       00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +     backtrace (crc 0): +       pcpu_alloc_noprof+0x453/0xd80 +       nft_counter_clone+0x9c/0x190 [nf_tables] +       nft_expr_clone+0x8f/0x1b0 [nf_tables] +       nft_dynset_new+0x2cb/0x5f0 [nf_tables] +       nft_rhash_update+0x236/0x11c0 [nf_tables] +       nft_dynset_eval+0x11f/0x670 [nf_tables] +       nft_do_chain+0x253/0x1700 [nf_tables] +       nft_do_chain_ipv4+0x18d/0x270 [nf_tables] +       nf_hook_slow+0xaa/0x1e0 +       ip_local_deliver+0x209/0x330 + +Fixes: 563125a73ac3 ("netfilter: nftables: generalize set extension to support for several expressions") +Reported-by: Gurpreet Shergill +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Florian Westphal +[ Minor conflict resolved. ] +Signed-off-by: Li hongliang <1468888505@139.com> +Signed-off-by: Sasha Levin +--- + include/net/netfilter/nf_tables.h | 2 ++ + net/netfilter/nf_tables_api.c | 4 ++-- + net/netfilter/nft_dynset.c | 10 +++++++++- + 3 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h +index 000ae2900f8c3..ab0567951e310 100644 +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -861,6 +861,8 @@ void *nft_set_elem_init(const struct nft_set *set, + u64 timeout, u64 expiration, gfp_t gfp); + int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set, + struct nft_expr *expr_array[]); ++void nft_set_elem_expr_destroy(const struct nft_ctx *ctx, ++ struct nft_set_elem_expr *elem_expr); + void nft_set_elem_destroy(const struct nft_set *set, void *elem, + bool destroy_expr); + void nf_tables_set_elem_destroy(const struct nft_ctx *ctx, +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 0aaddc1131c65..a0914a92e07dd 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -6464,8 +6464,8 @@ static void __nft_set_elem_expr_destroy(const struct nft_ctx *ctx, + } + } + +-static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx, +- struct nft_set_elem_expr *elem_expr) ++void nft_set_elem_expr_destroy(const struct nft_ctx *ctx, ++ struct nft_set_elem_expr *elem_expr) + { + struct nft_expr *expr; + u32 size; +diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c +index 9a0aaeed23602..87c6a02675ba3 100644 +--- a/net/netfilter/nft_dynset.c ++++ b/net/netfilter/nft_dynset.c +@@ -30,18 +30,26 @@ static int nft_dynset_expr_setup(const struct nft_dynset *priv, + const struct nft_set_ext *ext) + { + struct nft_set_elem_expr *elem_expr = nft_set_ext_expr(ext); ++ struct nft_ctx ctx = { ++ .net = read_pnet(&priv->set->net), ++ .family = priv->set->table->family, ++ }; + struct nft_expr *expr; + int i; + + for (i = 0; i < priv->num_exprs; i++) { + expr = nft_setelem_expr_at(elem_expr, elem_expr->size); + if (nft_expr_clone(expr, priv->expr_array[i], GFP_ATOMIC) < 0) +- return -1; ++ goto err_out; + + elem_expr->size += priv->expr_array[i]->ops->size; + } + + return 0; ++err_out: ++ nft_set_elem_expr_destroy(&ctx, elem_expr); ++ ++ return -1; + } + + static void *nft_dynset_new(struct nft_set *set, const struct nft_expr *expr, +-- +2.53.0 + diff --git a/queue-6.6/nfc-nci-complete-pending-data-exchange-on-device-clo.patch b/queue-6.6/nfc-nci-complete-pending-data-exchange-on-device-clo.patch new file mode 100644 index 0000000000..b1edbe39db --- /dev/null +++ b/queue-6.6/nfc-nci-complete-pending-data-exchange-on-device-clo.patch @@ -0,0 +1,72 @@ +From 64b60fe4028935f561cedbd598a3318249a45809 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Apr 2026 16:11:19 +0800 +Subject: nfc: nci: complete pending data exchange on device close + +From: Jakub Kicinski + +[ Upstream commit 66083581945bd5b8e99fe49b5aeb83d03f62d053 ] + +In nci_close_device(), complete any pending data exchange before +closing. The data exchange callback (e.g. +rawsock_data_exchange_complete) holds a socket reference. + +NIPA occasionally hits this leak: + +unreferenced object 0xff1100000f435000 (size 2048): + comm "nci_dev", pid 3954, jiffies 4295441245 + hex dump (first 32 bytes): + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 27 00 01 40 00 00 00 00 00 00 00 00 00 00 00 00 '..@............ + backtrace (crc ec2b3c5): + __kmalloc_noprof+0x4db/0x730 + sk_prot_alloc.isra.0+0xe4/0x1d0 + sk_alloc+0x36/0x760 + rawsock_create+0xd1/0x540 + nfc_sock_create+0x11f/0x280 + __sock_create+0x22d/0x630 + __sys_socket+0x115/0x1d0 + __x64_sys_socket+0x72/0xd0 + do_syscall_64+0x117/0xfc0 + entry_SYSCALL_64_after_hwframe+0x4b/0x53 + +Fixes: 38f04c6b1b68 ("NFC: protect nci_data_exchange transactions") +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20260303162346.2071888-4-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Rajani Kantha <681739313@139.com> +Signed-off-by: Sasha Levin +--- + net/nfc/nci/core.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c +index e2ffdb06bf9aa..fb81d9909500f 100644 +--- a/net/nfc/nci/core.c ++++ b/net/nfc/nci/core.c +@@ -567,6 +567,10 @@ static int nci_close_device(struct nci_dev *ndev) + flush_workqueue(ndev->cmd_wq); + del_timer_sync(&ndev->cmd_timer); + del_timer_sync(&ndev->data_timer); ++ if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags)) ++ nci_data_exchange_complete(ndev, NULL, ++ ndev->cur_conn_id, ++ -ENODEV); + mutex_unlock(&ndev->req_lock); + return 0; + } +@@ -597,6 +601,11 @@ static int nci_close_device(struct nci_dev *ndev) + flush_workqueue(ndev->cmd_wq); + + del_timer_sync(&ndev->cmd_timer); ++ del_timer_sync(&ndev->data_timer); ++ ++ if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags)) ++ nci_data_exchange_complete(ndev, NULL, ndev->cur_conn_id, ++ -ENODEV); + + /* Clear flags except NCI_UNREG */ + ndev->flags &= BIT(NCI_UNREG); +-- +2.53.0 + diff --git a/queue-6.6/series b/queue-6.6/series index a8ae671f09..7b54b7e6e8 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -88,3 +88,13 @@ usbip-validate-number_of_packets-in-usbip_pack_ret_submit.patch usb-storage-expand-range-of-matched-versions-for-vl817-quirks-entry.patch usb-cdc-acm-add-quirks-for-yoga-book-9-14iah10-ingenic-touchscreen.patch usb-port-add-delay-after-usb_hub_set_port_power.patch +net-skb-fix-cross-cache-free-of-kfence-allocated-skb.patch +btrfs-merge-btrfs_orig_bbio_end_io-into-btrfs_bio_en.patch +iio-common-st_sensors-fix-use-of-uninitialize-device.patch +net-add-proper-rcu-protection-to-proc-net-ptype.patch +kvm-nvmx-fold-requested-virtual-interrupt-check-into.patch +net-sched-fix-tcf_layer_transport-handling-in-tcf_ge.patch +nfc-nci-complete-pending-data-exchange-on-device-clo.patch +blktrace-fix-__this_cpu_read-write-in-preemptible-co.patch +nf_tables-nft_dynset-fix-possible-stateful-expressio.patch +ice-fix-memory-leak-in-ice_set_ringparam.patch