Add various security fixes
This commit is contained in:
parent
bf94bb5914
commit
9f5a30bb07
|
@ -494,6 +494,11 @@ linux (4.15.17-1) UNRELEASED; urgency=medium
|
||||||
[ Ben Hutchings ]
|
[ Ben Hutchings ]
|
||||||
* wireless: Disable regulatory.db direct loading (see #892229)
|
* wireless: Disable regulatory.db direct loading (see #892229)
|
||||||
* Bump ABI to 3
|
* 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 ]
|
[ Vagrant Cascadian ]
|
||||||
* [armhf] Add patch to fix loading of imx6q-cpufreq module.
|
* [armhf] Add patch to fix loading of imx6q-cpufreq module.
|
||||||
|
|
96
debian/patches/bugfix/all/ext4-add-validity-checks-for-bitmap-block-numbers.patch
vendored
Normal file
96
debian/patches/bugfix/all/ext4-add-validity-checks-for-bitmap-block-numbers.patch
vendored
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
From: Theodore Ts'o <tytso@mit.edu>
|
||||||
|
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 <wen.xu@gatech.edu>
|
||||||
|
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
|
||||||
|
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 - "
|
46
debian/patches/bugfix/all/ext4-always-initialize-the-crc32c-checksum-driver.patch
vendored
Normal file
46
debian/patches/bugfix/all/ext4-always-initialize-the-crc32c-checksum-driver.patch
vendored
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
From: Theodore Ts'o <tytso@mit.edu>
|
||||||
|
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 <tytso@mit.edu>
|
||||||
|
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 */
|
40
debian/patches/bugfix/all/ext4-fail-ext4_iget-for-root-directory-if-unallocate.patch
vendored
Normal file
40
debian/patches/bugfix/all/ext4-fail-ext4_iget-for-root-directory-if-unallocate.patch
vendored
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
From: Theodore Ts'o <tytso@mit.edu>
|
||||||
|
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 <wen.xu@gatech.edu>
|
||||||
|
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
|
||||||
|
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 >
|
126
debian/patches/bugfix/all/scsi-libsas-defer-ata-device-eh-commands-to-libata.patch
vendored
Normal file
126
debian/patches/bugfix/all/scsi-libsas-defer-ata-device-eh-commands-to-libata.patch
vendored
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
From: Jason Yan <yanaijie@huawei.com>
|
||||||
|
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:
|
||||||
|
[<ffff0000088b7bd0>] ata_eh_finish+0xb4/0xcc
|
||||||
|
[<ffff0000088b8420>] ata_do_eh+0xc4/0xd8
|
||||||
|
[<ffff0000088b8478>] ata_std_error_handler+0x44/0x8c
|
||||||
|
[<ffff0000088b8068>] ata_scsi_port_error_handler+0x480/0x694
|
||||||
|
[<ffff000008875fc4>] async_sas_ata_eh+0x4c/0x80
|
||||||
|
[<ffff0000080f6be8>] async_run_entry_fn+0x4c/0x170
|
||||||
|
[<ffff0000080ebd70>] process_one_work+0x144/0x390
|
||||||
|
[<ffff0000080ec100>] worker_thread+0x144/0x418
|
||||||
|
[<ffff0000080f2c98>] kthread+0x10c/0x138
|
||||||
|
[<ffff0000080855dc>] 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 <yanaijie@huawei.com>
|
||||||
|
CC: Xiaofei Tan <tanxiaofei@huawei.com>
|
||||||
|
CC: John Garry <john.garry@huawei.com>
|
||||||
|
CC: Dan Williams <dan.j.williams@intel.com>
|
||||||
|
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||||
|
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
|
||||||
|
---
|
||||||
|
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;
|
||||||
|
}
|
|
@ -0,0 +1,283 @@
|
||||||
|
From: Jason Yan <yanaijie@huawei.com>
|
||||||
|
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] [<ffff0000082e7624>] sysfs_remove_group+0x94/0xa0
|
||||||
|
[ 82.043085] [<ffff00000864e320>] dpm_sysfs_remove+0x60/0x70
|
||||||
|
[ 82.043086] [<ffff00000863ee10>] device_del+0x138/0x308
|
||||||
|
[ 82.043089] [<ffff00000869a2d0>] sas_phy_delete+0x38/0x60
|
||||||
|
[ 82.043091] [<ffff00000869a86c>] do_sas_phy_delete+0x6c/0x80
|
||||||
|
[ 82.043093] [<ffff00000863dc20>] device_for_each_child+0x58/0xa0
|
||||||
|
[ 82.043095] [<ffff000008696f80>] sas_remove_children+0x40/0x50
|
||||||
|
[ 82.043100] [<ffff00000869d1bc>] sas_destruct_devices+0x64/0xa0
|
||||||
|
[ 82.043102] [<ffff0000080e93bc>] process_one_work+0x1fc/0x4b0
|
||||||
|
[ 82.043104] [<ffff0000080e96c0>] worker_thread+0x50/0x490
|
||||||
|
[ 82.043105] [<ffff0000080f0364>] kthread+0xfc/0x128
|
||||||
|
[ 82.043107] [<ffff0000080836c0>] 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 <yanaijie@huawei.com>
|
||||||
|
CC: John Garry <john.garry@huawei.com>
|
||||||
|
CC: Johannes Thumshirn <jthumshirn@suse.de>
|
||||||
|
CC: Ewan Milne <emilne@redhat.com>
|
||||||
|
CC: Christoph Hellwig <hch@lst.de>
|
||||||
|
CC: Tomas Henzl <thenzl@redhat.com>
|
||||||
|
CC: Dan Williams <dan.j.williams@intel.com>
|
||||||
|
Reviewed-by: Hannes Reinecke <hare@suse.com>
|
||||||
|
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
|
||||||
|
---
|
||||||
|
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) \
|
|
@ -120,6 +120,11 @@ features/all/lockdown/arm64-add-kernel-config-option-to-lock-down-when.patch
|
||||||
# Security fixes
|
# Security fixes
|
||||||
debian/i386-686-pae-pci-set-pci-nobios-by-default.patch
|
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/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
|
# Fix exported symbol versions
|
||||||
bugfix/all/module-disable-matching-missing-version-crc.patch
|
bugfix/all/module-disable-matching-missing-version-crc.patch
|
||||||
|
|
Loading…
Reference in New Issue