linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] libata/libsas cleanup fixes
@ 2024-06-29 12:42 Niklas Cassel
  2024-06-29 12:42 ` [PATCH 1/4] ata: libata-core: Fix null pointer dereference on error Niklas Cassel
                   ` (5 more replies)
  0 siblings, 6 replies; 12+ messages in thread
From: Niklas Cassel @ 2024-06-29 12:42 UTC (permalink / raw)
  To: Damien Le Moal, Niklas Cassel, John Garry, Jason Yan,
	James E.J. Bottomley, Martin K. Petersen, Jeff Garzik, Tejun Heo,
	Hannes Reinecke, Colin Ian King, Jens Axboe, Kai-Heng Feng
  Cc: linux-scsi, Niklas Cassel, linux-ide

Hello there,

This series takes the patches that are -stable material from this series:
https://lore.kernel.org/linux-ide/20240626180031.4050226-15-cassel@kernel.org/

Changes since series above:
-Fixed minor review comments for the four patches included in the series.
-Picked up tags.


Kind regards,
Niklas


Niklas Cassel (4):
  ata: libata-core: Fix null pointer dereference on error
  ata,scsi: libata-core: Do not leak memory for ata_port struct members
  ata: libata-core: Fix double free on error
  ata: ahci: Clean up sysfs file on error

 drivers/ata/ahci.c                 | 17 ++++++++++++-----
 drivers/ata/libata-core.c          | 29 ++++++++++++++++++-----------
 drivers/scsi/libsas/sas_ata.c      |  2 +-
 drivers/scsi/libsas/sas_discover.c |  2 +-
 include/linux/libata.h             |  1 +
 5 files changed, 33 insertions(+), 18 deletions(-)

-- 
2.45.2


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/4] ata: libata-core: Fix null pointer dereference on error
  2024-06-29 12:42 [PATCH 0/4] libata/libsas cleanup fixes Niklas Cassel
@ 2024-06-29 12:42 ` Niklas Cassel
  2024-06-30  9:36   ` John Garry
  2024-06-29 12:42 ` [PATCH 2/4] ata,scsi: libata-core: Do not leak memory for ata_port struct members Niklas Cassel
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Niklas Cassel @ 2024-06-29 12:42 UTC (permalink / raw)
  To: Damien Le Moal, Niklas Cassel, Tejun Heo, Jeff Garzik
  Cc: linux-scsi, John Garry, Jason Yan, Martin K. Petersen,
	James E.J. Bottomley, stable, Hannes Reinecke, linux-ide

If the ata_port_alloc() call in ata_host_alloc() fails,
ata_host_release() will get called.

However, the code in ata_host_release() tries to free ata_port struct
members unconditionally, which can lead to the following:

BUG: unable to handle page fault for address: 0000000000003990
PGD 0 P4D 0
Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI
CPU: 10 PID: 594 Comm: (udev-worker) Not tainted 6.10.0-rc5 #44
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-2.fc40 04/01/2014
RIP: 0010:ata_host_release.cold+0x2f/0x6e [libata]
Code: e4 4d 63 f4 44 89 e2 48 c7 c6 90 ad 32 c0 48 c7 c7 d0 70 33 c0 49 83 c6 0e 41
RSP: 0018:ffffc90000ebb968 EFLAGS: 00010246
RAX: 0000000000000041 RBX: ffff88810fb52e78 RCX: 0000000000000000
RDX: 0000000000000000 RSI: ffff88813b3218c0 RDI: ffff88813b3218c0
RBP: ffff88810fb52e40 R08: 0000000000000000 R09: 6c65725f74736f68
R10: ffffc90000ebb738 R11: 73692033203a746e R12: 0000000000000004
R13: 0000000000000000 R14: 0000000000000011 R15: 0000000000000006
FS:  00007f6cc55b9980(0000) GS:ffff88813b300000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000003990 CR3: 00000001122a2000 CR4: 0000000000750ef0
PKRU: 55555554
Call Trace:
 <TASK>
 ? __die_body.cold+0x19/0x27
 ? page_fault_oops+0x15a/0x2f0
 ? exc_page_fault+0x7e/0x180
 ? asm_exc_page_fault+0x26/0x30
 ? ata_host_release.cold+0x2f/0x6e [libata]
 ? ata_host_release.cold+0x2f/0x6e [libata]
 release_nodes+0x35/0xb0
 devres_release_group+0x113/0x140
 ata_host_alloc+0xed/0x120 [libata]
 ata_host_alloc_pinfo+0x14/0xa0 [libata]
 ahci_init_one+0x6c9/0xd20 [ahci]

Do not access ata_port struct members unconditionally.

Fixes: 633273a3ed1c ("libata-pmp: hook PMP support and enable it")
Cc: stable@vger.kernel.org
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Niklas Cassel <cassel@kernel.org>
---
 drivers/ata/libata-core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index e1bf8a19b3c8..f47838da75d7 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5518,6 +5518,9 @@ static void ata_host_release(struct kref *kref)
 	for (i = 0; i < host->n_ports; i++) {
 		struct ata_port *ap = host->ports[i];
 
+		if (!ap)
+			continue;
+
 		kfree(ap->pmp_link);
 		kfree(ap->slave_link);
 		kfree(ap->ncq_sense_buf);
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/4] ata,scsi: libata-core: Do not leak memory for ata_port struct members
  2024-06-29 12:42 [PATCH 0/4] libata/libsas cleanup fixes Niklas Cassel
  2024-06-29 12:42 ` [PATCH 1/4] ata: libata-core: Fix null pointer dereference on error Niklas Cassel
