Commit 03c37174 authored by Ding Hui's avatar Ding Hui Committed by Zheng Zengkai
Browse files

scsi: ses: Fix crash caused by kfree an invalid pointer

driver inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I3BNT6


CVE: NA

-----------------------------------------------

We can get a crash when disconnecting the iSCSI session,
the call trace like this:

  [ffff00002a00fb70] kfree at ffff00000830e224
  [ffff00002a00fba0] ses_intf_remove at ffff000001f200e4
  [ffff00002a00fbd0] device_del at ffff0000086b6a98
  [ffff00002a00fc50] device_unregister at ffff0000086b6d58
  [ffff00002a00fc70] __scsi_remove_device at ffff00000870608c
  [ffff00002a00fca0] scsi_remove_device at ffff000008706134
  [ffff00002a00fcc0] __scsi_remove_target at ffff0000087062e4
  [ffff00002a00fd10] scsi_remove_target at ffff0000087064c0
  [ffff00002a00fd70] __iscsi_unbind_session at ffff000001c872c4
  [ffff00002a00fdb0] process_one_work at ffff00000810f35c
  [ffff00002a00fe00] worker_thread at ffff00000810f648
  [ffff00002a00fe70] kthread at ffff000008116e98

In ses_intf_add, components count could be 0, and kcalloc 0 size scomp,
but not saved in edev->component[i].scratch

In this situation, edev->component[0].scratch is an invalid pointer,
when kfree it in ses_intf_remove_enclosure, a crash like above would happen
The call trace also could be other random cases when kfree cannot catch
the invalid pointer

We should not use edev->component[] array when the components count is 0
We also need check index when use edev->component[] array in
ses_enclosure_data_process

Another fix option is report error and do not attach in ses_intf_add if we
meet a zero component enclosure

Tested-by: default avatarZeng Zhicong <timmyzeng@163.com>
Signed-off-by: default avatarDing Hui <dinghui@sangfor.com.cn>
Reviewed-by: default avatarJason Yan <yanaijie@huawei.com>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: default avatarCheng Jian <cj.chengjian@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
Reviewed-by: default avatarJason Yan <yanaijie@huawei.com>
Acked-by: default avatarXie XiuQi <xiexiuqi@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent 8e7f07bc
Loading
Loading
Loading
Loading
+10 −8
Original line number Diff line number Diff line
@@ -491,9 +491,6 @@ static int ses_enclosure_find_by_addr(struct enclosure_device *edev,
	int i;
	struct ses_component *scomp;

	if (!edev->component[0].scratch)
		return 0;

	for (i = 0; i < edev->components; i++) {
		scomp = edev->component[i].scratch;
		if (scomp->addr != efd->addr)
@@ -579,8 +576,10 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
						components++,
						type_ptr[0],
						name);
				else
				else if (components < edev->components)
					ecomp = &edev->component[components++];
				else
					ecomp = ERR_PTR(-EINVAL);

				if (!IS_ERR(ecomp)) {
					if (addl_desc_ptr)
@@ -745,9 +744,11 @@ static int ses_intf_add(struct device *cdev,
		buf = NULL;
	}
page2_not_supported:
	if (components > 0) {
		scomp = kcalloc(components, sizeof(struct ses_component), GFP_KERNEL);
		if (!scomp)
			goto err_free;
	}

	edev = enclosure_register(cdev->parent, dev_name(&sdev->sdev_gendev),
				  components, &ses_enclosure_callbacks);
@@ -827,6 +828,7 @@ static void ses_intf_remove_enclosure(struct scsi_device *sdev)
	kfree(ses_dev->page2);
	kfree(ses_dev);

	if (edev->components > 0)
		kfree(edev->component[0].scratch);

	put_device(&edev->edev);