* [PATCH v2 1/4] scsi: target: file: use kmalloc() to allocate temporary protection buffer
2026-07-04 6:13 [PATCH v2 0/4] scsi: replace __get_free_pages() with kmalloc() Mike Rapoport (Microsoft)
@ 2026-07-04 6:13 ` Mike Rapoport (Microsoft)
2026-07-04 6:13 ` [PATCH v2 2/4] scsi: proc: use kmalloc() in proc writers Mike Rapoport (Microsoft)
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Mike Rapoport (Microsoft) @ 2026-07-04 6:13 UTC (permalink / raw)
To: Martin K. Petersen
Cc: Brian King, Hannes Reinecke, James E.J. Bottomley, Matthew Wilcox,
Mike Rapoport, Wen Xiong, linux-kernel, linux-mm, linux-scsi,
target-devel, Hannes Reinecke
fd_do_prot_unmap() uses __get_free_page() to allocate a temporary buffer
that is used to invalidate protection info for the unmapped region by
filling with 0xff pattern.
This buffer can be allocated with kmalloc() as there's nothing special
about it to go directly to the page allocator.
kmalloc() provides a better API that does not require ugly casts and
kfree() does not need to know the size of the freed object.
Replace use of __get_free_page() with kmalloc().
Link: https://lore.kernel.org/all/635405e4-9423-4a25-a6e7-e03c8ea0bcbe@redhat.com
Reviewed-by: Hannes Reinecke <hare@kernel.org>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
drivers/target/target_core_file.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index 62ced9f5102f..ab9824a4852f 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -516,7 +516,7 @@ fd_do_prot_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
void *buf;
int rc;
- buf = (void *)__get_free_page(GFP_KERNEL);
+ buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!buf) {
pr_err("Unable to allocate FILEIO prot buf\n");
return -ENOMEM;
@@ -524,7 +524,7 @@ fd_do_prot_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
rc = fd_do_prot_fill(cmd->se_dev, lba, nolb, buf, PAGE_SIZE);
- free_page((unsigned long)buf);
+ kfree(buf);
return rc;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 2/4] scsi: proc: use kmalloc() in proc writers
2026-07-04 6:13 [PATCH v2 0/4] scsi: replace __get_free_pages() with kmalloc() Mike Rapoport (Microsoft)
2026-07-04 6:13 ` [PATCH v2 1/4] scsi: target: file: use kmalloc() to allocate temporary protection buffer Mike Rapoport (Microsoft)
@ 2026-07-04 6:13 ` Mike Rapoport (Microsoft)
2026-07-04 6:13 ` [PATCH v2 3/4] scsi: ipr: use kmalloc() to allocate IPR dump buffer memory Mike Rapoport (Microsoft)
2026-07-04 6:13 ` [PATCH v2 4/4] scsi: sym53c8xx_2: replace __get_free_pages() with kmalloc() Mike Rapoport (Microsoft)
3 siblings, 0 replies; 7+ messages in thread
From: Mike Rapoport (Microsoft) @ 2026-07-04 6:13 UTC (permalink / raw)
To: Martin K. Petersen
Cc: Brian King, Hannes Reinecke, James E.J. Bottomley, Matthew Wilcox,
Mike Rapoport, Wen Xiong, linux-kernel, linux-mm, linux-scsi,
target-devel, Hannes Reinecke, John Garry
proc_scsi_host_write(), proc_scsi_write() and proc_scsi_devinfo_write()
allocate temporary buffers for /proc writes using __get_free_page().
These buffers can be allocated with kmalloc() as there's nothing special
about them to go directly to the page allocator.
kmalloc() provides a better API that does not require ugly casts and
kfree() does not need to know the size of the freed object.
Replace use of __get_free_page() with kmalloc().
Link: https://lore.kernel.org/all/635405e4-9423-4a25-a6e7-e03c8ea0bcbe@redhat.com
Reviewed-by: Hannes Reinecke <hare@kernel.org>
Reviewed-by: John Garry <john.g.garry@oracle.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
drivers/scsi/scsi_devinfo.c | 5 +++--
drivers/scsi/scsi_proc.c | 9 +++++----
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 15ffbe93ac72..2bccadf4f22f 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -691,7 +691,8 @@ static ssize_t proc_scsi_devinfo_write(struct file *file,
if (!buf || length>PAGE_SIZE)
return -EINVAL;
- if (!(buffer = (char *) __get_free_page(GFP_KERNEL)))
+ buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!buffer)
return -ENOMEM;
if (copy_from_user(buffer, buf, length)) {
err =-EFAULT;
@@ -708,7 +709,7 @@ static ssize_t proc_scsi_devinfo_write(struct file *file,
scsi_dev_info_list_add_str(buffer);
out:
- free_page((unsigned long)buffer);
+ kfree(buffer);
return err;
}
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index 1799dcae775c..fdc355d783da 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -28,6 +28,7 @@
#include <linux/mutex.h>
#include <linux/gfp.h>
#include <linux/uaccess.h>
+#include <linux/slab.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
@@ -74,7 +75,7 @@ static ssize_t proc_scsi_host_write(struct file *file, const char __user *buf,
if (!shost->hostt->write_info)
return -EINVAL;
- page = (char *)__get_free_page(GFP_KERNEL);
+ page = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (page) {
ret = -EFAULT;
if (copy_from_user(page, buf, count))
@@ -82,7 +83,7 @@ static ssize_t proc_scsi_host_write(struct file *file, const char __user *buf,
ret = shost->hostt->write_info(shost, page, count);
}
out:
- free_page((unsigned long)page);
+ kfree(page);
return ret;
}
@@ -412,7 +413,7 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
if (!buf || length > PAGE_SIZE)
return -EINVAL;
- buffer = (char *)__get_free_page(GFP_KERNEL);
+ buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
@@ -467,7 +468,7 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
err = length;
out:
- free_page((unsigned long)buffer);
+ kfree(buffer);
return err;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 3/4] scsi: ipr: use kmalloc() to allocate IPR dump buffer memory
2026-07-04 6:13 [PATCH v2 0/4] scsi: replace __get_free_pages() with kmalloc() Mike Rapoport (Microsoft)
2026-07-04 6:13 ` [PATCH v2 1/4] scsi: target: file: use kmalloc() to allocate temporary protection buffer Mike Rapoport (Microsoft)
2026-07-04 6:13 ` [PATCH v2 2/4] scsi: proc: use kmalloc() in proc writers Mike Rapoport (Microsoft)
@ 2026-07-04 6:13 ` Mike Rapoport (Microsoft)
2026-07-04 6:28 ` sashiko-bot
2026-07-04 6:13 ` [PATCH v2 4/4] scsi: sym53c8xx_2: replace __get_free_pages() with kmalloc() Mike Rapoport (Microsoft)
3 siblings, 1 reply; 7+ messages in thread
From: Mike Rapoport (Microsoft) @ 2026-07-04 6:13 UTC (permalink / raw)
To: Martin K. Petersen
Cc: Brian King, Hannes Reinecke, James E.J. Bottomley, Matthew Wilcox,
Mike Rapoport, Wen Xiong, linux-kernel, linux-mm, linux-scsi,
target-devel, Hannes Reinecke
IPR dump machinery allocates memory to save adapter's crash dump using
__get_free_page().
This memory can be allocated with kmalloc() as there's nothing special
about it to go directly to the page allocator.
kmalloc() provides a better API that does not require ugly casts and
kfree() does not need to know the size of the freed object.
Replace use of __get_free_page() with kmalloc().
While on it, relax GFP_ATOMIC to GFP_NOIO for allocation of dump
buffers.
The allocations happen in a workqueue context, but with storage adapter
being in a state where it can't handle I/O.
Link: https://lore.kernel.org/all/635405e4-9423-4a25-a6e7-e03c8ea0bcbe@redhat.com
Tested-by: Wen Xiong <wenxiong@linux.ibm.com>
Reviewed-by: Hannes Reinecke <hare@kernel.org>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
drivers/scsi/ipr.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index d207e5e81afe..19153dd24736 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -2893,7 +2893,7 @@ static int ipr_sdt_copy(struct ipr_ioa_cfg *ioa_cfg,
(ioa_dump->hdr.len + bytes_copied) < max_dump_size) {
if (ioa_dump->page_offset >= PAGE_SIZE ||
ioa_dump->page_offset == 0) {
- page = (__be32 *)__get_free_page(GFP_ATOMIC);
+ page = kmalloc(PAGE_SIZE, GFP_NOIO);
if (!page) {
ipr_trace;
@@ -3226,7 +3226,7 @@ static void ipr_release_dump(struct kref *kref)
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
for (i = 0; i < dump->ioa_dump.next_page_index; i++)
- free_page((unsigned long) dump->ioa_dump.ioa_data[i]);
+ kfree(dump->ioa_dump.ioa_data[i]);
vfree(dump->ioa_dump.ioa_data);
kfree(dump);
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH v2 3/4] scsi: ipr: use kmalloc() to allocate IPR dump buffer memory
2026-07-04 6:13 ` [PATCH v2 3/4] scsi: ipr: use kmalloc() to allocate IPR dump buffer memory Mike Rapoport (Microsoft)
@ 2026-07-04 6:28 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-07-04 6:28 UTC (permalink / raw)
Cc: linux-scsi
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] The sysfs bin attribute read handler `ipr_read_dump` can enter an infinite loop in the kernel when reading from the `ioa_data` section at a page-aligned logical offset.
- [High] The sysfs dump read handler (`ipr_read_dump`) uses an untrusted `num_entries_used` value from the adapter firmware to calculate `sdt_end`, allowing an out-of-bounds read past the end of the `ipr_dump` structure.
--
commit c5fdd71b8661a08dfced04b150e6d5fc217eacda
Author: Mike Rapoport (Microsoft) <rppt@kernel.org>
scsi: ipr: use kmalloc() to allocate IPR dump buffer memory
This commit replaces the use of __get_free_page() with kmalloc() for
allocating IPR dump buffers. It also relaxes the allocation flag from
GFP_ATOMIC to GFP_NOIO since the allocations happen in a workqueue context.
Link: https://lore.kernel.org/all/635405e4-9423-4a25-a6e7-e03c8ea0bcbe@redhat.com
> diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
> index d207e5e81afe0..19153dd247363 100644
> --- a/drivers/scsi/ipr.c
> +++ b/drivers/scsi/ipr.c
[ ... ]
> @@ -3226,7 +3226,7 @@ static void ipr_release_dump(struct kref *kref)
> spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
>
> for (i = 0; i < dump->ioa_dump.next_page_index; i++)
> - free_page((unsigned long) dump->ioa_dump.ioa_data[i]);
> + kfree(dump->ioa_dump.ioa_data[i]);
>
> vfree(dump->ioa_dump.ioa_data);
> kfree(dump);
[Severity: High]
This isn't a bug introduced by this patch, but the sysfs dump read
handler ipr_read_dump() in drivers/scsi/ipr.c uses an untrusted
num_entries_used value from the adapter firmware to calculate sdt_end:
drivers/scsi/ipr.c:ipr_read_dump() {
...
sdt_end = offsetof(struct ipr_ioa_dump, sdt.entry) +
(be32_to_cpu(dump->ioa_dump.sdt.hdr.num_entries_used) *
sizeof(struct ipr_sdt_entry));
...
src = (u8 *)&dump->ioa_dump + off;
memcpy(buf, src, len);
...
}
While ipr_get_ioa_dump() caps the local variable num_entries, it leaves
the raw dump->ioa_dump.sdt.hdr.num_entries_used in the struct unchanged.
When ipr_read_dump() calculates sdt_end using this raw uncapped value,
it allows an out-of-bounds read past the end of the ipr_dump structure.
Could this lead to a kernel heap exposure when the adjacent kernel memory
is copied to user-space?
[Severity: High]
This is a pre-existing issue, but the sysfs bin attribute read handler
ipr_read_dump() in drivers/scsi/ipr.c can enter an infinite loop when
reading from the ioa_data section at a page-aligned logical offset:
drivers/scsi/ipr.c:ipr_read_dump() {
...
if ((off & PAGE_MASK) != ((off + count) & PAGE_MASK))
len = PAGE_ALIGN(off) - off;
...
}
If a user reads the sysfs dump file such that off starts at a page
boundary and count extends to or past the next page boundary (e.g.,
off = 0 and count = 4096), PAGE_ALIGN(off) - off evaluates to 0.
This results in a zero-length memcpy and no advancement of off or count.
Since there is no cond_resched(), could this lock up a CPU core in an
infinite loop?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260704-b4-scsi-v2-0-7d2d21a810de@kernel.org?part=3
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 4/4] scsi: sym53c8xx_2: replace __get_free_pages() with kmalloc()
2026-07-04 6:13 [PATCH v2 0/4] scsi: replace __get_free_pages() with kmalloc() Mike Rapoport (Microsoft)
` (2 preceding siblings ...)
2026-07-04 6:13 ` [PATCH v2 3/4] scsi: ipr: use kmalloc() to allocate IPR dump buffer memory Mike Rapoport (Microsoft)
@ 2026-07-04 6:13 ` Mike Rapoport (Microsoft)
2026-07-04 6:22 ` sashiko-bot
3 siblings, 1 reply; 7+ messages in thread
From: Mike Rapoport (Microsoft) @ 2026-07-04 6:13 UTC (permalink / raw)
To: Martin K. Petersen
Cc: Brian King, Hannes Reinecke, James E.J. Bottomley, Matthew Wilcox,
Mike Rapoport, Wen Xiong, linux-kernel, linux-mm, linux-scsi,
target-devel, Hannes Reinecke
sym53c8xx_2 driver has an internal memory allocator for small
allocations of the driver structures. The backing memory for that
allocator is allocated with __get_free_pages().
This memory can be allocated with kmalloc() as there's nothing special
about it to go directly to the page allocator.
kmalloc() provides a better API that does not require ugly casts and
kfree() does not need to know the size of the freed object.
Performance difference between kmalloc() and __get_free_pages() is not
measurable as both allocators take an object/page from a per-CPU list for
fast path allocations.
For the slow path the performance is anyway determined by the amount of
reclaim involved rather than by what allocator is used.
Replace use of __get_free_pages() with kmalloc() and free_pages() with
kfree().
Link: https://lore.kernel.org/all/635405e4-9423-4a25-a6e7-e03c8ea0bcbe@redhat.com
Reviewed-by: Hannes Reinecke <hare@kernel.org>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
drivers/scsi/sym53c8xx_2/sym_hipd.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
index 9231a2899064..aa365e8ba66f 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
@@ -1110,9 +1110,9 @@ sym_build_sge(struct sym_hcb *np, struct sym_tblmove *data, u64 badd, int len)
*/
#define sym_get_mem_cluster() \
- (void *) __get_free_pages(GFP_ATOMIC, SYM_MEM_PAGE_ORDER)
+ kmalloc(PAGE_SIZE << SYM_MEM_PAGE_ORDER, GFP_ATOMIC)
#define sym_free_mem_cluster(p) \
- free_pages((unsigned long)p, SYM_MEM_PAGE_ORDER)
+ kfree(p)
/*
* Link between free memory chunks of a given size.
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH v2 4/4] scsi: sym53c8xx_2: replace __get_free_pages() with kmalloc()
2026-07-04 6:13 ` [PATCH v2 4/4] scsi: sym53c8xx_2: replace __get_free_pages() with kmalloc() Mike Rapoport (Microsoft)
@ 2026-07-04 6:22 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-07-04 6:22 UTC (permalink / raw)
Cc: linux-scsi
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Replacing `__get_free_pages()` with `kmalloc()` breaks the internal custom buddy allocator because `kmalloc()` does not guarantee page-aligned memory, leading to memory leaks, incorrect block coalescing, and potential kernel crashes.
--
commit c528e5943bc5d64b931842bf0abd4f0d0100f91e
Author: Mike Rapoport (Microsoft) <rppt@kernel.org>
scsi: sym53c8xx_2: replace __get_free_pages() with kmalloc()
This commit replaces __get_free_pages() and free_pages() with kmalloc() and
kfree() for the internal memory allocator of the sym53c8xx_2 driver. The goal
is to improve the API usage, as kfree() does not require knowing the size of
the freed object.
Link: https://lore.kernel.org/all/635405e4-9423-4a25-a6e7-e03c8ea0bcbe@redhat.com
> diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
> index 9231a28990643..aa365e8ba66fc 100644
> --- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
> +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
> @@ -1110,9 +1110,9 @@ sym_build_sge(struct sym_hcb *np, struct sym_tblmove *data, u64 badd, int len)
> */
>
> #define sym_get_mem_cluster() \
> - (void *) __get_free_pages(GFP_ATOMIC, SYM_MEM_PAGE_ORDER)
> + kmalloc(PAGE_SIZE << SYM_MEM_PAGE_ORDER, GFP_ATOMIC)
[Severity: High]
Will this break the custom buddy allocator logic in ___sym_mfree?
The custom buddy allocator relies on XOR arithmetic and bitwise AND to find and
coalesce buddy blocks, which fundamentally requires the base address of the root
block (the memory cluster) to be naturally aligned to its size:
drivers/scsi/sym53c8xx_2/sym_malloc.c:___sym_mfree() {
...
b = a ^ s;
q = &h[i];
while (q->next && q->next != (m_link_p) b) {
q = q->next;
}
...
q->next = q->next->next;
a = a & b;
...
}
While __get_free_pages guarantees page alignment, kmalloc does not (especially
when KASAN or SLUB debugging is enabled).
If kmalloc returns an unaligned pointer, the XOR buddy calculation computes
incorrect buddy addresses. This prevents blocks from coalescing properly and
causes a memory leak.
Additionally, if blocks from differently offset clusters happen to merge, the
allocator reconstructs a naturally aligned base address that differs from the
original pointer returned by kmalloc. This can lead to calling kfree on an
invalid pointer, resulting in a kernel crash.
> #define sym_free_mem_cluster(p) \
> - free_pages((unsigned long)p, SYM_MEM_PAGE_ORDER)
> + kfree(p)
>
> /*
> * Link between free memory chunks of a given size.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260704-b4-scsi-v2-0-7d2d21a810de@kernel.org?part=4
^ permalink raw reply [flat|nested] 7+ messages in thread