Backport of the mainline fix to the kernel panic when Wine is run over CIFS share. This is intended for linux-6.1.y tree. Please apply. Bug and testing details:
Jan 24 15:15:20 kalt2test.dpt.local kernel: detected buffer overflow in strncpy Jan 24 15:15:20 kalt2test.dpt.local kernel: ------------[ cut here ]------------ Jan 24 15:15:20 kalt2test.dpt.local kernel: kernel BUG at lib/string_helpers.c:1027! Jan 24 15:15:20 kalt2test.dpt.local kernel: invalid opcode: 0000 [#1] PREEMPT SMP PTI Jan 24 15:15:20 kalt2test.dpt.local kernel: CPU: 1 PID: 4532 Comm: vr402352.res Tainted: G OE 6.1.73-un-def-alt1 #1 Jan 24 15:15:20 kalt2test.dpt.local kernel: Hardware name: Gigabyte Technology Co., Ltd. B360M-D3H/B360M D3H-CF, BIOS F12 03/14/2019 Jan 24 15:15:20 kalt2test.dpt.local kernel: RIP: 0010:fortify_panic+0xf/0x11 ... Jan 24 15:15:20 kalt2test.dpt.local kernel: Call Trace: Jan 24 15:15:20 kalt2test.dpt.local kernel: <TASK> Jan 24 15:15:20 kalt2test.dpt.local kernel: ? __die_body.cold+0x1a/0x1f Jan 24 15:15:20 kalt2test.dpt.local kernel: ? die+0x2b/0x50 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? do_trap+0xcf/0x120 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? fortify_panic+0xf/0x11 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? do_error_trap+0x83/0xb0 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? fortify_panic+0xf/0x11 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? exc_invalid_op+0x4e/0x70 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? fortify_panic+0xf/0x11 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? asm_exc_invalid_op+0x16/0x20 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? fortify_panic+0xf/0x11 Jan 24 15:15:20 kalt2test.dpt.local kernel: CIFSSMBSetEA.cold+0xc/0x18 [cifs] Jan 24 15:15:20 kalt2test.dpt.local kernel: cifs_xattr_set+0x596/0x690 [cifs] Jan 24 15:15:20 kalt2test.dpt.local kernel: ? evm_protected_xattr_common+0x41/0xb0 Jan 24 15:15:20 kalt2test.dpt.local kernel: __vfs_removexattr+0x52/0x70 Jan 24 15:15:20 kalt2test.dpt.local kernel: __vfs_removexattr_locked+0xbc/0x150 Jan 24 15:15:20 kalt2test.dpt.local kernel: vfs_removexattr+0x56/0x100 Jan 24 15:15:20 kalt2test.dpt.local kernel: removexattr+0x58/0x90 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? get_vtime_delta+0xf/0xb0 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? ct_kernel_exit.constprop.0+0x6b/0x80 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? __ct_user_enter+0x5a/0xd0 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? syscall_exit_to_user_mode+0x31/0x50 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? int80_emulation+0xb9/0x110 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? get_vtime_delta+0xf/0xb0 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? ct_kernel_exit.constprop.0+0x6b/0x80 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? __ct_user_enter+0x5a/0xd0 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? __fget_light.part.0+0x83/0xd0 Jan 24 15:15:20 kalt2test.dpt.local kernel: __ia32_sys_fremovexattr+0x80/0xa0 Jan 24 15:15:20 kalt2test.dpt.local kernel: int80_emulation+0xa9/0x110 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? get_vtime_delta+0xf/0xb0 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? vtime_user_exit+0x1c/0x70 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? __ct_user_exit+0x6c/0xc0 Jan 24 15:15:20 kalt2test.dpt.local kernel: ? int80_emulation+0x1b/0x110 Jan 24 15:15:20 kalt2test.dpt.local kernel: asm_int80_emulation+0x16/0x20 Jan 24 15:15:20 kalt2test.dpt.local kernel: RIP: 0023:0xf7e3b9b1
This backport is a simple cherry-pick of mainline commit 398d5843c032 ("cifs: Convert struct fealist away from 1-element array").
Build and runtime tested to fix the problem. Downstream bug report and test report: https://bugzilla.altlinux.org/49177
Difference from v0: - No changes, only a cover letter is added with bug details.
Kees Cook (1): cifs: Convert struct fealist away from 1-element array
fs/smb/client/cifspdu.h | 4 ++-- fs/smb/client/cifssmb.c | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-)
From: Kees Cook keescook@chromium.org
commit 398d5843c03261a2b68730f2f00643826bcec6ba upstream.
The kernel is globally removing the ambiguous 0-length and 1-element arrays in favor of flexible arrays, so that we can gain both compile-time and run-time array bounds checking[1].
While struct fealist is defined as a "fake" flexible array (via a 1-element array), it is only used for examination of the first array element. Walking the list is performed separately, so there is no reason to treat the "list" member of struct fealist as anything other than a single entry. Adjust the struct and code to match.
Additionally, struct fea uses the "name" member either as a dynamic string, or is manually calculated from the start of the struct. Redefine the member as a flexible array.
No machine code output differences are produced after these changes.
[1] For lots of details, see both: https://docs.kernel.org/process/deprecated.html#zero-length-and-one-element-... https://people.kernel.org/kees/bounded-flexible-arrays-in-c
Cc: Steve French sfrench@samba.org Cc: Paulo Alcantara pc@cjr.nz Cc: Ronnie Sahlberg lsahlber@redhat.com Cc: Shyam Prasad N sprasad@microsoft.com Cc: Tom Talpey tom@talpey.com Cc: linux-cifs@vger.kernel.org Cc: samba-technical@lists.samba.org Signed-off-by: Kees Cook keescook@chromium.org Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Vitaly Chikunov vt@altlinux.org --- fs/smb/client/cifspdu.h | 4 ++-- fs/smb/client/cifssmb.c | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/fs/smb/client/cifspdu.h b/fs/smb/client/cifspdu.h index 97bb1838555b..96ed0a4a2ce2 100644 --- a/fs/smb/client/cifspdu.h +++ b/fs/smb/client/cifspdu.h @@ -2593,7 +2593,7 @@ struct fea { unsigned char EA_flags; __u8 name_len; __le16 value_len; - char name[1]; + char name[]; /* optionally followed by value */ } __attribute__((packed)); /* flags for _FEA.fEA */ @@ -2601,7 +2601,7 @@ struct fea {
struct fealist { __le32 list_len; - struct fea list[1]; + struct fea list; } __attribute__((packed));
/* used to hold an arbitrary blob of data */ diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c index 67c5fc2b2db9..784fc5ba2c44 100644 --- a/fs/smb/client/cifssmb.c +++ b/fs/smb/client/cifssmb.c @@ -5697,7 +5697,7 @@ CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
/* account for ea list len */ list_len -= 4; - temp_fea = ea_response_data->list; + temp_fea = &ea_response_data->list; temp_ptr = (char *)temp_fea; while (list_len > 0) { unsigned int name_len; @@ -5812,7 +5812,7 @@ CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon, else name_len = strnlen(ea_name, 255);
- count = sizeof(*parm_data) + ea_value_len + name_len; + count = sizeof(*parm_data) + 1 + ea_value_len + name_len; pSMB->MaxParameterCount = cpu_to_le16(2); /* BB find max SMB PDU from sess */ pSMB->MaxDataCount = cpu_to_le16(1000); @@ -5836,14 +5836,14 @@ CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon, byte_count = 3 /* pad */ + params + count; pSMB->DataCount = cpu_to_le16(count); parm_data->list_len = cpu_to_le32(count); - parm_data->list[0].EA_flags = 0; + parm_data->list.EA_flags = 0; /* we checked above that name len is less than 255 */ - parm_data->list[0].name_len = (__u8)name_len; + parm_data->list.name_len = (__u8)name_len; /* EA names are always ASCII */ if (ea_name) - strncpy(parm_data->list[0].name, ea_name, name_len); - parm_data->list[0].name[name_len] = 0; - parm_data->list[0].value_len = cpu_to_le16(ea_value_len); + strncpy(parm_data->list.name, ea_name, name_len); + parm_data->list.name[name_len] = '\0'; + parm_data->list.value_len = cpu_to_le16(ea_value_len); /* caller ensures that ea_value_len is less than 64K but we need to ensure that it fits within the smb */
@@ -5851,7 +5851,7 @@ CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon, negotiated SMB buffer size BB */ /* if (ea_value_len > buffer_size - 512 (enough for header)) */ if (ea_value_len) - memcpy(parm_data->list[0].name+name_len+1, + memcpy(parm_data->list.name + name_len + 1, ea_value, ea_value_len);
pSMB->TotalDataCount = pSMB->DataCount;
linux-stable-mirror@lists.linaro.org