@ 2024-06-29 12:42 ` Niklas Cassel
  2024-06-30  9:42   ` John Garry
  2024-07-01  6:21   ` Hannes Reinecke
  2024-06-29 12:42 ` [PATCH 3/4] ata: libata-core: Fix double free on error Niklas Cassel
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 12+ messages in thread
From: Niklas Cassel @ 2024-06-29 12:42 UTC (permalink / raw)
  To: Damien Le Moal, Niklas Cassel, John Garry, Jason Yan,
	James E.J. Bottomley, Martin K. Petersen, Hannes Reinecke
  Cc: linux-scsi, Niklas Cassel, linux-ide

libsas is currently not freeing all the struct ata_port struct members,
e.g. ncq_sense_buf for a driver supporting Command Duration Limits (CDL).

Add a function, ata_port_free(), that is used to free a ata_port,
including its struct members. It makes sense to keep the code related to
freeing a ata_port in its own function, which will also free all the
struct members of struct ata_port.

Fixes: 18bd7718b5c4 ("scsi: ata: libata: Handle completion of CDL commands using policy 0xD")
Signed-off-by: Niklas Cassel <cassel@kernel.org>
---
 drivers/ata/libata-core.c          | 24 ++++++++++++++----------
 drivers/scsi/libsas/sas_ata.c      |  2 +-
 drivers/scsi/libsas/sas_discover.c |  2 +-
 include/linux/libata.h             |  1 +
 4 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index f47838da75d7..481baa55ebfc 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5490,6 +5490,18 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
 	return ap;
 }
 
