From: Xingang Wang wangxingang5@huawei.com
ascend inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I49RB2 CVE: NA
-------------------------------------------------
This reverts commit c50ad40d63ef0cc9e0b158354af08f1f98419273. The commit "svm: Add svm_set_user_mpam_en to enable/disable mpam for smmu" add and export interface in svm module, this makes the mpam depend on the svm module, just revert this to avoid coupling.
Signed-off-by: Xingang Wang wangxingang5@huawei.com Reviewed-by: Weilong Chen chenweilong@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/char/svm.c | 64 ------------------------------------- include/linux/ascend_smmu.h | 3 -- 2 files changed, 67 deletions(-)
diff --git a/drivers/char/svm.c b/drivers/char/svm.c index c877c75fdcd5f..000b9ad01c350 100644 --- a/drivers/char/svm.c +++ b/drivers/char/svm.c @@ -135,14 +135,11 @@ struct meminfo { struct svm_mpam { #define SVM_GET_DEV_MPAM (1 << 0) #define SVM_SET_DEV_MPAM (1 << 1) -#define SVM_GET_USER_MPAM_EN (1 << 2) -#define SVM_SET_USER_MPAM_EN (1 << 3) int flags; int pasid; int partid; int pmg; int s1mpam; - int user_mpam_en; };
struct phymeminfo { @@ -1505,14 +1502,6 @@ static int svm_get_core_mpam(struct device *dev, void *data) } }
- if (mpam->flags & SVM_GET_USER_MPAM_EN) { - err = arm_smmu_get_dev_user_mpam_en(dev, &mpam->user_mpam_en); - if (err) { - dev_err(dev, "set user_mpam_en failed, %d\n", err); - return err; - } - } - return err; }
@@ -1554,14 +1543,6 @@ static int svm_set_core_mpam(struct device *dev, void *data) } }
- if (mpam->flags & SVM_SET_USER_MPAM_EN) { - err = arm_smmu_set_dev_user_mpam_en(dev, mpam->user_mpam_en); - if (err) { - dev_err(dev, "set user_mpam_en failed, %d\n", err); - return err; - } - } - return 0; }
@@ -1655,51 +1636,6 @@ int svm_get_mpam(int pasid, int *partid, int *pmg, int *s1mpam) } EXPORT_SYMBOL_GPL(svm_get_mpam);
-/** - * svm_set_user_mpam_en() - set user_mpam_en - * @user_mpam_en: 0 for smmu mpam, 1 for user mpam - */ -int svm_set_user_mpam_en(int user_mpam_en) -{ - int err; - struct svm_mpam mpam, old_mpam; - - old_mpam.flags = SVM_GET_USER_MPAM_EN; - err = __svm_get_mpam(&old_mpam); - - mpam.flags = SVM_SET_USER_MPAM_EN, - mpam.user_mpam_en = user_mpam_en, - err = __svm_set_mpam(&mpam); - if (err) - goto rollback; - - return 0; - -rollback: - __svm_set_mpam(&mpam); - return err; -} -EXPORT_SYMBOL_GPL(svm_set_user_mpam_en); - -/** - * svm_set_user_mpam_en() - set user_mpam_en - * @user_mpam_en: pointer to user_mpam_en - */ -int svm_get_user_mpam_en(int *user_mpam_en) -{ - int err; - struct svm_mpam mpam; - - mpam.flags = SVM_GET_USER_MPAM_EN; - err = __svm_get_mpam(&mpam); - if (err) - return err; - - *user_mpam_en = mpam.user_mpam_en; - return 0; -} -EXPORT_SYMBOL_GPL(svm_get_user_mpam_en); - static int svm_set_rc(unsigned long __user *arg) { unsigned long addr, size, rc; diff --git a/include/linux/ascend_smmu.h b/include/linux/ascend_smmu.h index 32241a02a8a89..e570acfc8f6ac 100644 --- a/include/linux/ascend_smmu.h +++ b/include/linux/ascend_smmu.h @@ -15,7 +15,4 @@ extern int arm_smmu_get_dev_user_mpam_en(struct device *dev, int *user_mpam_en); extern int svm_get_mpam(int pasid, int *partid, int *pmg, int *s1mpam); extern int svm_set_mpam(int pasid, int partid, int pmg, int s1mpam);
-extern int svm_set_user_mpam_en(int user_mpam_en); -extern int svm_get_user_mpam_en(int *user_mpam_en); - #endif /* __LINUX_ASCEND_SMMU_H */
From: Xingang Wang wangxingang5@huawei.com
ascend inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I49RB2 CVE: NA
-------------------------------------------------
This reverts commit 464f69903da18e4248ecd76d5237acd60e5b3bf5. The commit "svm: Add support to set svm mpam configuration" add and export interface in svm module, this makes the mpam depend on the svm module, just revert this to avoid coupling.
Signed-off-by: Xingang Wang wangxingang5@huawei.com Reviewed-by: Weilong Chen chenweilong@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/char/svm.c | 79 ------------------------------------- include/linux/ascend_smmu.h | 1 - 2 files changed, 80 deletions(-)
diff --git a/drivers/char/svm.c b/drivers/char/svm.c index 000b9ad01c350..b4f3f4bbd0be9 100644 --- a/drivers/char/svm.c +++ b/drivers/char/svm.c @@ -134,7 +134,6 @@ struct meminfo {
struct svm_mpam { #define SVM_GET_DEV_MPAM (1 << 0) -#define SVM_SET_DEV_MPAM (1 << 1) int flags; int pasid; int partid; @@ -1529,84 +1528,6 @@ int __svm_get_mpam(struct svm_mpam *mpam) return 0; }
-static int svm_set_core_mpam(struct device *dev, void *data) -{ - int err = 0; - struct svm_mpam *mpam = data; - - if (mpam->flags & SVM_SET_DEV_MPAM) { - err = arm_smmu_set_dev_mpam(dev, mpam->pasid, mpam->partid, - mpam->pmg, mpam->s1mpam); - if (err) { - dev_err(dev, "set mpam failed, %d\n", err); - return err; - } - } - - return 0; -} - -static int __svm_set_mpam(struct svm_mpam *mpam) -{ - int err = 0; -#ifdef CONFIG_ACPI - struct core_device *cdev = NULL; -#else - struct svm_device *sdev = NULL; -#endif - -#ifdef CONFIG_ACPI - list_for_each_entry(cdev, &child_list, entry) { - err = svm_set_core_mpam(&cdev->dev, mpam); - if (err) - return err; - } -#else - list_for_each_entry(sdev, &sdev_list, entry) { - err = device_for_each_child(sdev->dev, mpam, svm_set_core_mpam); - if (err) - return err; - } -#endif - - return 0; -} - -/** - * svm_set_mpam() - set mpam configuration of all core device in smmu - * @pasid: substream id - * @partid: mpam partition id - * @pmg: mpam pmg - * @s1mpam: 0 for ste mpam, 1 for cd mpam - */ -int svm_set_mpam(int pasid, int partid, int pmg, int s1mpam) -{ - int err; - struct svm_mpam mpam, old_mpam; - - old_mpam.flags = SVM_GET_DEV_MPAM; - old_mpam.pasid = pasid; - err = __svm_get_mpam(&old_mpam); - if (err) - return err; - - mpam.flags = SVM_SET_DEV_MPAM; - mpam.pasid = pasid; - mpam.partid = partid; - mpam.pmg = pmg; - mpam.s1mpam = s1mpam; - err = __svm_set_mpam(&mpam); - if (err) - goto rollback; - - return 0; - -rollback: - __svm_set_mpam(&old_mpam); - return err; -} -EXPORT_SYMBOL_GPL(svm_set_mpam); - /** * svm_get_mpam() - get smmu mpam configuration of core device * @pasid: substream id diff --git a/include/linux/ascend_smmu.h b/include/linux/ascend_smmu.h index e570acfc8f6ac..a6d2058599be5 100644 --- a/include/linux/ascend_smmu.h +++ b/include/linux/ascend_smmu.h @@ -13,6 +13,5 @@ extern int arm_smmu_set_dev_user_mpam_en(struct device *dev, int user_mpam_en); extern int arm_smmu_get_dev_user_mpam_en(struct device *dev, int *user_mpam_en);
extern int svm_get_mpam(int pasid, int *partid, int *pmg, int *s1mpam); -extern int svm_set_mpam(int pasid, int partid, int pmg, int s1mpam);
#endif /* __LINUX_ASCEND_SMMU_H */
From: Xingang Wang wangxingang5@huawei.com
ascend inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I49RB2 CVE: NA
-------------------------------------------------
This reverts commit 0cc88dd88008d71ccc6fcbbcc4c027383eb6f5a6. The commit "svm: Add support to get svm mpam configuration" add and export interface in svm module, this makes the mpam depend on the svm module, just revert this to avoid coupling.
Signed-off-by: Xingang Wang wangxingang5@huawei.com Reviewed-by: Weilong Chen chenweilong@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/char/svm.c | 85 ------------------------------------- include/linux/ascend_smmu.h | 2 - 2 files changed, 87 deletions(-)
diff --git a/drivers/char/svm.c b/drivers/char/svm.c index b4f3f4bbd0be9..dd0a9babcbee2 100644 --- a/drivers/char/svm.c +++ b/drivers/char/svm.c @@ -32,7 +32,6 @@ #include <linux/sched/mm.h> #include <linux/msi.h> #include <linux/acpi.h> -#include <linux/ascend_smmu.h> #include <linux/share_pool.h>
#define SVM_DEVICE_NAME "svm" @@ -77,11 +76,8 @@ struct svm_device { struct device *dev; phys_addr_t l2buff; unsigned long l2size; - struct list_head entry; };
-static LIST_HEAD(sdev_list); - struct svm_bind_process { pid_t vpid; u64 ttbr; @@ -132,15 +128,6 @@ struct meminfo { unsigned long hugetlbtotal; };
-struct svm_mpam { -#define SVM_GET_DEV_MPAM (1 << 0) - int flags; - int pasid; - int partid; - int pmg; - int s1mpam; -}; - struct phymeminfo { unsigned long normal_total; unsigned long normal_free; @@ -1487,76 +1474,6 @@ int svm_get_pasid(pid_t vpid, int dev_id __maybe_unused) } EXPORT_SYMBOL_GPL(svm_get_pasid);
-static int svm_get_core_mpam(struct device *dev, void *data) -{ - int err = 0; - struct svm_mpam *mpam = data; - - if (mpam->flags & SVM_GET_DEV_MPAM) { - err = arm_smmu_get_dev_mpam(dev, mpam->pasid, &mpam->partid, - &mpam->pmg, &mpam->s1mpam); - if (err) { - dev_err(dev, "get mpam failed, %d\n", err); - return err; - } - } - - return err; -} - -int __svm_get_mpam(struct svm_mpam *mpam) -{ - int err = 0; -#ifdef CONFIG_ACPI - struct core_device *cdev = NULL; -#else - struct svm_device *sdev = NULL; -#endif -#ifdef CONFIG_ACPI - list_for_each_entry(cdev, &child_list, entry) { - err = svm_get_core_mpam(&cdev->dev, mpam); - if (err) - return err; - } -#else - list_for_each_entry(sdev, &sdev_list, entry) { - err = device_for_each_child(sdev->dev, mpam, svm_get_core_mpam); - if (err) - return err; - } -#endif - return 0; -} - -/** - * svm_get_mpam() - get smmu mpam configuration of core device - * @pasid: substream id - * @partid: pointer to partid - * @pmg: pointer to pmg - * @s1mpam: pointer to s1mpam - */ -int svm_get_mpam(int pasid, int *partid, int *pmg, int *s1mpam) -{ - int err = 0; - struct svm_mpam mpam; - - if (!partid || !pmg || !s1mpam) - return -EINVAL; - - mpam.flags = SVM_GET_DEV_MPAM, - mpam.pasid = pasid, - err = __svm_get_mpam(&mpam); - if (err) - return err; - - *partid = mpam.partid; - *pmg = mpam.pmg; - *s1mpam = mpam.s1mpam; - - return 0; -} -EXPORT_SYMBOL_GPL(svm_get_mpam); - static int svm_set_rc(unsigned long __user *arg) { unsigned long addr, size, rc; @@ -2237,7 +2154,6 @@ static int svm_device_probe(struct platform_device *pdev) if (sdev->miscdev.name == NULL) return -ENOMEM;
- list_add(&sdev->entry, &sdev_list); dev_set_drvdata(dev, sdev); err = misc_register(&sdev->miscdev); if (err) { @@ -2294,7 +2210,6 @@ static int svm_device_remove(struct platform_device *pdev)
device_for_each_child(sdev->dev, NULL, svm_remove_core); misc_deregister(&sdev->miscdev); - list_del(&sdev->entry);
return 0; } diff --git a/include/linux/ascend_smmu.h b/include/linux/ascend_smmu.h index a6d2058599be5..c52968e98944c 100644 --- a/include/linux/ascend_smmu.h +++ b/include/linux/ascend_smmu.h @@ -12,6 +12,4 @@ extern int arm_smmu_get_dev_mpam(struct device *dev, int ssid, int *partid, extern int arm_smmu_set_dev_user_mpam_en(struct device *dev, int user_mpam_en); extern int arm_smmu_get_dev_user_mpam_en(struct device *dev, int *user_mpam_en);
-extern int svm_get_mpam(int pasid, int *partid, int *pmg, int *s1mpam); - #endif /* __LINUX_ASCEND_SMMU_H */
From: Matej Genci matej.genci@nutanix.com
mainline inclusion from mainline-5.10 commit beef6fd02b90 category: bugfix bugzilla: NA CVE: NA
-------------------------------------------------
VirtIO 1.0 spec says:
The removed and rescan events ... when sent for LUN 0, they MAY apply to the entire target so the driver can ask the initiator to rescan the target to detect this.
This change introduces the behaviour described above by scanning the entire SCSI target when LUN is set to 0. This is both a functional and a performance fix. It aligns the driver with the spec and allows control planes to hotplug targets with large numbers of LUNs without having to request a RESCAN for each one of them.
Link: https://lore.kernel.org/r/CY4PR02MB33354370E0A81E75DD9DFE74FB520@CY4PR02MB33... Suggested-by: Felipe Franciosi felipe@nutanix.com Acked-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Matej Genci matej.genci@nutanix.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Wenchao Hao haowenchao@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Reviewed-by: Miaohe Lin linmiaohe@huawei.com Reviewed-by: Miaohe Lin linmiaohe@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/scsi/virtio_scsi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 3d331a864b2fc..8118c06f491b9 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -323,7 +323,12 @@ static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi,
switch (virtio32_to_cpu(vscsi->vdev, event->reason)) { case VIRTIO_SCSI_EVT_RESET_RESCAN: - scsi_add_device(shost, 0, target, lun); + if (lun == 0) { + scsi_scan_target(&shost->shost_gendev, 0, target, + SCAN_WILD_CARD, SCSI_SCAN_INITIAL); + } else { + scsi_add_device(shost, 0, target, lun); + } break; case VIRTIO_SCSI_EVT_RESET_REMOVED: sdev = scsi_device_lookup(shost, 0, target, lun);
From: "Michael S. Tsirkin" mst@redhat.com
mainline inclusion from mainline-5.15 commit ff63198850f3 category: bugfix bugzilla: NA CVE: NA
-------------------------------------------------
It turns out that access to config space before completing the feature negotiation is broken for big endian guests at least with QEMU hosts up to 6.1 inclusive. This affects any device that accesses config space in the validate callback: at the moment that is virtio-net with VIRTIO_NET_F_MTU but since 82e89ea077b9 ("virtio-blk: Add validation for block size in config space") that also started affecting virtio-blk with VIRTIO_BLK_F_BLK_SIZE. Further, unlike VIRTIO_NET_F_MTU which is off by default on QEMU, VIRTIO_BLK_F_BLK_SIZE is on by default, which resulted in lots of people not being able to boot VMs on BE.
The spec is very clear that what we are doing is legal so QEMU needs to be fixed, but given it's been broken for so many years and no one noticed, we need to give QEMU a bit more time before applying this.
Further, this patch is incomplete (does not check blk size is a power of two) and it duplicates the logic from nbd.
Revert for now, and we'll reapply a cleaner logic in the next release.
Cc: stable@vger.kernel.org Fixes: 82e89ea077b9 ("virtio-blk: Add validation for block size in config space") Cc: Xie Yongji xieyongji@bytedance.com Signed-off-by: Michael S. Tsirkin mst@redhat.com Signed-off-by: Wenchao Hao haowenchao@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Reviewed-by: Miaohe Lin linmiaohe@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/block/virtio_blk.c | 39 ++++++-------------------------------- 1 file changed, 6 insertions(+), 33 deletions(-)
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index c113d2170b1ec..e7afaf28f6348 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -786,28 +786,6 @@ static const struct blk_mq_ops virtio_mq_ops = { static unsigned int virtblk_queue_depth; module_param_named(queue_depth, virtblk_queue_depth, uint, 0444);
-static int virtblk_validate(struct virtio_device *vdev) -{ - u32 blk_size; - - if (!vdev->config->get) { - dev_err(&vdev->dev, "%s failure: config access disabled\n", - __func__); - return -EINVAL; - } - - if (!virtio_has_feature(vdev, VIRTIO_BLK_F_BLK_SIZE)) - return 0; - - blk_size = virtio_cread32(vdev, - offsetof(struct virtio_blk_config, blk_size)); - - if (blk_size < SECTOR_SIZE || blk_size > PAGE_SIZE) - __virtio_clear_bit(vdev, VIRTIO_BLK_F_BLK_SIZE); - - return 0; -} - static int virtblk_probe(struct virtio_device *vdev) { struct virtio_blk *vblk; @@ -818,6 +796,12 @@ static int virtblk_probe(struct virtio_device *vdev) u16 min_io_size; u8 physical_block_exp, alignment_offset;
+ if (!vdev->config->get) { + dev_err(&vdev->dev, "%s failure: config access disabled\n", + __func__); + return -EINVAL; + } + err = ida_simple_get(&vd_index_ida, 0, minor_to_index(1 << MINORBITS), GFP_KERNEL); if (err < 0) @@ -933,14 +917,6 @@ static int virtblk_probe(struct virtio_device *vdev) else blk_size = queue_logical_block_size(q);
- if (unlikely(blk_size < SECTOR_SIZE || blk_size > PAGE_SIZE)) { - dev_err(&vdev->dev, - "block size is changed unexpectedly, now is %u\n", - blk_size); - err = -EINVAL; - goto err_cleanup_disk; - } - /* Use topology information if available */ err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY, struct virtio_blk_config, physical_block_exp, @@ -1000,8 +976,6 @@ static int virtblk_probe(struct virtio_device *vdev) device_add_disk(&vdev->dev, vblk->disk); return 0;
-err_cleanup_disk: - blk_cleanup_queue(vblk->disk->queue); out_free_tags: blk_mq_free_tag_set(&vblk->tag_set); out_put_disk: @@ -1111,7 +1085,6 @@ static struct virtio_driver virtio_blk = { .driver.name = KBUILD_MODNAME, .driver.owner = THIS_MODULE, .id_table = id_table, - .validate = virtblk_validate, .probe = virtblk_probe, .remove = virtblk_remove, .config_changed = virtblk_config_changed,
From: Xie Yongji xieyongji@bytedance.com
mainline inclusion from mainline-5.16 commit 570b1cac4776 category: bugfix bugzilla: NA CVE: NA
-------------------------------------------------
There are some duplicated codes to validate the block size in block drivers. This limitation actually comes from block layer, so this patch tries to add a new block layer helper for that.
Signed-off-by: Xie Yongji xieyongji@bytedance.com Link: https://lore.kernel.org/r/20211026144015.188-2-xieyongji@bytedance.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Wenchao Hao haowenchao@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Reviewed-by: Miaohe Lin linmiaohe@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- include/linux/blkdev.h | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 109add33b3318..28ea02865ecc1 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -56,6 +56,14 @@ struct blk_stat_callback; */ #define BLKCG_MAX_POLS 5
+static inline int blk_validate_block_size(unsigned int bsize) +{ + if (bsize < 512 || bsize > PAGE_SIZE || !is_power_of_2(bsize)) + return -EINVAL; + + return 0; +} + typedef void (rq_end_io_fn)(struct request *, blk_status_t);
#define BLK_RL_SYNCFULL (1U << 0)
From: Xie Yongji xieyongji@bytedance.com
mainline inclusion from mainline-5.16 commit 57a13a5b8157 category: bugfix bugzilla: NA CVE: NA
-------------------------------------------------
The block layer can't support a block size larger than page size yet. And a block size that's too small or not a power of two won't work either. If a misconfigured device presents an invalid block size in configuration space, it will result in the kernel crash something like below:
[ 506.154324] BUG: kernel NULL pointer dereference, address: 0000000000000008 [ 506.160416] RIP: 0010:create_empty_buffers+0x24/0x100 [ 506.174302] Call Trace: [ 506.174651] create_page_buffers+0x4d/0x60 [ 506.175207] block_read_full_page+0x50/0x380 [ 506.175798] ? __mod_lruvec_page_state+0x60/0xa0 [ 506.176412] ? __add_to_page_cache_locked+0x1b2/0x390 [ 506.177085] ? blkdev_direct_IO+0x4a0/0x4a0 [ 506.177644] ? scan_shadow_nodes+0x30/0x30 [ 506.178206] ? lru_cache_add+0x42/0x60 [ 506.178716] do_read_cache_page+0x695/0x740 [ 506.179278] ? read_part_sector+0xe0/0xe0 [ 506.179821] read_part_sector+0x36/0xe0 [ 506.180337] adfspart_check_ICS+0x32/0x320 [ 506.180890] ? snprintf+0x45/0x70 [ 506.181350] ? read_part_sector+0xe0/0xe0 [ 506.181906] bdev_disk_changed+0x229/0x5c0 [ 506.182483] blkdev_get_whole+0x6d/0x90 [ 506.183013] blkdev_get_by_dev+0x122/0x2d0 [ 506.183562] device_add_disk+0x39e/0x3c0 [ 506.184472] virtblk_probe+0x3f8/0x79b [virtio_blk] [ 506.185461] virtio_dev_probe+0x15e/0x1d0 [virtio]
So let's use a block layer helper to validate the block size.
Conflict: origin patch used blk_cleanup_disk() which is introduced in f525464a8000 (block: add blk_alloc_disk and blk_cleanup_disk APIs) to clean resource, this patch just call blk_cleanup_queue() to perform the same operations.
Signed-off-by: Xie Yongji xieyongji@bytedance.com Acked-by: Michael S. Tsirkin mst@redhat.com Link: https://lore.kernel.org/r/20211026144015.188-5-xieyongji@bytedance.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Wenchao Hao haowenchao@huawei.com Reviewed-by: Miaohe Lin linmiaohe@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/block/virtio_blk.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index e7afaf28f6348..4da0012922e84 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -912,9 +912,17 @@ static int virtblk_probe(struct virtio_device *vdev) err = virtio_cread_feature(vdev, VIRTIO_BLK_F_BLK_SIZE, struct virtio_blk_config, blk_size, &blk_size); - if (!err) + if (!err) { + err = blk_validate_block_size(blk_size); + if (err) { + dev_err(&vdev->dev, + "virtio_blk: invalid block size: 0x%x\n", + blk_size); + goto out_cleanup_disk; + } + blk_queue_logical_block_size(q, blk_size); - else + } else blk_size = queue_logical_block_size(q);
/* Use topology information if available */ @@ -976,6 +984,8 @@ static int virtblk_probe(struct virtio_device *vdev) device_add_disk(&vdev->dev, vblk->disk); return 0;
+out_cleanup_disk: + blk_cleanup_queue(vblk->disk->queue); out_free_tags: blk_mq_free_tag_set(&vblk->tag_set); out_put_disk:
From: Jason Wang jasowang@redhat.com
mainline inclusion from mainline-5.16 commit 6ae6ff6f6e7d category: bugfix bugzilla: NA CVE: NA
-------------------------------------------------
If an untrusted device neogitates BLK_F_MQ but advertises a zero num_queues, the driver may end up trying to allocating zero size buffers where ZERO_SIZE_PTR is returned which may pass the checking against the NULL. This will lead unexpected results.
Fixing this by failing the probe in this case.
Cc: Paolo Bonzini pbonzini@redhat.com Cc: Stefan Hajnoczi stefanha@redhat.com Cc: Stefano Garzarella sgarzare@redhat.com Signed-off-by: Jason Wang jasowang@redhat.com Link: https://lore.kernel.org/r/20211019070152.8236-2-jasowang@redhat.com Signed-off-by: Michael S. Tsirkin mst@redhat.com Reviewed-by: Stefano Garzarella sgarzare@redhat.com Reviewed-by: Stefan Hajnoczi stefanha@redhat.com Signed-off-by: Wenchao Hao haowenchao@huawei.com Reviewed-by: Miaohe Lin linmiaohe@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/block/virtio_blk.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 4da0012922e84..8ec6b00138265 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -582,6 +582,10 @@ static int init_vq(struct virtio_blk *vblk) num_vqs = 1;
num_vqs = min_t(unsigned int, nr_cpu_ids, num_vqs); + if (!err && !num_vqs) { + dev_err(&vdev->dev, "MQ advertisted but zero queues reported\n"); + return -EINVAL; + }
vblk->vqs = kmalloc_array(num_vqs, sizeof(*vblk->vqs), GFP_KERNEL); if (!vblk->vqs)
From: Yanling Song songyl@ramaxel.com
Ramaxel inclusion category: features bugzilla: https://gitee.com/openeuler/kernel/issues/I4ON8F CVE: NA
Changes: 1. Split scmd_tmout_nonpt into two parameters: scmd_tmout_vd/scmd_tmout_rawdisk 2. Return -ETIME instead of -EINVAL when command is timeout. 3. Add one module parameters: max_io_force.
Signed-off-by: Yanling Song songyl@ramaxel.com Reviewed-by: Jiang Yu yujiang@ramaxel.com Reviewed-by: Zhang Lei zhanglei48@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/scsi/spraid/spraid_main.c | 96 +++++++++++++++---------------- 1 file changed, 45 insertions(+), 51 deletions(-)
diff --git a/drivers/scsi/spraid/spraid_main.c b/drivers/scsi/spraid/spraid_main.c index 519b39f44e914..7069582d741ab 100644 --- a/drivers/scsi/spraid/spraid_main.c +++ b/drivers/scsi/spraid/spraid_main.c @@ -42,10 +42,17 @@ static u32 admin_tmout = 60; module_param(admin_tmout, uint, 0644); MODULE_PARM_DESC(admin_tmout, "admin commands timeout (seconds)");
-static u32 scmd_tmout_nonpt = 180; -module_param(scmd_tmout_nonpt, uint, 0644); -MODULE_PARM_DESC(scmd_tmout_nonpt, - "scsi commands timeout for rawdisk&raid(seconds)"); +static u32 scmd_tmout_rawdisk = 180; +module_param(scmd_tmout_rawdisk, uint, 0644); +MODULE_PARM_DESC(scmd_tmout_rawdisk, "scsi commands timeout for rawdisk(seconds)"); + +static u32 scmd_tmout_vd = 180; +module_param(scmd_tmout_vd, uint, 0644); +MODULE_PARM_DESC(scmd_tmout_vd, "scsi commands timeout for vd(seconds)"); + +static bool max_io_force; +module_param(max_io_force, bool, 0644); +MODULE_PARM_DESC(max_io_force, "force max_hw_sectors_kb = 1024, default false(performance first)");
static int ioq_depth_set(const char *val, const struct kernel_param *kp); static const struct kernel_param_ops ioq_depth_ops = { @@ -78,7 +85,7 @@ static unsigned char log_debug_switch; module_param_cb(log_debug_switch, &log_debug_switch_ops, &log_debug_switch, 0644); MODULE_PARM_DESC(log_debug_switch, - "set log state, default non-zero for switch on"); + "set log state, default zero for switch off");
static int small_pool_num_set(const char *val, const struct kernel_param *kp) { @@ -132,7 +139,6 @@ static struct workqueue_struct *spraid_wq; #define SPRAID_DRV_VERSION "1.0.0.0"
#define ADMIN_TIMEOUT (admin_tmout * HZ) -#define ADMIN_ERR_TIMEOUT 32757
#define SPRAID_WAIT_ABNL_CMD_TIMEOUT (3 * 2)
@@ -242,13 +248,6 @@ static int spraid_pci_enable(struct spraid_dev *hdev) goto disable; }
- ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); - if (ret < 0) { - dev_err(hdev->dev, - "Allocate one IRQ for setup admin channel failed\n"); - goto disable; - } - hdev->cap = lo_hi_readq(hdev->bar + SPRAID_REG_CAP); hdev->ioq_depth = min_t(u32, SPRAID_CAP_MQES(hdev->cap) + 1, io_queue_depth); @@ -261,13 +260,21 @@ static int spraid_pci_enable(struct spraid_dev *hdev) maskbit); maskbit = SPRAID_DMA_MSK_BIT_MAX; } - if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(maskbit))) { + if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(maskbit)) && + dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) { dev_err(hdev->dev, "set dma mask and coherent failed\n"); goto disable; }
dev_info(hdev->dev, "set dma mask[%llu] success\n", maskbit);
+ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + + if (ret < 0) { + dev_err(hdev->dev, "Allocate one IRQ for setup admin channel failed\n"); + goto disable; + } + pci_enable_pcie_error_reporting(pdev); pci_save_state(pdev);
@@ -840,6 +847,9 @@ static void spraid_map_status(struct spraid_iod *iod, struct scsi_cmnd *scmd, break; default: set_host_byte(scmd, DID_BAD_TARGET); + dev_warn(iod->spraidq->hdev->dev, "[%s] cid[%d] qid[%d];" + "bad status[0x%x]\n", __func__, cqe->cmd_id, + le16_to_cpu(cqe->sq_id), le16_to_cpu(cqe->status)); break; } } @@ -981,32 +991,17 @@ static void spraid_slave_destroy(struct scsi_device *sdev)
static int spraid_slave_configure(struct scsi_device *sdev) { - u16 idx; - unsigned int timeout = scmd_tmout_nonpt * HZ; + unsigned int timeout = scmd_tmout_rawdisk * HZ; struct spraid_dev *hdev = shost_priv(sdev->host); struct spraid_sdev_hostdata *hostdata = sdev->hostdata; u32 max_sec = sdev->host->max_sectors;
if (hostdata) { - idx = hostdata->hdid - 1; - if (sdev->channel == hdev->devices[idx].channel && - sdev->id == le16_to_cpu(hdev->devices[idx].target) && - sdev->lun < hdev->devices[idx].lun) { - if (SPRAID_DEV_INFO_ATTR_PT(hdev->devices[idx].attr)) - timeout = 30 * HZ; - else - timeout = scmd_tmout_nonpt * HZ; - max_sec = le16_to_cpu(hdev->devices[idx].max_io_kb) - << 1; - } else { - dev_err(hdev->dev, - "[%s] err, sdev->channel:id:lun[%d:%d:%lld];" - "devices[%d], channel:target:lun[%d:%d:%d]\n", - __func__, sdev->channel, sdev->id, sdev->lun, - idx, hdev->devices[idx].channel, - hdev->devices[idx].target, - hdev->devices[idx].lun); - } + if (SPRAID_DEV_INFO_ATTR_VD(hostdata->attr)) + timeout = scmd_tmout_vd * HZ; + else if (SPRAID_DEV_INFO_ATTR_RAWDISK(hostdata->attr)) + timeout = scmd_tmout_rawdisk * HZ; + max_sec = hostdata->max_io_kb << 1; } else { dev_err(hdev->dev, "[%s] err, sdev->hostdata is null\n", __func__); @@ -1018,11 +1013,12 @@ static int spraid_slave_configure(struct scsi_device *sdev) if ((max_sec == 0) || (max_sec > sdev->host->max_sectors)) max_sec = sdev->host->max_sectors;
- dev_info(hdev->dev, - "[%s] sdev->channel:id:lun[%d:%d:%lld];" - " scmd_timeout[%d]s, maxsec[%d]\n", - __func__, sdev->channel, sdev->id, - sdev->lun, timeout / HZ, max_sec); + if (!max_io_force) + blk_queue_max_hw_sectors(sdev->request_queue, max_sec); + + dev_info(hdev->dev, "[%s] sdev->channel:id:lun[%d:%d:%lld];" + "scmd_timeout[%d]s, maxsec[%d]\n", __func__, sdev->channel, + sdev->id, sdev->lun, timeout / HZ, max_sec);
return 0; } @@ -1677,7 +1673,7 @@ static int spraid_submit_admin_sync_cmd(struct spraid_dev *hdev, cmd->usr_cmd.opcode, cmd->usr_cmd.info_0.subopcode); WRITE_ONCE(adm_cmd->state, SPRAID_CMD_TIMEOUT); spraid_put_cmd(hdev, adm_cmd, SPRAID_CMD_ADM); - return -EINVAL; + return -ETIME; }
if (result0) @@ -2630,9 +2626,6 @@ static int spraid_user_admin_cmd(struct spraid_dev *hdev, struct bsg_job *job) return -EBUSY; }
- dev_info(hdev->dev, "[%s] opcode[0x%x] subopcode[0x%x] init\n", - __func__, cmd->opcode, cmd->info_0.subopcode); - memset(&admin_cmd, 0, sizeof(admin_cmd)); admin_cmd.common.opcode = cmd->opcode; admin_cmd.common.flags = cmd->flags; @@ -2659,10 +2652,11 @@ static int spraid_user_admin_cmd(struct spraid_dev *hdev, struct bsg_job *job) memcpy(job->reply, result, sizeof(result)); }
- dev_info(hdev->dev, "[%s] opcode[0x%x] subopcode[0x%x];" - " status[0x%x] result0[0x%x] result1[0x%x]\n", - __func__, cmd->opcode, cmd->info_0.subopcode, - status, result[0], result[1]); + if (status) + dev_info(hdev->dev, "[%s] opcode[0x%x] subopcode[0x%x];" + " status[0x%x] result0[0x%x] result1[0x%x]\n", + __func__, cmd->opcode, cmd->info_0.subopcode, + status, result[0], result[1]);
spraid_bsg_unmap_data(hdev, job);
@@ -2742,7 +2736,7 @@ static int spraid_submit_ioq_sync_cmd(struct spraid_dev *hdev, (le32_to_cpu(cmd->common.cdw3[0]) & 0xffff)); WRITE_ONCE(pt_cmd->state, SPRAID_CMD_TIMEOUT); spraid_put_cmd(hdev, pt_cmd, SPRAID_CMD_IOPT); - return -EINVAL; + return -ETIME; }
if (result && reslen) { @@ -3140,7 +3134,7 @@ static int spraid_abort_handler(struct scsi_cmnd *scmd)
dev_warn(hdev->dev, "cid[%d] qid[%d] timeout, aborting\n", cid, hwq); ret = spraid_send_abort_cmd(hdev, hostdata->hdid, hwq, cid); - if (ret != ADMIN_ERR_TIMEOUT) { + if (ret != -ETIME) { ret = spraid_wait_abnl_cmd_done(iod); if (ret) { dev_warn(hdev->dev, "cid[%d] qid[%d] abort failed;" @@ -3623,7 +3617,7 @@ static int spraid_bsg_host_dispatch(struct bsg_job *job) struct spraid_bsg_request *bsg_req = job->request; int ret = 0;
- dev_info(hdev->dev, "[%s] msgcode[%d], msglen[%d], timeout[%d];" + dev_log_dbg(hdev->dev, "[%s] msgcode[%d], msglen[%d], timeout[%d];" " req_nsge[%d], req_len[%d]\n", __func__, bsg_req->msgcode, job->request_len, rq->timeout, job->request_payload.sg_cnt,