]>
Commit | Line | Data |
---|---|---|
dc2c48bd GKH |
1 | From f23a4d6e07570826fe95023ca1aa96a011fa9f84 Mon Sep 17 00:00:00 2001 |
2 | From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> | |
3 | Date: Wed, 13 Mar 2024 08:21:20 -0300 | |
4 | Subject: scsi: core: Fix unremoved procfs host directory regression | |
5 | ||
6 | From: Guilherme G. Piccoli <gpiccoli@igalia.com> | |
7 | ||
8 | commit f23a4d6e07570826fe95023ca1aa96a011fa9f84 upstream. | |
9 | ||
10 | Commit fc663711b944 ("scsi: core: Remove the /proc/scsi/${proc_name} | |
11 | directory earlier") fixed a bug related to modules loading/unloading, by | |
12 | adding a call to scsi_proc_hostdir_rm() on scsi_remove_host(). But that led | |
13 | to a potential duplicate call to the hostdir_rm() routine, since it's also | |
14 | called from scsi_host_dev_release(). That triggered a regression report, | |
15 | which was then fixed by commit be03df3d4bfe ("scsi: core: Fix a procfs host | |
16 | directory removal regression"). The fix just dropped the hostdir_rm() call | |
17 | from dev_release(). | |
18 | ||
19 | But it happens that this proc directory is created on scsi_host_alloc(), | |
20 | and that function "pairs" with scsi_host_dev_release(), while | |
21 | scsi_remove_host() pairs with scsi_add_host(). In other words, it seems the | |
22 | reason for removing the proc directory on dev_release() was meant to cover | |
23 | cases in which a SCSI host structure was allocated, but the call to | |
24 | scsi_add_host() didn't happen. And that pattern happens to exist in some | |
25 | error paths, for example. | |
26 | ||
27 | Syzkaller causes that by using USB raw gadget device, error'ing on | |
28 | usb-storage driver, at usb_stor_probe2(). By checking that path, we can see | |
29 | that the BadDevice label leads to a scsi_host_put() after a SCSI host | |
30 | allocation, but there's no call to scsi_add_host() in such path. That leads | |
31 | to messages like this in dmesg (and a leak of the SCSI host proc | |
32 | structure): | |
33 | ||
34 | usb-storage 4-1:87.51: USB Mass Storage device detected | |
35 | proc_dir_entry 'scsi/usb-storage' already registered | |
36 | WARNING: CPU: 1 PID: 3519 at fs/proc/generic.c:377 proc_register+0x347/0x4e0 fs/proc/generic.c:376 | |
37 | ||
38 | The proper fix seems to still call scsi_proc_hostdir_rm() on dev_release(), | |
39 | but guard that with the state check for SHOST_CREATED; there is even a | |
40 | comment in scsi_host_dev_release() detailing that: such conditional is | |
41 | meant for cases where the SCSI host was allocated but there was no calls to | |
42 | {add,remove}_host(), like the usb-storage case. | |
43 | ||
44 | This is what we propose here and with that, the error path of usb-storage | |
45 | does not trigger the warning anymore. | |
46 | ||
47 | Reported-by: syzbot+c645abf505ed21f931b5@syzkaller.appspotmail.com | |
48 | Fixes: be03df3d4bfe ("scsi: core: Fix a procfs host directory removal regression") | |
49 | Cc: stable@vger.kernel.org | |
50 | Cc: Bart Van Assche <bvanassche@acm.org> | |
51 | Cc: John Garry <john.g.garry@oracle.com> | |
52 | Cc: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com> | |
53 | Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com> | |
54 | Link: https://lore.kernel.org/r/20240313113006.2834799-1-gpiccoli@igalia.com | |
55 | Reviewed-by: Bart Van Assche <bvanassche@acm.org> | |
56 | Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> | |
57 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
58 | --- | |
59 | drivers/scsi/hosts.c | 7 ++++--- | |
60 | 1 file changed, 4 insertions(+), 3 deletions(-) | |
61 | ||
62 | --- a/drivers/scsi/hosts.c | |
63 | +++ b/drivers/scsi/hosts.c | |
64 | @@ -334,12 +334,13 @@ static void scsi_host_dev_release(struct | |
65 | ||
66 | if (shost->shost_state == SHOST_CREATED) { | |
67 | /* | |
68 | - * Free the shost_dev device name here if scsi_host_alloc() | |
69 | - * and scsi_host_put() have been called but neither | |
70 | + * Free the shost_dev device name and remove the proc host dir | |
71 | + * here if scsi_host_{alloc,put}() have been called but neither | |
72 | * scsi_host_add() nor scsi_host_remove() has been called. | |
73 | * This avoids that the memory allocated for the shost_dev | |
74 | - * name is leaked. | |
75 | + * name as well as the proc dir structure are leaked. | |
76 | */ | |
77 | + scsi_proc_hostdir_rm(shost->hostt); | |
78 | kfree(dev_name(&shost->shost_dev)); | |
79 | } | |
80 |