+void ata_port_free(struct ata_port *ap)
+{
+	if (!ap)
+		return;
+
+	kfree(ap->pmp_link);
+	kfree(ap->slave_link);
+	kfree(ap->ncq_sense_buf);
+	kfree(ap);
+}
+EXPORT_SYMBOL_GPL(ata_port_free);
+
 static void ata_devres_release(struct device *gendev, void *res)
 {
 	struct ata_host *host = dev_get_drvdata(gendev);
@@ -5516,15 +5528,7 @@ static void ata_host_release(struct kref *kref)
 	int i;
 
 	for (i = 0; i < host->n_ports; i++) {
-		struct ata_port *ap = host->ports[i];
-
-		if (!ap)
-			continue;
-
-		kfree(ap->pmp_link);
-		kfree(ap->slave_link);
-		kfree(ap->ncq_sense_buf);
-		kfree(ap);
+		ata_port_free(host->ports[i]);
 		host->ports[i] = NULL;
 	}
 	kfree(host);
@@ -5907,7 +5911,7 @@ int ata_host_register(struct ata_host *host, const struct scsi_host_template *sh
 	 * allocation time.
 	 */
 	for (i = host->n_ports; host->ports[i]; i++)
-		kfree(host->ports[i]);
+		ata_port_free(host->ports[i]);
 
 	/* give ports names and add SCSI hosts */
 	for (i = 0; i < host->n_ports; i++) {
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 4c69fc63c119..1f247a8cd185 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -618,7 +618,7 @@ int sas_ata_init(struct domain_device *found_dev)
 	return 0;
 
 destroy_port:
-	kfree(ap);
+	ata_port_free(ap);
 free_host:
 	ata_host_put(ata_host);
 	return rc;
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index 8fb7c41c0962..48d975c6dbf2 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -301,7 +301,7 @@ void sas_free_device(struct kref *kref)
 
 	if (dev_is_sata(dev) && dev->sata_dev.ap) {
 		ata_sas_tport_delete(dev->sata_dev.ap);
-		kfree(dev->sata_dev.ap);
+		ata_port_free(dev->sata_dev.ap);
 		ata_host_put(dev->sata_dev.ata_host);
 		dev->sata_dev.ata_host = NULL;
 		dev->sata_dev.ap = NULL;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 13fb41d25da6..7d3bd7c9664a 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -1249,6 +1249,7 @@ extern int ata_slave_link_init(struct ata_port *ap);
 extern struct ata_port *ata_sas_port_alloc(struct ata_host *,
 					   struct ata_port_info *, struct Scsi_Host *);
 extern void ata_port_probe(struct ata_port *ap);
+extern void ata_port_free(struct ata_port *ap);
 extern int ata_sas_tport_add(struct device *parent, struct ata_port *ap);
 extern void ata_sas_tport_delete(struct ata_port *ap);
 int ata_sas_device_configure(struct scsi_device *sdev, struct queue_limits *lim,
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/4] ata: libata-core: Fix double free on error
  2024-06-29 12:42 [PATCH 0/4] libata/libsas cleanup fixes Niklas Cassel
  2024-06-29 12:42 ` [PATCH 1/4] ata: libata-core: Fix null pointer dereference on error Niklas Cassel
  2024-06-29 12:42 ` [PATCH 2/4] ata,scsi: libata-core: Do not leak memory for ata_port struct members Niklas Cassel
@ 2024-06-29 12:42 ` Niklas Cassel
  2024-06-29 12:42 ` [PATCH 4/4] ata: ahci: Clean up sysfs file " Niklas Cassel
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Niklas Cassel @ 2024-06-29 12:42 UTC (permalink / raw)
  To: Damien Le Moal, Niklas Cassel, Tejun Heo, Colin Ian King
  Cc: linux-scsi, John Garry, Jason Yan, Martin K. Petersen,
	James E.J. Bottomley, stable, Hannes Reinecke, linux-ide

If e.g. the ata_port_alloc() call in ata_host_alloc() fails, we will jump
to the err_out label, which will call devres_release_group().
devres_release_group() will trigger a call to ata_host_release().
ata_host_release() calls kfree(host), so executing the kfree(host) in
ata_host_alloc() will lead to a double free:

kernel BUG at mm/slub.c:553!
Oops: invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
CPU: 11 PID: 599 Comm: (udev-worker) Not tainted 6.10.0-rc5 #47
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-2.fc40 04/01/2014
RIP: 0010:kfree+0x2cf/0x2f0
Code: 5d 41 5e 41 5f 5d e9 80 d6 ff ff 4d 89 f1 41 b8 01 00 00 00 48 89 d9 48 89 da
RSP: 0018:ffffc90000f377f0 EFLAGS: 00010246
RAX: ffff888112b1f2c0 RBX: ffff888112b1f2c0 RCX: ffff888112b1f320
RDX: 000000000000400b RSI: ffffffffc02c9de5 RDI: ffff888112b1f2c0
RBP: ffffc90000f37830 R08: 0000000000000000 R09: 0000000000000000
R10: ffffc90000f37610 R11: 617461203a736b6e R12: ffffea00044ac780
R13: ffff888100046400 R14: ffffffffc02c9de5 R15: 0000000000000006
FS:  00007f2f1cabe980(0000) GS:ffff88813b380000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f2f1c3acf75 CR3: 0000000111724000 CR4: 0000000000750ef0
PKRU: 55555554
Call Trace:
 <TASK>
 ? __die_body.cold+0x19/0x27
 ? die+0x2e/0x50
 ? do_trap+0xca/0x110
 ? do_error_trap+0x6a/0x90
 ? kfree+0x2cf/0x2f0
 ? exc_invalid_op+0x50/0x70
 ? kfree+0x2cf/0x2f0
 ? asm_exc_invalid_op+0x1a/0x20
 ? ata_host_alloc+0xf5/0x120 [libata]
 ? ata_host_alloc+0xf5/0x120 [libata]
 ? kfree+0x2cf/0x2f0
 ata_host_alloc+0xf5/0x120 [libata]
 ata_host_alloc_pinfo+0x14/0xa0 [libata]
 ahci_init_one+0x6c9/0xd20 [ahci]

Ensure that we will not call kfree(host) twice, by performing the kfree()
only if the devres_open_group() call failed.

Fixes: dafd6c496381 ("libata: ensure host is free'd on error exit paths")
Cc: stable@vger.kernel.org
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Niklas Cassel <cassel@kernel.org>
---
 drivers/ata/libata-core.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 481baa55ebfc..e0455a182af7 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5578,8 +5578,10 @@ struct ata_host *ata_host_alloc(struct device *dev, int max_ports)
 	if (!host)
 		return NULL;
 
-	if (!devres_open_group(dev, NULL, GFP_KERNEL))
-		goto err_free;
+	if (!devres_open_group(dev, NULL, GFP_KERNEL)) {
+		kfree(host);
+		return NULL;
+	}
 
 	dr = devres_alloc(ata_devres_release, 0, GFP_KERNEL);
 	if (!dr)
@@ -5611,8 +5613,6 @@ struct ata_host *ata_host_alloc(struct device *dev, int max_ports)
 
  err_out:
 	devres_release_group(dev, NULL);
- err_free:
-	kfree(host);
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(ata_host_alloc);
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/4] ata: ahci: Clean up sysfs file on error
  2024-06-29 12:42 [PATCH 0/4] libata/libsas cleanup fixes Niklas Cassel
                   ` (2 preceding siblings ...)
  2024-06-29 12:42 ` [PATCH 3/4] ata: libata-core: Fix double free on error Niklas Cassel
@ 2024-06-29 12:42 ` Niklas Cassel
  2024-06-30 21:02 ` [PATCH 0/4] libata/libsas cleanup fixes Niklas Cassel
  2024-06-30 21:05 ` Niklas Cassel
  5 siblings, 0 replies; 12+ messages in thread
From: Niklas Cassel @ 2024-06-29 12:42 UTC (permalink / raw)
  To: Damien Le Moal, Niklas Cassel, Jens Axboe, Kai-Heng Feng
  Cc: linux-scsi, John Garry, Jason Yan, Martin K. Petersen,
	James E.J. Bottomley, stable, Hannes Reinecke, linux-ide

.probe() (ahci_init_one()) calls sysfs_add_file_to_group(), however,
if probe() fails after this call, we currently never call
sysfs_remove_file_from_group().

(The sysfs_remove_file_from_group() call in .remove() (ahci_remove_one())
does not help, as .remove() is not called on .probe() error.)

Thus, if probe() fails after the sysfs_add_file_to_group() call, the next
time we insmod the module we will get:

sysfs: cannot create duplicate filename '/devices/pci0000:00/0000:00:04.0/remapped_nvme'
CPU: 11 PID: 954 Comm: modprobe Not tainted 6.10.0-rc5 #43
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-2.fc40 04/01/2014
Call Trace:
 <TASK>
 dump_stack_lvl+0x5d/0x80
 sysfs_warn_dup.cold+0x17/0x23
 sysfs_add_file_mode_ns+0x11a/0x130
 sysfs_add_file_to_group+0x7e/0xc0
 ahci_init_one+0x31f/0xd40 [ahci]

Fixes: 894fba7f434a ("ata: ahci: Add sysfs attribute to show remapped NVMe device count")
Cc: stable@vger.kernel.org
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Niklas Cassel <cassel@kernel.org>
---
 drivers/ata/ahci.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 5eb38fbbbecd..fc6fd583faf8 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1975,8 +1975,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
 
 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
-	if (!host)
-		return -ENOMEM;
+	if (!host) {
+		rc = -ENOMEM;
+		goto err_rm_sysfs_file;
+	}
 	host->private_data = hpriv;
 
 	if (ahci_init_msi(pdev, n_ports, hpriv) < 0) {
@@ -2031,11 +2033,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	/* initialize adapter */
 	rc = ahci_configure_dma_masks(pdev, hpriv);
 	if (rc)
-		return rc;
+		goto err_rm_sysfs_file;
 
 	rc = ahci_pci_reset_controller(host);
 	if (rc)
-		return rc;
+		goto err_rm_sysfs_file;
 
 	ahci_pci_init_controller(host);
 	ahci_pci_print_info(host);
@@ -2044,10 +2046,15 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	rc = ahci_host_activate(host, &ahci_sht);
 	if (rc)
-		return rc;
+		goto err_rm_sysfs_file;
 
 	pm_runtime_put_noidle(&pdev->dev);
 	return 0;
+
+err_rm_sysfs_file:
+	sysfs_remove_file_from_group(&pdev->dev.kobj,
+				     &dev_attr_remapped_nvme.attr, NULL);
+	return rc;
 }
 
 static void ahci_shutdown_one(struct pci_dev *pdev)
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/4] ata: libata-core: Fix null pointer dereference on error
  2024-06-29 12:42 ` [PATCH 1/4] ata: libata-core: Fix null pointer dereference on error Niklas Cassel
@ 2024-06-30  9:36   ` John Garry
  0 siblings, 0 replies; 12+ messages in thread
From: John Garry @ 2024-06-30  9:36 UTC (permalink / raw)
  To: Niklas Cassel, Damien Le Moal, Tejun Heo, Jeff Garzik
  Cc: linux-scsi, Jason Yan, Martin K. Petersen, James E.J. Bottomley,
	stable, Hannes Reinecke, linux-ide


> 
> Fixes: 633273a3ed1c ("libata-pmp: hook PMP support and enable it")
> Cc:stable@vger.kernel.org
> Reviewed-by: Damien Le Moal<dlemoal@kernel.org>
> Reviewed-by: Hannes Reinecke<hare@suse.de>
> Signed-off-by: Niklas Cassel<cassel@kernel.org>
> ---

Reviewed-by: John Garry <john.g.garry@oracle.com>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/4] ata,scsi: libata-core: Do not leak memory for ata_port struct members
  2024-06-29 12:42 ` [PATCH 2/4] ata,scsi: libata-core: Do not leak memory for ata_port struct members Niklas Cassel
@ 2024-06-30  9:42   ` John Garry
  2024-06-30 20:28     ` Niklas Cassel
  2024-07-01  6:21   ` Hannes Reinecke
  1 sibling, 1 reply; 12+ messages in thread
From: John Garry @ 2024-06-30  9:42 UTC (permalink / raw)
  To: Niklas Cassel, Damien Le Moal, Jason Yan, James E.J. Bottomley,
	Martin K. Petersen, Hannes Reinecke
  Cc: linux-scsi, Niklas Cassel, linux-ide

On 29/06/2024 13:42, Niklas Cassel wrote:
> libsas is currently not freeing all the struct ata_port struct members,
> e.g. ncq_sense_buf for a driver supporting Command Duration Limits (CDL).
> 
> Add a function, ata_port_free(), that is used to free a ata_port,
> including its struct members. It makes sense to keep the code related to
> freeing a ata_port in its own function, which will also free all the
> struct members of struct ata_port.
> 
> Fixes: 18bd7718b5c4 ("scsi: ata: libata: Handle completion of CDL commands using policy 0xD")
> Signed-off-by: Niklas Cassel <cassel@kernel.org>

Apart from a couple of nitpicks:

Reviewed-by: John Garry <john.g.garry@oracle.com>

> ---
>   drivers/ata/libata-core.c          | 24 ++++++++++++++----------
>   drivers/scsi/libsas/sas_ata.c      |  2 +-
>   drivers/scsi/libsas/sas_discover.c |  2 +-
>   include/linux/libata.h             |  1 +
>   4 files changed, 17 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
> index f47838da75d7..481baa55ebfc 100644
> --- a/drivers/ata/libata-core.c
> +++ b/drivers/ata/libata-core.c
> @@ -5490,6 +5490,18 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
>   	return ap;
>   }
>   
> +void ata_port_free(struct ata_port *ap)
> +{
> +	if (!ap)
> +		return;

nit: personally I'd have the caller check this. The main reason for that 
is that often it seems an unnecessary check.

> +
> +	kfree(ap->pmp_link);
> +	kfree(ap->slave_link);
> +	kfree(ap->ncq_sense_buf);
> +	kfree(ap);
> +}
> +EXPORT_SYMBOL_GPL(ata_port_free);
> +
>   static void ata_devres_release(struct device *gendev, void *res)
>   {
>   	struct ata_host *host = dev_get_drvdata(gendev);
> @@ -5516,15 +5528,7 @@ static void ata_host_release(struct kref *kref)
>   	int i;
>   
>   	for (i = 0; i < host->n_ports; i++) {
> -		struct ata_port *ap = host->ports[i];
> -
> -		if (!ap)
> -			continue;
> -
> -		kfree(ap->pmp_link);
> -		kfree(ap->slave_link);
> -		kfree(ap->ncq_sense_buf);
> -		kfree(ap);
> +		ata_port_free(host->ports[i]);
>   		host->ports[i] = NULL;
>   	}
>   	kfree(host);
> @@ -5907,7 +5911,7 @@ int ata_host_register(struct ata_host *host, const struct scsi_host_template *sh
>   	 * allocation time.
>   	 */
>   	for (i = host->n_ports; host->ports[i]; i++)
> -		kfree(host->ports[i]);
> +		ata_port_free(host->ports[i]);
>   
>   	/* give ports names and add SCSI hosts */
>   	for (i = 0; i < host->n_ports; i++) {
> diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
> index 4c69fc63c119..1f247a8cd185 100644
> --- a/drivers/scsi/libsas/sas_ata.c
> +++ b/drivers/scsi/libsas/sas_ata.c
> @@ -618,7 +618,7 @@ int sas_ata_init(struct domain_device *found_dev)
>   	return 0;
>   
>   destroy_port:
> -	kfree(ap);
> +	ata_port_free(ap);

nit: If not a nuisance, could we change the label name to free_port, 
like free_host, below. No big deal.

>   free_host:
>   	ata_host_put(ata_host);
>   	return rc;
> diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
> index 8fb7c41c0962..48d975c6dbf2 100644
> --- a/drivers/scsi/libsas/sas_discover.c
> +++ b/drivers/scsi/libsas/sas_discover.c
> @@ -301,7 +301,7 @@ void sas_free_device(struct kref *kref)
>   
>   	if (dev_is_sata(dev) && dev->sata_dev.ap) {
>   		ata_sas_tport_delete(dev->sata_dev.ap);
> -		kfree(dev->sata_dev.ap);
> +		ata_port_free(dev->sata_dev.ap);
>   		ata_host_put(dev->sata_dev.ata_host);
>   		dev->sata_dev.ata_host = NULL;
>   		dev->sata_dev.ap = NULL;
> diff --git a/include/linux/libata.h b/include/linux/libata.h
> index 13fb41d25da6..7d3bd7c9664a 100644
> --- a/include/linux/libata.h
> +++ b/include/linux/libata.h
> @@ -1249,6 +1249,7 @@ extern int ata_slave_link_init(struct ata_port *ap);
>   extern struct ata_port *ata_sas_port_alloc(struct ata_host *,
>   					   struct ata_port_info *, struct Scsi_Host *);
>   extern void ata_port_probe(struct ata_port *ap);
> +extern void ata_port_free(struct ata_port *ap);
>   extern int ata_sas_tport_add(struct device *parent, struct ata_port *ap);
>   extern void ata_sas_tport_delete(struct ata_port *ap);
>   int ata_sas_device_configure(struct scsi_device *sdev, struct queue_limits *lim,


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/4] ata,scsi: libata-core: Do not leak memory for ata_port struct members
  2024-06-30  9:42   ` John Garry
@ 2024-06-30 20:28     ` Niklas Cassel
  0 siblings, 0 replies; 12+ messages in thread
From: Niklas Cassel @ 2024-06-30 20:28 UTC (permalink / raw)
  To: John Garry
  Cc: Damien Le Moal, Jason Yan, James E.J. Bottomley,
	Martin K. Petersen, Hannes Reinecke, linux-scsi, Niklas Cassel,
	linux-ide

On Sun, Jun 30, 2024 at 10:42:45AM +0100, John Garry wrote:
> On 29/06/2024 13:42, Niklas Cassel wrote:
> > libsas is currently not freeing all the struct ata_port struct members,
> > e.g. ncq_sense_buf for a driver supporting Command Duration Limits (CDL).
> > 
> > Add a function, ata_port_free(), that is used to free a ata_port,
> > including its struct members. It makes sense to keep the code related to
> > freeing a ata_port in its own function, which will also free all the
> > struct members of struct ata_port.
> > 
> > Fixes: 18bd7718b5c4 ("scsi: ata: libata: Handle completion of CDL commands using policy 0xD")
> > Signed-off-by: Niklas Cassel <cassel@kernel.org>
> 
> Apart from a couple of nitpicks:
> 
> Reviewed-by: John Garry <john.g.garry@oracle.com>
> 
> > ---
> >   drivers/ata/libata-core.c          | 24 ++++++++++++++----------
> >   drivers/scsi/libsas/sas_ata.c      |  2 +-
> >   drivers/scsi/libsas/sas_discover.c |  2 +-
> >   include/linux/libata.h             |  1 +
> >   4 files changed, 17 insertions(+), 12 deletions(-)
> > 
> > diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
> > index f47838da75d7..481baa55ebfc 100644
> > --- a/drivers/ata/libata-core.c
> > +++ b/drivers/ata/libata-core.c
> > @@ -5490,6 +5490,18 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
> >   	return ap;
> >   }
> > +void ata_port_free(struct ata_port *ap)
> > +{
> > +	if (!ap)
> > +		return;
> 
> nit: personally I'd have the caller check this. The main reason for that is
> that often it seems an unnecessary check.

People are used to free() family of functions handling NULL,
so I think it is wise to keep it as is.


> 
> > +
> > +	kfree(ap->pmp_link);
> > +	kfree(ap->slave_link);
> > +	kfree(ap->ncq_sense_buf);
> > +	kfree(ap);
> > +}
> > +EXPORT_SYMBOL_GPL(ata_port_free);
> > +
> >   static void ata_devres_release(struct device *gendev, void *res)
> >   {
> >   	struct ata_host *host = dev_get_drvdata(gendev);
> > @@ -5516,15 +5528,7 @@ static void ata_host_release(struct kref *kref)
> >   	int i;
> >   	for (i = 0; i < host->n_ports; i++) {
> > -		struct ata_port *ap = host->ports[i];
> > -
> > -		if (!ap)
> > -			continue;
> > -
> > -		kfree(ap->pmp_link);
> > -		kfree(ap->slave_link);
> > -		kfree(ap->ncq_sense_buf);
> > -		kfree(ap);
> > +		ata_port_free(host->ports[i]);
> >   		host->ports[i] = NULL;
> >   	}
> >   	kfree(host);
> > @@ -5907,7 +5911,7 @@ int ata_host_register(struct ata_host *host, const struct scsi_host_template *sh
> >   	 * allocation time.
> >   	 */
> >   	for (i = host->n_ports; host->ports[i]; i++)
> > -		kfree(host->ports[i]);
> > +		ata_port_free(host->ports[i]);
> >   	/* give ports names and add SCSI hosts */
> >   	for (i = 0; i < host->n_ports; i++) {
> > diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
> > index 4c69fc63c119..1f247a8cd185 100644
> > --- a/drivers/scsi/libsas/sas_ata.c
> > +++ b/drivers/scsi/libsas/sas_ata.c
> > @@ -618,7 +618,7 @@ int sas_ata_init(struct domain_device *found_dev)
> >   	return 0;
> >   destroy_port:
> > -	kfree(ap);
> > +	ata_port_free(ap);
> 
> nit: If not a nuisance, could we change the label name to free_port, like
> free_host, below. No big deal.

Sure, will fixup when applying.


> 
> >   free_host:
> >   	ata_host_put(ata_host);
> >   	return rc;
> > diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
> > index 8fb7c41c0962..48d975c6dbf2 100644
> > --- a/drivers/scsi/libsas/sas_discover.c
> > +++ b/drivers/scsi/libsas/sas_discover.c
> > @@ -301,7 +301,7 @@ void sas_free_device(struct kref *kref)
> >   	if (dev_is_sata(dev) && dev->sata_dev.ap) {
> >   		ata_sas_tport_delete(dev->sata_dev.ap);
> > -		kfree(dev->sata_dev.ap);
> > +		ata_port_free(dev->sata_dev.ap);
> >   		ata_host_put(dev->sata_dev.ata_host);
> >   		dev->sata_dev.ata_host = NULL;
> >   		dev->sata_dev.ap = NULL;
> > diff --git a/include/linux/libata.h b/include/linux/libata.h
> > index 13fb41d25da6..7d3bd7c9664a 100644
> > --- a/include/linux/libata.h
> > +++ b/include/linux/libata.h
> > @@ -1249,6 +1249,7 @@ extern int ata_slave_link_init(struct ata_port *ap);
> >   extern struct ata_port *ata_sas_port_alloc(struct ata_host *,
> >   					   struct ata_port_info *, struct Scsi_Host *);
> >   extern void ata_port_probe(struct ata_port *ap);
> > +extern void ata_port_free(struct ata_port *ap);
> >   extern int ata_sas_tport_add(struct device *parent, struct ata_port *ap);
> >   extern void ata_sas_tport_delete(struct ata_port *ap);
> >   int ata_sas_device_configure(struct scsi_device *sdev, struct queue_limits *lim,
> 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/4] libata/libsas cleanup fixes
  2024-06-29 12:42 [PATCH 0/4] libata/libsas cleanup fixes Niklas Cassel
                   ` (3 preceding siblings ...)
  2024-06-29 12:42 ` [PATCH 4/4] ata: ahci: Clean up sysfs file " Niklas Cassel
@ 2024-06-30 21:02 ` Niklas Cassel
  2024-07-03  2:37   ` Martin K. Petersen
  2024-06-30 21:05 ` Niklas Cassel
  5 siblings, 1 reply; 12+ messages in thread
From: Niklas Cassel @ 2024-06-30 21:02 UTC (permalink / raw)
  To: Damien Le Moal, John Garry, Jason Yan, James E.J. Bottomley,
	Martin K. Petersen, Jeff Garzik, Tejun Heo, Hannes Reinecke,
	Colin Ian King, Jens Axboe, Kai-Heng Feng
  Cc: linux-scsi, Niklas Cassel, linux-ide

On Sat, Jun 29, 2024 at 02:42:10PM +0200, Niklas Cassel wrote:
> Hello there,
> 
> This series takes the patches that are -stable material from this series:
> https://lore.kernel.org/linux-ide/20240626180031.4050226-15-cassel@kernel.org/
> 
> Changes since series above:
> -Fixed minor review comments for the four patches included in the series.
> -Picked up tags.
> 
> 
> Kind regards,
> Niklas
> 
> 
> Niklas Cassel (4):
>   ata: libata-core: Fix null pointer dereference on error
>   ata,scsi: libata-core: Do not leak memory for ata_port struct members
>   ata: libata-core: Fix double free on error
>   ata: ahci: Clean up sysfs file on error
> 
>  drivers/ata/ahci.c                 | 17 ++++++++++++-----
>  drivers/ata/libata-core.c          | 29 ++++++++++++++++++-----------
>  drivers/scsi/libsas/sas_ata.c      |  2 +-
>  drivers/scsi/libsas/sas_discover.c |  2 +-
>  include/linux/libata.h             |  1 +
>  5 files changed, 33 insertions(+), 18 deletions(-)

Martin, James,

considering that the libsas change is extremely trivial,
and that the libsas maintainer (John) has added his R-b tag,
I will simply take this via the libata tree.

Please tell me if you have a problem with this, and it will
never happen again. (I would never do this for something that
wasn't extremely trivial.)


Kind regards,
Niklas

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/4] libata/libsas cleanup fixes
  2024-06-29 12:42 [PATCH 0/4] libata/libsas cleanup fixes Niklas Cassel
                   ` (4 preceding siblings ...)
  2024-06-30 21:02 ` [PATCH 0/4] libata/libsas cleanup fixes Niklas Cassel
@ 2024-06-30 21:05 ` Niklas Cassel
  5 siblings, 0 replies; 12+ messages in thread
From: Niklas Cassel @ 2024-06-30 21:05 UTC (permalink / raw)
  To: Damien Le Moal, John Garry, Jason Yan, James E.J. Bottomley,
	Martin K. Petersen, Jeff Garzik, Tejun Heo, Hannes Reinecke,
	Colin Ian King, Jens Axboe, Kai-Heng Feng, Niklas Cassel
  Cc: linux-scsi, Niklas Cassel, linux-ide

On Sat, 29 Jun 2024 14:42:10 +0200, Niklas Cassel wrote:
> This series takes the patches that are -stable material from this series:
> https://lore.kernel.org/linux-ide/20240626180031.4050226-15-cassel@kernel.org/
> 
> Changes since series above:
> -Fixed minor review comments for the four patches included in the series.
> -Picked up tags.
> 
> [...]

Applied to libata/linux.git (for-6.10-fixes), thanks!

[1/4] ata: libata-core: Fix null pointer dereference on error
      https://git.kernel.org/libata/linux/c/5d92c7c5
[2/4] ata,scsi: libata-core: Do not leak memory for ata_port struct members
      https://git.kernel.org/libata/linux/c/f6549f53
[3/4] ata: libata-core: Fix double free on error
      https://git.kernel.org/libata/linux/c/ab9e0c52
[4/4] ata: ahci: Clean up sysfs file on error
      https://git.kernel.org/libata/linux/c/eeb25a09

Kind regards,
Niklas


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/4] ata,scsi: libata-core: Do not leak memory for ata_port struct members
  2024-06-29 12:42 ` [PATCH 2/4] ata,scsi: libata-core: Do not leak memory for ata_port struct members Niklas Cassel
  2024-06-30  9:42   ` John Garry
@ 2024-07-01  6:21   ` Hannes Reinecke
  1 sibling, 0 replies; 12+ messages in thread
From: Hannes Reinecke @ 2024-07-01  6:21 UTC (permalink / raw)
  To: Niklas Cassel, Damien Le Moal, John Garry, Jason Yan,
	James E.J. Bottomley, Martin K. Petersen
  Cc: linux-scsi, Niklas Cassel, linux-ide

On 6/29/24 14:42, Niklas Cassel wrote:
> libsas is currently not freeing all the struct ata_port struct members,
> e.g. ncq_sense_buf for a driver supporting Command Duration Limits (CDL).
> 
> Add a function, ata_port_free(), that is used to free a ata_port,
> including its struct members. It makes sense to keep the code related to
> freeing a ata_port in its own function, which will also free all the
> struct members of struct ata_port.
> 
> Fixes: 18bd7718b5c4 ("scsi: ata: libata: Handle completion of CDL commands using policy 0xD")
> Signed-off-by: Niklas Cassel <cassel@kernel.org>
> ---
>   drivers/ata/libata-core.c          | 24 ++++++++++++++----------
>   drivers/scsi/libsas/sas_ata.c      |  2 +-
>   drivers/scsi/libsas/sas_discover.c |  2 +-
>   include/linux/libata.h             |  1 +
>   4 files changed, 17 insertions(+), 12 deletions(-)
> 
Reviewed-by: Hannes Reinecke <hare@suse.de>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                  Kernel Storage Architect
hare@suse.de                                +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/4] libata/libsas cleanup fixes
  2024-06-30 21:02 ` [PATCH 0/4] libata/libsas cleanup fixes Niklas Cassel
@ 2024-07-03  2:37   ` Martin K. Petersen
  0 siblings, 0 replies; 12+ messages in thread
From: Martin K. Petersen @ 2024-07-03  2:37 UTC (permalink / raw)
  To: Niklas Cassel
  Cc: Damien Le Moal, John Garry, Jason Yan, James E.J. Bottomley,
	Martin K. Petersen, Jeff Garzik, Tejun Heo, Hannes Reinecke,
	Colin Ian King, Jens Axboe, Kai-Heng Feng, linux-scsi,
	Niklas Cassel, linux-ide


Niklas,

> considering that the libsas change is extremely trivial, and that the
> libsas maintainer (John) has added his R-b tag, I will simply take
> this via the libata tree.

That's fine!

-- 
Martin K. Petersen	Oracle Linux Engineering

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2024-07-03  2:37 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-29 12:42 [PATCH 0/4] libata/libsas cleanup fixes Niklas Cassel
2024-06-29 12:42 ` [PATCH 1/4] ata: libata-core: Fix null pointer dereference on error Niklas Cassel
2024-06-30  9:36   ` John Garry
2024-06-29 12:42 ` [PATCH 2/4] ata,scsi: libata-core: Do not leak memory for ata_port struct members Niklas Cassel
2024-06-30  9:42   ` John Garry
2024-06-30 20:28     ` Niklas Cassel
2024-07-01  6:21   ` Hannes Reinecke
2024-06-29 12:42 ` [PATCH 3/4] ata: libata-core: Fix double free on error Niklas Cassel
2024-06-29 12:42 ` [PATCH 4/4] ata: ahci: Clean up sysfs file " Niklas Cassel
2024-06-30 21:02 ` [PATCH 0/4] libata/libsas cleanup fixes Niklas Cassel
2024-07-03  2:37   ` Martin K. Petersen
2024-06-30 21:05 ` Niklas Cassel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).