diff --git a/debian/changelog b/debian/changelog index 42c385756..b316fff68 100644 --- a/debian/changelog +++ b/debian/changelog @@ -494,6 +494,11 @@ linux (4.15.17-1) UNRELEASED; urgency=medium [ Ben Hutchings ] * wireless: Disable regulatory.db direct loading (see #892229) * Bump ABI to 3 + * scsi: libsas: direct call probe and destruct (CVE-2017-18232) + * ext4: fail ext4_iget for root directory if unallocated (CVE-2018-1092) + * ext4: add validity checks for bitmap block numbers (CVE-2018-1093) + * ext4: always initialize the crc32c checksum driver (CVE-2018-1094) + * scsi: libsas: defer ata device eh commands to libata (CVE-2018-10021) [ Vagrant Cascadian ] * [armhf] Add patch to fix loading of imx6q-cpufreq module. diff --git a/debian/patches/bugfix/all/ext4-add-validity-checks-for-bitmap-block-numbers.patch b/debian/patches/bugfix/all/ext4-add-validity-checks-for-bitmap-block-numbers.patch new file mode 100644 index 000000000..049282ccf --- /dev/null +++ b/debian/patches/bugfix/all/ext4-add-validity-checks-for-bitmap-block-numbers.patch @@ -0,0 +1,96 @@ +From: Theodore Ts'o +Date: Mon, 26 Mar 2018 23:54:10 -0400 +Subject: ext4: add validity checks for bitmap block numbers +Origin: https://git.kernel.org/linus/7dac4a1726a9c64a517d595c40e95e2d0d135f6f +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2018-1093 + +An privileged attacker can cause a crash by mounting a crafted ext4 +image which triggers a out-of-bounds read in the function +ext4_valid_block_bitmap() in fs/ext4/balloc.c. + +This issue has been assigned CVE-2018-1093. + +BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=199181 +BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1560782 +Reported-by: Wen Xu +Signed-off-by: Theodore Ts'o +Cc: stable@vger.kernel.org +--- + fs/ext4/balloc.c | 16 ++++++++++++++-- + fs/ext4/ialloc.c | 7 +++++++ + 2 files changed, 21 insertions(+), 2 deletions(-) + +--- a/fs/ext4/balloc.c ++++ b/fs/ext4/balloc.c +@@ -340,20 +340,25 @@ static ext4_fsblk_t ext4_valid_block_bit + /* check whether block bitmap block number is set */ + blk = ext4_block_bitmap(sb, desc); + offset = blk - group_first_block; +- if (!ext4_test_bit(EXT4_B2C(sbi, offset), bh->b_data)) ++ if (offset < 0 || EXT4_B2C(sbi, offset) >= sb->s_blocksize || ++ !ext4_test_bit(EXT4_B2C(sbi, offset), bh->b_data)) + /* bad block bitmap */ + return blk; + + /* check whether the inode bitmap block number is set */ + blk = ext4_inode_bitmap(sb, desc); + offset = blk - group_first_block; +- if (!ext4_test_bit(EXT4_B2C(sbi, offset), bh->b_data)) ++ if (offset < 0 || EXT4_B2C(sbi, offset) >= sb->s_blocksize || ++ !ext4_test_bit(EXT4_B2C(sbi, offset), bh->b_data)) + /* bad block bitmap */ + return blk; + + /* check whether the inode table block number is set */ + blk = ext4_inode_table(sb, desc); + offset = blk - group_first_block; ++ if (offset < 0 || EXT4_B2C(sbi, offset) >= sb->s_blocksize || ++ EXT4_B2C(sbi, offset + sbi->s_itb_per_group) >= sb->s_blocksize) ++ return blk; + next_zero_bit = ext4_find_next_zero_bit(bh->b_data, + EXT4_B2C(sbi, offset + EXT4_SB(sb)->s_itb_per_group), + EXT4_B2C(sbi, offset)); +@@ -419,6 +424,7 @@ struct buffer_head * + ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group) + { + struct ext4_group_desc *desc; ++ struct ext4_sb_info *sbi = EXT4_SB(sb); + struct buffer_head *bh; + ext4_fsblk_t bitmap_blk; + int err; +@@ -427,6 +433,12 @@ ext4_read_block_bitmap_nowait(struct sup + if (!desc) + return ERR_PTR(-EFSCORRUPTED); + bitmap_blk = ext4_block_bitmap(sb, desc); ++ if ((bitmap_blk <= le32_to_cpu(sbi->s_es->s_first_data_block)) || ++ (bitmap_blk >= ext4_blocks_count(sbi->s_es))) { ++ ext4_error(sb, "Invalid block bitmap block %llu in " ++ "block_group %u", bitmap_blk, block_group); ++ return ERR_PTR(-EFSCORRUPTED); ++ } + bh = sb_getblk(sb, bitmap_blk); + if (unlikely(!bh)) { + ext4_error(sb, "Cannot get buffer for block bitmap - " +--- a/fs/ext4/ialloc.c ++++ b/fs/ext4/ialloc.c +@@ -160,6 +160,7 @@ static struct buffer_head * + ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) + { + struct ext4_group_desc *desc; ++ struct ext4_sb_info *sbi = EXT4_SB(sb); + struct buffer_head *bh = NULL; + ext4_fsblk_t bitmap_blk; + int err; +@@ -169,6 +170,12 @@ ext4_read_inode_bitmap(struct super_bloc + return ERR_PTR(-EFSCORRUPTED); + + bitmap_blk = ext4_inode_bitmap(sb, desc); ++ if ((bitmap_blk <= le32_to_cpu(sbi->s_es->s_first_data_block)) || ++ (bitmap_blk >= ext4_blocks_count(sbi->s_es))) { ++ ext4_error(sb, "Invalid inode bitmap blk %llu in " ++ "block_group %u", bitmap_blk, block_group); ++ return ERR_PTR(-EFSCORRUPTED); ++ } + bh = sb_getblk(sb, bitmap_blk); + if (unlikely(!bh)) { + ext4_error(sb, "Cannot read inode bitmap - " diff --git a/debian/patches/bugfix/all/ext4-always-initialize-the-crc32c-checksum-driver.patch b/debian/patches/bugfix/all/ext4-always-initialize-the-crc32c-checksum-driver.patch new file mode 100644 index 000000000..3e2f57379 --- /dev/null +++ b/debian/patches/bugfix/all/ext4-always-initialize-the-crc32c-checksum-driver.patch @@ -0,0 +1,46 @@ +From: Theodore Ts'o +Date: Thu, 29 Mar 2018 22:10:31 -0400 +Subject: ext4: always initialize the crc32c checksum driver +Origin: https://git.kernel.org/linus/a45403b51582a87872927a3e0fc0a389c26867f1 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2018-1094 + +The extended attribute code now uses the crc32c checksum for hashing +purposes, so we should just always always initialize it. We also want +to prevent NULL pointer dereferences if one of the metadata checksum +features is enabled after the file sytsem is originally mounted. + +This issue has been assigned CVE-2018-1094. + +https://bugzilla.kernel.org/show_bug.cgi?id=199183 +https://bugzilla.redhat.com/show_bug.cgi?id=1560788 + +Signed-off-by: Theodore Ts'o +Cc: stable@vger.kernel.org +--- + fs/ext4/super.c | 15 ++++++--------- + 1 file changed, 6 insertions(+), 9 deletions(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3489,15 +3489,12 @@ static int ext4_fill_super(struct super_ + } + + /* Load the checksum driver */ +- if (ext4_has_feature_metadata_csum(sb) || +- ext4_has_feature_ea_inode(sb)) { +- sbi->s_chksum_driver = crypto_alloc_shash("crc32c", 0, 0); +- if (IS_ERR(sbi->s_chksum_driver)) { +- ext4_msg(sb, KERN_ERR, "Cannot load crc32c driver."); +- ret = PTR_ERR(sbi->s_chksum_driver); +- sbi->s_chksum_driver = NULL; +- goto failed_mount; +- } ++ sbi->s_chksum_driver = crypto_alloc_shash("crc32c", 0, 0); ++ if (IS_ERR(sbi->s_chksum_driver)) { ++ ext4_msg(sb, KERN_ERR, "Cannot load crc32c driver."); ++ ret = PTR_ERR(sbi->s_chksum_driver); ++ sbi->s_chksum_driver = NULL; ++ goto failed_mount; + } + + /* Check superblock checksum */ diff --git a/debian/patches/bugfix/all/ext4-fail-ext4_iget-for-root-directory-if-unallocate.patch b/debian/patches/bugfix/all/ext4-fail-ext4_iget-for-root-directory-if-unallocate.patch new file mode 100644 index 000000000..f241c3bfb --- /dev/null +++ b/debian/patches/bugfix/all/ext4-fail-ext4_iget-for-root-directory-if-unallocate.patch @@ -0,0 +1,40 @@ +From: Theodore Ts'o +Date: Thu, 29 Mar 2018 21:56:09 -0400 +Subject: ext4: fail ext4_iget for root directory if unallocated +Origin: https://git.kernel.org/linus/8e4b5eae5decd9dfe5a4ee369c22028f90ab4c44 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2018-1092 + +If the root directory has an i_links_count of zero, then when the file +system is mounted, then when ext4_fill_super() notices the problem and +tries to call iput() the root directory in the error return path, +ext4_evict_inode() will try to free the inode on disk, before all of +the file system structures are set up, and this will result in an OOPS +caused by a NULL pointer dereference. + +This issue has been assigned CVE-2018-1092. + +https://bugzilla.kernel.org/show_bug.cgi?id=199179 +https://bugzilla.redhat.com/show_bug.cgi?id=1560777 + +Reported-by: Wen Xu +Signed-off-by: Theodore Ts'o +Cc: stable@vger.kernel.org +--- + fs/ext4/inode.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4745,6 +4745,12 @@ struct inode *ext4_iget(struct super_blo + goto bad_inode; + raw_inode = ext4_raw_inode(&iloc); + ++ if ((ino == EXT4_ROOT_INO) && (raw_inode->i_links_count == 0)) { ++ EXT4_ERROR_INODE(inode, "root inode unallocated"); ++ ret = -EFSCORRUPTED; ++ goto bad_inode; ++ } ++ + if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) { + ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize); + if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize > diff --git a/debian/patches/bugfix/all/scsi-libsas-defer-ata-device-eh-commands-to-libata.patch b/debian/patches/bugfix/all/scsi-libsas-defer-ata-device-eh-commands-to-libata.patch new file mode 100644 index 000000000..960baebcd --- /dev/null +++ b/debian/patches/bugfix/all/scsi-libsas-defer-ata-device-eh-commands-to-libata.patch @@ -0,0 +1,126 @@ +From: Jason Yan +Date: Thu, 8 Mar 2018 10:34:53 +0800 +Subject: scsi: libsas: defer ata device eh commands to libata +Origin: https://git.kernel.org/linus/318aaf34f1179b39fa9c30fa0f3288b645beee39 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2018-10021 + +When ata device doing EH, some commands still attached with tasks are +not passed to libata when abort failed or recover failed, so libata did +not handle these commands. After these commands done, sas task is freed, +but ata qc is not freed. This will cause ata qc leak and trigger a +warning like below: + +WARNING: CPU: 0 PID: 28512 at drivers/ata/libata-eh.c:4037 +ata_eh_finish+0xb4/0xcc +CPU: 0 PID: 28512 Comm: kworker/u32:2 Tainted: G W OE 4.14.0#1 +...... +Call trace: +[] ata_eh_finish+0xb4/0xcc +[] ata_do_eh+0xc4/0xd8 +[] ata_std_error_handler+0x44/0x8c +[] ata_scsi_port_error_handler+0x480/0x694 +[] async_sas_ata_eh+0x4c/0x80 +[] async_run_entry_fn+0x4c/0x170 +[] process_one_work+0x144/0x390 +[] worker_thread+0x144/0x418 +[] kthread+0x10c/0x138 +[] ret_from_fork+0x10/0x18 + +If ata qc leaked too many, ata tag allocation will fail and io blocked +for ever. + +As suggested by Dan Williams, defer ata device commands to libata and +merge sas_eh_finish_cmd() with sas_eh_defer_cmd(). libata will handle +ata qcs correctly after this. + +Signed-off-by: Jason Yan +CC: Xiaofei Tan +CC: John Garry +CC: Dan Williams +Reviewed-by: Dan Williams +Signed-off-by: Martin K. Petersen +--- + drivers/scsi/libsas/sas_scsi_host.c | 33 +++++++++++++-------------------- + 1 file changed, 13 insertions(+), 20 deletions(-) + +--- a/drivers/scsi/libsas/sas_scsi_host.c ++++ b/drivers/scsi/libsas/sas_scsi_host.c +@@ -222,6 +222,7 @@ out_done: + static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) + { + struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host); ++ struct domain_device *dev = cmd_to_domain_dev(cmd); + struct sas_task *task = TO_SAS_TASK(cmd); + + /* At this point, we only get called following an actual abort +@@ -230,6 +231,14 @@ static void sas_eh_finish_cmd(struct scs + */ + sas_end_task(cmd, task); + ++ if (dev_is_sata(dev)) { ++ /* defer commands to libata so that libata EH can ++ * handle ata qcs correctly ++ */ ++ list_move_tail(&cmd->eh_entry, &sas_ha->eh_ata_q); ++ return; ++ } ++ + /* now finish the command and move it on to the error + * handler done list, this also takes it off the + * error handler pending list. +@@ -237,22 +246,6 @@ static void sas_eh_finish_cmd(struct scs + scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q); + } + +-static void sas_eh_defer_cmd(struct scsi_cmnd *cmd) +-{ +- struct domain_device *dev = cmd_to_domain_dev(cmd); +- struct sas_ha_struct *ha = dev->port->ha; +- struct sas_task *task = TO_SAS_TASK(cmd); +- +- if (!dev_is_sata(dev)) { +- sas_eh_finish_cmd(cmd); +- return; +- } +- +- /* report the timeout to libata */ +- sas_end_task(cmd, task); +- list_move_tail(&cmd->eh_entry, &ha->eh_ata_q); +-} +- + static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd *my_cmd) + { + struct scsi_cmnd *cmd, *n; +@@ -260,7 +253,7 @@ static void sas_scsi_clear_queue_lu(stru + list_for_each_entry_safe(cmd, n, error_q, eh_entry) { + if (cmd->device->sdev_target == my_cmd->device->sdev_target && + cmd->device->lun == my_cmd->device->lun) +- sas_eh_defer_cmd(cmd); ++ sas_eh_finish_cmd(cmd); + } + } + +@@ -630,12 +623,12 @@ static void sas_eh_handle_sas_errors(str + case TASK_IS_DONE: + SAS_DPRINTK("%s: task 0x%p is done\n", __func__, + task); +- sas_eh_defer_cmd(cmd); ++ sas_eh_finish_cmd(cmd); + continue; + case TASK_IS_ABORTED: + SAS_DPRINTK("%s: task 0x%p is aborted\n", + __func__, task); +- sas_eh_defer_cmd(cmd); ++ sas_eh_finish_cmd(cmd); + continue; + case TASK_IS_AT_LU: + SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); +@@ -646,7 +639,7 @@ static void sas_eh_handle_sas_errors(str + "recovered\n", + SAS_ADDR(task->dev), + cmd->device->lun); +- sas_eh_defer_cmd(cmd); ++ sas_eh_finish_cmd(cmd); + sas_scsi_clear_queue_lu(work_q, cmd); + goto Again; + } diff --git a/debian/patches/bugfix/all/scsi-libsas-direct-call-probe-and-destruct.patch b/debian/patches/bugfix/all/scsi-libsas-direct-call-probe-and-destruct.patch new file mode 100644 index 000000000..122149346 --- /dev/null +++ b/debian/patches/bugfix/all/scsi-libsas-direct-call-probe-and-destruct.patch @@ -0,0 +1,283 @@ +From: Jason Yan +Date: Fri, 8 Dec 2017 17:42:09 +0800 +Subject: scsi: libsas: direct call probe and destruct +Origin: https://git.kernel.org/linus/0558f33c06bb910e2879e355192227a8e8f0219d +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-18232 + +In commit 87c8331fcf72 ("[SCSI] libsas: prevent domain rediscovery +competing with ata error handling") introduced disco mutex to prevent +rediscovery competing with ata error handling and put the whole +revalidation in the mutex. But the rphy add/remove needs to wait for the +error handling which also grabs the disco mutex. This may leads to dead +lock.So the probe and destruct event were introduce to do the rphy +add/remove asynchronously and out of the lock. + +The asynchronously processed workers makes the whole discovery process +not atomic, the other events may interrupt the process. For example, +if a loss of signal event inserted before the probe event, the +sas_deform_port() is called and the port will be deleted. + +And sas_port_delete() may run before the destruct event, but the +port-x:x is the top parent of end device or expander. This leads to +a kernel WARNING such as: + +[ 82.042979] sysfs group 'power' not found for kobject 'phy-1:0:22' +[ 82.042983] ------------[ cut here ]------------ +[ 82.042986] WARNING: CPU: 54 PID: 1714 at fs/sysfs/group.c:237 +sysfs_remove_group+0x94/0xa0 +[ 82.043059] Call trace: +[ 82.043082] [] sysfs_remove_group+0x94/0xa0 +[ 82.043085] [] dpm_sysfs_remove+0x60/0x70 +[ 82.043086] [] device_del+0x138/0x308 +[ 82.043089] [] sas_phy_delete+0x38/0x60 +[ 82.043091] [] do_sas_phy_delete+0x6c/0x80 +[ 82.043093] [] device_for_each_child+0x58/0xa0 +[ 82.043095] [] sas_remove_children+0x40/0x50 +[ 82.043100] [] sas_destruct_devices+0x64/0xa0 +[ 82.043102] [] process_one_work+0x1fc/0x4b0 +[ 82.043104] [] worker_thread+0x50/0x490 +[ 82.043105] [] kthread+0xfc/0x128 +[ 82.043107] [] ret_from_fork+0x10/0x50 + +Make probe and destruct a direct call in the disco and revalidate function, +but put them outside the lock. The whole discovery or revalidate won't +be interrupted by other events. And the DISCE_PROBE and DISCE_DESTRUCT +event are deleted as a result of the direct call. + +Introduce a new list to destruct the sas_port and put the port delete after +the destruct. This makes sure the right order of destroying the sysfs +kobject and fix the warning above. + +In sas_ex_revalidate_domain() have a loop to find all broadcasted +device, and sometimes we have a chance to find the same expander twice. +Because the sas_port will be deleted at the end of the whole revalidate +process, sas_port with the same name cannot be added before this. +Otherwise the sysfs will complain of creating duplicate filename. Since +the LLDD will send broadcast for every device change, we can only +process one expander's revalidation. + +[mkp: kbuild test robot warning] + +Signed-off-by: Jason Yan +CC: John Garry +CC: Johannes Thumshirn +CC: Ewan Milne +CC: Christoph Hellwig +CC: Tomas Henzl +CC: Dan Williams +Reviewed-by: Hannes Reinecke +Signed-off-by: Martin K. Petersen +--- + drivers/scsi/libsas/sas_ata.c | 1 - + drivers/scsi/libsas/sas_discover.c | 32 ++++++++++++++++++-------------- + drivers/scsi/libsas/sas_expander.c | 8 +++----- + drivers/scsi/libsas/sas_internal.h | 1 + + drivers/scsi/libsas/sas_port.c | 3 +++ + include/scsi/libsas.h | 3 +-- + include/scsi/scsi_transport_sas.h | 1 + + 7 files changed, 27 insertions(+), 22 deletions(-) + +--- a/drivers/scsi/libsas/sas_ata.c ++++ b/drivers/scsi/libsas/sas_ata.c +@@ -730,7 +730,6 @@ int sas_discover_sata(struct domain_devi + if (res) + return res; + +- sas_discover_event(dev->port, DISCE_PROBE); + return 0; + } + +--- a/drivers/scsi/libsas/sas_discover.c ++++ b/drivers/scsi/libsas/sas_discover.c +@@ -212,13 +212,9 @@ void sas_notify_lldd_dev_gone(struct dom + } + } + +-static void sas_probe_devices(struct work_struct *work) ++static void sas_probe_devices(struct asd_sas_port *port) + { + struct domain_device *dev, *n; +- struct sas_discovery_event *ev = to_sas_discovery_event(work); +- struct asd_sas_port *port = ev->port; +- +- clear_bit(DISCE_PROBE, &port->disc.pending); + + /* devices must be domain members before link recovery and probe */ + list_for_each_entry(dev, &port->disco_list, disco_list_node) { +@@ -294,7 +290,6 @@ int sas_discover_end_dev(struct domain_d + res = sas_notify_lldd_dev_found(dev); + if (res) + return res; +- sas_discover_event(dev->port, DISCE_PROBE); + + return 0; + } +@@ -353,13 +348,9 @@ static void sas_unregister_common_dev(st + sas_put_device(dev); + } + +-static void sas_destruct_devices(struct work_struct *work) ++void sas_destruct_devices(struct asd_sas_port *port) + { + struct domain_device *dev, *n; +- struct sas_discovery_event *ev = to_sas_discovery_event(work); +- struct asd_sas_port *port = ev->port; +- +- clear_bit(DISCE_DESTRUCT, &port->disc.pending); + + list_for_each_entry_safe(dev, n, &port->destroy_list, disco_list_node) { + list_del_init(&dev->disco_list_node); +@@ -370,6 +361,16 @@ static void sas_destruct_devices(struct + } + } + ++static void sas_destruct_ports(struct asd_sas_port *port) ++{ ++ struct sas_port *sas_port, *p; ++ ++ list_for_each_entry_safe(sas_port, p, &port->sas_port_del_list, del_list) { ++ list_del_init(&sas_port->del_list); ++ sas_port_delete(sas_port); ++ } ++} ++ + void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev) + { + if (!test_bit(SAS_DEV_DESTROY, &dev->state) && +@@ -384,7 +385,6 @@ void sas_unregister_dev(struct asd_sas_p + if (!test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) { + sas_rphy_unlink(dev->rphy); + list_move_tail(&dev->disco_list_node, &port->destroy_list); +- sas_discover_event(dev->port, DISCE_DESTRUCT); + } + } + +@@ -490,6 +490,8 @@ static void sas_discover_domain(struct w + port->port_dev = NULL; + } + ++ sas_probe_devices(port); ++ + SAS_DPRINTK("DONE DISCOVERY on port %d, pid:%d, result:%d\n", port->id, + task_pid_nr(current), error); + } +@@ -523,6 +525,10 @@ static void sas_revalidate_domain(struct + port->id, task_pid_nr(current), res); + out: + mutex_unlock(&ha->disco_mutex); ++ ++ sas_destruct_devices(port); ++ sas_destruct_ports(port); ++ sas_probe_devices(port); + } + + /* ---------- Events ---------- */ +@@ -578,10 +584,8 @@ void sas_init_disc(struct sas_discovery + static const work_func_t sas_event_fns[DISC_NUM_EVENTS] = { + [DISCE_DISCOVER_DOMAIN] = sas_discover_domain, + [DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain, +- [DISCE_PROBE] = sas_probe_devices, + [DISCE_SUSPEND] = sas_suspend_devices, + [DISCE_RESUME] = sas_resume_devices, +- [DISCE_DESTRUCT] = sas_destruct_devices, + }; + + disc->pending = 0; +--- a/drivers/scsi/libsas/sas_expander.c ++++ b/drivers/scsi/libsas/sas_expander.c +@@ -1916,7 +1916,8 @@ static void sas_unregister_devs_sas_addr + sas_port_delete_phy(phy->port, phy->phy); + sas_device_set_phy(found, phy->port); + if (phy->port->num_phys == 0) +- sas_port_delete(phy->port); ++ list_add_tail(&phy->port->del_list, ++ &parent->port->sas_port_del_list); + phy->port = NULL; + } + } +@@ -2124,7 +2125,7 @@ int sas_ex_revalidate_domain(struct doma + struct domain_device *dev = NULL; + + res = sas_find_bcast_dev(port_dev, &dev); +- while (res == 0 && dev) { ++ if (res == 0 && dev) { + struct expander_device *ex = &dev->ex_dev; + int i = 0, phy_id; + +@@ -2136,9 +2137,6 @@ int sas_ex_revalidate_domain(struct doma + res = sas_rediscover(dev, phy_id); + i = phy_id + 1; + } while (i < ex->num_phys); +- +- dev = NULL; +- res = sas_find_bcast_dev(port_dev, &dev); + } + return res; + } +--- a/drivers/scsi/libsas/sas_internal.h ++++ b/drivers/scsi/libsas/sas_internal.h +@@ -101,6 +101,7 @@ int sas_try_ata_reset(struct asd_sas_phy + void sas_hae_reset(struct work_struct *work); + + void sas_free_device(struct kref *kref); ++void sas_destruct_devices(struct asd_sas_port *port); + + extern const work_func_t sas_phy_event_fns[PHY_NUM_EVENTS]; + extern const work_func_t sas_port_event_fns[PORT_NUM_EVENTS]; +--- a/drivers/scsi/libsas/sas_port.c ++++ b/drivers/scsi/libsas/sas_port.c +@@ -66,6 +66,7 @@ static void sas_resume_port(struct asd_s + rc = sas_notify_lldd_dev_found(dev); + if (rc) { + sas_unregister_dev(port, dev); ++ sas_destruct_devices(port); + continue; + } + +@@ -219,6 +220,7 @@ void sas_deform_port(struct asd_sas_phy + + if (port->num_phys == 1) { + sas_unregister_domain_devices(port, gone); ++ sas_destruct_devices(port); + sas_port_delete(port->port); + port->port = NULL; + } else { +@@ -313,6 +315,7 @@ static void sas_init_port(struct asd_sas + INIT_LIST_HEAD(&port->dev_list); + INIT_LIST_HEAD(&port->disco_list); + INIT_LIST_HEAD(&port->destroy_list); ++ INIT_LIST_HEAD(&port->sas_port_del_list); + spin_lock_init(&port->phy_list_lock); + INIT_LIST_HEAD(&port->phy_list); + port->ha = sas_ha; +--- a/include/scsi/libsas.h ++++ b/include/scsi/libsas.h +@@ -81,10 +81,8 @@ enum phy_event { + enum discover_event { + DISCE_DISCOVER_DOMAIN = 0U, + DISCE_REVALIDATE_DOMAIN, +- DISCE_PROBE, + DISCE_SUSPEND, + DISCE_RESUME, +- DISCE_DESTRUCT, + DISC_NUM_EVENTS, + }; + +@@ -261,6 +259,7 @@ struct asd_sas_port { + struct list_head dev_list; + struct list_head disco_list; + struct list_head destroy_list; ++ struct list_head sas_port_del_list; + enum sas_linkrate linkrate; + + struct sas_work work; +--- a/include/scsi/scsi_transport_sas.h ++++ b/include/scsi/scsi_transport_sas.h +@@ -156,6 +156,7 @@ struct sas_port { + + struct mutex phy_list_mutex; + struct list_head phy_list; ++ struct list_head del_list; /* libsas only */ + }; + + #define dev_to_sas_port(d) \ diff --git a/debian/patches/series b/debian/patches/series index 60d9c7238..d37ebb640 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -120,6 +120,11 @@ features/all/lockdown/arm64-add-kernel-config-option-to-lock-down-when.patch # Security fixes debian/i386-686-pae-pci-set-pci-nobios-by-default.patch bugfix/all/mac80211_hwsim-fix-possible-memory-leak-in-hwsim_new.patch +bugfix/all/scsi-libsas-direct-call-probe-and-destruct.patch +bugfix/all/ext4-fail-ext4_iget-for-root-directory-if-unallocate.patch +bugfix/all/ext4-add-validity-checks-for-bitmap-block-numbers.patch +bugfix/all/ext4-always-initialize-the-crc32c-checksum-driver.patch +bugfix/all/scsi-libsas-defer-ata-device-eh-commands-to-libata.patch # Fix exported symbol versions bugfix/all/module-disable-matching-missing-version-crc.patch