From b798ff1eae53e92b43c715caeacb07db360eedf8 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 14 Dec 2023 07:39:49 -0500 Subject: [PATCH] Fixes for 6.1 Signed-off-by: Sasha Levin --- ...t-underflow-from-error-handling-race.patch | 146 +++++++++++ ...fix-warning-in-ext4_dio_write_end_io.patch | 69 +++++ ...ict-detection-of-patched-firmware-on.patch | 47 ++++ ...s_getattr_nosec-to-get-the-i_version.patch | 100 ++++++++ .../ksmbd-fix-memory-leak-in-smb2_lock.patch | 41 +++ ...ix-stack-teardown-in-ftrace_no_trace.patch | 52 ++++ ...b-device-driver-for-config-selection.patch | 240 ++++++++++++++++++ ...or-device-id-pair-for-asus-usb-c2500.patch | 50 ++++ ...r-device-id-pair-for-d-link-dub-e250.patch | 51 ++++ queue-6.1/series | 10 + ...i_version-handling-into-struct-kstat.patch | 112 ++++++++ 11 files changed, 918 insertions(+) create mode 100644 queue-6.1/afs-fix-refcount-underflow-from-error-handling-race.patch create mode 100644 queue-6.1/ext4-fix-warning-in-ext4_dio_write_end_io.patch create mode 100644 queue-6.1/hid-lenovo-restrict-detection-of-patched-firmware-on.patch create mode 100644 queue-6.1/ima-use-vfs_getattr_nosec-to-get-the-i_version.patch create mode 100644 queue-6.1/ksmbd-fix-memory-leak-in-smb2_lock.patch create mode 100644 queue-6.1/powerpc-ftrace-fix-stack-teardown-in-ftrace_no_trace.patch create mode 100644 queue-6.1/r8152-add-usb-device-driver-for-config-selection.patch create mode 100644 queue-6.1/r8152-add-vendor-device-id-pair-for-asus-usb-c2500.patch create mode 100644 queue-6.1/r8152-add-vendor-device-id-pair-for-d-link-dub-e250.patch create mode 100644 queue-6.1/series create mode 100644 queue-6.1/vfs-plumb-i_version-handling-into-struct-kstat.patch diff --git a/queue-6.1/afs-fix-refcount-underflow-from-error-handling-race.patch b/queue-6.1/afs-fix-refcount-underflow-from-error-handling-race.patch new file mode 100644 index 00000000000..df80418b37b --- /dev/null +++ b/queue-6.1/afs-fix-refcount-underflow-from-error-handling-race.patch @@ -0,0 +1,146 @@ +From fa2ced2c325a9bcb8678d6651833911c0da2901d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Dec 2023 21:43:52 +0000 +Subject: afs: Fix refcount underflow from error handling race + +From: David Howells + +[ Upstream commit 52bf9f6c09fca8c74388cd41cc24e5d1bff812a9 ] + +If an AFS cell that has an unreachable (eg. ENETUNREACH) server listed (VL +server or fileserver), an asynchronous probe to one of its addresses may +fail immediately because sendmsg() returns an error. When this happens, a +refcount underflow can happen if certain events hit a very small window. + +The way this occurs is: + + (1) There are two levels of "call" object, the afs_call and the + rxrpc_call. Each of them can be transitioned to a "completed" state + in the event of success or failure. + + (2) Asynchronous afs_calls are self-referential whilst they are active to + prevent them from evaporating when they're not being processed. This + reference is disposed of when the afs_call is completed. + + Note that an afs_call may only be completed once; once completed + completing it again will do nothing. + + (3) When a call transmission is made, the app-side rxrpc code queues a Tx + buffer for the rxrpc I/O thread to transmit. The I/O thread invokes + sendmsg() to transmit it - and in the case of failure, it transitions + the rxrpc_call to the completed state. + + (4) When an rxrpc_call is completed, the app layer is notified. In this + case, the app is kafs and it schedules a work item to process events + pertaining to an afs_call. + + (5) When the afs_call event processor is run, it goes down through the + RPC-specific handler to afs_extract_data() to retrieve data from rxrpc + - and, in this case, it picks up the error from the rxrpc_call and + returns it. + + The error is then propagated to the afs_call and that is completed + too. At this point the self-reference is released. + + (6) If the rxrpc I/O thread manages to complete the rxrpc_call within the + window between rxrpc_send_data() queuing the request packet and + checking for call completion on the way out, then + rxrpc_kernel_send_data() will return the error from sendmsg() to the + app. + + (7) Then afs_make_call() will see an error and will jump to the error + handling path which will attempt to clean up the afs_call. + + (8) The problem comes when the error handling path in afs_make_call() + tries to unconditionally drop an async afs_call's self-reference. + This self-reference, however, may already have been dropped by + afs_extract_data() completing the afs_call + + (9) The refcount underflows when we return to afs_do_probe_vlserver() and + that tries to drop its reference on the afs_call. + +Fix this by making afs_make_call() attempt to complete the afs_call rather +than unconditionally putting it. That way, if afs_extract_data() manages +to complete the call first, afs_make_call() won't do anything. + +The bug can be forced by making do_udp_sendmsg() return -ENETUNREACH and +sticking an msleep() in rxrpc_send_data() after the 'success:' label to +widen the race window. + +The error message looks something like: + + refcount_t: underflow; use-after-free. + WARNING: CPU: 3 PID: 720 at lib/refcount.c:28 refcount_warn_saturate+0xba/0x110 + ... + RIP: 0010:refcount_warn_saturate+0xba/0x110 + ... + afs_put_call+0x1dc/0x1f0 [kafs] + afs_fs_get_capabilities+0x8b/0xe0 [kafs] + afs_fs_probe_fileserver+0x188/0x1e0 [kafs] + afs_lookup_server+0x3bf/0x3f0 [kafs] + afs_alloc_server_list+0x130/0x2e0 [kafs] + afs_create_volume+0x162/0x400 [kafs] + afs_get_tree+0x266/0x410 [kafs] + vfs_get_tree+0x25/0xc0 + fc_mount+0xe/0x40 + afs_d_automount+0x1b3/0x390 [kafs] + __traverse_mounts+0x8f/0x210 + step_into+0x340/0x760 + path_openat+0x13a/0x1260 + do_filp_open+0xaf/0x160 + do_sys_openat2+0xaf/0x170 + +or something like: + + refcount_t: underflow; use-after-free. + ... + RIP: 0010:refcount_warn_saturate+0x99/0xda + ... + afs_put_call+0x4a/0x175 + afs_send_vl_probes+0x108/0x172 + afs_select_vlserver+0xd6/0x311 + afs_do_cell_detect_alias+0x5e/0x1e9 + afs_cell_detect_alias+0x44/0x92 + afs_validate_fc+0x9d/0x134 + afs_get_tree+0x20/0x2e6 + vfs_get_tree+0x1d/0xc9 + fc_mount+0xe/0x33 + afs_d_automount+0x48/0x9d + __traverse_mounts+0xe0/0x166 + step_into+0x140/0x274 + open_last_lookups+0x1c1/0x1df + path_openat+0x138/0x1c3 + do_filp_open+0x55/0xb4 + do_sys_openat2+0x6c/0xb6 + +Fixes: 34fa47612bfe ("afs: Fix race in async call refcounting") +Reported-by: Bill MacAllister +Closes: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1052304 +Suggested-by: Jeffrey E Altman +Signed-off-by: David Howells +Reviewed-by: Jeffrey Altman +cc: Marc Dionne +cc: linux-afs@lists.infradead.org +Link: https://lore.kernel.org/r/2633992.1702073229@warthog.procyon.org.uk/ # v1 +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + fs/afs/rxrpc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c +index c62939e5ea1f0..37036db63aff3 100644 +--- a/fs/afs/rxrpc.c ++++ b/fs/afs/rxrpc.c +@@ -424,7 +424,7 @@ void afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_t gfp) + if (call->async) { + if (cancel_work_sync(&call->async_work)) + afs_put_call(call); +- afs_put_call(call); ++ afs_set_call_complete(call, ret, 0); + } + + ac->error = ret; +-- +2.43.0 + diff --git a/queue-6.1/ext4-fix-warning-in-ext4_dio_write_end_io.patch b/queue-6.1/ext4-fix-warning-in-ext4_dio_write_end_io.patch new file mode 100644 index 00000000000..9c531984eb1 --- /dev/null +++ b/queue-6.1/ext4-fix-warning-in-ext4_dio_write_end_io.patch @@ -0,0 +1,69 @@ +From fa4a667935aef3de2b90ab79cb6f8ae2afcfd38d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Nov 2023 10:56:53 +0100 +Subject: ext4: fix warning in ext4_dio_write_end_io() + +From: Jan Kara + +[ Upstream commit 619f75dae2cf117b1d07f27b046b9ffb071c4685 ] + +The syzbot has reported that it can hit the warning in +ext4_dio_write_end_io() because i_size < i_disksize. Indeed the +reproducer creates a race between DIO IO completion and truncate +expanding the file and thus ext4_dio_write_end_io() sees an inconsistent +inode state where i_disksize is already updated but i_size is not +updated yet. Since we are careful when setting up DIO write and consider +it extending (and thus performing the IO synchronously with i_rwsem held +exclusively) whenever it goes past either of i_size or i_disksize, we +can use the same test during IO completion without risking entering +ext4_handle_inode_extension() without i_rwsem held. This way we make it +obvious both i_size and i_disksize are large enough when we report DIO +completion without relying on unreliable WARN_ON. + +Reported-by: +Fixes: 91562895f803 ("ext4: properly sync file size update after O_SYNC direct IO") +Signed-off-by: Jan Kara +Reviewed-by: Ritesh Harjani (IBM) +Link: https://lore.kernel.org/r/20231130095653.22679-1-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/file.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/fs/ext4/file.c b/fs/ext4/file.c +index 8ebe4dc7b0170..18f5fd2a163b0 100644 +--- a/fs/ext4/file.c ++++ b/fs/ext4/file.c +@@ -339,9 +339,10 @@ static void ext4_inode_extension_cleanup(struct inode *inode, ssize_t count) + return; + } + /* +- * If i_disksize got extended due to writeback of delalloc blocks while +- * the DIO was running we could fail to cleanup the orphan list in +- * ext4_handle_inode_extension(). Do it now. ++ * If i_disksize got extended either due to writeback of delalloc ++ * blocks or extending truncate while the DIO was running we could fail ++ * to cleanup the orphan list in ext4_handle_inode_extension(). Do it ++ * now. + */ + if (!list_empty(&EXT4_I(inode)->i_orphan) && inode->i_nlink) { + handle_t *handle = ext4_journal_start(inode, EXT4_HT_INODE, 2); +@@ -376,10 +377,11 @@ static int ext4_dio_write_end_io(struct kiocb *iocb, ssize_t size, + * blocks. But the code in ext4_iomap_alloc() is careful to use + * zeroed/unwritten extents if this is possible; thus we won't leave + * uninitialized blocks in a file even if we didn't succeed in writing +- * as much as we intended. ++ * as much as we intended. Also we can race with truncate or write ++ * expanding the file so we have to be a bit careful here. + */ +- WARN_ON_ONCE(i_size_read(inode) < READ_ONCE(EXT4_I(inode)->i_disksize)); +- if (pos + size <= READ_ONCE(EXT4_I(inode)->i_disksize)) ++ if (pos + size <= READ_ONCE(EXT4_I(inode)->i_disksize) && ++ pos + size <= i_size_read(inode)) + return size; + return ext4_handle_inode_extension(inode, pos, size); + } +-- +2.43.0 + diff --git a/queue-6.1/hid-lenovo-restrict-detection-of-patched-firmware-on.patch b/queue-6.1/hid-lenovo-restrict-detection-of-patched-firmware-on.patch new file mode 100644 index 00000000000..13f36f78c29 --- /dev/null +++ b/queue-6.1/hid-lenovo-restrict-detection-of-patched-firmware-on.patch @@ -0,0 +1,47 @@ +From 6487a1978104e0362dd4c8bdacdcbac02faa931f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Dec 2023 15:31:48 +0200 +Subject: HID: lenovo: Restrict detection of patched firmware only to USB + cptkbd + +From: Mikhail Khvainitski + +[ Upstream commit 43527a0094c10dfbf0d5a2e7979395a38de3ff65 ] + +Commit 46a0a2c96f0f ("HID: lenovo: Detect quirk-free fw on cptkbd and +stop applying workaround") introduced a regression for ThinkPad +TrackPoint Keyboard II which has similar quirks to cptkbd (so it uses +the same workarounds) but slightly different so that there are +false-positives during detecting well-behaving firmware. This commit +restricts detecting well-behaving firmware to the only model which +known to have one and have stable enough quirks to not cause +false-positives. + +Fixes: 46a0a2c96f0f ("HID: lenovo: Detect quirk-free fw on cptkbd and stop applying workaround") +Link: https://lore.kernel.org/linux-input/ZXRiiPsBKNasioqH@jekhomev/ +Link: https://bbs.archlinux.org/viewtopic.php?pid=2135468#p2135468 +Signed-off-by: Mikhail Khvainitski +Tested-by: Yauhen Kharuzhy +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-lenovo.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c +index 7c1b33be9d134..149a3c74346b4 100644 +--- a/drivers/hid/hid-lenovo.c ++++ b/drivers/hid/hid-lenovo.c +@@ -692,7 +692,8 @@ static int lenovo_event_cptkbd(struct hid_device *hdev, + * so set middlebutton_state to 3 + * to never apply workaround anymore + */ +- if (cptkbd_data->middlebutton_state == 1 && ++ if (hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD && ++ cptkbd_data->middlebutton_state == 1 && + usage->type == EV_REL && + (usage->code == REL_X || usage->code == REL_Y)) { + cptkbd_data->middlebutton_state = 3; +-- +2.43.0 + diff --git a/queue-6.1/ima-use-vfs_getattr_nosec-to-get-the-i_version.patch b/queue-6.1/ima-use-vfs_getattr_nosec-to-get-the-i_version.patch new file mode 100644 index 00000000000..d7ca0e018bf --- /dev/null +++ b/queue-6.1/ima-use-vfs_getattr_nosec-to-get-the-i_version.patch @@ -0,0 +1,100 @@ +From 6169658018937657f61d2ef9127d38476faafb14 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Apr 2023 12:55:51 -0400 +Subject: IMA: use vfs_getattr_nosec to get the i_version + +From: Jeff Layton + +[ Upstream commit db1d1e8b9867aae5c3e61ad7859abfcc4a6fd6c7 ] + +IMA currently accesses the i_version out of the inode directly when it +does a measurement. This is fine for most simple filesystems, but can be +problematic with more complex setups (e.g. overlayfs). + +Make IMA instead call vfs_getattr_nosec to get this info. This allows +the filesystem to determine whether and how to report the i_version, and +should allow IMA to work properly with a broader class of filesystems in +the future. + +Reported-and-Tested-by: Stefan Berger +Reviewed-by: Christian Brauner +Signed-off-by: Jeff Layton +Signed-off-by: Mimi Zohar +Signed-off-by: Sasha Levin +--- + security/integrity/ima/ima_api.c | 9 ++++++--- + security/integrity/ima/ima_main.c | 12 ++++++++---- + 2 files changed, 14 insertions(+), 7 deletions(-) + +diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c +index 026c8c9db9920..7a244e8ce65a5 100644 +--- a/security/integrity/ima/ima_api.c ++++ b/security/integrity/ima/ima_api.c +@@ -13,7 +13,6 @@ + #include + #include + #include +-#include + #include + + #include "ima.h" +@@ -246,10 +245,11 @@ int ima_collect_measurement(struct integrity_iint_cache *iint, + struct inode *real_inode = d_real_inode(file_dentry(file)); + const char *filename = file->f_path.dentry->d_name.name; + struct ima_max_digest_data hash; ++ struct kstat stat; + int result = 0; + int length; + void *tmpbuf; +- u64 i_version; ++ u64 i_version = 0; + + /* + * Always collect the modsig, because IMA might have already collected +@@ -268,7 +268,10 @@ int ima_collect_measurement(struct integrity_iint_cache *iint, + * to an initial measurement/appraisal/audit, but was modified to + * assume the file changed. + */ +- i_version = inode_query_iversion(inode); ++ result = vfs_getattr_nosec(&file->f_path, &stat, STATX_CHANGE_COOKIE, ++ AT_STATX_SYNC_AS_STAT); ++ if (!result && (stat.result_mask & STATX_CHANGE_COOKIE)) ++ i_version = stat.change_cookie; + hash.hdr.algo = algo; + hash.hdr.length = hash_digest_size[algo]; + +diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c +index 185666d90eebc..bba421f617312 100644 +--- a/security/integrity/ima/ima_main.c ++++ b/security/integrity/ima/ima_main.c +@@ -24,7 +24,6 @@ + #include + #include + #include +-#include + #include + #include + +@@ -164,11 +163,16 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, + + mutex_lock(&iint->mutex); + if (atomic_read(&inode->i_writecount) == 1) { ++ struct kstat stat; ++ + update = test_and_clear_bit(IMA_UPDATE_XATTR, + &iint->atomic_flags); +- if (!IS_I_VERSION(inode) || +- !inode_eq_iversion(inode, iint->version) || +- (iint->flags & IMA_NEW_FILE)) { ++ if ((iint->flags & IMA_NEW_FILE) || ++ vfs_getattr_nosec(&file->f_path, &stat, ++ STATX_CHANGE_COOKIE, ++ AT_STATX_SYNC_AS_STAT) || ++ !(stat.result_mask & STATX_CHANGE_COOKIE) || ++ stat.change_cookie != iint->version) { + iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE); + iint->measured_pcrs = 0; + if (update) +-- +2.43.0 + diff --git a/queue-6.1/ksmbd-fix-memory-leak-in-smb2_lock.patch b/queue-6.1/ksmbd-fix-memory-leak-in-smb2_lock.patch new file mode 100644 index 00000000000..d85953a6e25 --- /dev/null +++ b/queue-6.1/ksmbd-fix-memory-leak-in-smb2_lock.patch @@ -0,0 +1,41 @@ +From 6c8b314003c509619fad406bb142675500673098 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Dec 2023 22:50:48 +0800 +Subject: ksmbd: fix memory leak in smb2_lock() + +From: Zizhi Wo + +[ Upstream commit 8f1752723019db900fb60a5b9d0dfd3a2bdea36c ] + +In smb2_lock(), if setup_async_work() executes successfully, +work->cancel_argv will bind the argv that generated by kmalloc(). And +release_async_work() is called in ksmbd_conn_try_dequeue_request() or +smb2_lock() to release argv. +However, when setup_async_work function fails, work->cancel_argv has not +been bound to the argv, resulting in the previously allocated argv not +being released. Call kfree() to fix it. + +Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3") +Signed-off-by: Zizhi Wo +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/smb2pdu.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c +index 683152007566c..1598ad6155fef 100644 +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -7135,6 +7135,7 @@ int smb2_lock(struct ksmbd_work *work) + smb2_remove_blocked_lock, + argv); + if (rc) { ++ kfree(argv); + err = -ENOMEM; + goto out; + } +-- +2.43.0 + diff --git a/queue-6.1/powerpc-ftrace-fix-stack-teardown-in-ftrace_no_trace.patch b/queue-6.1/powerpc-ftrace-fix-stack-teardown-in-ftrace_no_trace.patch new file mode 100644 index 00000000000..48068d461c5 --- /dev/null +++ b/queue-6.1/powerpc-ftrace-fix-stack-teardown-in-ftrace_no_trace.patch @@ -0,0 +1,52 @@ +From 7c103535ae04f336f97c5657304b0bbb95fb9433 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Nov 2023 12:29:47 +0530 +Subject: powerpc/ftrace: Fix stack teardown in ftrace_no_trace + +From: Naveen N Rao + +[ Upstream commit 4b3338aaa74d7d4ec5b6734dc298f0db94ec83d2 ] + +Commit 41a506ef71eb ("powerpc/ftrace: Create a dummy stackframe to fix +stack unwind") added use of a new stack frame on ftrace entry to fix +stack unwind. However, the commit missed updating the offset used while +tearing down the ftrace stack when ftrace is disabled. Fix the same. + +In addition, the commit missed saving the correct stack pointer in +pt_regs. Update the same. + +Fixes: 41a506ef71eb ("powerpc/ftrace: Create a dummy stackframe to fix stack unwind") +Cc: stable@vger.kernel.org # v6.5+ +Signed-off-by: Naveen N Rao +Signed-off-by: Michael Ellerman +Link: https://msgid.link/20231130065947.2188860-1-naveen@kernel.org +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/trace/ftrace_mprofile.S | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/powerpc/kernel/trace/ftrace_mprofile.S b/arch/powerpc/kernel/trace/ftrace_mprofile.S +index 6f9c2dea905b7..f4a72b38488f7 100644 +--- a/arch/powerpc/kernel/trace/ftrace_mprofile.S ++++ b/arch/powerpc/kernel/trace/ftrace_mprofile.S +@@ -62,7 +62,7 @@ + .endif + + /* Save previous stack pointer (r1) */ +- addi r8, r1, SWITCH_FRAME_SIZE ++ addi r8, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE + PPC_STL r8, GPR1(r1) + + .if \allregs == 1 +@@ -182,7 +182,7 @@ ftrace_no_trace: + mflr r3 + mtctr r3 + REST_GPR(3, r1) +- addi r1, r1, SWITCH_FRAME_SIZE ++ addi r1, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE + mtlr r0 + bctr + #endif +-- +2.43.0 + diff --git a/queue-6.1/r8152-add-usb-device-driver-for-config-selection.patch b/queue-6.1/r8152-add-usb-device-driver-for-config-selection.patch new file mode 100644 index 00000000000..8e88141656a --- /dev/null +++ b/queue-6.1/r8152-add-usb-device-driver-for-config-selection.patch @@ -0,0 +1,240 @@ +From ed49446df76ff6b340f51701808fda7b59a6c73e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 6 Jan 2023 17:07:38 +0100 +Subject: r8152: add USB device driver for config selection +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Bjørn Mork + +[ Upstream commit ec51fbd1b8a2bca2948dede99c14ec63dc57ff6b ] + +Subclassing the generic USB device driver to override the +default configuration selection regardless of matching interface +drivers. + +The r815x family devices expose a vendor specific function which +the r8152 interface driver wants to handle. This is the preferred +device mode. Additionally one or more USB class functions are +usually supported for hosts lacking a vendor specific driver. The +choice is USB configuration based, with one alternate function per +configuration. + +Example device with both NCM and ECM alternate cfgs: + +T: Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 4 Spd=5000 MxCh= 0 +D: Ver= 3.20 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 9 #Cfgs= 3 +P: Vendor=0bda ProdID=8156 Rev=31.00 +S: Manufacturer=Realtek +S: Product=USB 10/100/1G/2.5G LAN +S: SerialNumber=001000001 +C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=256mA +I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=00 Driver=r8152 +E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms +E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms +E: Ad=83(I) Atr=03(Int.) MxPS= 2 Ivl=128ms +C: #Ifs= 2 Cfg#= 2 Atr=a0 MxPwr=256mA +I: If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=0d Prot=00 Driver= +E: Ad=83(I) Atr=03(Int.) MxPS= 16 Ivl=128ms +I: If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=01 Driver= +I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=01 Driver= +E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms +E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms +C: #Ifs= 2 Cfg#= 3 Atr=a0 MxPwr=256mA +I: If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=06 Prot=00 Driver= +E: Ad=83(I) Atr=03(Int.) MxPS= 16 Ivl=128ms +I: If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=00 Driver= +I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver= +E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms +E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms + +A problem with this is that Linux will prefer class functions over +vendor specific functions. Using the above example, Linux defaults +to cfg #2, running the device in a sub-optimal NCM mode. + +Previously we've attempted to work around the problem by +blacklisting the devices in the ECM class driver "cdc_ether", and +matching on the ECM class function in the vendor specific interface +driver. The latter has been used to switch back to the vendor +specific configuration when the driver is probed for a class +function. + +This workaround has several issues; +- class driver blacklists is additional maintanence cruft in an + unrelated driver +- class driver blacklists prevents users from optionally running + the devices in class mode +- each device needs double match entries in the vendor driver +- the initial probing as a class function slows down device + discovery + +Now these issues have become even worse with the introduction of +firmware supporting both NCM and ECM, where NCM ends up as the +default mode in Linux. To use the same workaround, we now have +to blacklist the devices in to two different class drivers and +add yet another match entry to the vendor specific driver. + +This patch implements an alternative workaround strategy - +independent of the interface drivers. It avoids adding a +blacklist to the cdc_ncm driver and will let us remove the +existing blacklist from the cdc_ether driver. + +As an additional bonus, removing the blacklists allow users to +select one of the other device modes if wanted. + +Signed-off-by: Bjørn Mork +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/usb/r8152.c | 115 ++++++++++++++++++++++++++++------------ + 1 file changed, 82 insertions(+), 33 deletions(-) + +diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c +index 4d833781294a4..1e53f43573ec2 100644 +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -9675,6 +9675,9 @@ static int rtl8152_probe(struct usb_interface *intf, + if (version == RTL_VER_UNKNOWN) + return -ENODEV; + ++ if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC) ++ return -ENODEV; ++ + if (!rtl_vendor_mode(intf)) + return -ENODEV; + +@@ -9875,43 +9878,35 @@ static void rtl8152_disconnect(struct usb_interface *intf) + } + } + +-#define REALTEK_USB_DEVICE(vend, prod) { \ +- USB_DEVICE_INTERFACE_CLASS(vend, prod, USB_CLASS_VENDOR_SPEC), \ +-}, \ +-{ \ +- USB_DEVICE_AND_INTERFACE_INFO(vend, prod, USB_CLASS_COMM, \ +- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), \ +-} +- + /* table of devices that work with this driver */ + static const struct usb_device_id rtl8152_table[] = { + /* Realtek */ +- REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8050), +- REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8053), +- REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8152), +- REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153), +- REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8155), +- REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8156), ++ { USB_DEVICE(VENDOR_ID_REALTEK, 0x8050) }, ++ { USB_DEVICE(VENDOR_ID_REALTEK, 0x8053) }, ++ { USB_DEVICE(VENDOR_ID_REALTEK, 0x8152) }, ++ { USB_DEVICE(VENDOR_ID_REALTEK, 0x8153) }, ++ { USB_DEVICE(VENDOR_ID_REALTEK, 0x8155) }, ++ { USB_DEVICE(VENDOR_ID_REALTEK, 0x8156) }, + + /* Microsoft */ +- REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab), +- REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07c6), +- REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0927), +- REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0c5e), +- REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101), +- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f), +- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3054), +- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3062), +- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3069), +- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3082), +- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205), +- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x720c), +- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7214), +- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x721e), +- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0xa387), +- REALTEK_USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041), +- REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff), +- REALTEK_USB_DEVICE(VENDOR_ID_TPLINK, 0x0601), ++ { USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab) }, ++ { USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07c6) }, ++ { USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0927) }, ++ { USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0c5e) }, ++ { USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101) }, ++ { USB_DEVICE(VENDOR_ID_LENOVO, 0x304f) }, ++ { USB_DEVICE(VENDOR_ID_LENOVO, 0x3054) }, ++ { USB_DEVICE(VENDOR_ID_LENOVO, 0x3062) }, ++ { USB_DEVICE(VENDOR_ID_LENOVO, 0x3069) }, ++ { USB_DEVICE(VENDOR_ID_LENOVO, 0x3082) }, ++ { USB_DEVICE(VENDOR_ID_LENOVO, 0x7205) }, ++ { USB_DEVICE(VENDOR_ID_LENOVO, 0x720c) }, ++ { USB_DEVICE(VENDOR_ID_LENOVO, 0x7214) }, ++ { USB_DEVICE(VENDOR_ID_LENOVO, 0x721e) }, ++ { USB_DEVICE(VENDOR_ID_LENOVO, 0xa387) }, ++ { USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041) }, ++ { USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff) }, ++ { USB_DEVICE(VENDOR_ID_TPLINK, 0x0601) }, + {} + }; + +@@ -9931,7 +9926,61 @@ static struct usb_driver rtl8152_driver = { + .disable_hub_initiated_lpm = 1, + }; + +-module_usb_driver(rtl8152_driver); ++static int rtl8152_cfgselector_probe(struct usb_device *udev) ++{ ++ struct usb_host_config *c; ++ int i, num_configs; ++ ++ /* The vendor mode is not always config #1, so to find it out. */ ++ c = udev->config; ++ num_configs = udev->descriptor.bNumConfigurations; ++ for (i = 0; i < num_configs; (i++, c++)) { ++ struct usb_interface_descriptor *desc = NULL; ++ ++ if (!c->desc.bNumInterfaces) ++ continue; ++ desc = &c->intf_cache[0]->altsetting->desc; ++ if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC) ++ break; ++ } ++ ++ if (i == num_configs) ++ return -ENODEV; ++ ++ if (usb_set_configuration(udev, c->desc.bConfigurationValue)) { ++ dev_err(&udev->dev, "Failed to set configuration %d\n", ++ c->desc.bConfigurationValue); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static struct usb_device_driver rtl8152_cfgselector_driver = { ++ .name = MODULENAME "-cfgselector", ++ .probe = rtl8152_cfgselector_probe, ++ .id_table = rtl8152_table, ++ .generic_subclass = 1, ++}; ++ ++static int __init rtl8152_driver_init(void) ++{ ++ int ret; ++ ++ ret = usb_register_device_driver(&rtl8152_cfgselector_driver, THIS_MODULE); ++ if (ret) ++ return ret; ++ return usb_register(&rtl8152_driver); ++} ++ ++static void __exit rtl8152_driver_exit(void) ++{ ++ usb_deregister(&rtl8152_driver); ++ usb_deregister_device_driver(&rtl8152_cfgselector_driver); ++} ++ ++module_init(rtl8152_driver_init); ++module_exit(rtl8152_driver_exit); + + MODULE_AUTHOR(DRIVER_AUTHOR); + MODULE_DESCRIPTION(DRIVER_DESC); +-- +2.43.0 + diff --git a/queue-6.1/r8152-add-vendor-device-id-pair-for-asus-usb-c2500.patch b/queue-6.1/r8152-add-vendor-device-id-pair-for-asus-usb-c2500.patch new file mode 100644 index 00000000000..57bb0afa462 --- /dev/null +++ b/queue-6.1/r8152-add-vendor-device-id-pair-for-asus-usb-c2500.patch @@ -0,0 +1,50 @@ +From 6a2a8189896130aefe756bbf2a616b6e173cd7f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 2 Dec 2023 17:17:12 -0800 +Subject: r8152: add vendor/device ID pair for ASUS USB-C2500 + +From: Kelly Kane + +[ Upstream commit 7037d95a047cd89b1f680eed253c6ab586bef1ed ] + +The ASUS USB-C2500 is an RTL8156 based 2.5G Ethernet controller. + +Add the vendor and product ID values to the driver. This makes Ethernet +work with the adapter. + +Signed-off-by: Kelly Kane +Link: https://lore.kernel.org/r/20231203011712.6314-1-kelly@hawknetworks.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/usb/r8152.c | 1 + + include/linux/usb/r8152.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c +index 09d2f3bdb0647..1c6d36282e0d7 100644 +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -9908,6 +9908,7 @@ static const struct usb_device_id rtl8152_table[] = { + { USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff) }, + { USB_DEVICE(VENDOR_ID_TPLINK, 0x0601) }, + { USB_DEVICE(VENDOR_ID_DLINK, 0xb301) }, ++ { USB_DEVICE(VENDOR_ID_ASUS, 0x1976) }, + {} + }; + +diff --git a/include/linux/usb/r8152.h b/include/linux/usb/r8152.h +index 287e9d83fb8bc..33a4c146dc19c 100644 +--- a/include/linux/usb/r8152.h ++++ b/include/linux/usb/r8152.h +@@ -30,6 +30,7 @@ + #define VENDOR_ID_NVIDIA 0x0955 + #define VENDOR_ID_TPLINK 0x2357 + #define VENDOR_ID_DLINK 0x2001 ++#define VENDOR_ID_ASUS 0x0b05 + + #if IS_REACHABLE(CONFIG_USB_RTL8152) + extern u8 rtl8152_get_version(struct usb_interface *intf); +-- +2.43.0 + diff --git a/queue-6.1/r8152-add-vendor-device-id-pair-for-d-link-dub-e250.patch b/queue-6.1/r8152-add-vendor-device-id-pair-for-d-link-dub-e250.patch new file mode 100644 index 00000000000..0a4ce0a8a3a --- /dev/null +++ b/queue-6.1/r8152-add-vendor-device-id-pair-for-d-link-dub-e250.patch @@ -0,0 +1,51 @@ +From b4b80dbfd763d9e7090a3669d225db81c5e93985 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 26 Aug 2023 01:05:50 +0200 +Subject: r8152: add vendor/device ID pair for D-Link DUB-E250 + +From: Antonio Napolitano + +[ Upstream commit 72f93a3136ee18fd59fa6579f84c07e93424681e ] + +The D-Link DUB-E250 is an RTL8156 based 2.5G Ethernet controller. + +Add the vendor and product ID values to the driver. This makes Ethernet +work with the adapter. + +Signed-off-by: Antonio Napolitano +Link: https://lore.kernel.org/r/CV200KJEEUPC.WPKAHXCQJ05I@mercurius +Signed-off-by: Jakub Kicinski +Stable-dep-of: 7037d95a047c ("r8152: add vendor/device ID pair for ASUS USB-C2500") +Signed-off-by: Sasha Levin +--- + drivers/net/usb/r8152.c | 1 + + include/linux/usb/r8152.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c +index 1e53f43573ec2..09d2f3bdb0647 100644 +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -9907,6 +9907,7 @@ static const struct usb_device_id rtl8152_table[] = { + { USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041) }, + { USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff) }, + { USB_DEVICE(VENDOR_ID_TPLINK, 0x0601) }, ++ { USB_DEVICE(VENDOR_ID_DLINK, 0xb301) }, + {} + }; + +diff --git a/include/linux/usb/r8152.h b/include/linux/usb/r8152.h +index 20d88b1defc30..287e9d83fb8bc 100644 +--- a/include/linux/usb/r8152.h ++++ b/include/linux/usb/r8152.h +@@ -29,6 +29,7 @@ + #define VENDOR_ID_LINKSYS 0x13b1 + #define VENDOR_ID_NVIDIA 0x0955 + #define VENDOR_ID_TPLINK 0x2357 ++#define VENDOR_ID_DLINK 0x2001 + + #if IS_REACHABLE(CONFIG_USB_RTL8152) + extern u8 rtl8152_get_version(struct usb_interface *intf); +-- +2.43.0 + diff --git a/queue-6.1/series b/queue-6.1/series new file mode 100644 index 00000000000..8405f69608a --- /dev/null +++ b/queue-6.1/series @@ -0,0 +1,10 @@ +r8152-add-usb-device-driver-for-config-selection.patch +r8152-add-vendor-device-id-pair-for-d-link-dub-e250.patch +r8152-add-vendor-device-id-pair-for-asus-usb-c2500.patch +vfs-plumb-i_version-handling-into-struct-kstat.patch +ima-use-vfs_getattr_nosec-to-get-the-i_version.patch +powerpc-ftrace-fix-stack-teardown-in-ftrace_no_trace.patch +ext4-fix-warning-in-ext4_dio_write_end_io.patch +ksmbd-fix-memory-leak-in-smb2_lock.patch +afs-fix-refcount-underflow-from-error-handling-race.patch +hid-lenovo-restrict-detection-of-patched-firmware-on.patch diff --git a/queue-6.1/vfs-plumb-i_version-handling-into-struct-kstat.patch b/queue-6.1/vfs-plumb-i_version-handling-into-struct-kstat.patch new file mode 100644 index 00000000000..57c38501509 --- /dev/null +++ b/queue-6.1/vfs-plumb-i_version-handling-into-struct-kstat.patch @@ -0,0 +1,112 @@ +From 64bb46638404acd0de4374537409e7c04a3bacf8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 4 Dec 2016 09:29:46 -0500 +Subject: vfs: plumb i_version handling into struct kstat + +From: Jeff Layton + +[ Upstream commit a1175d6b1bdaf4f74eda47ab18eb44194f9cb796 ] + +The NFS server has a lot of special handling for different types of +change attribute access, depending on the underlying filesystem. In +most cases, it's doing a getattr anyway and then fetching that value +after the fact. + +Rather that do that, add a new STATX_CHANGE_COOKIE flag that is a +kernel-only symbol (for now). If requested and getattr can implement it, +it can fill out this field. For IS_I_VERSION inodes, add a generic +implementation in vfs_getattr_nosec. Take care to mask +STATX_CHANGE_COOKIE off in requests from userland and in the result +mask. + +Since not all filesystems can give the same guarantees of monotonicity, +claim a STATX_ATTR_CHANGE_MONOTONIC flag that filesystems can set to +indicate that they offer an i_version value that can never go backward. + +Eventually if we decide to make the i_version available to userland, we +can just designate a field for it in struct statx, and move the +STATX_CHANGE_COOKIE definition to the uapi header. + +Reviewed-by: NeilBrown +Reviewed-by: Jan Kara +Signed-off-by: Jeff Layton +Stable-dep-of: db1d1e8b9867 ("IMA: use vfs_getattr_nosec to get the i_version") +Signed-off-by: Sasha Levin +--- + fs/stat.c | 17 +++++++++++++++-- + include/linux/stat.h | 9 +++++++++ + 2 files changed, 24 insertions(+), 2 deletions(-) + +diff --git a/fs/stat.c b/fs/stat.c +index ef50573c72a26..06fd3fc1ab84b 100644 +--- a/fs/stat.c ++++ b/fs/stat.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -119,6 +120,11 @@ int vfs_getattr_nosec(const struct path *path, struct kstat *stat, + stat->attributes_mask |= (STATX_ATTR_AUTOMOUNT | + STATX_ATTR_DAX); + ++ if ((request_mask & STATX_CHANGE_COOKIE) && IS_I_VERSION(inode)) { ++ stat->result_mask |= STATX_CHANGE_COOKIE; ++ stat->change_cookie = inode_query_iversion(inode); ++ } ++ + mnt_userns = mnt_user_ns(path->mnt); + if (inode->i_op->getattr) + return inode->i_op->getattr(mnt_userns, path, stat, +@@ -599,9 +605,11 @@ cp_statx(const struct kstat *stat, struct statx __user *buffer) + + memset(&tmp, 0, sizeof(tmp)); + +- tmp.stx_mask = stat->result_mask; ++ /* STATX_CHANGE_COOKIE is kernel-only for now */ ++ tmp.stx_mask = stat->result_mask & ~STATX_CHANGE_COOKIE; + tmp.stx_blksize = stat->blksize; +- tmp.stx_attributes = stat->attributes; ++ /* STATX_ATTR_CHANGE_MONOTONIC is kernel-only for now */ ++ tmp.stx_attributes = stat->attributes & ~STATX_ATTR_CHANGE_MONOTONIC; + tmp.stx_nlink = stat->nlink; + tmp.stx_uid = from_kuid_munged(current_user_ns(), stat->uid); + tmp.stx_gid = from_kgid_munged(current_user_ns(), stat->gid); +@@ -640,6 +648,11 @@ int do_statx(int dfd, struct filename *filename, unsigned int flags, + if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE) + return -EINVAL; + ++ /* STATX_CHANGE_COOKIE is kernel-only for now. Ignore requests ++ * from userland. ++ */ ++ mask &= ~STATX_CHANGE_COOKIE; ++ + error = vfs_statx(dfd, filename, flags, &stat, mask); + if (error) + return error; +diff --git a/include/linux/stat.h b/include/linux/stat.h +index ff277ced50e9f..52150570d37a5 100644 +--- a/include/linux/stat.h ++++ b/include/linux/stat.h +@@ -52,6 +52,15 @@ struct kstat { + u64 mnt_id; + u32 dio_mem_align; + u32 dio_offset_align; ++ u64 change_cookie; + }; + ++/* These definitions are internal to the kernel for now. Mainly used by nfsd. */ ++ ++/* mask values */ ++#define STATX_CHANGE_COOKIE 0x40000000U /* Want/got stx_change_attr */ ++ ++/* file attribute values */ ++#define STATX_ATTR_CHANGE_MONOTONIC 0x8000000000000000ULL /* version monotonically increases */ ++ + #endif +-- +2.43.0 + -- 2.47.3