6.12.2-rc1 review
Subsystems (8)
Greg Kroah-Hartman
maintainerPATCH 744/826 ALSA: hda/realtek: Enable speaker pins for Medion E15443 platform
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kailang Yang <[email protected]>
commit 31917b7bd892de730ab67b215c62aeeea778112e upstream.
Speaker has no sound for Medion E15443.
Added another speaker pins for Medion E15443 platform.
--- sound/pci/hda/patch_realtek.c | 9 +++++++++ 1 file changed, 9 insertions(+)
sound/pci/hda/patch_realtek.c +9 -0
@@ -7773,6 +7773,7 @@ enum {ALC287_FIXUP_LENOVO_SSID_17AA3820 ,ALC245_FIXUP_CLEVO_NOISY_MIC ,ALC269_FIXUP_VAIO_VJFH52_MIC_NO_PRESENCE , + ALC233_FIXUP_MEDION_MTL_SPK, };/* A special fixup for Lenovo C940 and Yoga Duet 7;
@@ -10147,6 +10148,13 @@ static const struct hda_fixup alc269_fix .chained = true, .chain_id =ALC269_FIXUP_LIMIT_INT_MIC_BOOST }, + [ALC233_FIXUP_MEDION_MTL_SPK] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl []) { + {0x1b ,0x90170110 }, + { } + }, + }, };static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -11013,6 +11021,7 @@ static const struct snd_pci_quirk alc269SND_PCI_QUIRK (0x2782 ,0x0228 ,"Infinix ZERO BOOK 13" ,ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13 ),SND_PCI_QUIRK (0x2782 ,0x0232 ,"CHUWI CoreBook XPro" ,ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO ),SND_PCI_QUIRK (0x2782 ,0x1707 ,"Vaio VJFE-ADL" ,ALC298_FIXUP_SPK_VOLUME ), +SND_PCI_QUIRK (0x2782 ,0x4900 ,"MEDION E15443" ,ALC233_FIXUP_MEDION_MTL_SPK ),SND_PCI_QUIRK (0x8086 ,0x2074 ,"Intel NUC 8" ,ALC233_FIXUP_INTEL_NUC8_DMIC ),SND_PCI_QUIRK (0x8086 ,0x2080 ,"Intel NUC 8 Rugged" ,ALC256_FIXUP_INTEL_NUC8_RUGGED ), SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", ALC256_FIXUP_INTEL_NUC10),
Greg Kroah-Hartman
maintainerPATCH 745/826 ALSA: hda/realtek: Set PCBeep to default value for ALC274
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kailang Yang <[email protected]>
commit 155699ccab7c78cbba69798242b68bc8ac66d5d2 upstream.
BIOS Enable PC beep path cause pop noise via speaker during boot time. Set to default value from driver will solve the issue.
--- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+)
sound/pci/hda/patch_realtek.c +2 -0
@@ -473,6 +473,8 @@ static void alc_fill_eapd_coef(struct hdbreak ;case 0x10ec0234 :case 0x10ec0274 : +alc_write_coef_idx (codec,0x6e ,0x0c25 ); + fallthrough;case 0x10ec0294 :case 0x10ec0700 :case 0x10ec0701 :
Greg Kroah-Hartman
maintainerPATCH 746/826 ALSA: hda/realtek: Fix Internal Speaker and Mic boost of Infinix Y4 Max
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dinesh Kumar <[email protected]>
commit 5ebe792a5139f1ce6e4aed22bef12e7e2660df96 upstream.
Internal Speaker of Infinix Y4 Max remains muted due to incorrect Pin configuration, and the Internal Mic records high noise. This patch corrects the Pin configuration for the Internal Speaker and limits the Internal Mic boost.
HW Probe for device: https://linux-hardware.org/?probe=6d4386c347
Test: Internal Speaker works fine, Mic has low noise.
--- sound/pci/hda/patch_realtek.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
sound/pci/hda/patch_realtek.c +11 -0
@@ -7548,6 +7548,7 @@ enum {ALC269_FIXUP_THINKPAD_ACPI ,ALC269_FIXUP_DMIC_THINKPAD_ACPI ,ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13 , +ALC269VC_FIXUP_INFINIX_Y4_MAX ,ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO ,ALC255_FIXUP_ACER_MIC_NO_PRESENCE , ALC255_FIXUP_ASUS_MIC_NO_PRESENCE,
@@ -8005,6 +8006,15 @@ static const struct hda_fixup alc269_fix .chained = true, .chain_id =ALC269_FIXUP_LIMIT_INT_MIC_BOOST }, + [ALC269VC_FIXUP_INFINIX_Y4_MAX] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl []) { + {0x1b ,0x90170150 },/* use as internal speaker */ + { } + }, + .chained = true, + .chain_id =ALC269_FIXUP_LIMIT_INT_MIC_BOOST + }, [ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl []) {
@@ -11022,6 +11032,7 @@ static const struct snd_pci_quirk alc269SND_PCI_QUIRK (0x2782 ,0x0214 ,"VAIO VJFE-CL" ,ALC269_FIXUP_LIMIT_INT_MIC_BOOST ),SND_PCI_QUIRK (0x2782 ,0x0228 ,"Infinix ZERO BOOK 13" ,ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13 ),SND_PCI_QUIRK (0x2782 ,0x0232 ,"CHUWI CoreBook XPro" ,ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO ), +SND_PCI_QUIRK (0x2782 ,0x1701 ,"Infinix Y4 Max" ,ALC269VC_FIXUP_INFINIX_Y4_MAX ),SND_PCI_QUIRK (0x2782 ,0x1707 ,"Vaio VJFE-ADL" ,ALC298_FIXUP_SPK_VOLUME ),SND_PCI_QUIRK (0x2782 ,0x4900 ,"MEDION E15443" ,ALC233_FIXUP_MEDION_MTL_SPK ), SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC),
Greg Kroah-Hartman
maintainerPATCH 747/826 ALSA: hda/realtek: fix mute/micmute LEDs dont work for EliteBook X G1i
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dirk Su <[email protected]>
commit 7ba81e4c3aa0ca25f06dc4456e7d36fa8e76385f upstream.
HP EliteBook X G1i needs ALC285_FIXUP_HP_GPIO_LED quirk to make mic-mute/audio-mute working.
--- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+)
sound/pci/hda/patch_realtek.c +1 -0
@@ -10592,6 +10592,7 @@ static const struct snd_pci_quirk alc269SND_PCI_QUIRK (0x103c ,0x8cdf ,"HP SnowWhite" ,ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED ),SND_PCI_QUIRK (0x103c ,0x8ce0 ,"HP SnowWhite" ,ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED ),SND_PCI_QUIRK (0x103c ,0x8cf5 ,"HP ZBook Studio 16" ,ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED ), +SND_PCI_QUIRK (0x103c ,0x8d84 ,"HP EliteBook X G1i" ,ALC285_FIXUP_HP_GPIO_LED ),SND_PCI_QUIRK (0x1043 ,0x103e ,"ASUS X540SA" ,ALC256_FIXUP_ASUS_MIC ),SND_PCI_QUIRK (0x1043 ,0x103f ,"ASUS TX300" ,ALC282_FIXUP_ASUS_TX300 ), SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
Greg Kroah-Hartman
maintainerPATCH 748/826 ALSA: hda/realtek: Apply quirk for Medion E15433
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
commit ca0f79f0286046f6a91c099dc941cf7afae198d6 upstream.
Medion E15433 laptop wich ALC269VC (SSID 2782:1705) needs the same workaround for the missing speaker as another model.
--- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+)
sound/pci/hda/patch_realtek.c +1 -0
@@ -11034,6 +11034,7 @@ static const struct snd_pci_quirk alc269SND_PCI_QUIRK (0x2782 ,0x0228 ,"Infinix ZERO BOOK 13" ,ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13 ),SND_PCI_QUIRK (0x2782 ,0x0232 ,"CHUWI CoreBook XPro" ,ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO ),SND_PCI_QUIRK (0x2782 ,0x1701 ,"Infinix Y4 Max" ,ALC269VC_FIXUP_INFINIX_Y4_MAX ), +SND_PCI_QUIRK (0x2782 ,0x1705 ,"MEDION E15433" ,ALC269VC_FIXUP_INFINIX_Y4_MAX ),SND_PCI_QUIRK (0x2782 ,0x1707 ,"Vaio VJFE-ADL" ,ALC298_FIXUP_SPK_VOLUME ),SND_PCI_QUIRK (0x2782 ,0x4900 ,"MEDION E15443" ,ALC233_FIXUP_MEDION_MTL_SPK ), SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC),
Greg Kroah-Hartman
maintainerPATCH 749/826 fs/smb/client: implement chmod() for SMB3 POSIX Extensions
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ralph Boehme <[email protected]>
commit d413eabff18d640031fc955d107ad9c03c3bf9f1 upstream.
The NT ACL format for an SMB3 POSIX Extensions chmod() is a single ACE with the magic S-1-5-88-3-mode SID:
NT Security Descriptor
Revision: 1
Type: 0x8004, Self Relative, DACL Present
Offset to owner SID: 56
Offset to group SID: 124
Offset to SACL: 0
Offset to DACL: 20
Owner: S-1-5-21-3177838999-3893657415-1037673384-1000
Group: S-1-22-2-1000
NT User (DACL) ACL
Revision: NT4 (2)
Size: 36
Num ACEs: 1
NT ACE: S-1-5-88-3-438, flags 0x00, Access Allowed, mask 0x00000000
Type: Access Allowed
NT ACE Flags: 0x00
Size: 28
Access required: 0x00000000
SID: S-1-5-88-3-438Owner and Group should be NULL, but the server is not required to fail the request if they are present.
--- fs/smb/client/cifsacl.c | 50 +++++++++++++++++++++++++++------------------- fs/smb/client/cifsproto.h | 4 ++- fs/smb/client/inode.c | 4 ++- fs/smb/client/smb2pdu.c | 2 - 4 files changed, 37 insertions(+), 23 deletions(-)
fs/smb/client/cifsacl.c +30 -20
@@ -885,12 +885,17 @@ unsigned int setup_authusers_ACE(struct* Fill in the special SID based on the mode. See * https://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx */ -unsigned int setup_special_mode_ACE (struct smb_ace *pntace,__u64 nmode) +unsigned int setup_special_mode_ACE (struct smb_ace *pntace, +bool posix, +__u64 nmode) {int i;unsigned int ace_size =28 ; - pntace->type =ACCESS_DENIED_ACE_TYPE ; +if (posix) + pntace->type =ACCESS_ALLOWED_ACE_TYPE ; +else + pntace->type =ACCESS_DENIED_ACE_TYPE ; pntace->flags =0x0 ; pntace->access_req =0 ; pntace->sid.num_subauth =3 ;
@@ -933,7 +938,8 @@ static void populate_new_aces(char *naclstruct smb_sid *pownersid, struct smb_sid *pgrpsid, __u64 *pnmode, u32 *pnum_aces, u16 *pnsize, - bool modefromsid) + bool modefromsid, + bool posix) { __u64 nmode;u32 num_aces =0 ;
@@ -950,13 +956,15 @@ static void populate_new_aces(char *nacl num_aces = *pnum_aces; nsize = *pnsize; -if (modefromsid) { - pnntace = (struct smb_ace *) (nacl_base + nsize); - nsize +=setup_special_mode_ACE (pnntace, nmode); - num_aces++; +if (modefromsid || posix) { pnntace = (struct smb_ace *) (nacl_base + nsize); - nsize +=setup_authusers_ACE (pnntace); + nsize +=setup_special_mode_ACE (pnntace, posix, nmode); num_aces++; +if (modefromsid) { + pnntace = (struct smb_ace *) (nacl_base + nsize); + nsize +=setup_authusers_ACE (pnntace); + num_aces++; + } goto set_size; }
@@ -1076,7 +1084,7 @@ static __u16 replace_sids_and_copy_aces(static int set_chmod_dacl (struct smb_acl *pdacl,struct smb_acl *pndacl,struct smb_sid *pownersid,struct smb_sid *pgrpsid, -__u64 *pnmode,bool mode_from_sid) +__u64 *pnmode,bool mode_from_sid,bool posix) {int i;u16 size =0 ;
@@ -1094,11 +1102,11 @@ static int set_chmod_dacl(struct smb_acl nsize =sizeof (struct smb_acl );/* If pdacl is NULL, we don't have a src. Simply populate new ACL. */ -if (!pdacl) { +if (!pdacl || posix) {populate_new_aces (nacl_base, pownersid, pgrpsid, pnmode, &num_aces, &nsize, - mode_from_sid); + mode_from_sid, posix); goto finalize_dacl; }
@@ -1115,7 +1123,7 @@ static int set_chmod_dacl(struct smb_aclpopulate_new_aces (nacl_base, pownersid, pgrpsid, pnmode, &num_aces, &nsize, - mode_from_sid); + mode_from_sid, posix); new_aces_set = true; }
@@ -1144,7 +1152,7 @@ next_ace:populate_new_aces (nacl_base, pownersid, pgrpsid, pnmode, &num_aces, &nsize, - mode_from_sid); + mode_from_sid, posix); new_aces_set = true; }
@@ -1251,7 +1259,7 @@ static int parse_sec_desc(struct cifs_sb/* Convert permission bits from mode to equivalent CIFS ACL */ static int build_sec_desc (struct smb_ntsd *pntsd,struct smb_ntsd *pnntsd,__u32 secdesclen,__u32 *pnsecdesclen,__u64 *pnmode,kuid_t uid,kgid_t gid, -bool mode_from_sid,bool id_from_sid,int *aclflag) +bool mode_from_sid,bool id_from_sid,bool posix,int *aclflag) {int rc =0 ;__u32 dacloffset;
@@ -1288,7 +1296,7 @@ static int build_sec_desc(struct smb_nts ndacl_ptr->num_aces =cpu_to_le32 (0 ); rc =set_chmod_dacl (dacl_ptr, ndacl_ptr, owner_sid_ptr, group_sid_ptr, - pnmode, mode_from_sid); + pnmode, mode_from_sid, posix); sidsoffset = ndacloffset +le16_to_cpu (ndacl_ptr->size);/* copy the non-dacl portion of secdesc */
@@ -1587,6 +1595,7 @@ id_mode_to_cifs_acl(struct inode *inode,struct tcon_link *tlink =cifs_sb_tlink (cifs_sb);struct smb_version_operations *ops;bool mode_from_sid, id_from_sid; +bool posix =tlink_tcon (tlink)->posix_extensions;const u32 info =0 ;if (IS_ERR (tlink))
@@ -1622,12 +1631,13 @@ id_mode_to_cifs_acl(struct inode *inode, id_from_sid = false;/* Potentially, five new ACEs can be added to the ACL for U,G,O mapping */ - nsecdesclen = secdesclen;if (pnmode && *pnmode !=NO_CHANGE_64 ) {/* chmod */ -if (mode_from_sid) - nsecdesclen +=2 *sizeof (struct smb_ace ); +if (posix) + nsecdesclen =1 *sizeof (struct smb_ace ); +else if (mode_from_sid) + nsecdesclen = secdesclen + (2 *sizeof (struct smb_ace ));else /* cifsacl */ - nsecdesclen +=5 *sizeof (struct smb_ace ); + nsecdesclen = secdesclen + (5 *sizeof (struct smb_ace )); }else {/* chown */ /* When ownership changes, changes new owner sid length could be different */ nsecdesclen =sizeof (struct smb_ntsd ) + (sizeof (struct smb_sid ) *2 );
@@ -1657,7 +1667,7 @@ id_mode_to_cifs_acl(struct inode *inode, } rc =build_sec_desc (pntsd, pnntsd, secdesclen, &nsecdesclen, pnmode, uid, gid, - mode_from_sid, id_from_sid, &aclflag); + mode_from_sid, id_from_sid, posix, &aclflag);cifs_dbg (NOISY ,"build_sec_desc rc: %d\n" , rc);
fs/smb/client/cifsproto.h +3 -1
@@ -244,7 +244,9 @@ extern int cifs_set_acl(struct mnt_idmapextern int set_cifs_acl (struct smb_ntsd *pntsd,__u32 len,struct inode *ino,const char *path,int flag);extern unsigned int setup_authusers_ACE (struct smb_ace *pace); -extern unsigned int setup_special_mode_ACE (struct smb_ace *pace,__u64 nmode); +extern unsigned int setup_special_mode_ACE (struct smb_ace *pace, +bool posix, +__u64 nmode);extern unsigned int setup_special_user_owner_ACE (struct smb_ace *pace);extern void dequeue_mid (struct mid_q_entry *mid,bool malformed);
fs/smb/client/inode.c +3 -1
@@ -3062,6 +3062,7 @@ cifs_setattr_nounix(struct dentry *direnint rc = -EACCES ;__u32 dosattr =0 ;__u64 mode =NO_CHANGE_64 ; +bool posix =cifs_sb_master_tcon (cifs_sb)->posix_extensions; xid =get_xid ();
@@ -3152,7 +3153,8 @@ cifs_setattr_nounix(struct dentry *diren mode = attrs->ia_mode; rc =0 ;if ((cifs_sb->mnt_cifs_flags &CIFS_MOUNT_CIFS_ACL ) || - (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_MODE_FROM_SID )) { + (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_MODE_FROM_SID ) || + posix) { rc =id_mode_to_cifs_acl (inode, full_path, &mode,INVALID_UID ,INVALID_GID );if (rc) {
fs/smb/client/smb2pdu.c +1 -1
@@ -2685,7 +2685,7 @@ create_sd_buf(umode_t mode, bool set_own ptr +=sizeof (struct smb3_acl );/* create one ACE to hold the mode embedded in reserved special SID */ - acelen =setup_special_mode_ACE ((struct smb_ace *)ptr, (__u64 )mode); + acelen =setup_special_mode_ACE ((struct smb_ace *)ptr, false, (__u64 )mode); ptr += acelen; acl_size = acelen +sizeof (struct smb3_acl ); ace_count =1 ;
Greg Kroah-Hartman
maintainerPATCH 750/826 smb: client: fix use-after-free of signing key
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paulo Alcantara <[email protected]>
commit 343d7fe6df9e247671440a932b6a73af4fa86d95 upstream.
Customers have reported use-after-free in @ses->auth_key.response with SMB2.1 + sign mounts which occurs due to following race:
task A task Bcifs_mount()
dfs_mount_share()
get_session()
cifs_mount_get_session() cifs_send_recv()
cifs_get_smb_ses() compound_send_recv()
cifs_setup_session() smb2_setup_request()
kfree_sensitive() smb2_calc_signature()
crypto_shash_setkey() *UAF*
Fix this by ensuring that we have a valid @ses->auth_key.response by checking whether @ses->ses_status is SES_GOOD or SES_EXITING with @ses->ses_lock held. After commit 24a9799aa8ef ("smb: client: fix UAF in smb2_reconnect_server()"), we made sure to call ->logoff() only when @ses was known to be good (e.g. valid ->auth_key.response), so it's safe to access signing key when @ses->ses_status == SES_EXITING.
--- fs/smb/client/smb2proto.h | 2 - fs/smb/client/smb2transport.c | 56 ++++++++++++++++++++++++++++++------------ 2 files changed, 40 insertions(+), 18 deletions(-)
fs/smb/client/smb2proto.h +0 -2
@@ -37,8 +37,6 @@ extern struct mid_q_entry *smb2_setup_re struct smb_rqst *rqst);extern struct mid_q_entry *smb2_setup_async_request (struct TCP_Server_Info *server,struct smb_rqst *rqst); -extern struct cifs_ses *smb2_find_smb_ses (struct TCP_Server_Info *server, -__u64 ses_id);extern struct cifs_tcon *smb2_find_smb_tcon (struct TCP_Server_Info *server,__u64 ses_id,__u32 tid); extern int smb2_calc_signature(struct smb_rqst *rqst,
fs/smb/client/smb2transport.c +40 -16
100 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 751/826 smb3: request handle caching when caching directories
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steve French <[email protected]>
commit 9ed9d83a51a9636d367c796252409e7b2f4de4d4 upstream.
This client was only requesting READ caching, not READ and HANDLE caching in the LeaseState on the open requests we send for directories. To delay closing a handle (e.g. for caching directory contents) we should be requesting HANDLE as well as READ (as we already do for deferred
close of files). See MS-SMB2 3.3.1.4 e.g.
--- fs/smb/client/smb2ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/smb/client/smb2ops.c +1 -1
@@ -4080,7 +4080,7 @@ map_oplock_to_lease(u8 oplock)if (oplock ==SMB2_OPLOCK_LEVEL_EXCLUSIVE )return SMB2_LEASE_WRITE_CACHING_LE |SMB2_LEASE_READ_CACHING_LE ;else if (oplock ==SMB2_OPLOCK_LEVEL_II ) -return SMB2_LEASE_READ_CACHING_LE ; +return SMB2_LEASE_READ_CACHING_LE |SMB2_LEASE_HANDLE_CACHING_LE ;else if (oplock ==SMB2_OPLOCK_LEVEL_BATCH )return SMB2_LEASE_HANDLE_CACHING_LE |SMB2_LEASE_READ_CACHING_LE |SMB2_LEASE_WRITE_CACHING_LE ;
Greg Kroah-Hartman
maintainerPATCH 752/826 smb: client: handle max length for SMB symlinks
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paulo Alcantara <[email protected]>
commit 0812340811e45ec4039d409049be53056182a552 upstream.
We can't use PATH_MAX for SMB symlinks because
(1) Windows Server will fail FSCTL_SET_REPARSE_POINT with STATUS_IO_REPARSE_DATA_INVALID when input buffer is larger than 16K, as specified in MS-FSA 2.1.5.10.37.
(2) The client won't be able to parse large SMB responses that includes SMB symlink path within SMB2_CREATE or SMB2_IOCTL responses.
Fix this by defining a maximum length value (4060) for SMB symlinks that both client and server can handle.
--- fs/smb/client/reparse.c | 5 ++++- fs/smb/client/reparse.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-)
fs/smb/client/reparse.c +4 -1
@@ -35,6 +35,9 @@ int smb2_create_reparse_symlink(const unu16 len, plen;int rc =0 ; +if (strlen (symname) >REPARSE_SYM_PATH_MAX ) +return -ENAMETOOLONG ; + sym =kstrdup (symname,GFP_KERNEL );if (!sym)return -ENOMEM ;
@@ -64,7 +67,7 @@ int smb2_create_reparse_symlink(const unif (rc <0 ) goto out; - plen =2 *UniStrnlen ((wchar_t *)path,PATH_MAX ); + plen =2 *UniStrnlen ((wchar_t *)path,REPARSE_SYM_PATH_MAX ); len =sizeof (*buf) + plen *2 ; buf =kzalloc (len,GFP_KERNEL );if (!buf) {
fs/smb/client/reparse.h +2 -0
@@ -12,6 +12,8 @@#include "fs_context.h" #include "cifsglob.h" +#define REPARSE_SYM_PATH_MAX 4060 +/* * Used only by cifs.ko to ignore reparse points from files when client or * server doesn't support FSCTL_GET_REPARSE_POINT.
Greg Kroah-Hartman
maintainerPATCH 753/826 smb: Dont leak cfid when reconnect races with open_cached_dir
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Aurich <[email protected]>
commit 7afb86733685c64c604d32faf00fa4a1f22c2ab1 upstream.
open_cached_dir() may either race with the tcon reconnection even before compound_send_recv() or directly trigger a reconnection via SMB2_open_init() or SMB_query_info_init().
The reconnection process invokes invalidate_all_cached_dirs() via cifs_mark_open_files_invalid(), which removes all cfids from the cfids->entries list but doesn't drop a ref if has_lease isn't true. This results in the currently-being-constructed cfid not being on the list, but still having a refcount of 2. It leaks if returned from open_cached_dir().
Fix this by setting cfid->has_lease when the ref is actually taken; the cfid will not be used by other threads until it has a valid time.
Addresses these kmemleaks:
unreferenced object 0xffff8881090c4000 (size 1024):
comm "bash", pid 1860, jiffies 4295126592 hex dump (first 32 bytes):
00 01 00 00 00 00 ad de 22 01 00 00 00 00 ad de ........".......
00 ca 45 22 81 88 ff ff f8 dc 4f 04 81 88 ff ff ..E"......O.....
backtrace (crc 6f58c20f):
[<ffffffff8b895a1e>] __kmalloc_cache_noprof+0x2be/0x350
[<ffffffff8bda06e3>] open_cached_dir+0x993/0x1fb0
[<ffffffff8bdaa750>] cifs_readdir+0x15a0/0x1d50
[<ffffffff8b9a853f>] iterate_dir+0x28f/0x4b0
[<ffffffff8b9a9aed>] __x64_sys_getdents64+0xfd/0x200
[<ffffffff8cf6da05>] do_syscall_64+0x95/0x1a0
[<ffffffff8d00012f>] entry_SYSCALL_64_after_hwframe+0x76/0x7eunreferenced object 0xffff8881044fdcf8 (size 8):
comm "bash", pid 1860, jiffies 4295126592
hex dump (first 8 bytes):
00 cc cc cc cc cc cc cc ........
backtrace (crc 10c106a9):
[<ffffffff8b89a3d3>] __kmalloc_node_track_caller_noprof+0x363/0x480
[<ffffffff8b7d7256>] kstrdup+0x36/0x60
[<ffffffff8bda0700>] open_cached_dir+0x9b0/0x1fb0
[<ffffffff8bdaa750>] cifs_readdir+0x15a0/0x1d50
[<ffffffff8b9a853f>] iterate_dir+0x28f/0x4b0
[<ffffffff8b9a9aed>] __x64_sys_getdents64+0xfd/0x200
[<ffffffff8cf6da05>] do_syscall_64+0x95/0x1a0
[<ffffffff8d00012f>] entry_SYSCALL_64_after_hwframe+0x76/0x7eAnd addresses these BUG splats when unmounting the SMB filesystem:
BUG: Dentry ffff888140590ba0{i=1000000000080,n=/} still in use (2) [unmount of cifs cifs]
WARNING: CPU: 3 PID: 3433 at fs/dcache.c:1536 umount_check+0xd0/0x100
Modules linked in:
CPU: 3 UID: 0 PID: 3433 Comm: bash Not tainted 6.12.0-rc4-g850925a8133c-dirty #49
Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 11/12/2020
RIP: 0010:umount_check+0xd0/0x100
Code: 8d 7c 24 40 e8 31 5a f4 ff 49 8b 54 24 40 41 56 49 89 e9 45 89 e8 48 89 d9 41 57 48 89 de 48 c7 c7 80 e7 db ac e8 f0 72 9a ff <0f> 0b 58 31 c0 5a 5b 5d 41 5c 41 5d 41 5e 41 5f e9 2b e5 5d 01 41
RSP: 0018:ffff88811cc27978 EFLAGS: 00010286
RAX: 0000000000000000 RBX: ffff888140590ba0 RCX: ffffffffaaf20bae
RDX: dffffc0000000000 RSI: 0000000000000008 RDI: ffff8881f6fb6f40
RBP: ffff8881462ec000 R08: 0000000000000001 R09: ffffed1023984ee3
R10: ffff88811cc2771f R11: 00000000016cfcc0 R12: ffff888134383e08
R13: 0000000000000002 R14: ffff8881462ec668 R15: ffffffffaceab4c0
FS: 00007f23bfa98740(0000) GS:ffff8881f6f80000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000556de4a6f808 CR3: 0000000123c80000 CR4: 0000000000350ef0
Call Trace:
<TASK>
d_walk+0x6a/0x530
shrink_dcache_for_umount+0x6a/0x200
generic_shutdown_super+0x52/0x2a0
kill_anon_super+0x22/0x40
cifs_kill_sb+0x159/0x1e0
deactivate_locked_super+0x66/0xe0
cleanup_mnt+0x140/0x210
task_work_run+0xfb/0x170
syscall_exit_to_user_mode+0x29f/0x2b0
do_syscall_64+0xa1/0x1a0
entry_SYSCALL_64_after_hwframe+0x76/0x7e
RIP: 0033:0x7f23bfb93ae7
Code: ff ff ff ff c3 66 0f 1f 44 00 00 48 8b 0d 11 93 0d 00 f7 d8 64 89 01 b8 ff ff ff ff eb bf 0f 1f 44 00 00 b8 50 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d e9 92 0d 00 f7 d8 64 89 01 48
RSP: 002b:00007ffee9138598 EFLAGS: 00000246 ORIG_RAX: 0000000000000050
RAX: 0000000000000000 RBX: 0000558f1803e9a0 RCX: 00007f23bfb93ae7
RDX: 0000000000000000 RSI: 0000000000000004 RDI: 0000558f1803e9a0
RBP: 0000558f1803e600 R08: 0000000000000007 R09: 0000558f17fab610
R10: d91d5ec34ab757b0 R11: 0000000000000246 R12: 0000000000000001
R13: 0000000000000000 R14: 0000000000000015 R15: 0000000000000000
</TASK>
irq event stamp: 1163486
hardirqs last enabled at (1163485): [<ffffffffac98d344>] _raw_spin_unlock_irqrestore+0x34/0x60
hardirqs last disabled at (1163486): [<ffffffffac97dcfc>] __schedule+0xc7c/0x19a0
softirqs last enabled at (1163482): [<ffffffffab79a3ee>] __smb_send_rqst+0x3de/0x990
softirqs last disabled at (1163480): [<ffffffffac2314f1>] release_sock+0x21/0xf0
---[ end trace 0000000000000000 ]---VFS: Busy inodes after unmount of cifs (cifs)
------------[ cut here ]------------ kernel BUG at fs/super.c:661! Oops: invalid opcode: 0000 [#1] PREEMPT SMP KASAN NOPTI CPU: 1 UID: 0 PID: 3433 Comm: bash Tainted: G W 6.12.0-rc4-g850925a8133c-dirty #49 Tainted: [W]=WARN Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 11/12/2020 RIP: 0010:generic_shutdown_super+0x290/0x2a0 Code: e8 15 7c f7 ff 48 8b 5d 28 48 89 df e8 09 7c f7 ff 48 8b 0b 48 89 ee 48 8d 95 68 06 00 00 48 c7 c7 80 7f db ac e8 00 69 af ff <0f> 0b 66 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 90 90 90 90 90 90 RSP: 0018:ffff88811cc27a50 EFLAGS: 00010246 RAX: 000000000000003e RBX: ffffffffae994420 RCX: 0000000000000027 RDX: 0000000000000000 RSI: ffffffffab06180e RDI: ffff8881f6eb18c8 RBP: ffff8881462ec000 R08: 0000000000000001 R09: ffffed103edd6319 R10: ffff8881f6eb18cb R11: 00000000016d3158 R12: ffff8881462ec9c0 R13: ffff8881462ec050 R14: 0000000000000001 R15: 0000000000000000 FS: 00007f23bfa98740(0000) GS:ffff8881f6e80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f8364005d68 CR3: 0000000123c80000 CR4: 0000000000350ef0 Call Trace: <TASK> kill_anon_super+0x22/0x40 cifs_kill_sb+0x159/0x1e0 deactivate_locked_super+0x66/0xe0 cleanup_mnt+0x140/0x210 task_work_run+0xfb/0x170 syscall_exit_to_user_mode+0x29f/0x2b0 do_syscall_64+0xa1/0x1a0 entry_SYSCALL_64_after_hwframe+0x76/0x7e RIP: 0033:0x7f23bfb93ae7 </TASK> Modules linked in: ---[ end trace 0000000000000000 ]--- RIP: 0010:generic_shutdown_super+0x290/0x2a0 Code: e8 15 7c f7 ff 48 8b 5d 28 48 89 df e8 09 7c f7 ff 48 8b 0b 48 89 ee 48 8d 95 68 06 00 00 48 c7 c7 80 7f db ac e8 00 69 af ff <0f> 0b 66 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 90 90 90 90 90 90 RSP: 0018:ffff88811cc27a50 EFLAGS: 00010246 RAX: 000000000000003e RBX: ffffffffae994420 RCX: 0000000000000027 RDX: 0000000000000000 RSI: ffffffffab06180e RDI: ffff8881f6eb18c8 RBP: ffff8881462ec000 R08: 0000000000000001 R09: ffffed103edd6319 R10: ffff8881f6eb18cb R11: 00000000016d3158 R12: ffff8881462ec9c0 R13: ffff8881462ec050 R14: 0000000000000001 R15: 0000000000000000 FS: 00007f23bfa98740(0000) GS:ffff8881f6e80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f8364005d68 CR3: 0000000123c80000 CR4: 0000000000350ef0
This reproduces eventually with an SMB mount and two shells running these loops concurrently
- while true; do
cd ~; sleep 1;
for i in {1..3}; do cd /mnt/test/subdir;
echo $PWD; sleep 1; cd ..; echo $PWD; sleep 1;
done;
echo ...;
done
- while true; do
iptables -F OUTPUT; mount -t cifs -a;
for _ in {0..2}; do ls /mnt/test/subdir/ | wc -l; done;
iptables -I OUTPUT -p tcp --dport 445 -j DROP;
sleep 10
echo "unmounting"; umount -l -t cifs -a; echo "done unmounting";
sleep 20
echo "recovering"; iptables -F OUTPUT;
sleep 10;done
--- fs/smb/client/cached_dir.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-)
fs/smb/client/cached_dir.c +14 -13
@@ -59,6 +59,16 @@ static struct cached_fid *find_or_createlist_add (&cfid->entry, &cfids->entries); cfid->on_list = true;kref_get (&cfid->refcount); +/* +* Set @cfid->has_lease to true during construction so that the lease +* reference can be put in cached_dir_lease_break() due to a potential +* lease break right after the request is sent or while @cfid is still +* being cached, or if a reconnection is triggered during construction. +* Concurrent processes won't be to use it yet due to @cfid->time being +* zero. +*/ + cfid->has_lease = true; +spin_unlock (&cfids->cfid_list_lock);return cfid; }
@@ -176,12 +186,12 @@ replay_again:return -ENOENT ; }/* -* Return cached fid if it has a lease. Otherwise, it is either a new -* entry or laundromat worker removed it from @cfids->entries. Caller -* will put last reference if the latter. +* Return cached fid if it is valid (has a lease and has a time). +* Otherwise, it is either a new entry or laundromat worker removed it +* from @cfids->entries. Caller will put last reference if the latter. */ spin_lock (&cfids->cfid_list_lock); -if (cfid->has_lease) { +if (cfid->has_lease && cfid->time) {spin_unlock (&cfids->cfid_list_lock); *ret_cfid = cfid;kfree (utf16_path);
@@ -267,15 +277,6 @@ replay_again:smb2_set_related (&rqst[1 ]); -/* -* Set @cfid->has_lease to true before sending out compounded request so -* its lease reference can be put in cached_dir_lease_break() due to a -* potential lease break right after the request is sent or while @cfid -* is still being cached. Concurrent processes won't be to use it yet -* due to @cfid->time being zero. -*/ - cfid->has_lease = true; -if (retries) {smb2_set_replay (server, &rqst[0 ]);smb2_set_replay (server, &rqst[1 ]);
Greg Kroah-Hartman
maintainerPATCH 754/826 smb: prevent use-after-free due to open_cached_dir error paths
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Aurich <[email protected]>
commit a9685b409a03b73d2980bbfa53eb47555802d0a9 upstream.
If open_cached_dir() encounters an error parsing the lease from the server, the error handling may race with receiving a lease break, resulting in open_cached_dir() freeing the cfid while the queued work is pending.
Update open_cached_dir() to drop refs rather than directly freeing the cfid.
Have cached_dir_lease_break(), cfids_laundromat_worker(), and invalidate_all_cached_dirs() clear has_lease immediately while still holding cfids->cfid_list_lock, and then use this to also simplify the reference counting in cfids_laundromat_worker() and invalidate_all_cached_dirs().
Fixes this KASAN splat (which manually injects an error and lease break in open_cached_dir()):
==================================================================
BUG: KASAN: slab-use-after-free in smb2_cached_lease_break+0x27/0xb0 Read of size 8 at addr ffff88811cc24c10 by task kworker/3:1/65 CPU: 3 UID: 0 PID: 65 Comm: kworker/3:1 Not tainted 6.12.0-rc6-g255cf264e6e5-dirty #87 Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 11/12/2020 Workqueue: cifsiod smb2_cached_lease_break Call Trace: <TASK> dump_stack_lvl+0x77/0xb0 print_report+0xce/0x660 kasan_report+0xd3/0x110 smb2_cached_lease_break+0x27/0xb0 process_one_work+0x50a/0xc50 worker_thread+0x2ba/0x530 kthread+0x17c/0x1c0 ret_from_fork+0x34/0x60 ret_from_fork_asm+0x1a/0x30 </TASK> Allocated by task 2464: kasan_save_stack+0x33/0x60 kasan_save_track+0x14/0x30 __kasan_kmalloc+0xaa/0xb0 open_cached_dir+0xa7d/0x1fb0 smb2_query_path_info+0x43c/0x6e0 cifs_get_fattr+0x346/0xf10 cifs_get_inode_info+0x157/0x210 cifs_revalidate_dentry_attr+0x2d1/0x460 cifs_getattr+0x173/0x470 vfs_statx_path+0x10f/0x160 vfs_statx+0xe9/0x150 vfs_fstatat+0x5e/0xc0 __do_sys_newfstatat+0x91/0xf0 do_syscall_64+0x95/0x1a0 entry_SYSCALL_64_after_hwframe+0x76/0x7e Freed by task 2464: kasan_save_stack+0x33/0x60 kasan_save_track+0x14/0x30 kasan_save_free_info+0x3b/0x60 __kasan_slab_free+0x51/0x70 kfree+0x174/0x520 open_cached_dir+0x97f/0x1fb0 smb2_query_path_info+0x43c/0x6e0 cifs_get_fattr+0x346/0xf10 cifs_get_inode_info+0x157/0x210 cifs_revalidate_dentry_attr+0x2d1/0x460 cifs_getattr+0x173/0x470 vfs_statx_path+0x10f/0x160 vfs_statx+0xe9/0x150 vfs_fstatat+0x5e/0xc0 __do_sys_newfstatat+0x91/0xf0 do_syscall_64+0x95/0x1a0 entry_SYSCALL_64_after_hwframe+0x76/0x7e Last potentially related work creation: kasan_save_stack+0x33/0x60 __kasan_record_aux_stack+0xad/0xc0 insert_work+0x32/0x100 __queue_work+0x5c9/0x870 queue_work_on+0x82/0x90 open_cached_dir+0x1369/0x1fb0 smb2_query_path_info+0x43c/0x6e0 cifs_get_fattr+0x346/0xf10 cifs_get_inode_info+0x157/0x210 cifs_revalidate_dentry_attr+0x2d1/0x460 cifs_getattr+0x173/0x470 vfs_statx_path+0x10f/0x160 vfs_statx+0xe9/0x150 vfs_fstatat+0x5e/0xc0 __do_sys_newfstatat+0x91/0xf0 do_syscall_64+0x95/0x1a0 entry_SYSCALL_64_after_hwframe+0x76/0x7e The buggy address belongs to the object at ffff88811cc24c00 which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 16 bytes inside of
freed 1024-byte region [ffff88811cc24c00, ffff88811cc25000)
--- fs/smb/client/cached_dir.c | 70 ++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 41 deletions(-)
fs/smb/client/cached_dir.c +29 -41
@@ -348,6 +348,7 @@ oshr_free:SMB2_query_info_free (&rqst[1 ]);free_rsp_buf (resp_buftype[0 ], rsp_iov[0 ].iov_base);free_rsp_buf (resp_buftype[1 ], rsp_iov[1 ].iov_base); +out:if (rc) {spin_lock (&cfids->cfid_list_lock);if (cfid->on_list) {
@@ -359,23 +360,14 @@ oshr_free:/* * We are guaranteed to have two references at this * point. One for the caller and one for a potential -* lease. Release the Lease-ref so that the directory -* will be closed when the caller closes the cached -* handle. +* lease. Release one here, and the second below. */ cfid->has_lease = false; -spin_unlock (&cfids->cfid_list_lock);kref_put (&cfid->refcount, smb2_close_cached_fid); - goto out; }spin_unlock (&cfids->cfid_list_lock); - } -out: -if (rc) { -if (cfid->is_open) -SMB2_close (0 , cfid->tcon, cfid->fid.persistent_fid, - cfid->fid.volatile_fid); -free_cached_dir (cfid); + +kref_put (&cfid->refcount, smb2_close_cached_fid); }else { *ret_cfid = cfid;atomic_inc (&tcon->num_remote_opens);
@@ -513,25 +505,24 @@ void invalidate_all_cached_dirs(struct c cfids->num_entries--; cfid->is_open = false; cfid->on_list = false; -/* To prevent race with smb2_cached_lease_break() */ -kref_get (&cfid->refcount); +if (cfid->has_lease) { +/* +* The lease was never cancelled from the server, +* so steal that reference. +*/ + cfid->has_lease = false; + }else +kref_get (&cfid->refcount); }spin_unlock (&cfids->cfid_list_lock);list_for_each_entry_safe (cfid, q, &entry, entry) {list_del (&cfid->entry);cancel_work_sync (&cfid->lease_break); -if (cfid->has_lease) { -/* -* We lease was never cancelled from the server so we -* need to drop the reference. -*/ -spin_lock (&cfids->cfid_list_lock); - cfid->has_lease = false; -spin_unlock (&cfids->cfid_list_lock); -kref_put (&cfid->refcount, smb2_close_cached_fid); - } -/* Drop the extra reference opened above*/ +/* +* Drop the ref-count from above, either the lease-ref (if there +* was one) or the extra one acquired. +*/ kref_put (&cfid->refcount, smb2_close_cached_fid); } }
@@ -542,9 +533,6 @@ smb2_cached_lease_break(struct work_strustruct cached_fid *cfid =container_of (work, struct cached_fid, lease_break); -spin_lock (&cfid->cfids->cfid_list_lock); - cfid->has_lease = false; -spin_unlock (&cfid->cfids->cfid_list_lock);kref_put (&cfid->refcount, smb2_close_cached_fid); }
@@ -562,6 +550,7 @@ int cached_dir_lease_break(struct cifs_t !memcmp(lease_key, cfid->fid.lease_key, SMB2_LEASE_KEY_SIZE)) { + cfid->has_lease = false; cfid->time =0 ;/* * We found a lease remove it from the list
@@ -639,8 +628,14 @@ static void cfids_laundromat_worker(stru cfid->on_list = false;list_move (&cfid->entry, &entry); cfids->num_entries--; -/* To prevent race with smb2_cached_lease_break() */ -kref_get (&cfid->refcount); +if (cfid->has_lease) { +/* +* Our lease has not yet been cancelled from the +* server. Steal that reference. +*/ + cfid->has_lease = false; + }else +kref_get (&cfid->refcount); } }spin_unlock (&cfids->cfid_list_lock);
@@ -652,17 +647,10 @@ static void cfids_laundromat_worker(stru* with it. */ cancel_work_sync (&cfid->lease_break); -if (cfid->has_lease) { -/* -* Our lease has not yet been cancelled from the server -* so we need to drop the reference. -*/ -spin_lock (&cfids->cfid_list_lock); - cfid->has_lease = false; -spin_unlock (&cfids->cfid_list_lock); -kref_put (&cfid->refcount, smb2_close_cached_fid); - } -/* Drop the extra reference opened above */ +/* +* Drop the ref-count from above, either the lease-ref (if there +* was one) or the extra one acquired. +*/ kref_put (&cfid->refcount, smb2_close_cached_fid); } queue_delayed_work(cifsiod_wq, &cfids->laundromat_work,
Greg Kroah-Hartman
maintainerPATCH 755/826 smb: During unmount, ensure all cached dir instances drop their dentry
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Aurich <[email protected]>
commit 3fa640d035e5ae526769615c35cb9ed4be6e3662 upstream.
The unmount process (cifs_kill_sb() calling close_all_cached_dirs()) can race with various cached directory operations, which ultimately results in dentries not being dropped and these kernel BUGs:
BUG: Dentry ffff88814f37e358{i=1000000000080,n=/} still in use (2) [unmount of cifs cifs]
VFS: Busy inodes after unmount of cifs (cifs)
------------[ cut here ]------------
kernel BUG at fs/super.c:661!This happens when a cfid is in the process of being cleaned up when, and has been removed from the cfids->entries list, including:
- Receiving a lease break from the server
- Server reconnection triggers invalidate_all_cached_dirs(), which removes all the cfids from the list
- The laundromat thread decides to expire an old cfid.
To solve these problems, dropping the dentry is done in queued work done in a newly-added cfid_put_wq workqueue, and close_all_cached_dirs() flushes that workqueue after it drops all the dentries of which it's aware. This is a global workqueue (rather than scoped to a mount), but the queued work is minimal.
The final cleanup work for cleaning up a cfid is performed via work queued in the serverclose_wq workqueue; this is done separate from dropping the dentries so that close_all_cached_dirs() doesn't block on any server operations.
Both of these queued works expect to invoked with a cfid reference and a tcon reference to avoid those objects from being freed while the work is ongoing.
While we're here, add proper locking to close_all_cached_dirs(), and locking around the freeing of cfid->dentry.
--- fs/smb/client/cached_dir.c | 156 ++++++++++++++++++++++++++++++++++++--------- fs/smb/client/cached_dir.h | 6 + fs/smb/client/cifsfs.c | 12 +++ fs/smb/client/cifsglob.h | 3 fs/smb/client/inode.c | 3 fs/smb/client/trace.h | 3 6 files changed, 147 insertions(+), 36 deletions(-)
fs/smb/client/cached_dir.c +126 -30
@@ -17,6 +17,11 @@ static void free_cached_dir(struct cachestatic void smb2_close_cached_fid (struct kref *ref);static void cfids_laundromat_worker (struct work_struct *work); +struct cached_dir_dentry { +struct list_head entry; +struct dentry *dentry; +}; + static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids, const char *path, bool lookup_only,
@@ -470,7 +475,10 @@ void close_all_cached_dirs(struct cifs_sstruct cifs_tcon *tcon;struct tcon_link *tlink;struct cached_fids *cfids; +struct cached_dir_dentry *tmp_list, *q; +LIST_HEAD (entry); +spin_lock (&cifs_sb->tlink_tree_lock);for (node =rb_first (root); node; node =rb_next (node)) { tlink = rb_entry(node, struct tcon_link, tl_rbnode); tcon =tlink_tcon (tlink);
@@ -479,11 +487,30 @@ void close_all_cached_dirs(struct cifs_s cfids = tcon->cfids;if (cfids ==NULL )continue ; +spin_lock (&cfids->cfid_list_lock);list_for_each_entry (cfid, &cfids->entries, entry) { -dput (cfid->dentry); + tmp_list =kmalloc (sizeof (*tmp_list),GFP_ATOMIC ); +if (tmp_list ==NULL ) +break ; +spin_lock (&cfid->fid_lock); + tmp_list->dentry = cfid->dentry; cfid->dentry =NULL ; +spin_unlock (&cfid->fid_lock); + +list_add_tail (&tmp_list->entry, &entry); } +spin_unlock (&cfids->cfid_list_lock); + } +spin_unlock (&cifs_sb->tlink_tree_lock); + +list_for_each_entry_safe (tmp_list, q, &entry, entry) { +list_del (&tmp_list->entry); +dput (tmp_list->dentry); +kfree (tmp_list); } + +/* Flush any pending work that will drop dentries */ +flush_workqueue (cfid_put_wq); }/*
@@ -494,14 +521,18 @@ void invalidate_all_cached_dirs(struct c {struct cached_fids *cfids = tcon->cfids;struct cached_fid *cfid, *q; -LIST_HEAD (entry);if (cfids ==NULL )return ; +/* +* Mark all the cfids as closed, and move them to the cfids->dying list. +* They'll be cleaned up later by cfids_invalidation_worker. Take +* a reference to each cfid during this process. +*/ spin_lock (&cfids->cfid_list_lock);list_for_each_entry_safe (cfid, q, &cfids->entries, entry) { -list_move (&cfid->entry, &entry); +list_move (&cfid->entry, &cfids->dying); cfids->num_entries--; cfid->is_open = false; cfid->on_list = false;
@@ -514,26 +545,47 @@ void invalidate_all_cached_dirs(struct c }else kref_get (&cfid->refcount); } +/* +* Queue dropping of the dentries once locks have been dropped +*/ +if (!list_empty (&cfids->dying)) +queue_work (cfid_put_wq, &cfids->invalidation_work);spin_unlock (&cfids->cfid_list_lock); - -list_for_each_entry_safe (cfid, q, &entry, entry) { -list_del (&cfid->entry); -cancel_work_sync (&cfid->lease_break); -/* -* Drop the ref-count from above, either the lease-ref (if there -* was one) or the extra one acquired. -*/ -kref_put (&cfid->refcount, smb2_close_cached_fid); - } }static void -smb2_cached_lease_break (struct work_struct *work) +cached_dir_offload_close (struct work_struct *work) {struct cached_fid *cfid =container_of (work, - struct cached_fid, lease_break); + struct cached_fid, close_work); +struct cifs_tcon *tcon = cfid->tcon; + +WARN_ON (cfid->on_list);kref_put (&cfid->refcount, smb2_close_cached_fid); +cifs_put_tcon (tcon, netfs_trace_tcon_ref_put_cached_close); +} + +/* +* Release the cached directory's dentry, and then queue work to drop cached +* directory itself (closing on server if needed). +* +* Must be called with a reference to the cached_fid and a reference to the +* tcon. +*/ +static void cached_dir_put_work (struct work_struct *work) +{ + struct cached_fid *cfid = container_of(work, struct cached_fid, + put_work); +struct dentry *dentry; + +spin_lock (&cfid->fid_lock); + dentry = cfid->dentry; + cfid->dentry =NULL ; +spin_unlock (&cfid->fid_lock); + +dput (dentry); +queue_work (serverclose_wq, &cfid->close_work); }int cached_dir_lease_break (struct cifs_tcon *tcon,__u8 lease_key[16 ])
@@ -560,8 +612,10 @@ int cached_dir_lease_break(struct cifs_t cfid->on_list = false; cfids->num_entries--; -queue_work (cifsiod_wq, - &cfid->lease_break); + ++tcon->tc_count; +trace_smb3_tcon_ref (tcon->debug_id, tcon->tc_count, + netfs_trace_tcon_ref_get_cached_lease_break); +queue_work (cfid_put_wq, &cfid->put_work);spin_unlock (&cfids->cfid_list_lock);return true; }
@@ -583,7 +637,8 @@ static struct cached_fid *init_cached_direturn NULL ; } -INIT_WORK (&cfid->lease_break, smb2_cached_lease_break); +INIT_WORK (&cfid->close_work, cached_dir_offload_close); +INIT_WORK (&cfid->put_work, cached_dir_put_work);INIT_LIST_HEAD (&cfid->entry);INIT_LIST_HEAD (&cfid->dirents.entries);mutex_init (&cfid->dirents.de_mutex);
@@ -596,6 +651,9 @@ static void free_cached_dir(struct cache {struct cached_dirent *dirent, *q; +WARN_ON (work_pending (&cfid->close_work)); +WARN_ON (work_pending (&cfid->put_work)); +dput (cfid->dentry); cfid->dentry =NULL ;
@@ -613,10 +671,30 @@ static void free_cached_dir(struct cachekfree (cfid); } +static void cfids_invalidation_worker (struct work_struct *work) +{ + struct cached_fids *cfids = container_of(work, struct cached_fids, + invalidation_work); +struct cached_fid *cfid, *q; +LIST_HEAD (entry); + +spin_lock (&cfids->cfid_list_lock); +/* move cfids->dying to the local list */ +list_cut_before (&entry, &cfids->dying, &cfids->dying); +spin_unlock (&cfids->cfid_list_lock); + +list_for_each_entry_safe (cfid, q, &entry, entry) { +list_del (&cfid->entry); +/* Drop the ref-count acquired in invalidate_all_cached_dirs */ +kref_put (&cfid->refcount, smb2_close_cached_fid); + } +} +static void cfids_laundromat_worker (struct work_struct *work) {struct cached_fids *cfids;struct cached_fid *cfid, *q; +struct dentry *dentry;LIST_HEAD (entry); cfids = container_of(work, struct cached_fids, laundromat_work.work);
@@ -642,18 +720,28 @@ static void cfids_laundromat_worker(strulist_for_each_entry_safe (cfid, q, &entry, entry) {list_del (&cfid->entry); -/* -* Cancel and wait for the work to finish in case we are racing -* with it. -*/ -cancel_work_sync (&cfid->lease_break); -/* -* Drop the ref-count from above, either the lease-ref (if there -* was one) or the extra one acquired. -*/ -kref_put (&cfid->refcount, smb2_close_cached_fid); + +spin_lock (&cfid->fid_lock); + dentry = cfid->dentry; + cfid->dentry =NULL ; +spin_unlock (&cfid->fid_lock); + +dput (dentry); +if (cfid->is_open) { +spin_lock (&cifs_tcp_ses_lock); + ++cfid->tcon->tc_count; +trace_smb3_tcon_ref (cfid->tcon->debug_id, cfid->tcon->tc_count, + netfs_trace_tcon_ref_get_cached_laundromat); +spin_unlock (&cifs_tcp_ses_lock); +queue_work (serverclose_wq, &cfid->close_work); + }else +/* +* Drop the ref-count from above, either the lease-ref (if there +* was one) or the extra one acquired. +*/ +kref_put (&cfid->refcount, smb2_close_cached_fid); } -queue_delayed_work (cifsiod_wq, &cfids->laundromat_work, +queue_delayed_work (cfid_put_wq, &cfids->laundromat_work, dir_cache_timeout *HZ ); }
@@ -666,9 +754,11 @@ struct cached_fids *init_cached_dirs(voireturn NULL ;spin_lock_init (&cfids->cfid_list_lock);INIT_LIST_HEAD (&cfids->entries); +INIT_LIST_HEAD (&cfids->dying); +INIT_WORK (&cfids->invalidation_work, cfids_invalidation_worker);INIT_DELAYED_WORK (&cfids->laundromat_work, cfids_laundromat_worker); -queue_delayed_work (cifsiod_wq, &cfids->laundromat_work, +queue_delayed_work (cfid_put_wq, &cfids->laundromat_work, dir_cache_timeout *HZ );return cfids;
@@ -687,12 +777,18 @@ void free_cached_dirs(struct cached_fidsreturn ;cancel_delayed_work_sync (&cfids->laundromat_work); +cancel_work_sync (&cfids->invalidation_work);spin_lock (&cfids->cfid_list_lock);list_for_each_entry_safe (cfid, q, &cfids->entries, entry) { cfid->on_list = false; cfid->is_open = false;list_move (&cfid->entry, &entry); + } +list_for_each_entry_safe (cfid, q, &cfids->dying, entry) { + cfid->on_list = false; + cfid->is_open = false; +list_move (&cfid->entry, &entry); }spin_unlock (&cfids->cfid_list_lock);
fs/smb/client/cached_dir.h +5 -1
@@ -44,7 +44,8 @@ struct cached_fid {spinlock_t fid_lock;struct cifs_tcon *tcon;struct dentry *dentry; -struct work_struct lease_break; +struct work_struct put_work; +struct work_struct close_work;struct smb2_file_all_info file_all_info;struct cached_dirents dirents; };
@@ -53,10 +54,13 @@ struct cached_fid {struct cached_fids {/* Must be held when: * - accessing the cfids->entries list +* - accessing the cfids->dying list */ spinlock_t cfid_list_lock;int num_entries;struct list_head entries; +struct list_head dying; +struct work_struct invalidation_work;struct delayed_work laundromat_work; };
fs/smb/client/cifsfs.c +11 -1
@@ -157,6 +157,7 @@ struct workqueue_struct *fileinfo_put_wqstruct workqueue_struct *cifsoplockd_wq;struct workqueue_struct *deferredclose_wq;struct workqueue_struct *serverclose_wq; +struct workqueue_struct *cfid_put_wq;__u32 cifs_lock_secret;/*
@@ -1895,9 +1896,16 @@ init_cifs(void) goto out_destroy_deferredclose_wq; } + cfid_put_wq =alloc_workqueue ("cfid_put_wq" , +WQ_FREEZABLE |WQ_MEM_RECLAIM ,0 ); +if (!cfid_put_wq) { + rc = -ENOMEM ; + goto out_destroy_serverclose_wq; + } + rc =cifs_init_inodecache ();if (rc) - goto out_destroy_serverclose_wq; + goto out_destroy_cfid_put_wq; rc =cifs_init_netfs ();if (rc)
@@ -1965,6 +1973,8 @@ out_destroy_netfs:cifs_destroy_netfs (); out_destroy_inodecache:cifs_destroy_inodecache (); +out_destroy_cfid_put_wq: +destroy_workqueue (cfid_put_wq); out_destroy_serverclose_wq:destroy_workqueue (serverclose_wq); out_destroy_deferredclose_wq:
fs/smb/client/cifsglob.h +2 -1
@@ -1983,7 +1983,7 @@ require use of the stronger protocol */* cifsInodeInfo->lock_sem cifsInodeInfo->llist cifs_init_once * ->can_cache_brlcks * cifsInodeInfo->deferred_lock cifsInodeInfo->deferred_closes cifsInodeInfo_alloc -* cached_fid->fid_mutex cifs_tcon->crfid tcon_info_alloc +* cached_fids->cfid_list_lock cifs_tcon->cfids->entries init_cached_dirs * cifsFileInfo->fh_mutex cifsFileInfo cifs_new_fileinfo * cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo * ->invalidHandle initiate_cifs_search
@@ -2071,6 +2071,7 @@ extern struct workqueue_struct *fileinfoextern struct workqueue_struct *cifsoplockd_wq;extern struct workqueue_struct *deferredclose_wq;extern struct workqueue_struct *serverclose_wq; +extern struct workqueue_struct *cfid_put_wq;extern __u32 cifs_lock_secret;extern mempool_t *cifs_sm_req_poolp;
fs/smb/client/inode.c +0 -3
@@ -2473,13 +2473,10 @@ cifs_dentry_needs_reval(struct dentry *dreturn true;if (!open_cached_dir_by_dentry (tcon, dentry->d_parent, &cfid)) { -spin_lock (&cfid->fid_lock);if (cfid->time && cifs_i->time > cfid->time) { -spin_unlock (&cfid->fid_lock);close_cached_dir (cfid);return false; } -spin_unlock (&cfid->fid_lock);close_cached_dir (cfid); }/*
fs/smb/client/trace.h +3 -0
@@ -44,6 +44,8 @@ EM(netfs_trace_tcon_ref_free_ipc, "FRE Ipc ") \ EM(netfs_trace_tcon_ref_free_ipc_fail, "FRE Ipc-F ") \ EM(netfs_trace_tcon_ref_free_reconnect_server, "FRE Reconn") \ + EM(netfs_trace_tcon_ref_get_cached_laundromat, "GET Ch-Lau") \ + EM(netfs_trace_tcon_ref_get_cached_lease_break, "GET Ch-Lea") \ EM(netfs_trace_tcon_ref_get_cancelled_close, "GET Cn-Cls") \ EM(netfs_trace_tcon_ref_get_dfs_refer, "GET DfsRef") \EM (netfs_trace_tcon_ref_get_find,"GET Find " ) \
@@ -52,6 +54,7 @@ EM(netfs_trace_tcon_ref_new, "NEW ") \ EM(netfs_trace_tcon_ref_new_ipc, "NEW Ipc ") \ EM(netfs_trace_tcon_ref_new_reconnect_server, "NEW Reconn") \ + EM(netfs_trace_tcon_ref_put_cached_close, "PUT Ch-Cls") \ EM(netfs_trace_tcon_ref_put_cancelled_close, "PUT Cn-Cls") \ EM(netfs_trace_tcon_ref_put_cancelled_close_fid, "PUT Cn-Fid") \EM (netfs_trace_tcon_ref_put_cancelled_mid,"PUT Cn-Mid" ) \
Greg Kroah-Hartman
maintainerPATCH 756/826 usb: misc: ljca: set small runtime autosuspend delay
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stanislaw Gruszka <[email protected]>
commit 2481af79671a6603fce201cbbc48f31e488e9fae upstream.
On some Lenovo platforms, the patch works around problems with ov2740 sensor initialization, which manifest themself like below:
[ 4.540476] ov2740 i2c-INT3474:01: error -EIO: failed to find sensor [ 4.542066] ov2740 i2c-INT3474:01: probe with driver ov2740 failed with error -5
or
[ 7.742633] ov2740 i2c-INT3474:01: chip id mismatch: 2740 != 0 [ 7.742638] ov2740 i2c-INT3474:01: error -ENXIO: failed to find sensor
and also by random failures of video stream start.
Issue can be reproduced by this script:
n=0
k=0
while [ $n -lt 50 ] ; do
sudo modprobe -r ov2740
sleep expr $RANDOM % 5
sudo modprobe ov2740
if media-ctl -p | grep -q ov2740 ; then
let k++
fi
let n++
done
echo Success rate $k/$n
Without the patch, success rate is approximately 15 or 50 tries. With the patch it does not fail.
This problem is some hardware or firmware malfunction, that can not be easy debug and fix. While setting small autosuspend delay is not perfect workaround as user can configure it to any value, it will prevent the failures by default.
Additionally setting small autosuspend delay should have positive effect on power consumption as for most ljca workloads device is used for just a few milliseconds flowed by long periods of at least 100ms of inactivity (usually more).
--- drivers/usb/misc/usb-ljca.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/usb/misc/usb-ljca.c +8 -0
@@ -811,6 +811,14 @@ static int ljca_probe(struct usb_interfaif (ret) goto err_free; +/* +* This works around problems with ov2740 initialization on some +* Lenovo platforms. The autosuspend delay, has to be smaller than +* the delay after setting the reset_gpio line in ov2740_resume(). +* Otherwise the sensor randomly fails to initialize. +*/ +pm_runtime_set_autosuspend_delay (&usb_dev->dev,10 ); +usb_enable_autosuspend (usb_dev);return 0 ;
Greg Kroah-Hartman
maintainerPATCH 757/826 usb: misc: ljca: move usb_autopm_put_interface() after wait for response
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stanislaw Gruszka <[email protected]>
commit 5c5d8eb8af06df615e8b1dc88e5847196c846045 upstream.
Do not mark interface as ready to suspend when we are still waiting for response messages from the device.
--- drivers/usb/misc/usb-ljca.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/usb/misc/usb-ljca.c +6 -6
@@ -332,14 +332,11 @@ static int ljca_send(struct ljca_adapter ret =usb_bulk_msg (adap->usb_dev, adap->tx_pipe, header, msg_len, &transferred,LJCA_WRITE_TIMEOUT_MS ); - -usb_autopm_put_interface (adap->intf); -if (ret <0 ) - goto out; + goto out_put;if (transferred != msg_len) { ret = -EIO ; - goto out; + goto out_put; }if (ack) {
@@ -347,11 +344,14 @@ static int ljca_send(struct ljca_adapter timeout);if (!ret) { ret = -ETIMEDOUT ; - goto out; + goto out_put; } } ret = adap->actual_length; +out_put: +usb_autopm_put_interface (adap->intf); + out:spin_lock_irqsave (&adap->lock, flags); adap->ex_buf =NULL ;
Greg Kroah-Hartman
maintainerPATCH 758/826 usb: dwc3: ep0: Dont clear ep0 DWC3_EP_TRANSFER_STARTED
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thinh Nguyen <[email protected]>
commit 5d2fb074dea289c41f5aaf2c3f68286bee370634 upstream.
The driver cannot issue the End Transfer command to the SETUP transfer. Don't clear DWC3_EP_TRANSFER_STARTED flag to make sure that the driver won't send Start Transfer command again, which can cause no-resource error. For example this can occur if the host issues a reset to the device.
--- drivers/usb/dwc3/ep0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/dwc3/ep0.c +1 -1
@@ -232,7 +232,7 @@ void dwc3_ep0_stall_and_restart(struct d/* stall is always issued on EP0 */ dep = dwc->eps[0 ];__dwc3_gadget_ep_set_halt (dep,1 , false); - dep->flags &=DWC3_EP_RESOURCE_ALLOCATED ; + dep->flags &=DWC3_EP_RESOURCE_ALLOCATED |DWC3_EP_TRANSFER_STARTED ; dep->flags |=DWC3_EP_ENABLED ; dwc->delayed_status = false;
Greg Kroah-Hartman
maintainerPATCH 759/826 usb: musb: Fix hardware lockup on first Rx endpoint request
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hubert Wiśniewski <[email protected]>
commit 3fc137386c4620305bbc2a216868c53f9245670a upstream.
There is a possibility that a request's callback could be invoked from usb_ep_queue() (call trace below, supplemented with missing calls):
req->complete from usb_gadget_giveback_request
(drivers/usb/gadget/udc/core.c:999) usb_gadget_giveback_request from musb_g_giveback (drivers/usb/musb/musb_gadget.c:147) musb_g_giveback from rxstate (drivers/usb/musb/musb_gadget.c:784) rxstate from musb_ep_restart (drivers/usb/musb/musb_gadget.c:1169) musb_ep_restart from musb_ep_restart_resume_work (drivers/usb/musb/musb_gadget.c:1176) musb_ep_restart_resume_work from musb_queue_resume_work (drivers/usb/musb/musb_core.c:2279) musb_queue_resume_work from musb_gadget_queue (drivers/usb/musb/musb_gadget.c:1241) musb_gadget_queue from usb_ep_queue (drivers/usb/gadget/udc/core.c:300)
According to the docstring of usb_ep_queue(), this should not happen:
"Note that @req's ->complete() callback must never be called from within usb_ep_queue() as that can create deadlock situations."
In fact, a hardware lockup might occur in the following sequence:
1. The gadget is initialized using musb_gadget_enable().
2. Meanwhile, a packet arrives, and the RXPKTRDY flag is set, raising an interrupt.
3. If IRQs are enabled, the interrupt is handled, but musb_g_rx() finds an empty queue (next_request() returns NULL). The interrupt flag has already been cleared by the glue layer handler, but the RXPKTRDY flag remains set.
4. The first request is enqueued using usb_ep_queue(), leading to the call of req->complete(), as shown in the call trace above.
5. If the callback enables IRQs and another packet is waiting, step (3) repeats. The request queue is empty because usb_g_giveback() removes the request before invoking the callback.
6. The endpoint remains locked up, as the interrupt triggered by hardware setting the RXPKTRDY flag has been handled, but the flag itself remains set.
For this scenario to occur, it is only necessary for IRQs to be enabled at some point during the complete callback. This happens with the USB Ethernet gadget, whose rx_complete() callback calls netif_rx(). If called in the task context, netif_rx() disables the bottom halves (BHs). When the BHs are re-enabled, IRQs are also enabled to allow soft IRQs to be processed. The gadget itself is initialized at module load (or at boot if built-in), but the first request is enqueued when the network interface is brought up, triggering rx_complete() in the task context via ioctl(). If a packet arrives while the interface is down, it can prevent the interface from receiving any further packets from the USB host.
The situation is quite complicated with many parties involved. This particular issue can be resolved in several possible ways:
1. Ensure that callbacks never enable IRQs. This would be difficult to enforce, as discovering how netif_rx() interacts with interrupts was already quite challenging and u_ether is not the only function driver. Similar "bugs" could be hidden in other drivers as well.
2. Disable MUSB interrupts in musb_g_giveback() before calling the callback and re-enable them afterwars (by calling musb_{dis,en}able_interrupts(), for example). This would ensure that MUSB interrupts are not handled during the callback, even if IRQs are enabled. In fact, it would allow IRQs to be enabled when releasing the lock. However, this feels like an inelegant hack.
3. Modify the interrupt handler to clear the RXPKTRDY flag if the request queue is empty. While this approach also feels like a hack, it wastes CPU time by attempting to handle incoming packets when the software is not ready to process them.
4. Flush the Rx FIFO instead of calling rxstate() in musb_ep_restart(). This ensures that the hardware can receive packets when there is at least one request in the queue. Once IRQs are enabled, the interrupt handler will be able to correctly process the next incoming packet (eventually calling rxstate()). This approach may cause one or two packets to be dropped (two if double buffering is enabled), but this seems to be a minor issue, as packet loss can occur when the software is not yet ready to process them. Additionally, this solution makes the gadget driver compliant with the rule mentioned in the docstring of usb_ep_queue().
There may be additional solutions, but from these four, the last one has been chosen as it seems to be the most appropriate, as it addresses the "bad" behavior of the driver.
--- drivers/usb/musb/musb_gadget.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
drivers/usb/musb/musb_gadget.c +10 -3
@@ -1161,12 +1161,19 @@ void musb_free_request(struct usb_ep *ep*/ void musb_ep_restart (struct musb *musb,struct musb_request *req) { +u16 csr; +void __iomem *epio = req->ep->hw_ep->regs; +trace_musb_req_start (req);musb_ep_select (musb->mregs, req->epnum); -if (req->tx) +if (req->tx) {txstate (musb, req); -else -rxstate (musb, req); + }else { + csr =musb_readw (epio,MUSB_RXCSR ); + csr |=MUSB_RXCSR_FLUSHFIFO |MUSB_RXCSR_P_WZC_BITS ; +musb_writew (epio,MUSB_RXCSR , csr); +musb_writew (epio,MUSB_RXCSR , csr); + } }static int musb_ep_restart_resume_work (struct musb *musb,void *data)
Greg Kroah-Hartman
maintainerPATCH 760/826 usb: dwc3: gadget: Add missing check for single port RAM in TxFIFO resizing logic
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Selvarasu Ganesan <[email protected]>
commit 61eb055cd3048ee01ca43d1be924167d33e16fdc upstream.
The existing implementation of the TxFIFO resizing logic only supports scenarios where more than one port RAM is used. However, there is a need to resize the TxFIFO in USB2.0-only mode where only a single port RAM is available. This commit introduces the necessary changes to support TxFIFO resizing in such scenarios by adding a missing check for single port RAM.
This fix addresses certain platform configurations where the existing TxFIFO resizing logic does not work properly due to the absence of support for single port RAM. By adding this missing check, we ensure that the TxFIFO resizing logic works correctly in all scenarios, including those with a single port RAM.
--- drivers/usb/dwc3/core.h | 4 +++ drivers/usb/dwc3/gadget.c | 54 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 50 insertions(+), 8 deletions(-)
drivers/usb/dwc3/core.h +4 -0
@@ -915,6 +915,7 @@ struct dwc3_hwparams {#define DWC3_MODE (n) ((n) & 0x7)/* HWPARAMS1 */ +#define DWC3_SPRAM_TYPE (n) (((n) >> 23) & 1)#define DWC3_NUM_INT (n) (((n) & (0x3f << 15)) >> 15)/* HWPARAMS3 */
@@ -925,6 +926,9 @@ struct dwc3_hwparams {#define DWC3_NUM_IN_EPS (p) (((p)->hwparams3 & \ (DWC3_NUM_IN_EPS_MASK)) >> 18) +/* HWPARAMS6 */ +#define DWC3_RAM0_DEPTH (n) (((n) & (0xffff0000)) >> 16) +/* HWPARAMS7 */ #define DWC3_RAM1_DEPTH (n) ((n) & 0xffff)
drivers/usb/dwc3/gadget.c +46 -8
97 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 761/826 usb: dwc3: gadget: Fix checking for number of TRBs left
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thinh Nguyen <[email protected]>
commit 02a6982b0ccfcdc39e20016f5fc9a1b7826a6ee7 upstream.
The check whether the TRB ring is full or empty in dwc3_calc_trbs_left() is insufficient. It assumes there are active TRBs if there's any request in the started_list. However, that's not the case for requests with a large SG list.
That is, if we have a single usb request that requires more TRBs than the total TRBs in the TRB ring, the queued TRBs will be available when all the TRBs in the ring are completed. But the request is only partially completed and remains in the started_list. With the current logic, the TRB ring is empty, but dwc3_calc_trbs_left() returns 0.
Fix this by additionally checking for the request->num_trbs for active TRB count.
--- drivers/usb/dwc3/gadget.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/usb/dwc3/gadget.c +6 -3
@@ -1215,11 +1215,14 @@ static u32 dwc3_calc_trbs_left(struct dw* pending to be processed by the driver. */ if (dep->trb_enqueue == dep->trb_dequeue) { +struct dwc3_request *req; +/* -* If there is any request remained in the started_list at -* this point, that means there is no TRB available. +* If there is any request remained in the started_list with +* active TRBs at this point, then there is no TRB available. */ -if (!list_empty (&dep->started_list)) + req =next_request (&dep->started_list); +if (req && req->num_trbs)return 0 ;return DWC3_TRB_NUM -1 ;
Greg Kroah-Hartman
maintainerPATCH 762/826 usb: dwc3: gadget: Fix looping of queued SG entries
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thinh Nguyen <[email protected]>
commit b7fc65f5141c24785dc8c19249ca4efcf71b3524 upstream.
The dwc3_request->num_queued_sgs is decremented on completion. If a partially completed request is handled, then the dwc3_request->num_queued_sgs no longer reflects the total number of num_queued_sgs (it would be cleared).
Correctly check the number of request SG entries remained to be prepare and queued. Failure to do this may cause null pointer dereference when accessing non-existent SG entry.
--- drivers/usb/dwc3/gadget.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/usb/dwc3/gadget.c +3 -3
@@ -1455,8 +1455,8 @@ static int dwc3_prepare_trbs_sg(struct dstruct scatterlist *s;int i;unsigned int length = req->request.length; -unsigned int remaining = req->request.num_mapped_sgs - - req->num_queued_sgs; +unsigned int remaining = req->num_pending_sgs; +unsigned int num_queued_sgs = req->request.num_mapped_sgs - remaining;unsigned int num_trbs = req->num_trbs;bool needs_extra_trb =dwc3_needs_extra_trb (dep, req);
@@ -1464,7 +1464,7 @@ static int dwc3_prepare_trbs_sg(struct d* If we resume preparing the request, then get the remaining length of * the request and resume where we left off. */ -for_each_sg (req->request.sg, s, req->num_queued_sgs, i) +for_each_sg (req->request.sg, s, num_queued_sgs, i) length -=sg_dma_len (s);for_each_sg (sg, s, remaining, i) {
Greg Kroah-Hartman
maintainerPATCH 763/826 staging: vchiq_arm: Fix missing refcount decrement in error path for fw_node
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Javier Carrasco <[email protected]>
commit 22a3703af127e897dc7df89372b85bb9dc331c5f upstream.
An error path was introduced without including the required call to of_node_put() to decrement the node's refcount and avoid leaking memory. If the call to kzalloc() for 'mgmt' fails, the probe returns without decrementing the refcount.
Use the automatic cleanup facility to fix the bug and protect the code against new error paths where the call to of_node_put() might be missing again.
--- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +2 -4
@@ -1715,7 +1715,6 @@ MODULE_DEVICE_TABLE(of, vchiq_of_match);static int vchiq_probe (struct platform_device *pdev) { -struct device_node *fw_node;const struct vchiq_platform_info *info;struct vchiq_drv_mgmt *mgmt;int ret;
@@ -1724,8 +1723,8 @@ static int vchiq_probe(struct platform_dif (!info)return -EINVAL ; - fw_node =of_find_compatible_node (NULL ,NULL , -"raspberrypi,bcm2835-firmware" ); + struct device_node *fw_node __free(device_node) = +of_find_compatible_node (NULL ,NULL ,"raspberrypi,bcm2835-firmware" );if (!fw_node) {dev_err (&pdev->dev,"Missing firmware node\n" );return -ENOENT ;
@@ -1736,7 +1735,6 @@ static int vchiq_probe(struct platform_dreturn -ENOMEM ; mgmt->fw =devm_rpi_firmware_get (&pdev->dev, fw_node); -of_node_put (fw_node);if (!mgmt->fw)return -EPROBE_DEFER ;
Greg Kroah-Hartman
maintainerPATCH 764/826 counter: stm32-timer-cnt: fix device_node handling in probe_encoder()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Javier Carrasco <[email protected]>
commit 147359e23e5c9652ff8c5a98a51a7323bd51c94a upstream.
Device nodes accessed via of_get_compatible_child() require of_node_put() to be called when the node is no longer required to avoid leaving a reference to the node behind, leaking the resource.
In this case, the usage of 'tnode' is straightforward and there are no error paths, allowing for a single of_node_put() when 'tnode' is no longer required.
--- drivers/counter/stm32-timer-cnt.c | 1 + 1 file changed, 1 insertion(+)
drivers/counter/stm32-timer-cnt.c +1 -0
@@ -700,6 +700,7 @@ static int stm32_timer_cnt_probe_encoder } ret =of_property_read_u32 (tnode,"reg" , &idx); +of_node_put (tnode);if (ret) {dev_err (dev,"Can't get index (%d)\n" , ret);return ret;
Greg Kroah-Hartman
maintainerPATCH 765/826 ublk: fix error code for unsupported command
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Lei <[email protected]>
commit 34c1227035b3ab930a1ae6ab6f22fec1af8ab09e upstream.
ENOTSUPP is for kernel use only, and shouldn't be sent to userspace.
Fix it by replacing it with EOPNOTSUPP.
--- drivers/block/ublk_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/block/ublk_drv.c +1 -1
@@ -2974,7 +2974,7 @@ static int ublk_ctrl_uring_cmd(struct io ret =ublk_ctrl_end_recovery (ub, cmd);break ;default : - ret = -ENOTSUPP ; + ret = -EOPNOTSUPP ;break ; }
Greg Kroah-Hartman
maintainerPATCH 766/826 lib: string_helpers: silence snprintf() output truncation warning
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bartosz Golaszewski <[email protected]>
commit a508ef4b1dcc82227edc594ffae583874dd425d7 upstream.
The output of ".%03u" with the unsigned int in range [0, 4294966295] may get truncated if the target buffer is not 12 bytes. This can't really happen here as the 'remainder' variable cannot exceed 999 but the compiler doesn't know it. To make it happy just increase the buffer to where the warning goes away.
--- lib/string_helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
lib/string_helpers.c +1 -1
@@ -57,7 +57,7 @@ int string_get_size(u64 size, u64 blk_sistatic const unsigned int rounding[] = {500 ,50 ,5 };int i =0 , j;u32 remainder =0 , sf_cap; -char tmp[8 ]; +char tmp[12 ];const char *unit; tmp[0 ] ='\0' ;
Greg Kroah-Hartman
maintainerPATCH 767/826 f2fs: fix to do sanity check on node blkaddr in truncate_node()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <[email protected]>
commit 6babe00ccd34fc65b78ef8b99754e32b4385f23d upstream.
syzbot reports a f2fs bug as below:
------------[ cut here ]------------ kernel BUG at fs/f2fs/segment.c:2534! RIP: 0010:f2fs_invalidate_blocks+0x35f/0x370 fs/f2fs/segment.c:2534 Call Trace: truncate_node+0x1ae/0x8c0 fs/f2fs/node.c:909 f2fs_remove_inode_page+0x5c2/0x870 fs/f2fs/node.c:1288 f2fs_evict_inode+0x879/0x15c0 fs/f2fs/inode.c:856 evict+0x4e8/0x9b0 fs/inode.c:723 f2fs_handle_failed_inode+0x271/0x2e0 fs/f2fs/inode.c:986 f2fs_create+0x357/0x530 fs/f2fs/namei.c:394 lookup_open fs/namei.c:3595 [inline] open_last_lookups fs/namei.c:3694 [inline] path_openat+0x1c03/0x3590 fs/namei.c:3930 do_filp_open+0x235/0x490 fs/namei.c:3960 do_sys_openat2+0x13e/0x1d0 fs/open.c:1415 do_sys_open fs/open.c:1430 [inline] __do_sys_openat fs/open.c:1446 [inline] __se_sys_openat fs/open.c:1441 [inline] __x64_sys_openat+0x247/0x2a0 fs/open.c:1441 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0010:f2fs_invalidate_blocks+0x35f/0x370 fs/f2fs/segment.c:2534
The root cause is: on a fuzzed image, blkaddr in nat entry may be corrupted, then it will cause system panic when using it in f2fs_invalidate_blocks(), to avoid this, let's add sanity check on nat blkaddr in truncate_node().
--- fs/f2fs/node.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
fs/f2fs/node.c +10 -0
@@ -905,6 +905,16 @@ static int truncate_node(struct dnode_ofif (err)return err; +if (ni.blk_addr !=NEW_ADDR && + !f2fs_is_valid_blkaddr (sbi, ni.blk_addr,DATA_GENERIC_ENHANCE )) { +f2fs_err_ratelimited (sbi, +"nat entry is corrupted, run fsck to fix it, ino:%u, " +"nid:%u, blkaddr:%u" , ni.ino, ni.nid, ni.blk_addr); +set_sbi_flag (sbi,SBI_NEED_FSCK ); +f2fs_handle_error (sbi,ERROR_INCONSISTENT_NAT ); +return -EFSCORRUPTED ; + } +/* Deallocate node address */ f2fs_invalidate_blocks (sbi, ni.blk_addr);dec_valid_node_count (sbi, dn->inode, dn->nid == dn->inode->i_ino);
Greg Kroah-Hartman
maintainerPATCH 768/826 ipc: fix memleak if msg_init_ns failed in create_ipc_ns
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ma Wupeng <[email protected]>
commit bc8f5921cd69188627c08041276238de222ab466 upstream.
Percpu memory allocation may failed during create_ipc_ns however this fail is not handled properly since ipc sysctls and mq sysctls is not released properly. Fix this by release these two resource when failure.
Here is the kmemleak stack when percpu failed:
unreferenced object 0xffff88819de2a600 (size 512):
comm "shmem_2nstest", pid 120711, jiffies 4300542254 hex dump (first 32 bytes):
60 aa 9d 84 ff ff ff ff fc 18 48 b2 84 88 ff ff `.........H.....
04 00 00 00 a4 01 00 00 20 e4 56 81 ff ff ff ff ........ .V.....
backtrace (crc be7cba35):
[<ffffffff81b43f83>] __kmalloc_node_track_caller_noprof+0x333/0x420
[<ffffffff81a52e56>] kmemdup_noprof+0x26/0x50
[<ffffffff821b2f37>] setup_mq_sysctls+0x57/0x1d0
[<ffffffff821b29cc>] copy_ipcs+0x29c/0x3b0
[<ffffffff815d6a10>] create_new_namespaces+0x1d0/0x920
[<ffffffff815d7449>] copy_namespaces+0x2e9/0x3e0
[<ffffffff815458f3>] copy_process+0x29f3/0x7ff0
[<ffffffff8154b080>] kernel_clone+0xc0/0x650
[<ffffffff8154b6b1>] __do_sys_clone+0xa1/0xe0
[<ffffffff843df8ff>] do_syscall_64+0xbf/0x1c0
[<ffffffff846000b0>] entry_SYSCALL_64_after_hwframe+0x4b/0x53--- ipc/namespace.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
ipc/namespace.c +3 -1
@@ -83,13 +83,15 @@ static struct ipc_namespace *create_ipc_ err =msg_init_ns (ns);if (err) - goto fail_put; + goto fail_ipc;sem_init_ns (ns);shm_init_ns (ns);return ns; +fail_ipc: +retire_ipc_sysctls (ns); fail_mq:retire_mq_sysctls (ns);
Greg Kroah-Hartman
maintainerPATCH 769/826 Input: cs40l50 - fix wrong usage of INIT_WORK()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuan Can <[email protected]>
commit 5c822c0ce5cc83ed4cd8394f3dc46dae8d9a681d upstream.
In cs40l50_add(), the work_data is a local variable and the work_data.work should initialize with INIT_WORK_ONSTACK() instead of INIT_WORK(). Small error in cs40l50_erase() also fixed in this commit.
--- drivers/input/misc/cs40l50-vibra.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/input/misc/cs40l50-vibra.c +4 -2
@@ -334,11 +334,12 @@ static int cs40l50_add(struct input_dev work_data.custom_len = effect->u.periodic.custom_len; work_data.vib = vib; work_data.effect = effect; -INIT_WORK (&work_data.work, cs40l50_add_worker); +INIT_WORK_ONSTACK (&work_data.work, cs40l50_add_worker);/* Push to the workqueue to serialize with playbacks */ queue_work (vib->vib_wq, &work_data.work);flush_work (&work_data.work); +destroy_work_on_stack (&work_data.work);kfree (work_data.custom_data);
@@ -467,11 +468,12 @@ static int cs40l50_erase(struct input_de work_data.vib = vib; work_data.effect = &dev->ff->effects[effect_id]; -INIT_WORK (&work_data.work, cs40l50_erase_worker); +INIT_WORK_ONSTACK (&work_data.work, cs40l50_erase_worker);/* Push to workqueue to serialize with playbacks */ queue_work (vib->vib_wq, &work_data.work);flush_work (&work_data.work); +destroy_work_on_stack (&work_data.work);return work_data.error; }
Greg Kroah-Hartman
maintainerPATCH 770/826 NFSD: Prevent a potential integer overflow
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
commit 7f33b92e5b18e904a481e6e208486da43e4dc841 upstream.
If the tag length is >= U32_MAX - 3 then the "length + 4" addition can result in an integer overflow. Address this by splitting the decoding into several steps so that decode_cb_compound4res() does not have to perform arithmetic on the unsafe length value.
--- fs/nfsd/nfs4callback.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
fs/nfsd/nfs4callback.c +7 -7
@@ -287,17 +287,17 @@ static int decode_cb_compound4res(structu32 length;__be32 *p; - p =xdr_inline_decode (xdr,4 +4 ); + p =xdr_inline_decode (xdr,XDR_UNIT );if (unlikely (p ==NULL )) goto out_overflow; - hdr->status =be32_to_cpup (p++); + hdr->status =be32_to_cpup (p);/* Ignore the tag */ - length =be32_to_cpup (p++); - p =xdr_inline_decode (xdr, length +4 ); -if (unlikely (p ==NULL )) +if (xdr_stream_decode_u32 (xdr, &length) <0 ) + goto out_overflow; +if (xdr_inline_decode (xdr, length) ==NULL ) + goto out_overflow; +if (xdr_stream_decode_u32 (xdr, &hdr->nops) <0 ) goto out_overflow; - p +=XDR_QUADLEN (length); - hdr->nops =be32_to_cpup (p);return 0 ; out_overflow:return -EIO ;
Greg Kroah-Hartman
maintainerPATCH 771/826 SUNRPC: make sure cache entry active before cache_show
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Erkun <[email protected]>
commit 2862eee078a4d2d1f584e7f24fa50dddfa5f3471 upstream.
The function c_show was called with protection from RCU. This only ensures that cp will not be freed. Therefore, the reference count for cp can drop to zero, which will trigger a refcount use-after-free warning when cache_get is called. To resolve this issue, use cache_get_rcu to ensure that cp remains active.
------------[ cut here ]------------ refcount_t: addition on 0; use-after-free. WARNING: CPU: 7 PID: 822 at lib/refcount.c:25 refcount_warn_saturate+0xb1/0x120 CPU: 7 UID: 0 PID: 822 Comm: cat Not tainted 6.12.0-rc3+ #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.1-2.fc37 04/01/2014 RIP: 0010:refcount_warn_saturate+0xb1/0x120 Call Trace: <TASK> c_show+0x2fc/0x380 [sunrpc] seq_read_iter+0x589/0x770 seq_read+0x1e5/0x270 proc_reg_read+0xe1/0x140 vfs_read+0x125/0x530 ksys_read+0xc1/0x160 do_syscall_64+0x5f/0x170 entry_SYSCALL_64_after_hwframe+0x76/0x7e
--- net/sunrpc/cache.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/sunrpc/cache.c +3 -1
@@ -1427,7 +1427,9 @@ static int c_show(struct seq_file *m, voseq_printf (m,"# expiry=%lld refcnt=%d flags=%lx\n" ,convert_to_wallclock (cp->expiry_time),kref_read (&cp->ref), cp->flags); -cache_get (cp); +if (!cache_get_rcu (cp)) +return 0 ; +if (cache_check (cd, cp,NULL ))/* cache_check does a cache_put on failure */ seq_puts (m,"# " );
Greg Kroah-Hartman
maintainerPATCH 772/826 um: Fix potential integer overflow during physmem setup
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tiwei Bie <[email protected]>
[ Upstream commit a98b7761f697e590ed5d610d87fa12be66f23419 ]
This issue happens when the real map size is greater than LONG_MAX, which can be easily triggered on UML/i386.
--- arch/um/kernel/physmem.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/um/kernel/physmem.c +3 -3
@@ -81,10 +81,10 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end, unsigned long len, unsigned long long highmem) {unsigned long reserve = reserve_end - start; -long map_size = len - reserve; +unsigned long map_size = len - reserve;int err; -if (map_size <=0 ) { +if (len <= reserve) {os_warn ("Too few physical memory! Needed=%lu, given=%lu\n" , reserve, len);exit (1 );
@@ -95,7 +95,7 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end, err =os_map_memory ((void *) reserve_end, physmem_fd, reserve, map_size,1 ,1 ,1 );if (err <0 ) { -os_warn ("setup_physmem - mapping %ld bytes of memory at 0x%p " +os_warn ("setup_physmem - mapping %lu bytes of memory at 0x%p " "failed - errno = %d\n" , map_size, (void *) reserve_end, err);exit (1 );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 773/826 um: Fix the return value of elf_core_copy_task_fpregs
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tiwei Bie <[email protected]>
[ Upstream commit 865e3845eeaa21e9a62abc1361644e67124f1ec0 ]
This function is expected to return a boolean value, which should be true on success and false on failure.
--- arch/um/kernel/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/um/kernel/process.c +1 -1
@@ -292,6 +292,6 @@ int elf_core_copy_task_fpregs(struct task_struct *t, elf_fpregset_t *fpu) {int cpu =current_thread_info ()->cpu; -return save_i387_registers (userspace_pid[cpu], (unsigned long *) fpu); +return save_i387_registers (userspace_pid[cpu], (unsigned long *) fpu) ==0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 774/826 kfifo: dont include dma-mapping.h in kfifo.h
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig <[email protected]>
[ Upstream commit 44059790a5cb9258ae6137387e4c39b717fd2ced ]
Nothing in kfifo.h directly needs dma-mapping.h, only two macros use DMA_MAPPING_ERROR when actually instantiated. Drop the dma-mapping.h include to reduce include bloat.
Add an explicity <linux/io.h> include to drivers/mailbox/omap-mailbox.c as that file uses __raw_readl and __raw_writel through a complicated include chain involving <linux/dma-mapping.h>
--- drivers/mailbox/omap-mailbox.c | 1 + include/linux/kfifo.h | 1 - samples/kfifo/dma-example.c | 1 + 3 files changed, 2 insertions(+), 1 deletion(-)
drivers/mailbox/omap-mailbox.c +1 -0
@@ -15,6 +15,7 @@#include <linux/slab.h> #include <linux/kfifo.h> #include <linux/err.h> +#include <linux/io.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h>
include/linux/kfifo.h +0 -1
@@ -37,7 +37,6 @@*/ #include <linux/array_size.h> -#include <linux/dma-mapping.h> #include <linux/spinlock.h> #include <linux/stddef.h> #include <linux/types.h>
samples/kfifo/dma-example.c +1 -0
@@ -9,6 +9,7 @@#include <linux/kfifo.h> #include <linux/module.h> #include <linux/scatterlist.h> +#include <linux/dma-mapping.h> /* * This module shows how to handle fifo dma operations.
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 775/826 um: ubd: Initialize ubds disk pointer in ubd_add
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tiwei Bie <[email protected]>
[ Upstream commit df700802abcac3c7c4a4ced099aa42b9a144eea8 ]
Currently, the initialization of the disk pointer in the ubd structure is missing. It should be initialized with the allocated gendisk pointer in ubd_add().
--- arch/um/drivers/ubd_kern.c | 2 ++ 1 file changed, 2 insertions(+)
arch/um/drivers/ubd_kern.c +2 -0
@@ -898,6 +898,8 @@ static int ubd_add(int n, char **error_out)if (err) goto out_cleanup_disk; + ubd_dev->disk = disk; +return 0 ; out_cleanup_disk:
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 776/826 um: Always dump trace for specified task in show_stack
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tiwei Bie <[email protected]>
[ Upstream commit 0f659ff362eac69777c4c191b7e5ccb19d76c67d ]
Currently, show_stack() always dumps the trace of the current task. However, it should dump the trace of the specified task if one is provided. Otherwise, things like running "echo t > sysrq-trigger" won't work as expected.
--- arch/um/kernel/sysrq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/um/kernel/sysrq.c +1 -1
@@ -52,5 +52,5 @@ void show_stack(struct task_struct *task, unsigned long *stack, }printk ("%sCall Trace:\n" , loglvl); -dump_trace (current, &stackops, (void *)loglvl); +dump_trace (task ?: current, &stackops, (void *)loglvl); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 777/826 NFSv4.0: Fix a use-after-free problem in the asynchronous open()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Trond Myklebust <[email protected]>
[ Upstream commit 2fdb05dc0931250574f0cb0ebeb5ed8e20f4a889 ]
Yang Erkun reports that when two threads are opening files at the same time, and are forced to abort before a reply is seen, then the call to nfs_release_seqid() in nfs4_opendata_free() can result in a use-after-free of the pointer to the defunct rpc task of the other thread.
The fix is to ensure that if the RPC call is aborted before the call to nfs_wait_on_sequence() is complete, then we must call nfs_release_seqid() in nfs4_open_release() before the rpc_task is freed.
--- fs/nfs/nfs4proc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
fs/nfs/nfs4proc.c +5 -3
@@ -2603,12 +2603,14 @@ static void nfs4_open_release(void *calldata)struct nfs4_opendata *data = calldata;struct nfs4_state *state =NULL ; +/* In case of error, no cleanup! */ +if (data->rpc_status !=0 || !data->rpc_done) { +nfs_release_seqid (data->o_arg.seqid); + goto out_free; + }/* If this request hasn't been cancelled, do nothing */ if (!data->cancelled) goto out_free; -/* In case of error, no cleanup! */ -if (data->rpc_status !=0 || !data->rpc_done) - goto out_free;/* In case we need an open_confirm, no cleanup! */ if (data->o_res.rflags &NFS4_OPEN_RESULT_CONFIRM ) goto out_free;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 778/826 nfs/localio: must clear res.replen in nfs_local_read_done
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit 650703bc4ed3edf841e851c99ab8e7ba9e5262a3 ]
Otherwise memory corruption can occur due to NFSv3 LOCALIO reads leaving garbage in res.replen:
- nfs3_read_done() copies that into server->read_hdrsize; from there nfs3_proc_read_setup() copies it to args.replen in new requests.
- nfs3_xdr_enc_read3args() passes that to rpc_prepare_reply_pages() which includes it in hdrsize for xdr_init_pages, so that rq_rcv_buf contains a ridiculous len.
- This is copied to rq_private_buf and xs_read_stream_request() eventually passes the kvec to sock_recvmsg() which receives incoming data into entirely the wrong place.
This is easily reproduced with NFSv3 LOCALIO that is servicing reads when it is made to pivot back to using normal RPC. This switch back to using normal NFSv3 with RPC can occur for a few reasons but this issue was exposed with a test that stops and then restarts the NFSv3 server while LOCALIO is performing heavy read IO.
--- fs/nfs/localio.c | 6 ++++++ 1 file changed, 6 insertions(+)
fs/nfs/localio.c +6 -0
@@ -354,6 +354,12 @@ nfs_local_read_done(struct nfs_local_kiocb *iocb, long status)nfs_local_pgio_done (hdr, status); +/* +* Must clear replen otherwise NFSv3 data corruption will occur +* if/when switching from LOCALIO back to using normal RPC. +*/ + hdr->res.replen =0 ; +if (hdr->res.count != hdr->args.count || hdr->args.offset + hdr->res.count >=i_size_read (file_inode (filp))) hdr->res.eof = true;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 779/826 rtc: st-lpc: Use IRQF_NO_AUTOEN flag in request_irq()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jinjie Ruan <[email protected]>
[ Upstream commit b6cd7adec0cf03f0aefc55676e71dd721cbc71a8 ]
If request_irq() fails in st_rtc_probe(), there is no need to enable the irq, and if it succeeds, disable_irq() after request_irq() still has a time gap in which interrupts can come.
request_irq() with IRQF_NO_AUTOEN flag will disable IRQ auto-enable when request IRQ.
--- drivers/rtc/rtc-st-lpc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/rtc/rtc-st-lpc.c +2 -3
@@ -218,15 +218,14 @@ static int st_rtc_probe(struct platform_device *pdev)return -EINVAL ; } - ret =devm_request_irq (&pdev->dev, rtc->irq, st_rtc_handler,0 , - pdev->name, rtc); + ret =devm_request_irq (&pdev->dev, rtc->irq, st_rtc_handler, +IRQF_NO_AUTOEN , pdev->name, rtc);if (ret) {dev_err (&pdev->dev,"Failed to request irq %i\n" , rtc->irq);return ret; }enable_irq_wake (rtc->irq); -disable_irq (rtc->irq); rtc->clk =devm_clk_get_enabled (&pdev->dev,NULL );if (IS_ERR (rtc->clk))
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 780/826 rtc: abx80x: Fix WDT bit position of the status register
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nobuhiro Iwamatsu <[email protected]>
[ Upstream commit 10e078b273ee7a2b8b4f05a64ac458f5e652d18d ]
The WDT bit in the status register is 5, not 6. This fixes from 6 to 5.
--- drivers/rtc/rtc-abx80x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/rtc/rtc-abx80x.c +1 -1
@@ -39,7 +39,7 @@#define ABX8XX_REG_STATUS 0x0f#define ABX8XX_STATUS_AF BIT(2)#define ABX8XX_STATUS_BLF BIT(4) -#define ABX8XX_STATUS_WDT BIT(6) +#define ABX8XX_STATUS_WDT BIT(5)#define ABX8XX_REG_CTRL1 0x10#define ABX8XX_CTRL_WRITE BIT(0)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 781/826 rtc: check if __rtc_read_time was successful in rtc_timer_do_work()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yongliang Gao <[email protected]>
[ Upstream commit e8ba8a2bc4f60a1065f23d6a0e7cbea945a0f40d ]
If the __rtc_read_time call fails,, the struct rtc_time tm; may contain uninitialized data, or an illegal date/time read from the RTC hardware.
When calling rtc_tm_to_ktime later, the result may be a very large value (possibly KTIME_MAX). If there are periodic timers in rtc->timerqueue, they will continually expire, may causing kernel softlockup.
--- drivers/rtc/interface.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/rtc/interface.c +6 -1
@@ -904,13 +904,18 @@ void rtc_timer_do_work(struct work_struct *work)struct timerqueue_node *next;ktime_t now;struct rtc_time tm; +int err;struct rtc_device *rtc = container_of(work, struct rtc_device, irqwork);mutex_lock (&rtc->ops_lock); again: -__rtc_read_time (rtc, &tm); + err =__rtc_read_time (rtc, &tm); +if (err) { +mutex_unlock (&rtc->ops_lock); +return ; + } now =rtc_tm_to_ktime (tm);while ((next =timerqueue_getnext (&rtc->timerqueue))) {if (next->expires > now)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 782/826 ubi: fastmap: wl: Schedule fm_work if wear-leveling pool is empty
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhihao Cheng <[email protected]>
[ Upstream commit c4595fe394a289927077e3da561db27811919ee0 ]
Since commit 14072ee33d5a ("ubi: fastmap: Check wl_pool for free peb before wear leveling"), wear_leveling_worker() won't schedule fm_work if wear-leveling pool is empty, which could temporarily disable the wear-leveling until the fastmap is updated(eg. pool becomes empty). Fix it by scheduling fm_work if wl_pool is empty during wear-leveing.
--- drivers/mtd/ubi/fastmap-wl.c | 19 ++++++++++++++++--- drivers/mtd/ubi/wl.c | 2 +- drivers/mtd/ubi/wl.h | 3 ++- 3 files changed, 19 insertions(+), 5 deletions(-)
drivers/mtd/ubi/fastmap-wl.c +16 -3
@@ -346,14 +346,27 @@ int ubi_wl_get_peb(struct ubi_device *ubi)* WL sub-system. * * @ubi: UBI device description object +* @need_fill: whether to fill wear-leveling pool when no PEBs are found */ -static struct ubi_wl_entry *next_peb_for_wl (struct ubi_device *ubi) +static struct ubi_wl_entry *next_peb_for_wl (struct ubi_device *ubi, +bool need_fill) {struct ubi_fm_pool *pool = &ubi->fm_wl_pool;int pnum; -if (pool->used == pool->size) +if (pool->used == pool->size) { +if (need_fill && !ubi->fm_work_scheduled) { +/* +* We cannot update the fastmap here because this +* function is called in atomic context. +* Let's fail here and refill/update it as soon as +* possible. +*/ + ubi->fm_work_scheduled =1 ; +schedule_work (&ubi->fm_work); + }return NULL ; + } pnum = pool->pebs[pool->used];return ubi->lookuptbl[pnum];
@@ -375,7 +388,7 @@ static bool need_wear_leveling(struct ubi_device *ubi)if (!ubi->used.rb_node)return false; - e =next_peb_for_wl (ubi); + e =next_peb_for_wl (ubi, false);if (!e) {if (!ubi->free.rb_node)return false;
drivers/mtd/ubi/wl.c +1 -1
@@ -683,7 +683,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,ubi_assert (!ubi->move_to_put);#ifdef CONFIG_MTD_UBI_FASTMAP - if (!next_peb_for_wl(ubi) || + if (!next_peb_for_wl(ubi, true) || #else if (!ubi->free.rb_node ||#endif
drivers/mtd/ubi/wl.h +2 -1
@@ -5,7 +5,8 @@static void update_fastmap_work_fn (struct work_struct *wrk);static struct ubi_wl_entry *find_anchor_wl_entry (struct rb_root *root);static struct ubi_wl_entry *get_peb_for_wl (struct ubi_device *ubi); -static struct ubi_wl_entry *next_peb_for_wl (struct ubi_device *ubi); +static struct ubi_wl_entry *next_peb_for_wl (struct ubi_device *ubi, +bool need_fill);static bool need_wear_leveling (struct ubi_device *ubi);static void ubi_fastmap_close (struct ubi_device *ubi);static inline void ubi_fastmap_init (struct ubi_device *ubi,int *count)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 783/826 ubifs: Correct the total block count by deducting journal reservation
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhihao Cheng <[email protected]>
[ Upstream commit 84a2bee9c49769310efa19601157ef50a1df1267 ]
Since commit e874dcde1cbf ("ubifs: Reserve one leb for each journal head while doing budget"), available space is calulated by deducting reservation for all journal heads. However, the total block count ( which is only used by statfs) is not updated yet, which will cause the wrong displaying for used space(total - available). Fix it by deducting reservation for all journal heads from total block count.
--- fs/ubifs/super.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/ubifs/super.c +3 -3
@@ -773,10 +773,10 @@ static void init_constants_master(struct ubifs_info *c)* necessary to report something for the 'statfs()' call. * * Subtract the LEB reserved for GC, the LEB which is reserved for -* deletions, minimum LEBs for the index, and assume only one journal -* head is available. +* deletions, minimum LEBs for the index, the LEBs which are reserved +* for each journal head. */ - tmp64 = c->main_lebs -1 -1 -MIN_INDEX_LEBS - c->jhead_cnt +1 ; + tmp64 = c->main_lebs -1 -1 -MIN_INDEX_LEBS - c->jhead_cnt; tmp64 *= (long long )c->leb_size - c->leb_overhead; tmp64 =ubifs_reported_space (c, tmp64); c->block_cnt = tmp64 >>UBIFS_BLOCK_SHIFT ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 784/826 ubi: fastmap: Fix duplicate slab cache names while attaching
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhihao Cheng <[email protected]>
[ Upstream commit bcddf52b7a17adcebc768d26f4e27cf79adb424c ]
Since commit 4c39529663b9 ("slab: Warn on duplicate cache names when DEBUG_VM=y"), the duplicate slab cache names can be detected and a kernel WARNING is thrown out.
In UBI fast attaching process, alloc_ai() could be invoked twice with the same slab cache name 'ubi_aeb_slab_cache', which will trigger following warning messages:
kmem_cache of name 'ubi_aeb_slab_cache' already exists
WARNING: CPU: 0 PID: 7519 at mm/slab_common.c:107
__kmem_cache_create_args+0x100/0x5f0
Modules linked in: ubi(+) nandsim [last unloaded: nandsim]
CPU: 0 UID: 0 PID: 7519 Comm: modprobe Tainted: G 6.12.0-rc2
RIP: 0010:__kmem_cache_create_args+0x100/0x5f0
Call Trace:
__kmem_cache_create_args+0x100/0x5f0
alloc_ai+0x295/0x3f0 [ubi]
ubi_attach+0x3c3/0xcc0 [ubi]
ubi_attach_mtd_dev+0x17cf/0x3fa0 [ubi]
ubi_init+0x3fb/0x800 [ubi]
do_init_module+0x265/0x7d0
__x64_sys_finit_module+0x7a/0xc0The problem could be easily reproduced by loading UBI device by fastmap with CONFIG_DEBUG_VM=y.
Fix it by using different slab names for alloc_ai() callers.
--- drivers/mtd/ubi/attach.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/mtd/ubi/attach.c +6 -6
@@ -1447,7 +1447,7 @@ static int scan_all(struct ubi_device *ubi, struct ubi_attach_info *ai,return err; } -static struct ubi_attach_info *alloc_ai (void ) +static struct ubi_attach_info *alloc_ai (const char *slab_name) {struct ubi_attach_info *ai;
@@ -1461,7 +1461,7 @@ static struct ubi_attach_info *alloc_ai(void)INIT_LIST_HEAD (&ai->alien);INIT_LIST_HEAD (&ai->fastmap); ai->volumes =RB_ROOT ; - ai->aeb_slab_cache =kmem_cache_create ("ubi_aeb_slab_cache" , + ai->aeb_slab_cache =kmem_cache_create (slab_name,sizeof (struct ubi_ainf_peb ),0 ,0 ,NULL );if (!ai->aeb_slab_cache) {
@@ -1491,7 +1491,7 @@ static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai) err = -ENOMEM ; - scan_ai =alloc_ai (); + scan_ai =alloc_ai ("ubi_aeb_slab_cache_fastmap" );if (!scan_ai) goto out;
@@ -1557,7 +1557,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)int err;struct ubi_attach_info *ai; - ai =alloc_ai (); + ai =alloc_ai ("ubi_aeb_slab_cache" );if (!ai)return -ENOMEM ;
@@ -1575,7 +1575,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)if (err >0 ||mtd_is_eccerr (err)) {if (err !=UBI_NO_FASTMAP ) {destroy_ai (ai); - ai =alloc_ai (); + ai =alloc_ai ("ubi_aeb_slab_cache" );if (!ai)return -ENOMEM ;
@@ -1614,7 +1614,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)if (ubi->fm &&ubi_dbg_chk_fastmap (ubi)) {struct ubi_attach_info *scan_ai; - scan_ai =alloc_ai (); + scan_ai =alloc_ai ("ubi_aeb_slab_cache_dbg_chk_fastmap" );if (!scan_ai) { err = -ENOMEM ; goto out_wl;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 785/826 ubifs: authentication: Fix use-after-free in ubifs_tnc_end_commit
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Waqar Hameed <[email protected]>
[ Upstream commit 4617fb8fc15effe8eda4dd898d4e33eb537a7140 ]
After an insertion in TNC, the tree might split and cause a node to change its znode->parent. A further deletion of other nodes in the tree (which also could free the nodes), the aforementioned node's znode->cparent could still point to a freed node. This znode->cparent may not be updated when getting nodes to commit in ubifs_tnc_start_commit(). This could then trigger a use-after-free when accessing the znode->cparent in write_index() in ubifs_tnc_end_commit().
This can be triggered by running
rm -f /etc/test-file.bin
dd if=/dev/urandom of=/etc/test-file.bin bs=1M count=60 conv=fsync
in a loop, and with CONFIG_UBIFS_FS_AUTHENTICATION. KASAN then reports:
BUG: KASAN: use-after-free in ubifs_tnc_end_commit+0xa5c/0x1950 Write of size 32 at addr ffffff800a3af86c by task ubifs_bgt0_20/153 Call trace: dump_backtrace+0x0/0x340 show_stack+0x18/0x24 dump_stack_lvl+0x9c/0xbc print_address_description.constprop.0+0x74/0x2b0 kasan_report+0x1d8/0x1f0 kasan_check_range+0xf8/0x1a0 memcpy+0x84/0xf4 ubifs_tnc_end_commit+0xa5c/0x1950 do_commit+0x4e0/0x1340 ubifs_bg_thread+0x234/0x2e0 kthread+0x36c/0x410 ret_from_fork+0x10/0x20 Allocated by task 401: kasan_save_stack+0x38/0x70 __kasan_kmalloc+0x8c/0xd0 __kmalloc+0x34c/0x5bc tnc_insert+0x140/0x16a4 ubifs_tnc_add+0x370/0x52c ubifs_jnl_write_data+0x5d8/0x870 do_writepage+0x36c/0x510 ubifs_writepage+0x190/0x4dc __writepage+0x58/0x154 write_cache_pages+0x394/0x830 do_writepages+0x1f0/0x5b0 filemap_fdatawrite_wbc+0x170/0x25c file_write_and_wait_range+0x140/0x190 ubifs_fsync+0xe8/0x290 vfs_fsync_range+0xc0/0x1e4 do_fsync+0x40/0x90 __arm64_sys_fsync+0x34/0x50 invoke_syscall.constprop.0+0xa8/0x260 do_el0_svc+0xc8/0x1f0 el0_svc+0x34/0x70 el0t_64_sync_handler+0x108/0x114 el0t_64_sync+0x1a4/0x1a8 Freed by task 403: kasan_save_stack+0x38/0x70 kasan_set_track+0x28/0x40 kasan_set_free_info+0x28/0x4c __kasan_slab_free+0xd4/0x13c kfree+0xc4/0x3a0 tnc_delete+0x3f4/0xe40 ubifs_tnc_remove_range+0x368/0x73c ubifs_tnc_remove_ino+0x29c/0x2e0 ubifs_jnl_delete_inode+0x150/0x260 ubifs_evict_inode+0x1d4/0x2e4 evict+0x1c8/0x450 iput+0x2a0/0x3c4 do_unlinkat+0x2cc/0x490 __arm64_sys_unlinkat+0x90/0x100 invoke_syscall.constprop.0+0xa8/0x260 do_el0_svc+0xc8/0x1f0 el0_svc+0x34/0x70 el0t_64_sync_handler+0x108/0x114 el0t_64_sync+0x1a4/0x1a8
The offending memcpy() in ubifs_copy_hash() has a use-after-free when a node becomes root in TNC but still has a cparent to an already freed node. More specifically, consider the following TNC:
zroot
/
/
zp1
/
/
znInserting a new node zn_new with a key smaller then zn will trigger a split in tnc_insert() if zp1 is full:
zroot
/ \
/ \
zp1 zp2
/ \
/ \ zn_new zn
zn->parent has now been moved to zp2, *but* zn->cparent still points to zp1.
Now, consider a removal of all the nodes _except_ zn. Just when tnc_delete() is about to delete zroot and zp2:
zroot
\
\
zp2
\
\
znzroot and zp2 get freed and the tree collapses:
zn
zn now becomes the new zroot.
get_znodes_to_commit() will now only find zn, the new zroot, and write_index() will check its znode->cparent that wrongly points to the already freed zp1. ubifs_copy_hash() thus gets wrongly called with znode->cparent->zbranch[znode->iip].hash that triggers the use-after-free!
Fix this by explicitly setting znode->cparent to NULL in get_znodes_to_commit() for the root node. The search for the dirty nodes is bottom-up in the tree. Thus, when find_next_dirty(znode) returns NULL, the current znode _is_ the root node. Add an assert for this.
--- fs/ubifs/tnc_commit.c | 2 ++ 1 file changed, 2 insertions(+)
fs/ubifs/tnc_commit.c +2 -0
@@ -657,6 +657,8 @@ static int get_znodes_to_commit(struct ubifs_info *c) znode->alt =0 ; cnext =find_next_dirty (znode);if (!cnext) { +ubifs_assert (c, !znode->parent); + znode->cparent =NULL ; znode->cnext = c->cnext;break ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 786/826 jffs2: fix use of uninitialized variable
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qingfang Deng <[email protected]>
[ Upstream commit 3ba44ee966bc3c41dd8a944f963466c8fcc60dc8 ]
When building the kernel with -Wmaybe-uninitialized, the compiler reports this warning:
In function 'jffs2_mark_erased_block',
inlined from 'jffs2_erase_pending_blocks' at fs/jffs2/erase.c:116:4:fs/jffs2/erase.c:474:9: warning: 'bad_offset' may be used uninitialized [-Wmaybe-uninitialized]
474 | jffs2_erase_failed(c, jeb, bad_offset);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fs/jffs2/erase.c: In function 'jffs2_erase_pending_blocks':
fs/jffs2/erase.c:402:18: note: 'bad_offset' was declared here
402 | uint32_t bad_offset;
| ^~~~~~~~~~When mtd->point() is used, jffs2_erase_pending_blocks can return -EIO without initializing bad_offset, which is later used at the filebad label in jffs2_mark_erased_block.
Fix it by initializing this variable.
--- fs/jffs2/erase.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
fs/jffs2/erase.c +3 -4
@@ -338,10 +338,9 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl }while (--retlen);mtd_unpoint (c->mtd, jeb->offset, c->sector_size);if (retlen) { -pr_warn ("Newly-erased block contained word 0x%lx at offset 0x%08tx\n" , - *wordebuf, - jeb->offset + - c->sector_size-retlen *sizeof (*wordebuf)); + *bad_offset = jeb->offset + c->sector_size - retlen *sizeof (*wordebuf); +pr_warn ("Newly-erased block contained word 0x%lx at offset 0x%08x\n" , + *wordebuf, *bad_offset);return -EIO ; }return 0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 787/826 hostfs: Fix the NULL vs IS_ERR() bug for __filemap_get_folio()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: ZhangPeng <[email protected]>
[ Upstream commit bed2cc482600296fe04edbc38005ba2851449c10 ]
The __filemap_get_folio() function returns error pointers. It never returns NULL. So use IS_ERR() to check it.
--- fs/hostfs/hostfs_kern.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/hostfs/hostfs_kern.c +2 -2
@@ -471,8 +471,8 @@ static int hostfs_write_begin(struct file *file, struct address_space *mapping, *foliop =__filemap_get_folio (mapping, index,FGP_WRITEBEGIN ,mapping_gfp_mask (mapping)); -if (!*foliop) -return -ENOMEM ; +if (IS_ERR (*foliop)) +return PTR_ERR (*foliop);return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 788/826 net/9p/usbg: fix handling of the failed kzalloc() memory allocation
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mirsad Todorovac <[email protected]>
[ Upstream commit ff1060813d9347e8c45c8b8cff93a4dfdb6726ad ]
On the linux-next, next-20241108 vanilla kernel, the coccinelle tool gave the following error report:
./net/9p/trans_usbg.c:912:5-11: ERROR: allocation function on line 911 returns NULL not ERR_PTR on failure
kzalloc() failure is fixed to handle the NULL return case on the memory exhaustion.
Message-ID: <[email protected]>
--- net/9p/trans_usbg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/9p/trans_usbg.c +2 -2
@@ -909,9 +909,9 @@ static struct usb_function_instance *usb9pfs_alloc_instance(void) usb9pfs_opts->buflen =DEFAULT_BUFLEN ; dev =kzalloc (sizeof (*dev),GFP_KERNEL ); -if (IS_ERR (dev)) { +if (!dev) {kfree (usb9pfs_opts); -return ERR_CAST (dev); +return ERR_PTR (-ENOMEM ); } usb9pfs_opts->dev = dev;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 789/826 rtc: rzn1: fix BCD to rtc_time conversion errors
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wolfram Sang <[email protected]>
[ Upstream commit 55727188dfa3572aecd946e58fab9e4a64f06894 ]
tm_mon describes months from 0 to 11, but the register contains BCD from 1 to 12. tm_year contains years since 1900, but the BCD contains 20XX. Apply the offsets when converting these numbers.
--- drivers/rtc/rtc-rzn1.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/rtc/rtc-rzn1.c +4 -4
@@ -111,8 +111,8 @@ static int rzn1_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_hour =bcd2bin (tm->tm_hour); tm->tm_wday =bcd2bin (tm->tm_wday); tm->tm_mday =bcd2bin (tm->tm_mday); - tm->tm_mon =bcd2bin (tm->tm_mon); - tm->tm_year =bcd2bin (tm->tm_year); + tm->tm_mon =bcd2bin (tm->tm_mon) -1 ; + tm->tm_year =bcd2bin (tm->tm_year) +100 ;return 0 ; }
@@ -128,8 +128,8 @@ static int rzn1_rtc_set_time(struct device *dev, struct rtc_time *tm) tm->tm_hour =bin2bcd (tm->tm_hour); tm->tm_wday =bin2bcd (rzn1_rtc_tm_to_wday (tm)); tm->tm_mday =bin2bcd (tm->tm_mday); - tm->tm_mon =bin2bcd (tm->tm_mon); - tm->tm_year =bin2bcd (tm->tm_year); + tm->tm_mon =bin2bcd (tm->tm_mon +1 ); + tm->tm_year =bin2bcd (tm->tm_year -100 ); val =readl (rtc->base +RZN1_RTC_CTL2 );if (!(val &RZN1_RTC_CTL2_STOPPED )) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 790/826 Revert "nfs: dont reuse partially completed requests in nfs_lock_and_join_requests"
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Trond Myklebust <[email protected]>
[ Upstream commit 66f9dac9077c9c063552e465212abeb8f97d28a7 ]
This reverts commit b571cfcb9dcac187c6d967987792d37cb0688610.
This patch appears to assume that if one request is complete, then the others will complete too before unlocking. That is not a valid assumption, since other requests could hit a non-fatal error or a short write that would cause them not to complete.
--- fs/nfs/write.c | 49 +++++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 20 deletions(-)
fs/nfs/write.c +29 -20
@@ -144,6 +144,31 @@ static void nfs_io_completion_put(struct nfs_io_completion *ioc)kref_put (&ioc->refcount, nfs_io_completion_release); } +static void +nfs_page_set_inode_ref (struct nfs_page *req,struct inode *inode) +{ +if (!test_and_set_bit (PG_INODE_REF , &req->wb_flags)) { +kref_get (&req->wb_kref); +atomic_long_inc (&NFS_I (inode)->nrequests); + } +} + +static int +nfs_cancel_remove_inode (struct nfs_page *req,struct inode *inode) +{ +int ret; + +if (!test_bit (PG_REMOVE , &req->wb_flags)) +return 0 ; + ret =nfs_page_group_lock (req); +if (ret) +return ret; +if (test_and_clear_bit (PG_REMOVE , &req->wb_flags)) +nfs_page_set_inode_ref (req, inode); +nfs_page_group_unlock (req); +return 0 ; +} +/** * nfs_folio_find_head_request - find head request associated with a folio * @folio: pointer to folio
@@ -540,7 +565,6 @@ static struct nfs_page *nfs_lock_and_join_requests(struct folio *folio)struct inode *inode = folio->mapping->host;struct nfs_page *head, *subreq;struct nfs_commit_info cinfo; -bool removed;int ret;/*
@@ -565,18 +589,18 @@ static struct nfs_page *nfs_lock_and_join_requests(struct folio *folio) goto retry; } - ret =nfs_page_group_lock (head); + ret =nfs_cancel_remove_inode (head, inode);if (ret <0 ) goto out_unlock; - removed =test_bit (PG_REMOVE , &head->wb_flags); + ret =nfs_page_group_lock (head); +if (ret <0 ) + goto out_unlock;/* lock each request in the page group */ for (subreq = head->wb_this_page; subreq != head; subreq = subreq->wb_this_page) { -if (test_bit (PG_REMOVE , &subreq->wb_flags)) - removed = true; ret =nfs_page_group_lock_subreq (head, subreq);if (ret <0 ) goto out_unlock;
@@ -584,21 +608,6 @@ static struct nfs_page *nfs_lock_and_join_requests(struct folio *folio)nfs_page_group_unlock (head); -/* -* If PG_REMOVE is set on any request, I/O on that request has -* completed, but some requests were still under I/O at the time -* we locked the head request. -* -* In that case the above wait for all requests means that all I/O -* has now finished, and we can restart from a clean slate. Let the -* old requests go away and start from scratch instead. -*/ -if (removed) { -nfs_unroll_locks (head, head); -nfs_unlock_and_release_request (head); - goto retry; - } -nfs_init_cinfo_from_inode (&cinfo, inode);nfs_join_page_group (head, &cinfo, inode);return head;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 791/826 nvme/multipath: Fix RCU list traversal to use SRCU primitive
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
[ Upstream commit 5dd18f09ce7399df6fffe80d1598add46c395ae9 ]
The code currently uses list_for_each_entry_rcu() while holding an SRCU lock, triggering false positive warnings with CONFIG_PROVE_RCU=y enabled:
drivers/nvme/host/multipath.c:168 RCU-list traversed in non-reader section!! drivers/nvme/host/multipath.c:227 RCU-list traversed in non-reader section!! drivers/nvme/host/multipath.c:260 RCU-list traversed in non-reader section!!
While the list is properly protected by SRCU lock, the code uses the wrong list traversal primitive. Replace list_for_each_entry_rcu() with list_for_each_entry_srcu() to correctly indicate SRCU-based protection and eliminate the false warning.
--- drivers/nvme/host/multipath.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-)
drivers/nvme/host/multipath.c +14 -7
@@ -165,7 +165,8 @@ void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl)int srcu_idx; srcu_idx =srcu_read_lock (&ctrl->srcu); -list_for_each_entry_rcu (ns, &ctrl->namespaces, list) { +list_for_each_entry_srcu (ns, &ctrl->namespaces, list, +srcu_read_lock_held (&ctrl->srcu)) {if (!ns->head->disk)continue ;kblockd_schedule_work (&ns->head->requeue_work);
@@ -209,7 +210,8 @@ void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl)int srcu_idx; srcu_idx =srcu_read_lock (&ctrl->srcu); -list_for_each_entry_rcu (ns, &ctrl->namespaces, list) { +list_for_each_entry_srcu (ns, &ctrl->namespaces, list, +srcu_read_lock_held (&ctrl->srcu)) {nvme_mpath_clear_current_path (ns);kblockd_schedule_work (&ns->head->requeue_work); }
@@ -224,7 +226,8 @@ void nvme_mpath_revalidate_paths(struct nvme_ns *ns)int srcu_idx; srcu_idx =srcu_read_lock (&head->srcu); -list_for_each_entry_rcu (ns, &head->list, siblings) { +list_for_each_entry_srcu (ns, &head->list, siblings, +srcu_read_lock_held (&head->srcu)) {if (capacity !=get_capacity (ns->disk))clear_bit (NVME_NS_READY , &ns->flags); }
@@ -257,7 +260,8 @@ static struct nvme_ns *__nvme_find_path(struct nvme_ns_head *head, int node)int found_distance =INT_MAX , fallback_distance =INT_MAX , distance;struct nvme_ns *found =NULL , *fallback =NULL , *ns; -list_for_each_entry_rcu (ns, &head->list, siblings) { +list_for_each_entry_srcu (ns, &head->list, siblings, +srcu_read_lock_held (&head->srcu)) {if (nvme_path_is_disabled (ns))continue ;
@@ -356,7 +360,8 @@ static struct nvme_ns *nvme_queue_depth_path(struct nvme_ns_head *head)unsigned int min_depth_opt =UINT_MAX , min_depth_nonopt =UINT_MAX ;unsigned int depth; -list_for_each_entry_rcu (ns, &head->list, siblings) { +list_for_each_entry_srcu (ns, &head->list, siblings, +srcu_read_lock_held (&head->srcu)) {if (nvme_path_is_disabled (ns))continue ;
@@ -424,7 +429,8 @@ static bool nvme_available_path(struct nvme_ns_head *head)if (!test_bit (NVME_NSHEAD_DISK_LIVE , &head->flags))return NULL ; -list_for_each_entry_rcu (ns, &head->list, siblings) { +list_for_each_entry_srcu (ns, &head->list, siblings, +srcu_read_lock_held (&head->srcu)) {if (test_bit (NVME_CTRL_FAILFAST_EXPIRED , &ns->ctrl->flags))continue ;switch (nvme_ctrl_state (ns->ctrl)) {
@@ -785,7 +791,8 @@ static int nvme_update_ana_state(struct nvme_ctrl *ctrl,return 0 ; srcu_idx =srcu_read_lock (&ctrl->srcu); -list_for_each_entry_rcu (ns, &ctrl->namespaces, list) { +list_for_each_entry_srcu (ns, &ctrl->namespaces, list, +srcu_read_lock_held (&ctrl->srcu)) {unsigned nsid; again: nsid =le32_to_cpu (desc->nsids[n]);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 792/826 blk-mq: add non_owner variant of start_freeze/unfreeze queue APIs
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Lei <[email protected]>
[ Upstream commit 8acdd0e7bfadda6b5103f2960d293581954454ed ]
Add non_owner variant of start_freeze/unfreeze queue APIs, so that the caller knows that what they are doing, and we can skip lockdep support for non_owner variant in per-call level.
Prepare for supporting lockdep for freezing/unfreezing queue.
Stable-dep-of: 3802f73bd807 ("block: fix uaf for flush rq while iterating tags")
--- block/blk-mq.c | 20 ++++++++++++++++++++ include/linux/blk-mq.h | 2 ++ 2 files changed, 22 insertions(+)
block/blk-mq.c +20 -0
@@ -196,6 +196,26 @@ void blk_mq_unfreeze_queue(struct request_queue *q) }EXPORT_SYMBOL_GPL (blk_mq_unfreeze_queue); +/* +* non_owner variant of blk_freeze_queue_start +* +* Unlike blk_freeze_queue_start, the queue doesn't need to be unfrozen +* by the same task. This is fragile and should not be used if at all +* possible. +*/ +void blk_freeze_queue_start_non_owner (struct request_queue *q) +{ +blk_freeze_queue_start (q); +} +EXPORT_SYMBOL_GPL (blk_freeze_queue_start_non_owner); + +/* non_owner variant of blk_mq_unfreeze_queue */ +void blk_mq_unfreeze_queue_non_owner (struct request_queue *q) +{ +__blk_mq_unfreeze_queue (q, false); +} +EXPORT_SYMBOL_GPL (blk_mq_unfreeze_queue_non_owner); +/* * FIXME: replace the scsi_internal_device_*block_nowait() calls in the * mpt3sas driver such that this function can be removed.
include/linux/blk-mq.h +2 -0
@@ -925,6 +925,8 @@ void blk_freeze_queue_start(struct request_queue *q);void blk_mq_freeze_queue_wait (struct request_queue *q);int blk_mq_freeze_queue_wait_timeout (struct request_queue *q,unsigned long timeout); +void blk_mq_unfreeze_queue_non_owner (struct request_queue *q); +void blk_freeze_queue_start_non_owner (struct request_queue *q);void blk_mq_map_queues (struct blk_mq_queue_map *qmap);void blk_mq_update_nr_hw_queues (struct blk_mq_tag_set *set,int nr_hw_queues);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 793/826 block: model freeze & enter queue as lock for supporting lockdep
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Lei <[email protected]>
[ Upstream commit f1be1788a32e8fa63416ad4518bbd1a85a825c9d ]
Recently we got several deadlock report[1][2][3] caused by blk_mq_freeze_queue and blk_enter_queue().
Turns out the two are just like acquiring read/write lock, so model them as read/write lock for supporting lockdep:
1) model q->q_usage_counter as two locks(io and queue lock)
- queue lock covers sync with blk_enter_queue()
- io lock covers sync with bio_enter_queue()
2) make the lockdep class/key as per-queue:
- different subsystem has very different lock use pattern, shared lock class causes false positive easily
- freeze_queue degrades to no lock in case that disk state becomes DEAD because bio_enter_queue() won't be blocked any more
- freeze_queue degrades to no lock in case that request queue becomes dying because blk_enter_queue() won't be blocked any more
3) model blk_mq_freeze_queue() as acquire_exclusive & try_lock
- it is exclusive lock, so dependency with blk_enter_queue() is covered
- it is trylock because blk_mq_freeze_queue() are allowed to run concurrently
4) model blk_enter_queue() & bio_enter_queue() as acquire_read()
- nested blk_enter_queue() are allowed
- dependency with blk_mq_freeze_queue() is covered
- blk_queue_exit() is often called from other contexts(such as irq), and it can't be annotated as lock_release(), so simply do it in blk_enter_queue(), this way still covered cases as many as possible
With lockdep support, such kind of reports may be reported asap and needn't wait until the real deadlock is triggered.
For example, lockdep report can be triggered in the report[3] with this patch applied.
[1] occasional block layer hang when setting 'echo noop > /sys/block/sda/queue/scheduler'
https://bugzilla.kernel.org/show_bug.cgi?id=219166
[2] del_gendisk() vs blk_queue_enter() race condition
https://lore.kernel.org/linux-block/[email protected]/
[3] queue_freeze & queue_enter deadlock in scsi
https://lore.kernel.org/linux-block/ZxG38G9BuFdBpBHZ@fedora/T/#u
Stable-dep-of: 3802f73bd807 ("block: fix uaf for flush rq while iterating tags")
--- block/blk-core.c | 18 ++++++++++++++++-- block/blk-mq.c | 26 ++++++++++++++++++++++---- block/blk.h | 29 ++++++++++++++++++++++++++--- block/genhd.c | 15 +++++++++++---- include/linux/blkdev.h | 6 ++++++ 5 files changed, 81 insertions(+), 13 deletions(-)
block/blk-core.c +16 -2
@@ -261,6 +261,8 @@ static void blk_free_queue(struct request_queue *q)blk_mq_release (q);ida_free (&blk_queue_ida, q->id); +lockdep_unregister_key (&q->io_lock_cls_key); +lockdep_unregister_key (&q->q_lock_cls_key);call_rcu (&q->rcu_head, blk_free_queue_rcu); }
@@ -278,18 +280,20 @@ void blk_put_queue(struct request_queue *q) }EXPORT_SYMBOL (blk_put_queue); -void blk_queue_start_drain (struct request_queue *q) +bool blk_queue_start_drain (struct request_queue *q) {/* * When queue DYING flag is set, we need to block new req * entering queue, so we call blk_freeze_queue_start() to * prevent I/O from crossing blk_queue_enter(). */ -blk_freeze_queue_start (q); +bool freeze =__blk_freeze_queue_start (q);if (queue_is_mq (q))blk_mq_wake_waiters (q);/* Make blk_queue_enter() reexamine the DYING flag. */ wake_up_all (&q->mq_freeze_wq); + +return freeze; }/**
@@ -321,6 +325,8 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags)return -ENODEV ; } +rwsem_acquire_read (&q->q_lockdep_map,0 ,0 , _RET_IP_); +rwsem_release (&q->q_lockdep_map, _RET_IP_);return 0 ; }
@@ -352,6 +358,8 @@ int __bio_queue_enter(struct request_queue *q, struct bio *bio) goto dead; } +rwsem_acquire_read (&q->io_lockdep_map,0 ,0 , _RET_IP_); +rwsem_release (&q->io_lockdep_map, _RET_IP_);return 0 ; dead:bio_io_error (bio);
@@ -441,6 +449,12 @@ struct request_queue *blk_alloc_queue(struct queue_limits *lim, int node_id) PERCPU_REF_INIT_ATOMIC, GFP_KERNEL);if (error) goto fail_stats; +lockdep_register_key (&q->io_lock_cls_key); +lockdep_register_key (&q->q_lock_cls_key); +lockdep_init_map (&q->io_lockdep_map,"&q->q_usage_counter(io)" , + &q->io_lock_cls_key,0 ); +lockdep_init_map (&q->q_lockdep_map,"&q->q_usage_counter(queue)" , + &q->q_lock_cls_key,0 ); q->nr_requests =BLKDEV_DEFAULT_RQ ;
block/blk-mq.c +22 -4
@@ -120,17 +120,29 @@ void blk_mq_in_flight_rw(struct request_queue *q, struct block_device *part, inflight[1 ] = mi.inflight[1 ]; } -void blk_freeze_queue_start (struct request_queue *q) +bool __blk_freeze_queue_start (struct request_queue *q) { +int freeze; +mutex_lock (&q->mq_freeze_lock);if (++q->mq_freeze_depth ==1 ) {percpu_ref_kill (&q->q_usage_counter);mutex_unlock (&q->mq_freeze_lock);if (queue_is_mq (q))blk_mq_run_hw_queues (q, false); + freeze = true; }else {mutex_unlock (&q->mq_freeze_lock); + freeze = false; } + +return freeze; +} + +void blk_freeze_queue_start (struct request_queue *q) +{ +if (__blk_freeze_queue_start (q)) +blk_freeze_acquire_lock (q, false, false); }EXPORT_SYMBOL_GPL (blk_freeze_queue_start);
@@ -176,8 +188,10 @@ void blk_mq_freeze_queue(struct request_queue *q) }EXPORT_SYMBOL_GPL (blk_mq_freeze_queue); -void __blk_mq_unfreeze_queue (struct request_queue *q,bool force_atomic) +bool __blk_mq_unfreeze_queue (struct request_queue *q,bool force_atomic) { +int unfreeze = false; +mutex_lock (&q->mq_freeze_lock);if (force_atomic) q->q_usage_counter.data->force_atomic = true;
@@ -186,13 +200,17 @@ void __blk_mq_unfreeze_queue(struct request_queue *q, bool force_atomic)if (!q->mq_freeze_depth) {percpu_ref_resurrect (&q->q_usage_counter);wake_up_all (&q->mq_freeze_wq); + unfreeze = true; }mutex_unlock (&q->mq_freeze_lock); + +return unfreeze; }void blk_mq_unfreeze_queue (struct request_queue *q) { -__blk_mq_unfreeze_queue (q, false); +if (__blk_mq_unfreeze_queue (q, false)) +blk_unfreeze_release_lock (q, false, false); }EXPORT_SYMBOL_GPL (blk_mq_unfreeze_queue);
@@ -205,7 +223,7 @@ EXPORT_SYMBOL_GPL(blk_mq_unfreeze_queue);*/ void blk_freeze_queue_start_non_owner (struct request_queue *q) { -blk_freeze_queue_start (q); +__blk_freeze_queue_start (q); }EXPORT_SYMBOL_GPL (blk_freeze_queue_start_non_owner);
block/blk.h +26 -3
@@ -4,6 +4,7 @@#include <linux/bio-integrity.h> #include <linux/blk-crypto.h> +#include <linux/lockdep.h> #include <linux/memblock.h> /* for max_pfn/max_low_pfn */ #include <linux/sched/sysctl.h> #include <linux/timekeeping.h>
@@ -35,8 +36,9 @@ struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size,void blk_free_flush_queue (struct blk_flush_queue *q);void blk_freeze_queue (struct request_queue *q); -void __blk_mq_unfreeze_queue (struct request_queue *q,bool force_atomic); -void blk_queue_start_drain (struct request_queue *q); +bool __blk_mq_unfreeze_queue (struct request_queue *q,bool force_atomic); +bool blk_queue_start_drain (struct request_queue *q); +bool __blk_freeze_queue_start (struct request_queue *q);int __bio_queue_enter (struct request_queue *q,struct bio *bio);void submit_bio_noacct_nocheck (struct bio *bio);void bio_await_chain (struct bio *bio);
@@ -69,8 +71,11 @@ static inline int bio_queue_enter(struct bio *bio) {struct request_queue *q =bdev_get_queue (bio->bi_bdev); -if (blk_try_enter_queue (q, false)) +if (blk_try_enter_queue (q, false)) { +rwsem_acquire_read (&q->io_lockdep_map,0 ,0 , _RET_IP_); +rwsem_release (&q->io_lockdep_map, _RET_IP_);return 0 ; + }return __bio_queue_enter (q, bio); }
@@ -734,4 +739,22 @@ void blk_integrity_verify(struct bio *bio);void blk_integrity_prepare (struct request *rq);void blk_integrity_complete (struct request *rq,unsigned int nr_bytes); +static inline void blk_freeze_acquire_lock (struct request_queue *q,bool + disk_dead,bool queue_dying) +{ +if (!disk_dead) +rwsem_acquire (&q->io_lockdep_map,0 ,1 , _RET_IP_); +if (!queue_dying) +rwsem_acquire (&q->q_lockdep_map,0 ,1 , _RET_IP_); +} + +static inline void blk_unfreeze_release_lock (struct request_queue *q,bool + disk_dead,bool queue_dying) +{ +if (!queue_dying) +rwsem_release (&q->q_lockdep_map, _RET_IP_); +if (!disk_dead) +rwsem_release (&q->io_lockdep_map, _RET_IP_); +} +#endif /* BLK_INTERNAL_H */
block/genhd.c +11 -4
@@ -581,13 +581,13 @@ static void blk_report_disk_dead(struct gendisk *disk, bool surprise)rcu_read_unlock (); } -static void __blk_mark_disk_dead (struct gendisk *disk) +static bool __blk_mark_disk_dead (struct gendisk *disk) {/* * Fail any new I/O. */ if (test_and_set_bit (GD_DEAD , &disk->state)) -return ; +return false;if (test_bit (GD_OWNS_QUEUE , &disk->state))blk_queue_flag_set (QUEUE_FLAG_DYING , disk->queue);
@@ -600,7 +600,7 @@ static void __blk_mark_disk_dead(struct gendisk *disk)/* * Prevent new I/O from crossing bio_queue_enter(). */ -blk_queue_start_drain (disk->queue); +return blk_queue_start_drain (disk->queue); }/**
@@ -641,6 +641,7 @@ void del_gendisk(struct gendisk *disk)struct request_queue *q = disk->queue;struct block_device *part;unsigned long idx; +bool start_drain, queue_dying;might_sleep ();
@@ -668,7 +669,10 @@ void del_gendisk(struct gendisk *disk)* Drop all partitions now that the disk is marked dead. */ mutex_lock (&disk->open_mutex); -__blk_mark_disk_dead (disk); + start_drain =__blk_mark_disk_dead (disk); + queue_dying =blk_queue_dying (q); +if (start_drain) +blk_freeze_acquire_lock (q, true, queue_dying);xa_for_each_start (&disk->part_tbl, idx, part,1 )drop_partition (part);mutex_unlock (&disk->open_mutex);
@@ -725,6 +729,9 @@ void del_gendisk(struct gendisk *disk)if (queue_is_mq (q))blk_mq_exit_queue (q); } + +if (start_drain) +blk_unfreeze_release_lock (q, true, queue_dying); }EXPORT_SYMBOL (del_gendisk);
include/linux/blkdev.h +6 -0
@@ -25,6 +25,7 @@#include <linux/uuid.h> #include <linux/xarray.h> #include <linux/file.h> +#include <linux/lockdep.h> struct module ;struct request_queue ;
@@ -471,6 +472,11 @@ struct request_queue {struct xarray hctx_table;struct percpu_ref q_usage_counter; +struct lock_class_key io_lock_cls_key; +struct lockdep_map io_lockdep_map; + +struct lock_class_key q_lock_cls_key; +struct lockdep_map q_lockdep_map;struct request *last_merge;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 794/826 block: fix uaf for flush rq while iterating tags
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yu Kuai <[email protected]>
[ Upstream commit 3802f73bd80766d70f319658f334754164075bc3 ]
blk_mq_clear_flush_rq_mapping() is not called during scsi probe, by checking blk_queue_init_done(). However, QUEUE_FLAG_INIT_DONE is cleared in del_gendisk by commit aec89dc5d421 ("block: keep q_usage_counter in atomic mode after del_gendisk"), hence for disk like scsi, following blk_mq_destroy_queue() will not clear flush rq from tags->rqs[] as well, cause following uaf that is found by our syzkaller for v6.6:
==================================================================
BUG: KASAN: slab-use-after-free in blk_mq_find_and_get_req+0x16e/0x1a0 block/blk-mq-tag.c:261 Read of size 4 at addr ffff88811c969c20 by task kworker/1:2H/224909 CPU: 1 PID: 224909 Comm: kworker/1:2H Not tainted 6.6.0-ga836a5060850 #32 Workqueue: kblockd blk_mq_timeout_work Call Trace: __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0x91/0xf0 lib/dump_stack.c:106 print_address_description.constprop.0+0x66/0x300 mm/kasan/report.c:364 print_report+0x3e/0x70 mm/kasan/report.c:475 kasan_report+0xb8/0xf0 mm/kasan/report.c:588 blk_mq_find_and_get_req+0x16e/0x1a0 block/blk-mq-tag.c:261 bt_iter block/blk-mq-tag.c:288 [inline] __sbitmap_for_each_set include/linux/sbitmap.h:295 [inline] sbitmap_for_each_set include/linux/sbitmap.h:316 [inline] bt_for_each+0x455/0x790 block/blk-mq-tag.c:325 blk_mq_queue_tag_busy_iter+0x320/0x740 block/blk-mq-tag.c:534 blk_mq_timeout_work+0x1a3/0x7b0 block/blk-mq.c:1673 process_one_work+0x7c4/0x1450 kernel/workqueue.c:2631 process_scheduled_works kernel/workqueue.c:2704 [inline] worker_thread+0x804/0xe40 kernel/workqueue.c:2785 kthread+0x346/0x450 kernel/kthread.c:388 ret_from_fork+0x4d/0x80 arch/x86/kernel/process.c:147 ret_from_fork_asm+0x1b/0x30 arch/x86/entry/entry_64.S:293 Allocated by task 942: kasan_save_stack+0x22/0x50 mm/kasan/common.c:45 kasan_set_track+0x25/0x30 mm/kasan/common.c:52 ____kasan_kmalloc mm/kasan/common.c:374 [inline] __kasan_kmalloc mm/kasan/common.c:383 [inline] __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:380 kasan_kmalloc include/linux/kasan.h:198 [inline] __do_kmalloc_node mm/slab_common.c:1007 [inline] __kmalloc_node+0x69/0x170 mm/slab_common.c:1014 kmalloc_node include/linux/slab.h:620 [inline] kzalloc_node include/linux/slab.h:732 [inline] blk_alloc_flush_queue+0x144/0x2f0 block/blk-flush.c:499 blk_mq_alloc_hctx+0x601/0x940 block/blk-mq.c:3788 blk_mq_alloc_and_init_hctx+0x27f/0x330 block/blk-mq.c:4261 blk_mq_realloc_hw_ctxs+0x488/0x5e0 block/blk-mq.c:4294 blk_mq_init_allocated_queue+0x188/0x860 block/blk-mq.c:4350 blk_mq_init_queue_data block/blk-mq.c:4166 [inline] blk_mq_init_queue+0x8d/0x100 block/blk-mq.c:4176 scsi_alloc_sdev+0x843/0xd50 drivers/scsi/scsi_scan.c:335 scsi_probe_and_add_lun+0x77c/0xde0 drivers/scsi/scsi_scan.c:1189 __scsi_scan_target+0x1fc/0x5a0 drivers/scsi/scsi_scan.c:1727 scsi_scan_channel drivers/scsi/scsi_scan.c:1815 [inline] scsi_scan_channel+0x14b/0x1e0 drivers/scsi/scsi_scan.c:1791 scsi_scan_host_selected+0x2fe/0x400 drivers/scsi/scsi_scan.c:1844 scsi_scan+0x3a0/0x3f0 drivers/scsi/scsi_sysfs.c:151 store_scan+0x2a/0x60 drivers/scsi/scsi_sysfs.c:191 dev_attr_store+0x5c/0x90 drivers/base/core.c:2388 sysfs_kf_write+0x11c/0x170 fs/sysfs/file.c:136 kernfs_fop_write_iter+0x3fc/0x610 fs/kernfs/file.c:338 call_write_iter include/linux/fs.h:2083 [inline] new_sync_write+0x1b4/0x2d0 fs/read_write.c:493 vfs_write+0x76c/0xb00 fs/read_write.c:586 ksys_write+0x127/0x250 fs/read_write.c:639 do_syscall_x64 arch/x86/entry/common.c:51 [inline] do_syscall_64+0x70/0x120 arch/x86/entry/common.c:81 entry_SYSCALL_64_after_hwframe+0x78/0xe2 Freed by task 244687: kasan_save_stack+0x22/0x50 mm/kasan/common.c:45 kasan_set_track+0x25/0x30 mm/kasan/common.c:52 kasan_save_free_info+0x2b/0x50 mm/kasan/generic.c:522 ____kasan_slab_free mm/kasan/common.c:236 [inline] __kasan_slab_free+0x12a/0x1b0 mm/kasan/common.c:244 kasan_slab_free include/linux/kasan.h:164 [inline] slab_free_hook mm/slub.c:1815 [inline] slab_free_freelist_hook mm/slub.c:1841 [inline] slab_free mm/slub.c:3807 [inline] __kmem_cache_free+0xe4/0x520 mm/slub.c:3820 blk_free_flush_queue+0x40/0x60 block/blk-flush.c:520 blk_mq_hw_sysfs_release+0x4a/0x170 block/blk-mq-sysfs.c:37 kobject_cleanup+0x136/0x410 lib/kobject.c:689 kobject_release lib/kobject.c:720 [inline] kref_put include/linux/kref.h:65 [inline] kobject_put+0x119/0x140 lib/kobject.c:737 blk_mq_release+0x24f/0x3f0 block/blk-mq.c:4144 blk_free_queue block/blk-core.c:298 [inline] blk_put_queue+0xe2/0x180 block/blk-core.c:314 blkg_free_workfn+0x376/0x6e0 block/blk-cgroup.c:144 process_one_work+0x7c4/0x1450 kernel/workqueue.c:2631 process_scheduled_works kernel/workqueue.c:2704 [inline] worker_thread+0x804/0xe40 kernel/workqueue.c:2785 kthread+0x346/0x450 kernel/kthread.c:388 ret_from_fork+0x4d/0x80 arch/x86/kernel/process.c:147 ret_from_fork_asm+0x1b/0x30 arch/x86/entry/entry_64.S:293
Other than blk_mq_clear_flush_rq_mapping(), the flag is only used in blk_register_queue() from initialization path, hence it's safe not to clear the flag in del_gendisk. And since QUEUE_FLAG_REGISTERED already make sure that queue should only be registered once, there is no need to test the flag as well.
Depends-on: commit aec89dc5d421 ("block: keep q_usage_counter in atomic mode after del_gendisk")
--- block/blk-sysfs.c | 6 ++---- block/genhd.c | 9 +++------ 2 files changed, 5 insertions(+), 10 deletions(-)
block/blk-sysfs.c +2 -4
@@ -794,10 +794,8 @@ int blk_register_queue(struct gendisk *disk)* faster to shut down and is made fully functional here as * request_queues for non-existent devices never get registered. */ -if (!blk_queue_init_done (q)) { -blk_queue_flag_set (QUEUE_FLAG_INIT_DONE , q); -percpu_ref_switch_to_percpu (&q->q_usage_counter); - } +blk_queue_flag_set (QUEUE_FLAG_INIT_DONE , q); +percpu_ref_switch_to_percpu (&q->q_usage_counter);return ret;
block/genhd.c +3 -6
@@ -722,13 +722,10 @@ void del_gendisk(struct gendisk *disk)* If the disk does not own the queue, allow using passthrough requests * again. Else leave the queue frozen to fail all I/O. */ -if (!test_bit (GD_OWNS_QUEUE , &disk->state)) { -blk_queue_flag_clear (QUEUE_FLAG_INIT_DONE , q); +if (!test_bit (GD_OWNS_QUEUE , &disk->state))__blk_mq_unfreeze_queue (q, true); - }else { -if (queue_is_mq (q)) -blk_mq_exit_queue (q); - } +else if (queue_is_mq (q)) +blk_mq_exit_queue (q);if (start_drain)blk_unfreeze_release_lock (q, true, queue_dying);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 795/826 block: return unsigned int from bdev_io_min
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig <[email protected]>
[ Upstream commit 46fd48ab3ea3eb3bb215684bd66ea3d260b091a9 ]
The underlying limit is defined as an unsigned int, so return that from bdev_io_min as well.
--- include/linux/blkdev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/blkdev.h +1 -1
@@ -1253,7 +1253,7 @@ static inline unsigned int queue_io_min(const struct request_queue *q)return q->limits.io_min; } -static inline int bdev_io_min (struct block_device *bdev) +static inline unsigned int bdev_io_min (struct block_device *bdev) {return queue_io_min (bdev_get_queue (bdev)); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 796/826 nvme-fabrics: fix kernel crash while shutting down controller
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nilay Shroff <[email protected]>
[ Upstream commit e9869c85c81168a1275f909d5972a3fc435304be ]
The nvme keep-alive operation, which executes at a periodic interval, could potentially sneak in while shutting down a fabric controller. This may lead to a race between the fabric controller admin queue destroy code path (invoked while shutting down controller) and hw/hctx queue dispatcher called from the nvme keep-alive async request queuing operation. This race could lead to the kernel crash shown below:
Call Trace:
autoremove_wake_function+0x0/0xbc (unreliable)
__blk_mq_sched_dispatch_requests+0x114/0x24c
blk_mq_sched_dispatch_requests+0x44/0x84
blk_mq_run_hw_queue+0x140/0x220
nvme_keep_alive_work+0xc8/0x19c [nvme_core]
process_one_work+0x200/0x4e0
worker_thread+0x340/0x504
kthread+0x138/0x140
start_kernel_thread+0x14/0x18While shutting down fabric controller, if nvme keep-alive request sneaks in then it would be flushed off. The nvme_keep_alive_end_io function is then invoked to handle the end of the keep-alive operation which decrements the admin->q_usage_counter and assuming this is the last/only request in the admin queue then the admin->q_usage_counter becomes zero. If that happens then blk-mq destroy queue operation (blk_mq_destroy_ queue()) which could be potentially running simultaneously on another cpu (as this is the controller shutdown code path) would forward progress and deletes the admin queue. So, now from this point onward we are not supposed to access the admin queue resources. However the issue here's that the nvme keep-alive thread running hw/hctx queue dispatch operation hasn't yet finished its work and so it could still potentially access the admin queue resource while the admin queue had been already deleted and that causes the above crash.
The above kernel crash is regression caused due to changes implemented in commit a54a93d0e359 ("nvme: move stopping keep-alive into nvme_uninit_ctrl()"). Ideally we should stop keep-alive before destroyin g the admin queue and freeing the admin tagset so that it wouldn't sneak in during the shutdown operation. However we removed the keep alive stop operation from the beginning of the controller shutdown code path in commit a54a93d0e359 ("nvme: move stopping keep-alive into nvme_uninit_ctrl()") and added it under nvme_uninit_ctrl() which executes very late in the shutdown code path after the admin queue is destroyed and its tagset is removed. So this change created the possibility of keep-alive sneaking in and interfering with the shutdown operation and causing observed kernel crash.
To fix the observed crash, we decided to move nvme_stop_keep_alive() from nvme_uninit_ctrl() to nvme_remove_admin_tag_set(). This change would ensure that we don't forward progress and delete the admin queue until the keep- alive operation is finished (if it's in-flight) or cancelled and that would help contain the race condition explained above and hence avoid the crash.
Moving nvme_stop_keep_alive() to nvme_remove_admin_tag_set() instead of adding nvme_stop_keep_alive() to the beginning of the controller shutdown code path in nvme_stop_ctrl(), as was the case earlier before commit a54a93d0e359 ("nvme: move stopping keep-alive into nvme_uninit_ctrl()"), would help save one callsite of nvme_stop_keep_alive().
--- drivers/nvme/host/core.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/nvme/host/core.c +5 -0
@@ -4591,6 +4591,11 @@ EXPORT_SYMBOL_GPL(nvme_alloc_admin_tag_set);void nvme_remove_admin_tag_set (struct nvme_ctrl *ctrl) { +/* +* As we're about to destroy the queue and free tagset +* we can not have keep-alive work running. +*/ +nvme_stop_keep_alive (ctrl);blk_mq_destroy_queue (ctrl->admin_q);blk_put_queue (ctrl->admin_q);if (ctrl->ops->flags &NVME_F_FABRICS ) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 797/826 9p/xen: fix init sequence
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Zenla <[email protected]>
[ Upstream commit 7ef3ae82a6ebbf4750967d1ce43bcdb7e44ff74b ]
Large amount of mount hangs observed during hotplugging of 9pfs devices. The 9pfs Xen driver attempts to initialize itself more than once, causing the frontend and backend to disagree: the backend listens on a channel that the frontend does not send on, resulting in stalled processing.
Only allow initialization of 9p frontend once.
Message-ID: <[email protected]>
--- net/9p/trans_xen.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
net/9p/trans_xen.c +5 -2
@@ -465,6 +465,7 @@ static int xen_9pfs_front_init(struct xenbus_device *dev) goto error; } +xenbus_switch_state (dev, XenbusStateInitialised);return 0 ; error_xenbus:
@@ -512,8 +513,10 @@ static void xen_9pfs_front_changed(struct xenbus_device *dev,break ;case XenbusStateInitWait: -if (!xen_9pfs_front_init (dev)) -xenbus_switch_state (dev, XenbusStateInitialised); +if (dev->state != XenbusStateInitialising) +break ; + +xen_9pfs_front_init (dev);break ;case XenbusStateConnected:
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 798/826 9p/xen: fix release of IRQ
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Zenla <[email protected]>
[ Upstream commit e43c608f40c065b30964f0a806348062991b802d ]
Kernel logs indicate an IRQ was double-freed.
Pass correct device ID during IRQ release.
Message-ID: <[email protected]>
--- net/9p/trans_xen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/9p/trans_xen.c +1 -1
@@ -286,7 +286,7 @@ static void xen_9pfs_front_free(struct xen_9pfs_front_priv *priv)if (!priv->rings[i].intf)break ;if (priv->rings[i].irq >0 ) -unbind_from_irqhandler (priv->rings[i].irq, priv->dev); +unbind_from_irqhandler (priv->rings[i].irq, ring);if (priv->rings[i].data.in) { for (j = 0; j < (1 << priv->rings[i].intf->ring_order);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 799/826 perf/arm-smmuv3: Fix lockdep assert in ->event_init()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chun-Tse Shao <[email protected]>
[ Upstream commit 02a55f2743012a8089f09f6867220c3d57f16564 ]
Same as
https://lore.kernel.org/all/[email protected]/,
we should skip for_each_sibling_event() for group leader since it doesn't have the ctx yet.
--- drivers/perf/arm_smmuv3_pmu.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-)
drivers/perf/arm_smmuv3_pmu.c +11 -8
@@ -431,6 +431,17 @@ static int smmu_pmu_event_init(struct perf_event *event)return -EINVAL ; } +/* +* Ensure all events are on the same cpu so all events are in the +* same cpu context, to avoid races on pmu_enable etc. +*/ + event->cpu = smmu_pmu->on_cpu; + + hwc->idx =-1 ; + +if (event->group_leader == event) +return 0 ; +for_each_sibling_event (sibling, event->group_leader) {if (is_software_event (sibling))continue ;
@@ -442,14 +453,6 @@ static int smmu_pmu_event_init(struct perf_event *event)return -EINVAL ; } - hwc->idx =-1 ; - -/* -* Ensure all events are on the same cpu so all events are in the -* same cpu context, to avoid races on pmu_enable etc. -*/ - event->cpu = smmu_pmu->on_cpu; -return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 800/826 perf/arm-cmn: Ensure port and device id bits are set properly
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namhyung Kim <[email protected]>
[ Upstream commit dfdf714fed559c09021df1d2a4bb64c0ad5f53bc ]
The portid_bits and deviceid_bits were set only for XP type nodes in the arm_cmn_discover() and it confused other nodes to find XP nodes. Copy the both bits from the XP nodes directly when it sets up a new node.
--- drivers/perf/arm-cmn.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/perf/arm-cmn.c +2 -2
@@ -2178,8 +2178,6 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)continue ; xp =arm_cmn_node_to_xp (cmn, dn); - dn->portid_bits = xp->portid_bits; - dn->deviceid_bits = xp->deviceid_bits; dn->dtc = xp->dtc; dn->dtm = xp->dtm;if (cmn->multi_dtm)
@@ -2420,6 +2418,8 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset) }arm_cmn_init_node_info (cmn, reg &CMN_CHILD_NODE_ADDR , dn); + dn->portid_bits = xp->portid_bits; + dn->deviceid_bits = xp->deviceid_bits;switch (dn->type) {case CMN_TYPE_DTC :
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 801/826 smb: client: disable directory caching when dir_cache_timeout is zero
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Henrique Carvalho <[email protected]>
[ Upstream commit ceaf1451990e3ea7fb50aebb5a149f57945f6e9f ]
Setting dir_cache_timeout to zero should disable the caching of directory contents. Currently, even when dir_cache_timeout is zero, some caching related functions are still invoked, which is unintended behavior.
Fix the issue by setting tcon->nohandlecache to true when dir_cache_timeout is zero, ensuring that directory handle caching is properly disabled.
--- fs/smb/client/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/smb/client/connect.c +1 -1
@@ -2594,7 +2594,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)if (ses->server->dialect >=SMB20_PROT_ID && (ses->server->capabilities &SMB2_GLOBAL_CAP_DIRECTORY_LEASING )) - nohandlecache = ctx->nohandlecache; + nohandlecache = ctx->nohandlecache || !dir_cache_timeout;else nohandlecache = true; tcon =tcon_info_alloc (!nohandlecache, netfs_trace_tcon_ref_new);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 802/826 x86/Documentation: Update algo in init_size description of boot protocol
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <[email protected]>
[ Upstream commit be4ca6c53e66cb275cf0d71f32dac0c4606b9dc0 ]
The init_size description of boot protocol has an example of the runtime start address for the compressed bzImage. For non-relocatable kernel it relies on the pref_address value (if not 0), but for relocatable case only pays respect to the load_addres and kernel_alignment, and it is inaccurate for the latter. Boot loader must consider the pref_address as the Linux kernel relocates to it before being decompressed as nicely described in this commit message a year ago:
43b1d3e68ee7 ("kexec: Allocate kernel above bzImage's pref_address")
Due to this documentation inaccuracy some of the bootloaders (*) made a mistake in the calculations and if kernel image is big enough, this may lead to unbootable configurations.
*)
In particular, kexec-tools missed that and resently got a couple of changes which will be part of v2.0.30 release. For the record, commit 43b1d3e68ee7 only fixed the kernel kexec implementation and also missed to update the init_size description.
While at it, make an example C-like looking as it's done elsewhere in the document and fix indentation as presribed by the reStructuredText specifications, so the syntax highliting will work properly.
--- Documentation/arch/x86/boot.rst | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
Documentation/arch/x86/boot.rst +13 -4
@@ -896,10 +896,19 @@ Offset/size: 0x260/4 The kernel runtime start address is determined by the following algorithm:: - if (relocatable_kernel) - runtime_start = align_up(load_address, kernel_alignment) - else - runtime_start = pref_address + if (relocatable_kernel) { + if (load_address < pref_address) + load_address = pref_address; + runtime_start = align_up(load_address, kernel_alignment); + } else { + runtime_start = pref_address; + } + +Hence the necessary memory window location and size can be estimated by +a boot loader as:: + + memory_window_start = runtime_start; + memory_window_size = init_size; ============ =============== Field name: handover_offset
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 803/826 cifs: Fix parsing native symlinks relative to the export
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pali Rohár <[email protected]>
[ Upstream commit 723f4ef90452aa629f3d923e92e0449d69362b1d ]
SMB symlink which has SYMLINK_FLAG_RELATIVE set is relative (as opposite of the absolute) and it can be relative either to the current directory (where is the symlink stored) or relative to the top level export path. To what it is relative depends on the first character of the symlink target path.
If the first character is path separator then symlink is relative to the export, otherwise to the current directory. Linux (and generally POSIX systems) supports only symlink paths relative to the current directory where is symlink stored.
Currently if Linux SMB client reads relative SMB symlink with first character as path separator (slash), it let as is. Which means that Linux interpret it as absolute symlink pointing from the root (/). But this location is different than the top level directory of SMB export (unless SMB export was mounted to the root) and thefore SMB symlinks relative to the export are interpreted wrongly by Linux SMB client.
Fix this problem. As Linux does not have equivalent of the path relative to the top of the mount point, convert such symlink target path relative to the current directory. Do this by prepending "../" pattern N times before the SMB target path, where N is the number of path separators found in SMB symlink path.
So for example, if SMB share is mounted to Linux path /mnt/share/, symlink is stored in file /mnt/share/test/folder1/symlink (so SMB symlink path is test\folder1\symlink) and SMB symlink target points to \test\folder2\file, then convert symlink target path to Linux path ../../test/folder2/file.
Deduplicate code for parsing SMB symlinks in native form from functions smb2_parse_symlink_response() and parse_reparse_native_symlink() into new function smb2_parse_native_symlink() and pass into this new function a new full_path parameter from callers, which specify SMB full path where is symlink stored.
This change fixes resolving of the native Windows symlinks relative to the top level directory of the SMB share.
Stable-dep-of: f4ca4f5a36ea ("cifs: Fix parsing reparse point with native symlink in SMB1 non-UNICODE session")
--- fs/smb/client/cifsglob.h | 1 + fs/smb/client/cifsproto.h | 1 + fs/smb/client/inode.c | 1 + fs/smb/client/reparse.c | 90 +++++++++++++++++++++++++++++++++------ fs/smb/client/reparse.h | 4 +- fs/smb/client/smb1ops.c | 3 +- fs/smb/client/smb2file.c | 21 +++++---- fs/smb/client/smb2inode.c | 6 ++- fs/smb/client/smb2proto.h | 9 +++- 9 files changed, 108 insertions(+), 28 deletions(-)
fs/smb/client/cifsglob.h +1 -0
@@ -588,6 +588,7 @@ struct smb_version_operations {/* Check for STATUS_NETWORK_NAME_DELETED */ bool (*is_network_name_deleted)(char *buf,struct TCP_Server_Info *srv);int (*parse_reparse_point)(struct cifs_sb_info *cifs_sb, +const char *full_path,struct kvec *rsp_iov,struct cifs_open_info_data *data); int (*create_reparse_symlink)(const unsigned int xid,
fs/smb/client/cifsproto.h +1 -0
@@ -668,6 +668,7 @@ char *extract_hostname(const char *unc);char *extract_sharename (const char *unc);int parse_reparse_point (struct reparse_data_buffer *buf,u32 plen,struct cifs_sb_info *cifs_sb, +const char *full_path,bool unicode,struct cifs_open_info_data *data); int __cifs_sfu_make_node(unsigned int xid, struct inode *inode, struct dentry *dentry, struct cifs_tcon *tcon,
fs/smb/client/inode.c +1 -0
@@ -1115,6 +1115,7 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data, rc =0 ; }else if (iov && server->ops->parse_reparse_point) { rc = server->ops->parse_reparse_point (cifs_sb, + full_path, iov, data); }break ;
fs/smb/client/reparse.c +78 -12
127 lines not on this page · raw message
fs/smb/client/reparse.h +3 -1
@@ -117,7 +117,9 @@ int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,int smb2_mknod_reparse (unsigned int xid,struct inode *inode,struct dentry *dentry,struct cifs_tcon *tcon,const char *full_path,umode_t mode,dev_t dev); -int smb2_parse_reparse_point (struct cifs_sb_info *cifs_sb,struct kvec *rsp_iov, +int smb2_parse_reparse_point (struct cifs_sb_info *cifs_sb, +const char *full_path, +struct kvec *rsp_iov,struct cifs_open_info_data *data);#endif /* _CIFS_REPARSE_H */
fs/smb/client/smb1ops.c +2 -1
@@ -994,6 +994,7 @@ static int cifs_query_symlink(const unsigned int xid, }static int cifs_parse_reparse_point (struct cifs_sb_info *cifs_sb, +const char *full_path,struct kvec *rsp_iov,struct cifs_open_info_data *data) {
@@ -1004,7 +1005,7 @@ static int cifs_parse_reparse_point(struct cifs_sb_info *cifs_sb, buf = (struct reparse_data_buffer *)((__u8 *)&io->hdr.Protocol +le32_to_cpu (io->DataOffset)); -return parse_reparse_point (buf, plen, cifs_sb, unicode, data); +return parse_reparse_point (buf, plen, cifs_sb, full_path, unicode, data); } static bool
fs/smb/client/smb2file.c +10 -11
@@ -63,12 +63,12 @@ static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov)return sym; } -int smb2_parse_symlink_response (struct cifs_sb_info *cifs_sb,const struct kvec *iov,char **path) +int smb2_parse_symlink_response (struct cifs_sb_info *cifs_sb,const struct kvec *iov, +const char *full_path,char **path) {struct smb2_symlink_err_rsp *sym;unsigned int sub_offs, sub_len;unsigned int print_offs, print_len; -char *s;if (!cifs_sb || !iov || !iov->iov_base || !iov->iov_len || !path)return -EINVAL ;
@@ -86,15 +86,13 @@ int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec iov->iov_len < SMB2_SYMLINK_STRUCT_SIZE + print_offs + print_len) return -EINVAL; - s =cifs_strndup_from_utf16 ((char *)sym->PathBuffer + sub_offs, sub_len, true, - cifs_sb->local_nls); -if (!s) -return -ENOMEM ; -convert_delimiter (s,'/' ); -cifs_dbg (FYI ,"%s: symlink target: %s\n" , __func__, s); - - *path = s; -return 0 ; +return smb2_parse_native_symlink (path, + (char *)sym->PathBuffer + sub_offs, + sub_len, + true, +le32_to_cpu (sym->Flags) &SYMLINK_FLAG_RELATIVE , + full_path, + cifs_sb); }int smb2_open_file (const unsigned int xid,struct cifs_open_parms *oparms,__u32 *oplock,void *buf)
@@ -126,6 +124,7 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 goto out;if (hdr->Status ==STATUS_STOPPED_ON_SYMLINK ) { rc =smb2_parse_symlink_response (oparms->cifs_sb, &err_iov, + oparms->path, &data->symlink_target);if (!rc) {memset (smb2_data,0 ,sizeof (*smb2_data));
fs/smb/client/smb2inode.c +4 -2
@@ -828,6 +828,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,static int parse_create_response (struct cifs_open_info_data *data,struct cifs_sb_info *cifs_sb, +const char *full_path,const struct kvec *iov) {struct smb2_create_rsp *rsp = iov->iov_base;
@@ -841,6 +842,7 @@ static int parse_create_response(struct cifs_open_info_data *data,break ;case STATUS_STOPPED_ON_SYMLINK : rc =smb2_parse_symlink_response (cifs_sb, iov, + full_path, &data->symlink_target);if (rc)return rc;
@@ -930,14 +932,14 @@ int smb2_query_path_info(const unsigned int xid,switch (rc) {case 0 : - rc =parse_create_response (data, cifs_sb, &out_iov[0 ]); + rc =parse_create_response (data, cifs_sb, full_path, &out_iov[0 ]);break ;case -EOPNOTSUPP :/* * BB TODO: When support for special files added to Samba * re-verify this path. */ - rc =parse_create_response (data, cifs_sb, &out_iov[0 ]); + rc =parse_create_response (data, cifs_sb, full_path, &out_iov[0 ]);if (rc || !data->reparse_point) goto out;
fs/smb/client/smb2proto.h +8 -1
@@ -111,7 +111,14 @@ extern int smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,struct cifs_sb_info *cifs_sb, const unsigned char *path, char *pbuf, unsigned int *pbytes_read); -int smb2_parse_symlink_response (struct cifs_sb_info *cifs_sb,const struct kvec *iov,char **path); +int smb2_parse_native_symlink (char **target,const char *buf,unsigned int len, +bool unicode,bool relative, +const char *full_path, +struct cifs_sb_info *cifs_sb); +int smb2_parse_symlink_response (struct cifs_sb_info *cifs_sb, +const struct kvec *iov, +const char *full_path, +char **path);int smb2_open_file (const unsigned int xid,struct cifs_open_parms *oparms,__u32 *oplock,void *buf); extern int smb2_unlock_range(struct cifsFileInfo *cfile,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 804/826 cifs: Fix parsing reparse point with native symlink in SMB1 non-UNICODE session
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pali Rohár <[email protected]>
[ Upstream commit f4ca4f5a36eac9b4da378a0f28cbbe38534a0901 ]
SMB1 NT_TRANSACT_IOCTL/FSCTL_GET_REPARSE_POINT even in non-UNICODE mode returns reparse buffer in UNICODE/UTF-16 format.
This is because FSCTL_GET_REPARSE_POINT is NT-based IOCTL which does not distinguish between 8-bit non-UNICODE and 16-bit UNICODE modes and its path buffers are always encoded in UTF-16.
This change fixes reading of native symlinks in SMB1 when UNICODE session is not active.
--- fs/smb/client/smb1ops.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
fs/smb/client/smb1ops.c +1 -2
@@ -1000,12 +1000,11 @@ static int cifs_parse_reparse_point(struct cifs_sb_info *cifs_sb, {struct reparse_data_buffer *buf;TRANSACT_IOCTL_RSP *io = rsp_iov->iov_base; -bool unicode = !!(io->hdr.Flags2 &SMBFLG2_UNICODE );u32 plen =le16_to_cpu (io->ByteCount); buf = (struct reparse_data_buffer *)((__u8 *)&io->hdr.Protocol +le32_to_cpu (io->DataOffset)); -return parse_reparse_point (buf, plen, cifs_sb, full_path, unicode, data); +return parse_reparse_point (buf, plen, cifs_sb, full_path, true, data); } static bool
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 805/826 rtc: ab-eoz9: dont fail temperature reads on undervoltage notification
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maxime Chevallier <[email protected]>
[ Upstream commit e0779a0dcf41a6452ac0a169cd96863feb5787c7 ]
The undervoltage flags reported by the RTC are useful to know if the time and date are reliable after a reboot. Although the threshold VLOW1 indicates that the thermometer has been shutdown and time compensation is off, it doesn't mean that the temperature readout is currently impossible.
As the system is running, the RTC voltage is now fully established and we can read the temperature.
--- drivers/rtc/rtc-ab-eoz9.c | 7 ------- 1 file changed, 7 deletions(-)
drivers/rtc/rtc-ab-eoz9.c +0 -7
@@ -396,13 +396,6 @@ static int abeoz9z3_temp_read(struct device *dev,if (ret <0 )return ret; -if ((val &ABEOZ9_REG_CTRL_STATUS_V1F ) || - (val &ABEOZ9_REG_CTRL_STATUS_V2F )) { -dev_err (dev, -"thermometer might be disabled due to low voltage\n" ); -return -EINVAL ; - } -switch (attr) {case hwmon_temp_input: ret =regmap_read (regmap,ABEOZ9_REG_REG_TEMP , &val);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 806/826 Rename .data.unlikely to .data..unlikely
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masahiro Yamada <[email protected]>
[ Upstream commit bb43a59944f45e89aa158740b8a16ba8f0b0fa2b ]
Commit 7ccaba5314ca ("consolidate WARN_...ONCE() static variables") was intended to collect all .data.unlikely sections into one chunk. However, this has not worked when CONFIG_LD_DEAD_CODE_DATA_ELIMINATION or CONFIG_LTO_CLANG is enabled, because .data.unlikely matches the .data.[0-9a-zA-Z_]* pattern in the DATA_MAIN macro.
Commit cb87481ee89d ("kbuild: linker script do not match C names unless LD_DEAD_CODE_DATA_ELIMINATION is configured") was introduced to suppress the issue for the default CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=n case, providing a minimal fix for stable backporting. We were aware this did not address the issue for CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y. The plan was to apply correct fixes and then revert cb87481ee89d. [1]
Seven years have passed since then, yet the #ifdef workaround remains in place.
Using a ".." separator in the section name fixes the issue for CONFIG_LD_DEAD_CODE_DATA_ELIMINATION and CONFIG_LTO_CLANG.
--- include/asm-generic/vmlinux.lds.h | 2 +- include/linux/rcupdate.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
include/asm-generic/vmlinux.lds.h +1 -1
@@ -350,7 +350,7 @@ *(.data..decrypted) \ *(.ref.data) \ *(.data..shared_aligned) /* percpu related */ \ - *(.data.unlikely) \ + *(.data..unlikely) \ __start_once = .; \ *(.data.once) \ __end_once = .; \
include/linux/rcupdate.h +1 -1
@@ -401,7 +401,7 @@ static inline int debug_lockdep_rcu_enabled(void)*/ #define RCU_LOCKDEP_WARN (c, s) \ do { \ - static bool __section(".data.unlikely") __warned; \ + static bool __section(".data..unlikely") __warned; \ if (debug_lockdep_rcu_enabled() && (c) && \ debug_lockdep_rcu_enabled() && !__warned) { \ __warned = true; \
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 807/826 Rename .data.once to .data..once to fix resetting WARN*_ONCE
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masahiro Yamada <[email protected]>
[ Upstream commit dbefa1f31a91670c9e7dac9b559625336206466f ]
Commit b1fca27d384e ("kernel debug: support resetting WARN*_ONCE") added support for clearing the state of once warnings. However, it is not functional when CONFIG_LD_DEAD_CODE_DATA_ELIMINATION or CONFIG_LTO_CLANG is enabled, because .data.once matches the .data.[0-9a-zA-Z_]* pattern in the DATA_MAIN macro.
Commit cb87481ee89d ("kbuild: linker script do not match C names unless LD_DEAD_CODE_DATA_ELIMINATION is configured") was introduced to suppress the issue for the default CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=n case, providing a minimal fix for stable backporting. We were aware this did not address the issue for CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y. The plan was to apply correct fixes and then revert cb87481ee89d. [1]
Seven years have passed since then, yet the #ifdef workaround remains in place. Meanwhile, commit b1fca27d384e introduced the .data.once section, and commit dc5723b02e52 ("kbuild: add support for Clang LTO") extended the #ifdef.
Using a ".." separator in the section name fixes the issue for CONFIG_LD_DEAD_CODE_DATA_ELIMINATION and CONFIG_LTO_CLANG.
--- include/asm-generic/vmlinux.lds.h | 2 +- include/linux/mmdebug.h | 6 +++--- include/linux/once.h | 4 ++-- include/linux/once_lite.h | 2 +- include/net/net_debug.h | 2 +- mm/internal.h | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-)
include/asm-generic/vmlinux.lds.h +1 -1
@@ -352,7 +352,7 @@ *(.data..shared_aligned) /* percpu related */ \ *(.data..unlikely) \ __start_once = .; \ - *(.data.once) \ + *(.data..once) \ __end_once = .; \STRUCT_ALIGN (); \ *(__tracepoints) \
include/linux/mmdebug.h +3 -3
@@ -46,7 +46,7 @@ void vma_iter_dump_tree(const struct vma_iterator *vmi); } \ } while (0)#define VM_WARN_ON_ONCE_PAGE (cond, page) ({ \ - static bool __section(".data.once") __warned; \ + static bool __section(".data..once") __warned; \ int __ret_warn_once = !!(cond); \ \ if (unlikely(__ret_warn_once && !__warned)) { \
@@ -66,7 +66,7 @@ void vma_iter_dump_tree(const struct vma_iterator *vmi);unlikely (__ret_warn); \ })#define VM_WARN_ON_ONCE_FOLIO (cond, folio) ({ \ - static bool __section(".data.once") __warned; \ + static bool __section(".data..once") __warned; \ int __ret_warn_once = !!(cond); \ \ if (unlikely(__ret_warn_once && !__warned)) { \
@@ -77,7 +77,7 @@ void vma_iter_dump_tree(const struct vma_iterator *vmi);unlikely (__ret_warn_once); \ })#define VM_WARN_ON_ONCE_MM (cond, mm) ({ \ - static bool __section(".data.once") __warned; \ + static bool __section(".data..once") __warned; \ int __ret_warn_once = !!(cond); \ \ if (unlikely(__ret_warn_once && !__warned)) { \
include/linux/once.h +2 -2
@@ -46,7 +46,7 @@ void __do_once_sleepable_done(bool *done, struct static_key_true *once_key,#define DO_ONCE (func, ...) \ ({ \ bool ___ret = false; \ - static bool __section(".data.once") ___done = false; \ + static bool __section(".data..once") ___done = false; \ static DEFINE_STATIC_KEY_TRUE(___once_key); \ if (static_branch_unlikely(&___once_key)) { \ unsigned long ___flags; \
@@ -64,7 +64,7 @@ void __do_once_sleepable_done(bool *done, struct static_key_true *once_key,#define DO_ONCE_SLEEPABLE (func, ...) \ ({ \ bool ___ret = false; \ - static bool __section(".data.once") ___done = false; \ + static bool __section(".data..once") ___done = false; \ static DEFINE_STATIC_KEY_TRUE(___once_key); \ if (static_branch_unlikely(&___once_key)) { \ ___ret = __do_once_sleepable_start(&___done); \
include/linux/once_lite.h +1 -1
@@ -12,7 +12,7 @@#define __ONCE_LITE_IF (condition) \ ({ \ - static bool __section(".data.once") __already_done; \ + static bool __section(".data..once") __already_done; \ bool __ret_cond = !!(condition); \ bool __ret_once = false; \ \
include/net/net_debug.h +1 -1
@@ -27,7 +27,7 @@ void netdev_info(const struct net_device *dev, const char *format, ...);#define netdev_level_once (level, dev, fmt, ...) \ do { \ - static bool __section(".data.once") __print_once; \ + static bool __section(".data..once") __print_once; \ \ if (!__print_once) { \ __print_once = true; \
mm/internal.h +1 -1
@@ -48,7 +48,7 @@ struct folio_batch;* when we specify __GFP_NOWARN. */ #define WARN_ON_ONCE_GFP (cond, gfp) ({ \ - static bool __section(".data.once") __warned; \ + static bool __section(".data..once") __warned; \ int __ret_warn_once = !!(cond); \ \ if (unlikely(!(gfp & __GFP_NOWARN) && __ret_warn_once && !__warned)) { \
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 808/826 kbuild: deb-pkg: Dont fail if modules.order is missing
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matt Fleming <[email protected]>
[ Upstream commit bcbbf493f2fa6fa1f0832f6b5b4c80a65de242d6 ]
Kernels built without CONFIG_MODULES might still want to create -dbg deb packages but install_linux_image_dbg() assumes modules.order always exists. This obviously isn't true if no modules were built, so we should skip reading modules.order in that case.
--- scripts/package/builddeb | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-)
scripts/package/builddeb +12 -10
@@ -96,16 +96,18 @@ install_linux_image_dbg () { # Parse modules.order directly because 'make modules_install' may sign, # compress modules, and then run unneeded depmod. - while read -r mod; do - mod="${mod%.o}.ko" - dbg="${pdir}/usr/lib/debug/lib/modules/${KERNELRELEASE}/kernel/${mod}" - buildid=$("${READELF}" -n "${mod}" | sed -n 's@^.*Build ID: \(..\)\(.*\)@\1/\2@p') - link="${pdir}/usr/lib/debug/.build-id/${buildid}.debug" - - mkdir -p "${dbg%/*}" "${link%/*}" - "${OBJCOPY}" --only-keep-debug "${mod}" "${dbg}" - ln -sf --relative "${dbg}" "${link}" - done < modules.order + if is_enabled CONFIG_MODULES; then + while read -r mod; do + mod="${mod%.o}.ko" + dbg="${pdir}/usr/lib/debug/lib/modules/${KERNELRELEASE}/kernel/${mod}" + buildid=$("${READELF}" -n "${mod}" | sed -n 's@^.*Build ID: \(..\)\(.*\)@\1/\2@p') + link="${pdir}/usr/lib/debug/.build-id/${buildid}.debug" + + mkdir -p "${dbg%/*}" "${link%/*}" + "${OBJCOPY}" --only-keep-debug "${mod}" "${dbg}" + ln -sf --relative "${dbg}" "${link}" + done < modules.order + fi # Build debug package # Different tools want the image in different locations
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 809/826 smb: Initialize cfid->tcon before performing network ops
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Aurich <[email protected]>
[ Upstream commit c353ee4fb119a2582d0e011f66a76a38f5cf984d ]
Avoid leaking a tcon ref when a lease break races with opening the cached directory. Processing the leak break might take a reference to the tcon in cached_dir_lease_break() and then fail to release the ref in cached_dir_offload_close, since cfid->tcon is still NULL.
--- fs/smb/client/cached_dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/smb/client/cached_dir.c +1 -1
@@ -227,6 +227,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, } } cfid->dentry = dentry; + cfid->tcon = tcon;/* * We do not hold the lock for the open because in case
@@ -298,7 +299,6 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, } goto oshr_free; } - cfid->tcon = tcon; cfid->is_open = true;spin_lock (&cfids->cfid_list_lock);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 810/826 block: Dont allow an atomic write be truncated in blkdev_write_iter()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Garry <[email protected]>
[ Upstream commit 2cbd51f1f8739fd2fdf4bae1386bcf75ce0176ba ]
A write which goes past the end of the bdev in blkdev_write_iter() will be truncated. Truncating cannot tolerated for an atomic write, so error that condition.
--- block/fops.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
block/fops.c +4 -1
@@ -677,6 +677,7 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)struct file *file = iocb->ki_filp;struct inode *bd_inode =bdev_file_inode (file);struct block_device *bdev =I_BDEV (bd_inode); +bool atomic = iocb->ki_flags &IOCB_ATOMIC ;loff_t size =bdev_nr_bytes (bdev);size_t shorted =0 ;ssize_t ret;
@@ -696,7 +697,7 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)if ((iocb->ki_flags & (IOCB_NOWAIT |IOCB_DIRECT )) ==IOCB_NOWAIT )return -EOPNOTSUPP ; -if (iocb->ki_flags &IOCB_ATOMIC ) { +if (atomic) { ret =generic_atomic_write_valid (iocb, from);if (ret)return ret;
@@ -704,6 +705,8 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) size -= iocb->ki_pos;if (iov_iter_count (from) > size) { +if (atomic) +return -EINVAL ; shorted =iov_iter_count (from) - size;iov_iter_truncate (from, size); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 811/826 modpost: remove incorrect code in do_eisa_entry()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masahiro Yamada <[email protected]>
[ Upstream commit 0c3e091319e4748cb36ac9a50848903dc6f54054 ]
This function contains multiple bugs after the following commits:
- ac551828993e ("modpost: i2c aliases need no trailing wildcard")
- 6543becf26ff ("mod/file2alias: make modalias generation safe for cross compiling")
Commit ac551828993e inserted the following code to do_eisa_entry():
else
strcat(alias, "*");
This is incorrect because 'alias' is uninitialized. If it is not NULL-terminated, strcat() could cause a buffer overrun.
Even if 'alias' happens to be zero-filled, it would output:
MODULE_ALIAS("*");This would match anything. As a result, the module could be loaded by any unrelated uevent from an unrelated subsystem.
Commit ac551828993e introduced another bug.
Prior to that commit, the conditional check was:
if (eisa->sig[0])
This checked if the first character of eisa_device_id::sig was not '\0'.
However, commit ac551828993e changed it as follows:
if (sig[0])
sig[0] is NOT the first character of the eisa_device_id::sig. The type of 'sig' is 'char (*)[8]', meaning that the type of 'sig[0]' is 'char [8]' instead of 'char'. 'sig[0]' and 'symval' refer to the same address, which never becomes NULL.
The correct conversion would have been:
if ((*sig)[0])
However, this if-conditional was meaningless because the earlier change in commit ac551828993e was incorrect.
This commit removes the entire incorrect code, which should never have been executed.
--- scripts/mod/file2alias.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
scripts/mod/file2alias.c +1 -4
@@ -809,10 +809,7 @@ static int do_eisa_entry(const char *filename, void *symval, char *alias) {DEF_FIELD_ADDR (symval, eisa_device_id, sig); -if (sig[0 ]) -sprintf (alias,EISA_DEVICE_MODALIAS_FMT "*" , *sig); -else -strcat (alias,"*" ); +sprintf (alias,EISA_DEVICE_MODALIAS_FMT "*" , *sig);return 1 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 812/826 cifs: during remount, make sure passwords are in sync
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shyam Prasad N <[email protected]>
[ Upstream commit 0f0e357902957fba28ed31bde0d6921c6bd1485d ]
This fixes scenarios where remount can overwrite the only currently working password, breaking reconnect.
We recently introduced a password2 field in both ses and ctx structs. This was done so as to allow the client to rotate passwords for a mount without any downtime. However, when the client transparently handles password rotation, it can swap the values of the two password fields in the ses struct, but not in smb3_fs_context struct that hangs off cifs_sb. This can lead to a situation where a remount unintentionally overwrites a working password in the ses struct.
In order to fix this, we first get the passwords in ctx struct in-sync with ses struct, before replacing them with what the passwords that could be passed as a part of remount.
Also, in order to avoid race condition between smb2_reconnect and smb3_reconfigure, we make sure to lock session_mutex before changing password and password2 fields of the ses structure.
--- fs/smb/client/fs_context.c | 83 +++++++++++++++++++++++++++++++++----- fs/smb/client/fs_context.h | 1 + 2 files changed, 75 insertions(+), 9 deletions(-)
fs/smb/client/fs_context.c +74 -9
@@ -890,12 +890,37 @@ do { \ cifs_sb->ctx->field =NULL ; \ }while (0 ) +int smb3_sync_session_ctx_passwords(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses) +{ +if (ses->password && + cifs_sb->ctx->password && +strcmp (ses->password, cifs_sb->ctx->password)) { +kfree_sensitive (cifs_sb->ctx->password); + cifs_sb->ctx->password =kstrdup (ses->password,GFP_KERNEL ); +if (!cifs_sb->ctx->password) +return -ENOMEM ; + } +if (ses->password2 && + cifs_sb->ctx->password2 && +strcmp (ses->password2, cifs_sb->ctx->password2)) { +kfree_sensitive (cifs_sb->ctx->password2); + cifs_sb->ctx->password2 =kstrdup (ses->password2,GFP_KERNEL ); +if (!cifs_sb->ctx->password2) { +kfree_sensitive (cifs_sb->ctx->password); + cifs_sb->ctx->password =NULL ; +return -ENOMEM ; + } + } +return 0 ; +} +static int smb3_reconfigure (struct fs_context *fc) {struct smb3_fs_context *ctx =smb3_fc2context (fc);struct dentry *root = fc->root;struct cifs_sb_info *cifs_sb =CIFS_SB (root->d_sb);struct cifs_ses *ses =cifs_sb_master_tcon (cifs_sb)->ses; +char *new_password =NULL , *new_password2 =NULL ;bool need_recon = false;int rc;
@@ -915,21 +940,61 @@ static int smb3_reconfigure(struct fs_context *fc)STEAL_STRING (cifs_sb, ctx,UNC );STEAL_STRING (cifs_sb, ctx, source);STEAL_STRING (cifs_sb, ctx, username); +if (need_recon == false)STEAL_STRING_SENSITIVE (cifs_sb, ctx, password);else { -kfree_sensitive (ses->password); - ses->password =kstrdup (ctx->password,GFP_KERNEL ); -if (!ses->password) -return -ENOMEM ; -kfree_sensitive (ses->password2); - ses->password2 =kstrdup (ctx->password2,GFP_KERNEL ); -if (!ses->password2) { -kfree_sensitive (ses->password); - ses->password =NULL ; +if (ctx->password) { + new_password =kstrdup (ctx->password,GFP_KERNEL ); +if (!new_password) +return -ENOMEM ; + }else +STEAL_STRING_SENSITIVE (cifs_sb, ctx, password); + } + +/* +* if a new password2 has been specified, then reset it's value +* inside the ses struct +*/ +if (ctx->password2) { + new_password2 =kstrdup (ctx->password2,GFP_KERNEL ); +if (!new_password2) { +kfree_sensitive (new_password);return -ENOMEM ; } + }else +STEAL_STRING_SENSITIVE (cifs_sb, ctx, password2); + +/* +* we may update the passwords in the ses struct below. Make sure we do +* not race with smb2_reconnect +*/ +mutex_lock (&ses->session_mutex); + +/* +* smb2_reconnect may swap password and password2 in case session setup +* failed. First get ctx passwords in sync with ses passwords. It should +* be okay to do this even if this function were to return an error at a +* later stage +*/ + rc =smb3_sync_session_ctx_passwords (cifs_sb, ses); +if (rc) +return rc; + +/* +* now that allocations for passwords are done, commit them +*/ +if (new_password) { +kfree_sensitive (ses->password); + ses->password = new_password; } +if (new_password2) { +kfree_sensitive (ses->password2); + ses->password2 = new_password2; + } + +mutex_unlock (&ses->session_mutex); +STEAL_STRING (cifs_sb, ctx, domainname);STEAL_STRING (cifs_sb, ctx, nodename);STEAL_STRING (cifs_sb, ctx, iocharset);
fs/smb/client/fs_context.h +1 -0
@@ -299,6 +299,7 @@ static inline struct smb3_fs_context *smb3_fc2context(const struct fs_context *f }extern int smb3_fs_context_dup (struct smb3_fs_context *new_ctx,struct smb3_fs_context *ctx); +extern int smb3_sync_session_ctx_passwords (struct cifs_sb_info *cifs_sb,struct cifs_ses *ses);extern void smb3_update_mnt_flags (struct cifs_sb_info *cifs_sb);/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 813/826 cifs: unlock on error in smb3_reconfigure()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit cda88d2fef7aa7de80b5697e8009fcbbb436f42d ]
Unlock before returning if smb3_sync_session_ctx_passwords() fails.
--- fs/smb/client/fs_context.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/smb/client/fs_context.c +3 -1
@@ -978,8 +978,10 @@ static int smb3_reconfigure(struct fs_context *fc)* later stage */ rc =smb3_sync_session_ctx_passwords (cifs_sb, ses); -if (rc) +if (rc) { +mutex_unlock (&ses->session_mutex);return rc; + }/* * now that allocations for passwords are done, commit them
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 814/826 nfs: ignore SB_RDONLY when mounting nfs
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li Lingfeng <[email protected]>
[ Upstream commit 52cb7f8f177878b4f22397b9c4d2c8f743766be3 ]
When exporting only one file system with fsid=0 on the server side, the client alternately uses the ro/rw mount options to perform the mount operation, and a new vfsmount is generated each time.
It can be reproduced as follows:
[root@localhost ~]# mount /dev/sda /mnt2
[root@localhost ~]# echo "/mnt2 *(rw,no_root_squash,fsid=0)" >/etc/exports [root@localhost ~]# systemctl restart nfs-server [root@localhost ~]# mount -t nfs -o ro,vers=4 127.0.0.1:/ /mnt/sdaa [root@localhost ~]# mount -t nfs -o rw,vers=4 127.0.0.1:/ /mnt/sdaa [root@localhost ~]# mount -t nfs -o ro,vers=4 127.0.0.1:/ /mnt/sdaa [root@localhost ~]# mount -t nfs -o rw,vers=4 127.0.0.1:/ /mnt/sdaa [root@localhost ~]# mount | grep nfs4
127.0.0.1:/ on /mnt/sdaa type nfs4 (ro,relatime,vers=4.2,rsize=1048576,... 127.0.0.1:/ on /mnt/sdaa type nfs4 (rw,relatime,vers=4.2,rsize=1048576,... 127.0.0.1:/ on /mnt/sdaa type nfs4 (ro,relatime,vers=4.2,rsize=1048576,... 127.0.0.1:/ on /mnt/sdaa type nfs4 (rw,relatime,vers=4.2,rsize=1048576,... [root@localhost ~]#
We expected that after mounting with the ro option, using the rw option to mount again would return EBUSY, but the actual situation was not the case.
As shown above, when mounting for the first time, a superblock with the ro flag will be generated, and at the same time, in do_new_mount_fc --> do_add_mount, it detects that the superblock corresponding to the current target directory is inconsistent with the currently generated one (path->mnt->mnt_sb != newmnt->mnt.mnt_sb), and a new vfsmount will be generated.
When mounting with the rw option for the second time, since no matching superblock can be found in the fs_supers list, a new superblock with the rw flag will be generated again. The superblock in use (ro) is different from the newly generated superblock (rw), and a new vfsmount will be generated again.
When mounting with the ro option for the third time, the superblock (ro) is found in fs_supers, the superblock in use (rw) is different from the found superblock (ro), and a new vfsmount will be generated again.
We can switch between ro/rw through remount, and only one superblock needs to be generated, thus avoiding the problem of repeated generation of vfsmount caused by switching superblocks.
Furthermore, This can also resolve the issue described in the link.
--- fs/nfs/internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfs/internal.h +1 -1
@@ -12,7 +12,7 @@#include <linux/nfslocalio.h> #include <linux/wait_bit.h> -#define NFS_SB_MASK (SB_RDONLY|SB_NOSUID|SB_NODEV|SB_NOEXEC|SB_SYNCHRONOUS) +#define NFS_SB_MASK (SB_NOSUID|SB_NODEV|SB_NOEXEC|SB_SYNCHRONOUS)extern const struct export_operations nfs_export_ops;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 815/826 sunrpc: clear XPRT_SOCK_UPD_TIMEOUT when reset transport
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Liu Jian <[email protected]>
[ Upstream commit 4db9ad82a6c823094da27de4825af693a3475d51 ]
Since transport->sock has been set to NULL during reset transport, XPRT_SOCK_UPD_TIMEOUT also needs to be cleared. Otherwise, the xs_tcp_set_socket_timeouts() may be triggered in xs_tcp_send_request() to dereference the transport->sock that has been set to NULL.
--- net/sunrpc/xprtsock.c | 1 + 1 file changed, 1 insertion(+)
net/sunrpc/xprtsock.c +1 -0
@@ -1198,6 +1198,7 @@ static void xs_sock_reset_state_flags(struct rpc_xprt *xprt)clear_bit (XPRT_SOCK_WAKE_WRITE , &transport->sock_state);clear_bit (XPRT_SOCK_WAKE_DISCONNECT , &transport->sock_state);clear_bit (XPRT_SOCK_NOSPACE , &transport->sock_state); +clear_bit (XPRT_SOCK_UPD_TIMEOUT , &transport->sock_state); }static void xs_run_error_worker (struct sock_xprt *transport,unsigned int nr)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 816/826 SUNRPC: timeout and cancel TLS handshake with -ETIMEDOUT
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Coddington <[email protected]>
[ Upstream commit d7bdd849ef1b681da03ac05ca0957b2cbe2d24b6 ]
We've noticed a situation where an unstable TCP connection can cause the TLS handshake to timeout waiting for userspace to complete it. When this happens, we don't want to return from xs_tls_handshake_sync() with zero, as this will cause the upper xprt to be set CONNECTED, and subsequent attempts to transmit will be returned with -EPIPE. The sunrpc machine does not recover from this situation and will spin attempting to transmit.
The return value of tls_handshake_cancel() can be used to detect a race with completion:
* tls_handshake_cancel - cancel a pending handshake
* Return values:
* %true - Uncompleted handshake request was canceled
* %false - Handshake request already completed or not found
If true, we do not want the upper xprt to be connected, so return -ETIMEDOUT. If false, its possible the handshake request was lost and that may be the reason for our timeout. Again we do not want the upper xprt to be connected, so return -ETIMEDOUT.
Ensure that we alway return an error from xs_tls_handshake_sync() if we call tls_handshake_cancel().
--- net/sunrpc/xprtsock.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
net/sunrpc/xprtsock.c +4 -5
@@ -2615,11 +2615,10 @@ static int xs_tls_handshake_sync(struct rpc_xprt *lower_xprt, struct xprtsec_par rc =wait_for_completion_interruptible_timeout (&lower_transport->handshake_done,XS_TLS_HANDSHAKE_TO );if (rc <=0 ) { -if (!tls_handshake_cancel (sk)) { -if (rc ==0 ) - rc = -ETIMEDOUT ; - goto out_put_xprt; - } +tls_handshake_cancel (sk); +if (rc ==0 ) + rc = -ETIMEDOUT ; + goto out_put_xprt; } rc = lower_transport->xprt_err;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 817/826 sunrpc: fix one UAF issue caused by sunrpc kernel tcp socket
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Liu Jian <[email protected]>
[ Upstream commit 3f23f96528e8fcf8619895c4c916c52653892ec1 ]
BUG: KASAN: slab-use-after-free in tcp_write_timer_handler+0x156/0x3e0 Read of size 1 at addr ffff888111f322cd by task swapper/0/0 CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 6.12.0-rc4-dirty #7 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 Call Trace: <IRQ> dump_stack_lvl+0x68/0xa0 print_address_description.constprop.0+0x2c/0x3d0 print_report+0xb4/0x270 kasan_report+0xbd/0xf0 tcp_write_timer_handler+0x156/0x3e0 tcp_write_timer+0x66/0x170 call_timer_fn+0xfb/0x1d0 __run_timers+0x3f8/0x480 run_timer_softirq+0x9b/0x100 handle_softirqs+0x153/0x390 __irq_exit_rcu+0x103/0x120 irq_exit_rcu+0xe/0x20 sysvec_apic_timer_interrupt+0x76/0x90 </IRQ> <TASK> asm_sysvec_apic_timer_interrupt+0x1a/0x20 RIP: 0010:default_idle+0xf/0x20 Code: 4c 01 c7 4c 29 c2 e9 72 ff ff ff 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 f3 0f 1e fa 66 90 0f 00 2d 33 f8 25 00 fb f4 <fa> c3 cc cc cc cc 66 66 2e 0f 1f 84 00 00 00 00 00 90 90 90 90 90 RSP: 0018:ffffffffa2007e28 EFLAGS: 00000242 RAX: 00000000000f3b31 RBX: 1ffffffff4400fc7 RCX: ffffffffa09c3196 RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffffff9f00590f RBP: 0000000000000000 R08: 0000000000000001 R09: ffffed102360835d R10: ffff88811b041aeb R11: 0000000000000001 R12: 0000000000000000 R13: ffffffffa202d7c0 R14: 0000000000000000 R15: 00000000000147d0 default_idle_call+0x6b/0xa0 cpuidle_idle_call+0x1af/0x1f0 do_idle+0xbc/0x130 cpu_startup_entry+0x33/0x40 rest_init+0x11f/0x210 start_kernel+0x39a/0x420 x86_64_start_reservations+0x18/0x30 x86_64_start_kernel+0x97/0xa0 common_startup_64+0x13e/0x141 </TASK> Allocated by task 595: kasan_save_stack+0x24/0x50 kasan_save_track+0x14/0x30 __kasan_slab_alloc+0x87/0x90 kmem_cache_alloc_noprof+0x12b/0x3f0 copy_net_ns+0x94/0x380 create_new_namespaces+0x24c/0x500 unshare_nsproxy_namespaces+0x75/0xf0 ksys_unshare+0x24e/0x4f0 __x64_sys_unshare+0x1f/0x30 do_syscall_64+0x70/0x180 entry_SYSCALL_64_after_hwframe+0x76/0x7e Freed by task 100: kasan_save_stack+0x24/0x50 kasan_save_track+0x14/0x30 kasan_save_free_info+0x3b/0x60 __kasan_slab_free+0x54/0x70 kmem_cache_free+0x156/0x5d0 cleanup_net+0x5d3/0x670 process_one_work+0x776/0xa90 worker_thread+0x2e2/0x560 kthread+0x1a8/0x1f0 ret_from_fork+0x34/0x60 ret_from_fork_asm+0x1a/0x30
Reproduction script:
mkdir -p /mnt/nfsshare
mkdir -p /mnt/nfs/netns_1
mkfs.ext4 /dev/sdb
mount /dev/sdb /mnt/nfsshare
systemctl restart nfs-server
chmod 777 /mnt/nfsshare
exportfs -i -o rw,no_root_squash *:/mnt/nfsshare
ip netns add netns_1
ip link add name veth_1_peer type veth peer veth_1 ifconfig veth_1_peer 11.11.0.254 up
ip link set veth_1 netns netns_1
ip netns exec netns_1 ifconfig veth_1 11.11.0.1
ip netns exec netns_1 /root/iptables -A OUTPUT -d 11.11.0.254 -p tcp \
--tcp-flags FIN FIN -j DROP
(note: In my environment, a DESTROY_CLIENTID operation is always sent
immediately, breaking the nfs tcp connection.)
ip netns exec netns_1 timeout -s 9 300 mount -t nfs -o proto=tcp,vers=4.1 \ 11.11.0.254:/mnt/nfsshare /mnt/nfs/netns_1
ip netns del netns_1
The reason here is that the tcp socket in netns_1 (nfs side) has been shutdown and closed (done in xs_destroy), but the FIN message (with ack) is discarded, and the nfsd side keeps sending retransmission messages. As a result, when the tcp sock in netns_1 processes the received message, it sends the message (FIN message) in the sending queue, and the tcp timer is re-established. When the network namespace is deleted, the net structure accessed by tcp's timer handler function causes problems.
To fix this problem, let's hold netns refcnt for the tcp kernel socket as done in other modules. This is an ugly hack which can easily be backported to earlier kernels. A proper fix which cleans up the interfaces will follow, but may not be so easy to backport.
--- net/sunrpc/svcsock.c | 4 ++++ net/sunrpc/xprtsock.c | 7 +++++++ 2 files changed, 11 insertions(+)
net/sunrpc/svcsock.c +4 -0
@@ -1551,6 +1551,10 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv, newlen = error;if (protocol ==IPPROTO_TCP ) { +__netns_tracker_free (net, &sock->sk->ns_tracker, false); + sock->sk->sk_net_refcnt =1 ; +get_net_track (net, &sock->sk->ns_tracker,GFP_KERNEL ); +sock_inuse_add (net,1 );if ((error =kernel_listen (sock,64 )) <0 ) goto bummer; }
net/sunrpc/xprtsock.c +7 -0
@@ -1940,6 +1940,13 @@ static struct socket *xs_create_sock(struct rpc_xprt *xprt, goto out; } +if (protocol ==IPPROTO_TCP ) { +__netns_tracker_free (xprt->xprt_net, &sock->sk->ns_tracker, false); + sock->sk->sk_net_refcnt =1 ; +get_net_track (xprt->xprt_net, &sock->sk->ns_tracker,GFP_KERNEL ); +sock_inuse_add (xprt->xprt_net,1 ); + } + filp =sock_alloc_file (sock,O_NONBLOCK ,NULL );if (IS_ERR (filp))return ERR_CAST (filp);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 818/826 nfs/blocklayout: Dont attempt unregister for invalid block device
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Coddington <[email protected]>
[ Upstream commit 3a4ce14d9a6b868e0787e4582420b721c04ee41e ]
Since commit d869da91cccb ("nfs/blocklayout: Fix premature PR key unregistration") an unmount of a pNFS SCSI layout-enabled NFS may dereference a NULL block_device in:
bl_unregister_scsi+0x16/0xe0 [blocklayoutdriver] bl_free_device+0x70/0x80 [blocklayoutdriver] bl_free_deviceid_node+0x12/0x30 [blocklayoutdriver] nfs4_put_deviceid_node+0x60/0xc0 [nfsv4] nfs4_deviceid_purge_client+0x132/0x190 [nfsv4] unset_pnfs_layoutdriver+0x59/0x60 [nfsv4] nfs4_destroy_server+0x36/0x70 [nfsv4] nfs_free_server+0x23/0xe0 [nfs] deactivate_locked_super+0x30/0xb0 cleanup_mnt+0xba/0x150 task_work_run+0x59/0x90 syscall_exit_to_user_mode+0x217/0x220 do_syscall_64+0x8e/0x160
This happens because even though we were able to create the nfs4_deviceid_node, the lookup for the device was unable to attach the block device to the pnfs_block_dev.
If we never found a block device to register, we can avoid this case with the PNFS_BDEV_REGISTERED flag. Move the deref behind the test for the flag.
--- fs/nfs/blocklayout/dev.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
fs/nfs/blocklayout/dev.c +2 -4
@@ -20,9 +20,6 @@ static void bl_unregister_scsi(struct pnfs_block_dev *dev)const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;int status; -if (!test_and_clear_bit (PNFS_BDEV_REGISTERED , &dev->flags)) -return ; - status = ops->pr_register (bdev, dev->pr_key,0 , false);if (status)trace_bl_pr_key_unreg_err (bdev, dev->pr_key, status);
@@ -58,7 +55,8 @@ static void bl_unregister_dev(struct pnfs_block_dev *dev)return ; } -if (dev->type ==PNFS_BLOCK_VOLUME_SCSI ) +if (dev->type ==PNFS_BLOCK_VOLUME_SCSI && +test_and_clear_bit (PNFS_BDEV_REGISTERED , &dev->flags))bl_unregister_scsi (dev); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 819/826 nfs/blocklayout: Limit repeat device registration on failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Coddington <[email protected]>
[ Upstream commit 614733f9441ed53bb442d4734112ec1e24bd6da7 ]
Every pNFS SCSI IO wants to do LAYOUTGET, then within the layout find the device which can drive GETDEVINFO, then finally may need to prep the device with a reservation. This slow work makes a mess of IO latencies if one of the later steps is going to fail for awhile.
If we're unable to register a SCSI device, ensure we mark the device as unavailable so that it will timeout and be re-added via GETDEVINFO. This avoids repeated doomed attempts to register a device in the IO path.
Add some clarifying comments as well.
--- fs/nfs/blocklayout/blocklayout.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
fs/nfs/blocklayout/blocklayout.c +14 -1
@@ -571,19 +571,32 @@ bl_find_get_deviceid(struct nfs_server *server,if (!node)return ERR_PTR (-ENODEV ); +/* +* Devices that are marked unavailable are left in the cache with a +* timeout to avoid sending GETDEVINFO after every LAYOUTGET, or +* constantly attempting to register the device. Once marked as +* unavailable they must be deleted and never reused. +*/ if (test_bit (NFS_DEVICEID_UNAVAILABLE , &node->flags)) {unsigned long end = jiffies;unsigned long start = end -PNFS_DEVICE_RETRY_TIMEOUT ;if (!time_in_range (node->timestamp_unavailable, start, end)) { +/* Uncork subsequent GETDEVINFO operations for this device */ nfs4_delete_deviceid (node->ld, node->nfs_client, id); goto retry; } goto out_put; } - if (!bl_register_dev(container_of(node, struct pnfs_block_dev, node))) + if (!bl_register_dev(container_of(node, struct pnfs_block_dev, node))) { +/* +* If we cannot register, treat this device as transient: +* Make a negative cache entry for the device +*/ +nfs4_mark_deviceid_unavailable (node); goto out_put; + }return node;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 820/826 block, bfq: fix bfqq uaf in bfq_limit_depth()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yu Kuai <[email protected]>
[ Upstream commit e8b8344de3980709080d86c157d24e7de07d70ad ]
Set new allocated bfqq to bic or remove freed bfqq from bic are both protected by bfqd->lock, however bfq_limit_depth() is deferencing bfqq from bic without the lock, this can lead to UAF if the io_context is shared by multiple tasks.
For example, test bfq with io_uring can trigger following UAF in v6.6:
==================================================================
BUG: KASAN: slab-use-after-free in bfqq_group+0x15/0x50 Call Trace: <TASK> dump_stack_lvl+0x47/0x80 print_address_description.constprop.0+0x66/0x300 print_report+0x3e/0x70 kasan_report+0xb4/0xf0 bfqq_group+0x15/0x50 bfqq_request_over_limit+0x130/0x9a0 bfq_limit_depth+0x1b5/0x480 __blk_mq_alloc_requests+0x2b5/0xa00 blk_mq_get_new_requests+0x11d/0x1d0 blk_mq_submit_bio+0x286/0xb00 submit_bio_noacct_nocheck+0x331/0x400 __block_write_full_folio+0x3d0/0x640 writepage_cb+0x3b/0xc0 write_cache_pages+0x254/0x6c0 write_cache_pages+0x254/0x6c0 do_writepages+0x192/0x310 filemap_fdatawrite_wbc+0x95/0xc0 __filemap_fdatawrite_range+0x99/0xd0 filemap_write_and_wait_range.part.0+0x4d/0xa0 blkdev_read_iter+0xef/0x1e0 io_read+0x1b6/0x8a0 io_issue_sqe+0x87/0x300 io_wq_submit_work+0xeb/0x390 io_worker_handle_work+0x24d/0x550 io_wq_worker+0x27f/0x6c0 ret_from_fork_asm+0x1b/0x30 </TASK> Allocated by task 808602: kasan_save_stack+0x1e/0x40 kasan_set_track+0x21/0x30 __kasan_slab_alloc+0x83/0x90 kmem_cache_alloc_node+0x1b1/0x6d0 bfq_get_queue+0x138/0xfa0 bfq_get_bfqq_handle_split+0xe3/0x2c0 bfq_init_rq+0x196/0xbb0 bfq_insert_request.isra.0+0xb5/0x480 bfq_insert_requests+0x156/0x180 blk_mq_insert_request+0x15d/0x440 blk_mq_submit_bio+0x8a4/0xb00 submit_bio_noacct_nocheck+0x331/0x400 __blkdev_direct_IO_async+0x2dd/0x330 blkdev_write_iter+0x39a/0x450 io_write+0x22a/0x840 io_issue_sqe+0x87/0x300 io_wq_submit_work+0xeb/0x390 io_worker_handle_work+0x24d/0x550 io_wq_worker+0x27f/0x6c0 ret_from_fork+0x2d/0x50 ret_from_fork_asm+0x1b/0x30 Freed by task 808589: kasan_save_stack+0x1e/0x40 kasan_set_track+0x21/0x30 kasan_save_free_info+0x27/0x40 __kasan_slab_free+0x126/0x1b0 kmem_cache_free+0x10c/0x750 bfq_put_queue+0x2dd/0x770 __bfq_insert_request.isra.0+0x155/0x7a0 bfq_insert_request.isra.0+0x122/0x480 bfq_insert_requests+0x156/0x180 blk_mq_dispatch_plug_list+0x528/0x7e0 blk_mq_flush_plug_list.part.0+0xe5/0x590 __blk_flush_plug+0x3b/0x90 blk_finish_plug+0x40/0x60 do_writepages+0x19d/0x310 filemap_fdatawrite_wbc+0x95/0xc0 __filemap_fdatawrite_range+0x99/0xd0 filemap_write_and_wait_range.part.0+0x4d/0xa0 blkdev_read_iter+0xef/0x1e0 io_read+0x1b6/0x8a0 io_issue_sqe+0x87/0x300 io_wq_submit_work+0xeb/0x390 io_worker_handle_work+0x24d/0x550 io_wq_worker+0x27f/0x6c0 ret_from_fork+0x2d/0x50 ret_from_fork_asm+0x1b/0x30
Fix the problem by protecting bic_to_bfqq() with bfqd->lock.
--- block/bfq-iosched.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-)
block/bfq-iosched.c +24 -13
@@ -582,23 +582,31 @@ static struct request *bfq_choose_req(struct bfq_data *bfqd,#define BFQ_LIMIT_INLINE_DEPTH 16#ifdef CONFIG_BFQ_GROUP_IOSCHED -static bool bfqq_request_over_limit (struct bfq_queue *bfqq,int limit) +static bool bfqq_request_over_limit (struct bfq_data *bfqd, +struct bfq_io_cq *bic,blk_opf_t opf, +unsigned int act_idx,int limit) { -struct bfq_data *bfqd = bfqq->bfqd; -struct bfq_entity *entity = &bfqq->entity;struct bfq_entity *inline_entities[BFQ_LIMIT_INLINE_DEPTH ];struct bfq_entity **entities = inline_entities; -int depth, level, alloc_depth =BFQ_LIMIT_INLINE_DEPTH ; -int class_idx = bfqq->ioprio_class -1 ; +int alloc_depth =BFQ_LIMIT_INLINE_DEPTH ;struct bfq_sched_data *sched_data; +struct bfq_entity *entity; +struct bfq_queue *bfqq;unsigned long wsum;bool ret = false; - -if (!entity->on_st_or_in_serv) -return false; +int depth; +int level; retry:spin_lock_irq (&bfqd->lock); + bfqq =bic_to_bfqq (bic,op_is_sync (opf), act_idx); +if (!bfqq) + goto out; + + entity = &bfqq->entity; +if (!entity->on_st_or_in_serv) + goto out; +/* +1 for bfqq entity, root cgroup not included */ depth =bfqg_to_blkg (bfqq_group (bfqq))->blkcg->css.cgroup->level +1 ;if (depth > alloc_depth) {
@@ -643,7 +651,7 @@ static bool bfqq_request_over_limit(struct bfq_queue *bfqq, int limit)* class. */ wsum =0 ; -for (i =0 ; i <= class_idx; i++) { +for (i =0 ; i <= bfqq->ioprio_class -1 ; i++) { wsum = wsum *IOPRIO_BE_NR + sched_data->service_tree[i].wsum; }
@@ -666,7 +674,9 @@ static bool bfqq_request_over_limit(struct bfq_queue *bfqq, int limit) return ret; }#else -static bool bfqq_request_over_limit (struct bfq_queue *bfqq,int limit) +static bool bfqq_request_over_limit (struct bfq_data *bfqd, +struct bfq_io_cq *bic,blk_opf_t opf, +unsigned int act_idx,int limit) {return false; }
@@ -704,8 +714,9 @@ static void bfq_limit_depth(blk_opf_t opf, struct blk_mq_alloc_data *data) }for (act_idx =0 ; bic && act_idx < bfqd->num_actuators; act_idx++) { -struct bfq_queue *bfqq = -bic_to_bfqq (bic,op_is_sync (opf), act_idx); +/* Fast path to check if bfqq is already allocated. */ +if (!bic_to_bfqq (bic,op_is_sync (opf), act_idx)) +continue ;/* * Does queue (or any parent entity) exceed number of
@@ -713,7 +724,7 @@ static void bfq_limit_depth(blk_opf_t opf, struct blk_mq_alloc_data *data)* limit depth so that it cannot consume more * available requests and thus starve other entities. */ -if (bfqq &&bfqq_request_over_limit (bfqq, limit)) { +if (bfqq_request_over_limit (bfqd, bic, opf, act_idx, limit)) { depth =1 ;break ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 821/826 brd: decrease the number of allocated pages which discarded
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Xianwei <[email protected]>
[ Upstream commit 82734209bedd65a8b508844bab652b464379bfdd ]
The number of allocated pages which discarded will not decrease. Fix it.
--- drivers/block/brd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/block/brd.c +3 -1
@@ -231,8 +231,10 @@ static void brd_do_discard(struct brd_device *brd, sector_t sector, u32 size)xa_lock (&brd->brd_pages);while (size >=PAGE_SIZE && aligned_sector < rd_size *2 ) { page =__xa_erase (&brd->brd_pages, aligned_sector >>PAGE_SECTORS_SHIFT ); -if (page) +if (page) {__free_page (page); + brd->brd_nr_pages--; + } aligned_sector +=PAGE_SECTORS ; size -=PAGE_SIZE ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 822/826 sh: intc: Fix use-after-free bug in register_intc_controller()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit 63e72e551942642c48456a4134975136cdcb9b3c ]
In the error handling for this function, d is freed without ever removing it from intc_list which would lead to a use after free. To fix this, let's only add it to the list after everything has succeeded.
--- drivers/sh/intc/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/sh/intc/core.c +1 -1
@@ -209,7 +209,6 @@ int __init register_intc_controller(struct intc_desc *desc) goto err0;INIT_LIST_HEAD (&d->list); -list_add_tail (&d->list, &intc_list);raw_spin_lock_init (&d->lock);INIT_RADIX_TREE (&d->tree,GFP_ATOMIC );
@@ -369,6 +368,7 @@ int __init register_intc_controller(struct intc_desc *desc) d->skip_suspend = desc->skip_syscore_suspend; +list_add_tail (&d->list, &intc_list); nr_intc_controllers++;return 0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 823/826 tools/power turbostat: Fix trailing \n parsing
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Rui <[email protected]>
[ Upstream commit fed8511cc8996989178823052dc0200643e1389a ]
parse_cpu_string() parses the string input either from command line or from /sys/fs/cgroup/cpuset.cpus.effective to get a list of CPUs that turbostat can run with.
The cpu string returned by /sys/fs/cgroup/cpuset.cpus.effective contains a trailing '\n', but strtoul() fails to treat this as an error.
That says, for the code below
val = ("\n", NULL, 10);val returns 0, and errno is also not set.
As a result, CPU0 is erroneously considered as allowed CPU and this causes failures when turbostat tries to run on CPU0.
get_counters: Could not migrate to CPU 0
...
turbostat: re-initialized with num_cpus 8, allowed_cpus 5
get_counters: Could not migrate to CPU 0
Add a check to return immediately if '\n' or '\0' is detected.
--- tools/power/x86/turbostat/turbostat.c | 3 +++ 1 file changed, 3 insertions(+)
tools/power/x86/turbostat/turbostat.c +3 -0
@@ -5385,6 +5385,9 @@ static int parse_cpu_str(char *cpu_str, cpu_set_t *cpu_set, int cpu_set_size)if (*next =='-' )/* no negative cpu numbers */ return 1 ; +if (*next =='\0' || *next =='\n' ) +break ; + start =strtoul (next, &next,10 );if (start >=CPU_SUBSET_MAXCPUS )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 824/826 tools/power turbostat: Fix childs argument forwarding
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Patryk Wlazlyn <[email protected]>
[ Upstream commit 1da0daf746342dfdc114e4dc8fbf3ece28666d4f ]
Add '+' to optstring when early scanning for --no-msr and --no-perf. It causes option processing to stop as soon as a nonoption argument is encountered, effectively skipping child's arguments.
--- tools/power/x86/turbostat/turbostat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/power/x86/turbostat/turbostat.c +1 -1
@@ -9784,7 +9784,7 @@ void cmdline(int argc, char **argv)* Parse some options early, because they may make other options invalid, * like adding the MSR counter with --add and at the same time using --no-msr. */ -while ((opt =getopt_long_only (argc, argv,"MPn:" , long_options, &option_index)) !=-1 ) { +while ((opt =getopt_long_only (argc, argv,"+MPn:" , long_options, &option_index)) !=-1 ) {switch (opt) {case 'M' : no_msr =1 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 825/826 block: always verify unfreeze lock on the owner task
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Lei <[email protected]>
commit 6a78699838a0ddeed3620ddf50c1521f1fe1e811 upstream.
commit f1be1788a32e ("block: model freeze & enter queue as lock for supporting lockdep") tries to apply lockdep for verifying freeze & unfreeze. However, the verification is only done the outmost freeze and unfreeze. This way is actually not correct because q->mq_freeze_depth still may drop to zero on other task instead of the freeze owner task.
Fix this issue by always verifying the last unfreeze lock on the owner task context, and make sure both the outmost freeze & unfreeze are verified in the current task.
--- block/blk-core.c | 2 - block/blk-mq.c | 62 ++++++++++++++++++++++++++++++++++++++++++------- block/blk.h | 3 +- include/linux/blkdev.h | 4 +++ 4 files changed, 61 insertions(+), 10 deletions(-)
block/blk-core.c +1 -1
@@ -287,7 +287,7 @@ bool blk_queue_start_drain(struct reques* entering queue, so we call blk_freeze_queue_start() to * prevent I/O from crossing blk_queue_enter(). */ -bool freeze =__blk_freeze_queue_start (q); +bool freeze =__blk_freeze_queue_start (q, current);if (queue_is_mq (q))blk_mq_wake_waiters (q);/* Make blk_queue_enter() reexamine the DYING flag. */
block/blk-mq.c +54 -8
103 lines not on this page · raw message
block/blk.h +2 -1
@@ -38,7 +38,8 @@ void blk_free_flush_queue(struct blk_fluvoid blk_freeze_queue (struct request_queue *q);bool __blk_mq_unfreeze_queue (struct request_queue *q,bool force_atomic);bool blk_queue_start_drain (struct request_queue *q); -bool __blk_freeze_queue_start (struct request_queue *q); +bool __blk_freeze_queue_start (struct request_queue *q, +struct task_struct *owner);int __bio_queue_enter (struct request_queue *q,struct bio *bio);void submit_bio_noacct_nocheck (struct bio *bio);void bio_await_chain (struct bio *bio);
include/linux/blkdev.h +4 -0
@@ -572,6 +572,10 @@ struct request_queue {struct throtl_data *td;#endif struct rcu_head rcu_head; +#ifdef CONFIG_LOCKDEP +struct task_struct *mq_freeze_owner; +int mq_freeze_owner_depth; +#endif wait_queue_head_t mq_freeze_wq;/* * Protect concurrent access to q_usage_counter by
Greg Kroah-Hartman
maintainerPATCH 826/826 block: dont verify IO lock for freeze/unfreeze in elevator_init_mq()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Lei <[email protected]>
commit 357e1b7f730bd85a383e7afa75a3caba329c5707 upstream.
elevator_init_mq() is only called at the entry of add_disk_fwnode() when disk IO isn't allowed yet.
So not verify io lock(q->io_lockdep_map) for freeze & unfreeze in elevator_init_mq().
--- block/elevator.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
block/elevator.c +8 -2
@@ -598,13 +598,19 @@ void elevator_init_mq(struct request_que* drain any dispatch activities originated from passthrough * requests, then no need to quiesce queue which may add long boot * latency, especially when lots of disks are involved. +* +* Disk isn't added yet, so verifying queue lock only manually. */ -blk_mq_freeze_queue (q); +blk_freeze_queue_start_non_owner (q); +blk_freeze_acquire_lock (q, true, false); +blk_mq_freeze_queue_wait (q); +blk_mq_cancel_work_sync (q); err =blk_mq_init_sched (q, e); -blk_mq_unfreeze_queue (q); +blk_unfreeze_release_lock (q, true, false); +blk_mq_unfreeze_queue_non_owner (q);if (err) { pr_warn("\"%s\" elevator initialization failed, "
Am 03.12.2024 um 15:35 schrieb Greg Kroah-Hartman:
Quoted 4 lines
This is the start of the stable review cycle for the 6.12.2 release. There are 826 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Builds, boots and works on my 2-socket Ivy Bridge Xeon E5-2697 v2 server. No dmesg oddities or regressions found.
Beste Grüße,
Peter Schneider
Signature · 8 lines
Climb the mountain not to plant your flag, but to embrace the challenge, enjoy the air and behold the view. Climb it so you can see the world, not so the world can see you. -- David McCullough Jr. OpenPGP: 0xA3828BD796CCE11A8CADE8866E3A92C92C3FF244 Download: https://www.peters-netzplatz.de/download/pschneider1968_pub.asc https://keys.mailvelope.com/pks/lookup?op=get&[email protected] https://keys.mailvelope.com/pks/lookup?op=get&[email protected]
Quoted 4 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.12.2 release. There are 826 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.12.2 release. There are 826 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 05 Dec 2024 14:45:11 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.2-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.12.y
and the diffstat can be found below.thanks,
greg k-h
Same build issue as the one reported for perf on 6.11.11-rc1:
util/stat-display.c: In function 'uniquify_event_name':util/stat-display.c:895:45: error: 'struct evsel' has no member named 'alternate_hw_config'
895 | if (counter->pmu->is_core &&counter->alternate_hw_config != PERF_COUNT_HW_MAX)
| ^~
caused by 629f9fa8142105b4cb07e9b4d4452dab0ca40914 ("perf stat: Uniquify event name improvements")
Signature · 1 line
Florian
Hello,
Quoted 7 lines · On Tue, 3 Dec 2024 15:35:27 +0100 Greg Kroah-Hartman…
This is the start of the stable review cycle for the 6.12.2 release. There are 826 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 05 Dec 2024 14:45:11 +0000. Anything received after that time might be too late.
This rc kernel passes DAMON functionality test[1] on my test machine. Attaching the test results summary below. Please note that I retrieved the kernel from linux-stable-rc tree[2].
[1] https://github.com/damonitor/damon-tests/tree/next/corr
[2] 1b3321bcbfba ("Linux 6.12.2-rc1")
Thanks,
SJ
[...]
---
ok 9 selftests: damon: damos_tried_regions.py
ok 10 selftests: damon: damon_nr_regions.py
ok 11 selftests: damon: reclaim.sh
ok 12 selftests: damon: lru_sort.sh
ok 13 selftests: damon: debugfs_empty_targets.sh
ok 14 selftests: damon: debugfs_huge_count_read_write.sh
ok 15 selftests: damon: debugfs_duplicate_context_creation.sh ok 16 selftests: damon: debugfs_rm_non_contexts.sh
ok 17 selftests: damon: debugfs_target_ids_read_before_terminate_race.sh ok 18 selftests: damon: debugfs_target_ids_pid_leak.sh
ok 19 selftests: damon: sysfs_update_removed_scheme_dir.sh
ok 20 selftests: damon: sysfs_update_schemes_tried_regions_hang.py ok 1 selftests: damon-tests: kunit.sh
ok 2 selftests: damon-tests: huge_count_read_write.sh
ok 3 selftests: damon-tests: buffer_overflow.sh
ok 4 selftests: damon-tests: rm_contexts.sh
ok 5 selftests: damon-tests: record_null_deref.sh
ok 6 selftests: damon-tests: dbgfs_target_ids_read_before_terminate_race.sh ok 7 selftests: damon-tests: dbgfs_target_ids_pid_leak.sh
ok 8 selftests: damon-tests: damo_tests.sh
ok 9 selftests: damon-tests: masim-record.sh
ok 10 selftests: damon-tests: build_i386.sh
ok 11 selftests: damon-tests: build_arm64.sh # SKIP
ok 12 selftests: damon-tests: build_m68k.sh # SKIP
ok 13 selftests: damon-tests: build_i386_idle_flag.sh
ok 14 selftests: damon-tests: build_i386_highpte.sh
ok 15 selftests: damon-tests: build_nomemcg.sh
[33m
[92mPASS [39m
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.12.2 release. There are 826 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 05 Dec 2024 14:45:11 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.2-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.12.y
and the diffstat can be found below.thanks,
greg k-h
Built and booted successfully on RISC-V RV64 (HiFive Unmatched).
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.12.2 release. There are 826 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 05 Dec 2024 14:45:11 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.2-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.12.y
and the diffstat can be found below.thanks,
greg k-h
Results from Linaro’s test farm.
Regressions on arm64, arm, x86_64 riscv and powerpc.
1) The allmodconfig builds failed on arm64, arm, riscv and x86_64 due to following build warnings / errors.
Build errors for allmodconfig:
--------------drivers/gpu/drm/imx/ipuv3/parallel-display.c:75:3: error: variable 'num_modes' is uninitialized when used here [-Werror,-Wuninitialized]
75 | num_modes++;
| ^~~~~~~~~
drivers/gpu/drm/imx/ipuv3/parallel-display.c:55:15: note: initialize
the variable 'num_modes' to silence this warning
55 | int num_modes;
| ^
| = 01 error generated.
make[8]: *** [scripts/Makefile.build:229:drivers/gpu/drm/imx/ipuv3/parallel-display.o] Error 1 drivers/gpu/drm/imx/ipuv3/imx-ldb.c:143:3: error: variable 'num_modes' is uninitialized when used here [-Werror,-Wuninitialized]
143 | num_modes++;
| ^~~~~~~~~
drivers/gpu/drm/imx/ipuv3/imx-ldb.c:133:15: note: initialize the
variable 'num_modes' to silence this warning
133 | int num_modes;
| ^
| = 01 error generated.
2) The powerpc builds failed due to this build warnings / errors.
ERROR: modpost: "gcm_update"
[arch/powerpc/crypto/aes-gcm-p10-crypto.ko] undefined!
3) As other reported perf build failures util/stat-display.c: In function 'uniquify_event_name':
util/stat-display.c:895:45: error: 'struct evsel' has no member
named 'alternate_hw_config'
895 | if (counter->pmu->is_core &&
counter->alternate_hw_config != PERF_COUNT_HW_MAX)
| ^~
Build errors:
---------------
ERROR: modpost: "gcm_update" [arch/powerpc/crypto/aes-gcm-p10-crypto.ko] undefined!
## Build
* kernel: 6.12.2-rc1
* git: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
* git commit: 1b3321bcbfba89474cbae3673f3dac9c456ce4b9
* git describe: v6.12.1-827-g1b3321bcbfba
* test details:
https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-6.12.y/build/v6.12.1-827-g1b3321bcbfba
## Test Regressions (compared to v6.12-4-g11741096a22c)
* arm, build
- gcc-13-lkftconfig-perf
* arm64, build
- clang-19-allmodconfig
- gcc-13-lkftconfig-perf
* powerpc, build
- clang-19-defconfig
- clang-nightly-defconfig
- clang-nightly-lkftconfig-hardening
- clang-nightly-lkftconfig-lto-full
- clang-nightly-lkftconfig-lto-thing
- gcc-13-defconfig
- gcc-13-lkftconfig-hardening
- gcc-8-defconfig
- gcc-8-lkftconfig-hardening
- korg-clang-19-lkftconfig-hardening
- korg-clang-19-lkftconfig-lto-full
- korg-clang-19-lkftconfig-lto-thing
* riscv, build
- clang-19-allmodconfig
* x86_64, build
- clang-19-allmodconfig
- gcc-13-lkftconfig-perf
## Metric Regressions (compared to v6.12-4-g11741096a22c)
## Test Fixes (compared to v6.12-4-g11741096a22c)
## Metric Fixes (compared to v6.12-4-g11741096a22c)
## Test result summary
total: 157764, pass: 129957, fail: 2971, skip: 24836, xfail: 0
## Build Summary
* arc: 5 total, 5 passed, 0 failed
* arm: 138 total, 135 passed, 3 failed
* arm64: 52 total, 50 passed, 2 failed
* i386: 18 total, 17 passed, 1 failed
* mips: 34 total, 33 passed, 1 failed
* parisc: 4 total, 3 passed, 1 failed
* powerpc: 40 total, 27 passed, 13 failed
* riscv: 24 total, 22 passed, 2 failed
* s390: 22 total, 21 passed, 1 failed
* sh: 5 total, 5 passed, 0 failed
* sparc: 4 total, 3 passed, 1 failed
* x86_64: 44 total, 42 passed, 2 failed
## Test suites summary
* boot
* commands
* kselftest-arm64
* kselftest-breakpoints
* kselftest-capabilities
* kselftest-cgroup
* kselftest-clone3
* kselftest-core
* kselftest-cpu-hotplug
* kselftest-cpufreq
* kselftest-efivarfs
* kselftest-exec
* kselftest-filesystems
* kselftest-filesystems-binderfs
* kselftest-filesystems-epoll
* kselftest-firmware
* kselftest-fpu
* kselftest-ftrace
* kselftest-futex
* kselftest-gpio
* kselftest-intel_pstate
* kselftest-ipc
* kselftest-kcmp
* kselftest-kvm
* kselftest-livepatch
* kselftest-membarrier
* kselftest-memfd
* kselftest-mincore
* kselftest-mqueue
* kselftest-net
* kselftest-net-mptcp
* kselftest-openat2
* kselftest-ptrace
* kselftest-rseq
* kselftest-rtc
* kselftest-rust
* kselftest-seccomp
* kselftest-sigaltstack
* kselftest-size
* kselftest-tc-testing
* kselftest-timers
* kselftest-tmpfs
* kselftest-tpm2
* kselftest-user_events
* kselftest-vDSO
* kselftest-watchdog
* kselftest-x86
* kunit
* kvm-unit-tests
* libgpiod
* libhugetlbfs
* log-parser-boot
* log-parser-test
* ltp-commands
* ltp-containers
* ltp-controllers
* ltp-cpuhotplug
* ltp-crypto
* ltp-cve
* ltp-dio
* ltp-fcntl-locktests
* ltp-fs
* ltp-fs_bind
* ltp-fs_perms_simple
* ltp-hugetlb
* ltp-ipc
* ltp-math
* ltp-mm
* ltp-nptl
* ltp-pty
* ltp-sched
* ltp-smoke
* ltp-syscalls
* ltp-tracing
* rcutorture
--
Linaro LKFT
https://lkft.linaro.org
Quoted 7 lines · Naresh Kamboju
Quoted 5 lines · Greg Kroah-Hartman
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.2-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.12.y
and the diffstat can be found below
...
Quoted 14 lines
1) The allmodconfig builds failed on arm64, arm, riscv and
x86_64due to following build warnings / errors.Build errors for allmodconfig:
--------------drivers/gpu/drm/imx/ipuv3/parallel-display.c:75:3: error: variable 'num_modes' is uninitialized when used here [-Werror,-Wuninitialized]75 | num_modes++; | ^~~~~~~~~ drivers/gpu/drm/imx/ipuv3/parallel-display.c:55:15: note: initialize the variable 'num_modes' to silence this warning 55 | int num_modes; | ^ | = 0
Quoted 3 lines
1 error generated.
make[8]: *** [scripts/Makefile.build:229:drivers/gpu/drm/imx/ipuv3/parallel-display.o] Error 1
Introduced by backporting commit 5f6e56d3319d ("drm/imx:
parallel-display: switch to drm_panel_bridge") without commit f94b9707a1c9 ("drm/imx: parallel-display: switch to imx_legacy_bridge / drm_bridge_connector"). The latter change also had a follow up fix in commit ef214002e6b3 ("drm/imx: parallel-display: add legacy bridge Kconfig dependency").
Quoted 10 lines
drivers/gpu/drm/imx/ipuv3/imx-ldb.c:143:3: error: variable 'num_modes' is uninitialized when used here [-Werror,-Wuninitialized]143 | num_modes++; | ^~~~~~~~~ drivers/gpu/drm/imx/ipuv3/imx-ldb.c:133:15: note: initialize the variable 'num_modes' to silence this warning 133 | int num_modes; | ^ | = 01 error generated.
Introduced by backporting commit 5c5843b20bbb ("drm/imx: ldb: switch to drm_panel_bridge") without commit 4c3d525f6573 ("drm/imx: ldb: switch to imx_legacy_bridge / drm_bridge_connector").
These are both upstream patch series bisectability issues, not anything that stable specifically did, as the num_nodes initialization was removed by the first change but the entire function containing num_nodes was removed by the second change so when the series was taken atomically upstream, nobody notices. However, I do wonder why these patches are being picked up, as they don't really read like fixes to me and the cover letter of the original series does not really make it seem like it either.
Cheers,
Nathan
Greg Kroah-Hartman
maintainerQuoted 49 lines · Nathan Chancellor
Quoted 7 lines · Naresh Kamboju
Quoted 5 lines · Greg Kroah-Hartman
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.2-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.12.y
and the diffstat can be found below...
Quoted 14 lines
1) The allmodconfig builds failed on arm64, arm, riscv and
x86_64due to following build warnings / errors.Build errors for allmodconfig:
--------------drivers/gpu/drm/imx/ipuv3/parallel-display.c:75:3: error: variable 'num_modes' is uninitialized when used here [-Werror,-Wuninitialized]75 | num_modes++; | ^~~~~~~~~ drivers/gpu/drm/imx/ipuv3/parallel-display.c:55:15: note: initialize the variable 'num_modes' to silence this warning 55 | int num_modes; | ^ | = 0Quoted 3 lines
1 error generated.
make[8]: *** [scripts/Makefile.build:229:drivers/gpu/drm/imx/ipuv3/parallel-display.o] Error 1Introduced by backporting commit
5f6e56d3319d("drm/imx:
parallel-display: switch todrm_panel_bridge") without commitf94b9707a1c9("drm/imx: parallel-display: switch toimx_legacy_bridge/drm_bridge_connector"). The latter change also had a follow up fix in commitef214002e6b3("drm/imx: parallel-display: add legacy bridgeKconfigdependency").Quoted 10 lines
drivers/gpu/drm/imx/ipuv3/imx-ldb.c:143:3: error: variable 'num_modes' is uninitialized when used here [-Werror,-Wuninitialized]143 | num_modes++; | ^~~~~~~~~ drivers/gpu/drm/imx/ipuv3/imx-ldb.c:133:15: note: initialize the variable 'num_modes' to silence this warning 133 | int num_modes; | ^ | = 01 error generated.
Introduced by backporting commit
5c5843b20bbb("drm/imx: ldb: switch todrm_panel_bridge") without commit4c3d525f6573("drm/imx: ldb: switch toimx_legacy_bridge/drm_bridge_connector").
Quoted 8 lines
These are both upstream patch series bisectability issues, not anything that stable specifically did, as the
num_nodesinitialization was removed by the first change but the entire function containingnum_nodeswas removed by the second change so when the series was taken atomically upstream, nobody notices. However, I do wonder why these patches are being picked up, as they don't really read like fixes to me and the cover letter of the original series does not really make it seem like it either.
Thanks, I'll just rip them both out now.
greg k-h
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.12.2 release. There are 826 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 05 Dec 2024 14:45:11 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.2-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.12.y
and the diffstat can be found below.thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah
Quoted 8 lines · On Tue, 03 Dec 2024 15:35:27 +0100 Greg Kroah-Hartman…
This is the start of the stable review cycle for the 6.12.2 release. There are 826 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 05 Dec 2024 14:45:11 +0000. Anything received after that time might be too late.
Boot-tested under QEMU for Rust x86_64, arm64 and riscv64; built-tested for loongarch64:
Thanks!
Cheers,
Miguel
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.12.2 release. There are 826 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 05 Dec 2024 14:45:11 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.2-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.12.y
and the diffstat can be found below.thanks,
greg k-h
OVERVIEW
Builds: 26 passed, 0 failed
Boot tests: 57 passed, 0 failed
CI systems: broonie, maestro
REVISION
Commit
name: v6.12.1-827-g1b3321bcbfba
hash: 1b3321bcbfba89474cbae3673f3dac9c456ce4b9
Checked out from
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.12.yBUILDS
No build failures found
BOOT TESTS
No boot failures found
See complete and up-to-date report at:
https://kcidb.kernelci.org/d/revision/revision?orgId=1&var-git_commit_hash=1b3321bcbfba89474cbae3673f3dac9c456ce4b9&var-patchset_hash=
Thanks,
KernelCI team
Hi!
Quoted 7 lines
This is the start of the stable review cycle for the 6.12.2 release. There are 826 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 05 Dec 2024 14:45:11 +0000. Anything received after that time might be too late.
CIP testing did not find any problems here:
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/tree/linux-6.12.y
6.11 passes our testing, too:
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/tree/linux-6.11.y
Best regards,
Pavel
Signature · 2 lines
DENX Software Engineering GmbH, Managing Director: Erika Unter HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Jon Hunter
maintainerQuoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.12.2 release. There are 826 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 05 Dec 2024 14:45:11 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.2-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.12.y
and the diffstat can be found below.thanks,
greg k-h
Failures detected for Tegra ...
Test results for stable-v6.12:
10 builds: 10 pass, 0 fail
26 boots: 26 pass, 0 fail
116 tests: 115 pass, 1 failLinux version: 6.12.2-rc1-g1b3321bcbfba
Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000,
tegra194-p2972-0000, tegra194-p3509-0000+p3668-0000,
tegra20-ventana, tegra210-p2371-2180,
tegra210-p3450-0000, tegra30-cardhu-a04Test failures: tegra186-p2771-0000: pm-system-suspend.sh
Jon
Quoted 26 lines · Jon Hunter
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.12.2 release. There are 826 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 05 Dec 2024 14:45:11 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.2-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.12.y
and the diffstat can be found below.thanks,
greg k-h
Failures detected for Tegra ...
Test results for stable-v6.12:
10 builds: 10 pass, 0 fail 26 boots: 26 pass, 0 fail 116 tests: 115 pass, 1 fail
Quoted 7 lines
Linux version: 6.12.2-rc1-g1b3321bcbfba
Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000,tegra194-p2972-0000, tegra194-p3509-0000+p3668-0000, tegra20-ventana, tegra210-p2371-2180, tegra210-p3450-0000, tegra30-cardhu-a04Test failures: tegra186-p2771-0000:
pm-system-suspend.sh
This is a known issue in the mainline that was not caught for Linux v6.12. It is intermittent and so not easily caught. The good news is that a fix [0] has been identified and once in mainline we can backport for stable. It is a networking issue that is causing random test failures when running with NFS.
With that for this update ...
Jon
[0] https://lore.kernel.org/netdev/[email protected]/
Signature · 1 line
nvpublic