From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Mike Christie <michael.christie@oracle.com>,
Lee Duncan <lduncan@suse.com>, Ding Hui <dinghui@sangfor.com.cn>,
"Martin K . Petersen" <martin.petersen@oracle.com>,
Sasha Levin <sashal@kernel.org>,
cleech@redhat.com, jejb@linux.ibm.com,
open-iscsi@googlegroups.com, linux-scsi@vger.kernel.org
Subject: [PATCH AUTOSEL 6.1 07/20] scsi: iscsi_tcp: Fix UAF during logout when accessing the shost ipaddress
Date: Tue, 31 Jan 2023 09:59:33 -0500 [thread overview]
Message-ID: <20230131145946.1249850-7-sashal@kernel.org> (raw)
In-Reply-To: <20230131145946.1249850-1-sashal@kernel.org>
From: Mike Christie <michael.christie@oracle.com>
[ Upstream commit 6f1d64b13097e85abda0f91b5638000afc5f9a06 ]
Bug report and analysis from Ding Hui.
During iSCSI session logout, if another task accesses the shost ipaddress
attr, we can get a KASAN UAF report like this:
[ 276.942144] BUG: KASAN: use-after-free in _raw_spin_lock_bh+0x78/0xe0
[ 276.942535] Write of size 4 at addr ffff8881053b45b8 by task cat/4088
[ 276.943511] CPU: 2 PID: 4088 Comm: cat Tainted: G E 6.1.0-rc8+ #3
[ 276.943997] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 11/12/2020
[ 276.944470] Call Trace:
[ 276.944943] <TASK>
[ 276.945397] dump_stack_lvl+0x34/0x48
[ 276.945887] print_address_description.constprop.0+0x86/0x1e7
[ 276.946421] print_report+0x36/0x4f
[ 276.947358] kasan_report+0xad/0x130
[ 276.948234] kasan_check_range+0x35/0x1c0
[ 276.948674] _raw_spin_lock_bh+0x78/0xe0
[ 276.949989] iscsi_sw_tcp_host_get_param+0xad/0x2e0 [iscsi_tcp]
[ 276.951765] show_host_param_ISCSI_HOST_PARAM_IPADDRESS+0xe9/0x130 [scsi_transport_iscsi]
[ 276.952185] dev_attr_show+0x3f/0x80
[ 276.953005] sysfs_kf_seq_show+0x1fb/0x3e0
[ 276.953401] seq_read_iter+0x402/0x1020
[ 276.954260] vfs_read+0x532/0x7b0
[ 276.955113] ksys_read+0xed/0x1c0
[ 276.955952] do_syscall_64+0x38/0x90
[ 276.956347] entry_SYSCALL_64_after_hwframe+0x63/0xcd
[ 276.956769] RIP: 0033:0x7f5d3a679222
[ 276.957161] Code: c0 e9 b2 fe ff ff 50 48 8d 3d 32 c0 0b 00 e8 a5 fe 01 00 0f 1f 44 00 00 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 0f 05 <48> 3d 00 f0 ff ff 77 56 c3 0f 1f 44 00 00 48 83 ec 28 48 89 54 24
[ 276.958009] RSP: 002b:00007ffc864d16a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000000
[ 276.958431] RAX: ffffffffffffffda RBX: 0000000000020000 RCX: 00007f5d3a679222
[ 276.958857] RDX: 0000000000020000 RSI: 00007f5d3a4fe000 RDI: 0000000000000003
[ 276.959281] RBP: 00007f5d3a4fe000 R08: 00000000ffffffff R09: 0000000000000000
[ 276.959682] R10: 0000000000000022 R11: 0000000000000246 R12: 0000000000020000
[ 276.960126] R13: 0000000000000003 R14: 0000000000000000 R15: 0000557a26dada58
[ 276.960536] </TASK>
[ 276.961357] Allocated by task 2209:
[ 276.961756] kasan_save_stack+0x1e/0x40
[ 276.962170] kasan_set_track+0x21/0x30
[ 276.962557] __kasan_kmalloc+0x7e/0x90
[ 276.962923] __kmalloc+0x5b/0x140
[ 276.963308] iscsi_alloc_session+0x28/0x840 [scsi_transport_iscsi]
[ 276.963712] iscsi_session_setup+0xda/0xba0 [libiscsi]
[ 276.964078] iscsi_sw_tcp_session_create+0x1fd/0x330 [iscsi_tcp]
[ 276.964431] iscsi_if_create_session.isra.0+0x50/0x260 [scsi_transport_iscsi]
[ 276.964793] iscsi_if_recv_msg+0xc5a/0x2660 [scsi_transport_iscsi]
[ 276.965153] iscsi_if_rx+0x198/0x4b0 [scsi_transport_iscsi]
[ 276.965546] netlink_unicast+0x4d5/0x7b0
[ 276.965905] netlink_sendmsg+0x78d/0xc30
[ 276.966236] sock_sendmsg+0xe5/0x120
[ 276.966576] ____sys_sendmsg+0x5fe/0x860
[ 276.966923] ___sys_sendmsg+0xe0/0x170
[ 276.967300] __sys_sendmsg+0xc8/0x170
[ 276.967666] do_syscall_64+0x38/0x90
[ 276.968028] entry_SYSCALL_64_after_hwframe+0x63/0xcd
[ 276.968773] Freed by task 2209:
[ 276.969111] kasan_save_stack+0x1e/0x40
[ 276.969449] kasan_set_track+0x21/0x30
[ 276.969789] kasan_save_free_info+0x2a/0x50
[ 276.970146] __kasan_slab_free+0x106/0x190
[ 276.970470] __kmem_cache_free+0x133/0x270
[ 276.970816] device_release+0x98/0x210
[ 276.971145] kobject_cleanup+0x101/0x360
[ 276.971462] iscsi_session_teardown+0x3fb/0x530 [libiscsi]
[ 276.971775] iscsi_sw_tcp_session_destroy+0xd8/0x130 [iscsi_tcp]
[ 276.972143] iscsi_if_recv_msg+0x1bf1/0x2660 [scsi_transport_iscsi]
[ 276.972485] iscsi_if_rx+0x198/0x4b0 [scsi_transport_iscsi]
[ 276.972808] netlink_unicast+0x4d5/0x7b0
[ 276.973201] netlink_sendmsg+0x78d/0xc30
[ 276.973544] sock_sendmsg+0xe5/0x120
[ 276.973864] ____sys_sendmsg+0x5fe/0x860
[ 276.974248] ___sys_sendmsg+0xe0/0x170
[ 276.974583] __sys_sendmsg+0xc8/0x170
[ 276.974891] do_syscall_64+0x38/0x90
[ 276.975216] entry_SYSCALL_64_after_hwframe+0x63/0xcd
We can easily reproduce by two tasks:
1. while :; do iscsiadm -m node --login; iscsiadm -m node --logout; done
2. while :; do cat \
/sys/devices/platform/host*/iscsi_host/host*/ipaddress; done
iscsid | cat
--------------------------------+---------------------------------------
|- iscsi_sw_tcp_session_destroy |
|- iscsi_session_teardown |
|- device_release |
|- iscsi_session_release ||- dev_attr_show
|- kfree | |- show_host_param_
| ISCSI_HOST_PARAM_IPADDRESS
| |- iscsi_sw_tcp_host_get_param
| |- r/w tcp_sw_host->session (UAF)
|- iscsi_host_remove |
|- iscsi_host_free |
Fix the above bug by splitting the session removal into 2 parts:
1. removal from iSCSI class which includes sysfs and removal from host
tracking.
2. freeing of session.
During iscsi_tcp host and session removal we can remove the session from
sysfs then remove the host from sysfs. At this point we know userspace is
not accessing the kernel via sysfs so we can free the session and host.
Link: https://lore.kernel.org/r/20230117193937.21244-2-michael.christie@oracle.com
Signed-off-by: Mike Christie <michael.christie@oracle.com>
Reviewed-by: Lee Duncan <lduncan@suse.com>
Acked-by: Ding Hui <dinghui@sangfor.com.cn>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/scsi/iscsi_tcp.c | 11 +++++++++--
drivers/scsi/libiscsi.c | 38 +++++++++++++++++++++++++++++++-------
include/scsi/libiscsi.h | 2 ++
3 files changed, 42 insertions(+), 9 deletions(-)
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 5fb1f364e815..9c0c8f34ef67 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -982,10 +982,17 @@ static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session)
if (WARN_ON_ONCE(session->leadconn))
return;
+ iscsi_session_remove(cls_session);
+ /*
+ * Our get_host_param needs to access the session, so remove the
+ * host from sysfs before freeing the session to make sure userspace
+ * is no longer accessing the callout.
+ */
+ iscsi_host_remove(shost, false);
+
iscsi_tcp_r2tpool_free(cls_session->dd_data);
- iscsi_session_teardown(cls_session);
- iscsi_host_remove(shost, false);
+ iscsi_session_free(cls_session);
iscsi_host_free(shost);
}
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index d95f4bcdeb2e..6e811d753cb1 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -3104,17 +3104,32 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
}
EXPORT_SYMBOL_GPL(iscsi_session_setup);
-/**
- * iscsi_session_teardown - destroy session, host, and cls_session
- * @cls_session: iscsi session
+/*
+ * issi_session_remove - Remove session from iSCSI class.
*/
-void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+void iscsi_session_remove(struct iscsi_cls_session *cls_session)
{
struct iscsi_session *session = cls_session->dd_data;
- struct module *owner = cls_session->transport->owner;
struct Scsi_Host *shost = session->host;
iscsi_remove_session(cls_session);
+ /*
+ * host removal only has to wait for its children to be removed from
+ * sysfs, and iscsi_tcp needs to do iscsi_host_remove before freeing
+ * the session, so drop the session count here.
+ */
+ iscsi_host_dec_session_cnt(shost);
+}
+EXPORT_SYMBOL_GPL(iscsi_session_remove);
+
+/**
+ * iscsi_session_free - Free iscsi session and it's resources
+ * @cls_session: iscsi session
+ */
+void iscsi_session_free(struct iscsi_cls_session *cls_session)
+{
+ struct iscsi_session *session = cls_session->dd_data;
+ struct module *owner = cls_session->transport->owner;
iscsi_pool_free(&session->cmdpool);
kfree(session->password);
@@ -3132,10 +3147,19 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
kfree(session->discovery_parent_type);
iscsi_free_session(cls_session);
-
- iscsi_host_dec_session_cnt(shost);
module_put(owner);
}
+EXPORT_SYMBOL_GPL(iscsi_session_free);
+
+/**
+ * iscsi_session_teardown - destroy session and cls_session
+ * @cls_session: iscsi session
+ */
+void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+{
+ iscsi_session_remove(cls_session);
+ iscsi_session_free(cls_session);
+}
EXPORT_SYMBOL_GPL(iscsi_session_teardown);
/**
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 654cc3918c94..7fb3cb787df4 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -422,6 +422,8 @@ extern int iscsi_host_get_max_scsi_cmds(struct Scsi_Host *shost,
extern struct iscsi_cls_session *
iscsi_session_setup(struct iscsi_transport *, struct Scsi_Host *shost,
uint16_t, int, int, uint32_t, unsigned int);
+void iscsi_session_remove(struct iscsi_cls_session *cls_session);
+void iscsi_session_free(struct iscsi_cls_session *cls_session);
extern void iscsi_session_teardown(struct iscsi_cls_session *);
extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
extern int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
--
2.39.0
next prev parent reply other threads:[~2023-01-31 15:00 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-01-31 14:59 [PATCH AUTOSEL 6.1 01/20] i2c: designware-pci: Add new PCI IDs for AMD NAVI GPU Sasha Levin
2023-01-31 14:59 ` [PATCH AUTOSEL 6.1 02/20] i2c: mxs: suppress probe-deferral error message Sasha Levin
2023-01-31 14:59 ` [PATCH AUTOSEL 6.1 03/20] scsi: target: core: Fix warning on RT kernels Sasha Levin
2023-01-31 14:59 ` [PATCH AUTOSEL 6.1 04/20] x86/aperfmperf: Erase stale arch_freq_scale values when disabling frequency invariance readings Sasha Levin
2023-01-31 14:59 ` [PATCH AUTOSEL 6.1 05/20] perf/x86/intel: Add Emerald Rapids Sasha Levin
2023-01-31 14:59 ` [PATCH AUTOSEL 6.1 06/20] perf/x86/intel/cstate: " Sasha Levin
2023-01-31 14:59 ` Sasha Levin [this message]
2023-01-31 14:59 ` [PATCH AUTOSEL 6.1 08/20] scsi: iscsi_tcp: Fix UAF during login when accessing the shost ipaddress Sasha Levin
2023-01-31 14:59 ` [PATCH AUTOSEL 6.1 09/20] i2c: rk3x: fix a bunch of kernel-doc warnings Sasha Levin
2023-01-31 14:59 ` [PATCH AUTOSEL 6.1 10/20] Revert "gfs2: stop using generic_writepages in gfs2_ail1_start_one" Sasha Levin
2023-01-31 14:59 ` [PATCH AUTOSEL 6.1 11/20] x86/build: Move '-mindirect-branch-cs-prefix' out of GCC-only block Sasha Levin
2023-01-31 14:59 ` [PATCH AUTOSEL 6.1 12/20] ACPI: video: Add backlight=native DMI quirk for HP Pavilion g6-1d80nr Sasha Levin
2023-01-31 14:59 ` [PATCH AUTOSEL 6.1 13/20] platform/x86: dell-wmi: Add a keymap for KEY_MUTE in type 0x0010 table Sasha Levin
2023-01-31 14:59 ` [PATCH AUTOSEL 6.1 14/20] platform/x86: hp-wmi: Handle Omen Key event Sasha Levin
2023-01-31 14:59 ` [PATCH AUTOSEL 6.1 15/20] platform/x86: gigabyte-wmi: add support for B450M DS3H WIFI-CF Sasha Levin
2023-01-31 14:59 ` [PATCH AUTOSEL 6.1 16/20] platform/x86/amd: pmc: Disable IRQ1 wakeup for RN/CZN Sasha Levin
2023-01-31 14:59 ` [PATCH AUTOSEL 6.1 17/20] net/x25: Fix to not accept on connected socket Sasha Levin
2023-01-31 14:59 ` [PATCH AUTOSEL 6.1 18/20] drm/amd/display: Fix timing not changning when freesync video is enabled Sasha Levin
2023-01-31 14:59 ` [PATCH AUTOSEL 6.1 19/20] bcache: Silence memcpy() run-time false positive warnings Sasha Levin
2023-01-31 14:59 ` [PATCH AUTOSEL 6.1 20/20] amdgpu: fix build on non-DCN platforms Sasha Levin
2023-01-31 15:27 ` Deucher, Alexander
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230131145946.1249850-7-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=cleech@redhat.com \
--cc=dinghui@sangfor.com.cn \
--cc=jejb@linux.ibm.com \
--cc=lduncan@suse.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=martin.petersen@oracle.com \
--cc=michael.christie@oracle.com \
--cc=open-iscsi@googlegroups.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox