* [PATCH v1 1/4] powerpc/perf: hv-gpci: bound sysfs hex formatting to PAGE_SIZE
2026-08-07 3:11 [PATCH v1 0/4] powerpc: assorted fixes (gpci, imc, energy, iommu) Xixin Liu
2026-08-07 3:11 ` [PATCH v1 4/4] powerpc/iommu: fix debugfs name buffer for 64-bit it_index Xixin Liu
@ 2026-08-07 3:11 ` Xixin Liu
2026-08-07 3:11 ` [PATCH v1 3/4] powerpc/pseries: energy: bound H_BEST_ENERGY cnt and sysfs output Xixin Liu
2026-08-07 3:11 ` [PATCH v1 2/4] powerpc/powernv: opal-imc: fix debugfs name buffer size Xixin Liu
3 siblings, 0 replies; 5+ messages in thread
From: Xixin Liu @ 2026-08-07 3:11 UTC (permalink / raw)
To: linuxppc-dev; +Cc: maddy, mpe, npiggin, chleroy, linux-kernel, liuxixin
hv-gpci sysfs show paths format hypervisor counter bytes with sprintf()
into a PAGE_SIZE buffer, and only sometimes check the length afterwards.
Each byte becomes two hex digits plus newlines, so the output can grow
past PAGE_SIZE. Checking after sprintf() is too late: the write already
overflowed the sysfs buffer. One path had no size check at all.
Use sysfs_emit_at() so formatting stays within the sysfs buffer. If a
field cannot fit completely, return -EFBIG rather than silently
truncating.
Signed-off-by: Xixin Liu <liuxixin@kylinos.cn>
---
arch/powerpc/perf/hv-gpci.c | 77 +++++++++++++++++++++++++------------
1 file changed, 52 insertions(+), 25 deletions(-)
diff --git a/arch/powerpc/perf/hv-gpci.c b/arch/powerpc/perf/hv-gpci.c
index 76495744f..14a4f414b 100644
--- a/arch/powerpc/perf/hv-gpci.c
+++ b/arch/powerpc/perf/hv-gpci.c
@@ -136,6 +136,7 @@ static unsigned long systeminfo_gpci_request(u32 req, u32 starting_index,
{
unsigned long ret;
size_t i, j;
+ int len;
arg->params.counter_request = cpu_to_be32(req);
arg->params.starting_index = cpu_to_be32(starting_index);
@@ -177,17 +178,23 @@ static unsigned long systeminfo_gpci_request(u32 req, u32 starting_index,
for (i = 0; i < be16_to_cpu(arg->params.returned_values); i++) {
j = i * be16_to_cpu(arg->params.cv_element_size);
- for (; j < (i + 1) * be16_to_cpu(arg->params.cv_element_size); j++)
- *n += sprintf(buf + *n, "%02x", (u8)arg->bytes[j]);
- *n += sprintf(buf + *n, "\n");
- }
-
- if (*n >= PAGE_SIZE) {
- pr_info("System information exceeds PAGE_SIZE\n");
- return -EFBIG;
+ for (; j < (i + 1) * be16_to_cpu(arg->params.cv_element_size); j++) {
+ len = sysfs_emit_at(buf, *n, "%02x", (u8)arg->bytes[j]);
+ if (len != 2)
+ goto emit_failed;
+ *n += len;
+ }
+ len = sysfs_emit_at(buf, *n, "\n");
+ if (len != 1)
+ goto emit_failed;
+ *n += len;
}
return ret;
+
+emit_failed:
+ pr_info("System information does not fit in sysfs buffer\n");
+ return -EFBIG;
}
static ssize_t processor_bus_topology_show(struct device *dev, struct device_attribute *attr,
@@ -470,12 +477,13 @@ static ssize_t affinity_domain_via_domain_show(struct device *dev, struct device
return ret;
}
-static void affinity_domain_via_partition_result_parse(int returned_values,
+static int affinity_domain_via_partition_result_parse(int returned_values,
int element_size, char *buf, size_t *last_element,
size_t *n, struct hv_gpci_request_buffer *arg)
{
size_t i = 0, j = 0;
size_t k, l, m;
+ int len;
uint16_t total_affinity_domain_ele, size_of_each_affinity_domain_ele;
/*
@@ -492,27 +500,44 @@ static void affinity_domain_via_partition_result_parse(int returned_values,
*/
while (i < returned_values) {
k = j;
- for (; k < j + element_size; k++)
- *n += sprintf(buf + *n, "%02x", (u8)arg->bytes[k]);
- *n += sprintf(buf + *n, "\n");
+ for (; k < j + element_size; k++) {
+ len = sysfs_emit_at(buf, *n, "%02x", (u8)arg->bytes[k]);
+ if (len != 2)
+ return -EFBIG;
+ *n += len;
+ }
+ len = sysfs_emit_at(buf, *n, "\n");
+ if (len != 1)
+ return -EFBIG;
+ *n += len;
total_affinity_domain_ele = (u8)arg->bytes[k - 2] << 8 | (u8)arg->bytes[k - 3];
size_of_each_affinity_domain_ele = (u8)arg->bytes[k] << 8 | (u8)arg->bytes[k - 1];
for (l = 0; l < total_affinity_domain_ele; l++) {
for (m = 0; m < size_of_each_affinity_domain_ele; m++) {
- *n += sprintf(buf + *n, "%02x", (u8)arg->bytes[k]);
+ len = sysfs_emit_at(buf, *n, "%02x", (u8)arg->bytes[k]);
+ if (len != 2)
+ return -EFBIG;
+ *n += len;
k++;
}
- *n += sprintf(buf + *n, "\n");
+ len = sysfs_emit_at(buf, *n, "\n");
+ if (len != 1)
+ return -EFBIG;
+ *n += len;
}
- *n += sprintf(buf + *n, "\n");
+ len = sysfs_emit_at(buf, *n, "\n");
+ if (len != 1)
+ return -EFBIG;
+ *n += len;
i++;
j = k;
}
*last_element = k;
+ return 0;
}
static ssize_t affinity_domain_via_partition_show(struct device *dev, struct device_attribute *attr,
@@ -555,12 +580,10 @@ static ssize_t affinity_domain_via_partition_show(struct device *dev, struct dev
* to buffer util we get all the information.
*/
while (ret == H_PARAMETER) {
- affinity_domain_via_partition_result_parse(
- be16_to_cpu(arg->params.returned_values) - 1,
- be16_to_cpu(arg->params.cv_element_size), buf,
- &last_element, &n, arg);
-
- if (n >= PAGE_SIZE) {
+ if (affinity_domain_via_partition_result_parse(
+ be16_to_cpu(arg->params.returned_values) - 1,
+ be16_to_cpu(arg->params.cv_element_size), buf,
+ &last_element, &n, arg)) {
put_cpu_var(hv_gpci_reqb);
pr_debug("System information does not fit in sysfs buffer\n");
return -EFBIG;
@@ -587,10 +610,14 @@ static ssize_t affinity_domain_via_partition_show(struct device *dev, struct dev
}
parse_result:
- affinity_domain_via_partition_result_parse(
- be16_to_cpu(arg->params.returned_values),
- be16_to_cpu(arg->params.cv_element_size),
- buf, &last_element, &n, arg);
+ if (affinity_domain_via_partition_result_parse(
+ be16_to_cpu(arg->params.returned_values),
+ be16_to_cpu(arg->params.cv_element_size),
+ buf, &last_element, &n, arg)) {
+ put_cpu_var(hv_gpci_reqb);
+ pr_debug("System information does not fit in sysfs buffer\n");
+ return -EFBIG;
+ }
put_cpu_var(hv_gpci_reqb);
return n;
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v1 4/4] powerpc/iommu: fix debugfs name buffer for 64-bit it_index
2026-08-07 3:11 [PATCH v1 0/4] powerpc: assorted fixes (gpci, imc, energy, iommu) Xixin Liu
@ 2026-08-07 3:11 ` Xixin Liu
2026-08-07 3:11 ` [PATCH v1 1/4] powerpc/perf: hv-gpci: bound sysfs hex formatting to PAGE_SIZE Xixin Liu
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Xixin Liu @ 2026-08-07 3:11 UTC (permalink / raw)
To: linuxppc-dev; +Cc: maddy, mpe, npiggin, chleroy, linux-kernel, liuxixin
iommu debugfs names sprintf() "%08lx" into char name[10]. The "8" in
%08lx is a minimum width, so a 64-bit it_index can need up to 16 hex
digits plus NUL.
Size the buffer for an unsigned long and use snprintf.
Signed-off-by: Xixin Liu <liuxixin@kylinos.cn>
---
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index ee1b5cb557c9..e8f48aef7832 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -53,10 +53,11 @@
static void iommu_debugfs_add(struct iommu_table *tbl)
{
- char name[10];
+ /* unsigned long hex + NUL; %08lx is a minimum width only */
+ char name[2 * sizeof(unsigned long) + 1];
struct dentry *liobn_entry;
- sprintf(name, "%08lx", tbl->it_index);
+ snprintf(name, sizeof(name), "%08lx", tbl->it_index);
liobn_entry = debugfs_create_dir(name, iommu_debugfs_dir);
debugfs_create_file_unsafe("weight", 0400, liobn_entry, tbl, &iommu_debugfs_fops_weight);
@@ -70,9 +71,9 @@
static void iommu_debugfs_del(struct iommu_table *tbl)
{
- char name[10];
+ char name[2 * sizeof(unsigned long) + 1];
- sprintf(name, "%08lx", tbl->it_index);
+ snprintf(name, sizeof(name), "%08lx", tbl->it_index);
debugfs_lookup_and_remove(name, iommu_debugfs_dir);
}
#else
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v1 3/4] powerpc/pseries: energy: bound H_BEST_ENERGY cnt and sysfs output
2026-08-07 3:11 [PATCH v1 0/4] powerpc: assorted fixes (gpci, imc, energy, iommu) Xixin Liu
2026-08-07 3:11 ` [PATCH v1 4/4] powerpc/iommu: fix debugfs name buffer for 64-bit it_index Xixin Liu
2026-08-07 3:11 ` [PATCH v1 1/4] powerpc/perf: hv-gpci: bound sysfs hex formatting to PAGE_SIZE Xixin Liu
@ 2026-08-07 3:11 ` Xixin Liu
2026-08-07 3:11 ` [PATCH v1 2/4] powerpc/powernv: opal-imc: fix debugfs name buffer size Xixin Liu
3 siblings, 0 replies; 5+ messages in thread
From: Xixin Liu @ 2026-08-07 3:11 UTC (permalink / raw)
To: linuxppc-dev; +Cc: maddy, mpe, npiggin, chleroy, linux-kernel, liuxixin
The H_BEST_ENERGY sysfs path takes cnt from the hypercall return buffer
and walks buf_page[2*i+1] without checking that cnt fits in the single
page allocated for the hcall, and sprintf()s into the PAGE_SIZE sysfs
buffer without remaining-space checks.
Clamp cnt to the number of u32 pairs that fit in the page, and stop
formatting before overflowing the sysfs page.
Signed-off-by: Xixin Liu <liuxixin@kylinos.cn>
---
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/pseries_energy.c b/arch/powerpc/platforms/pseries/pseries_energy.c
index fdaf85ecd39b..8344f00656e5 100644
--- a/arch/powerpc/platforms/pseries/pseries_energy.c
+++ b/arch/powerpc/platforms/pseries/pseries_energy.c
@@ -209,16 +209,28 @@
return -EINVAL;
}
+ /*
+ * Each entry occupies two u32s in buf_page. Never walk past the
+ * page, and never sprintf past the PAGE_SIZE sysfs buffer.
+ */
cnt = retbuf[0];
+ if (cnt > (PAGE_SIZE / sizeof(u32)) / 2)
+ cnt = (PAGE_SIZE / sizeof(u32)) / 2;
+
for (i = 0; i < cnt; i++) {
cpu = drc_index_to_cpu(buf_page[2*i+1]);
if ((cpu_online(cpu) && !activate) ||
- (!cpu_online(cpu) && activate))
+ (!cpu_online(cpu) && activate)) {
+ if (s - page >= PAGE_SIZE - 16)
+ break;
s += sprintf(s, "%d,", cpu);
+ }
}
if (s > page) { /* Something to show */
s--; /* Suppress last comma */
- s += sprintf(s, "\n");
+ /* sprintf needs room for '\n' and trailing NUL. */
+ if (s - page < PAGE_SIZE - 1)
+ s += sprintf(s, "\n");
}
free_page((unsigned long) buf_page);
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v1 0/4] powerpc: assorted fixes (gpci, imc, energy, iommu)
@ 2026-08-07 3:11 Xixin Liu
2026-08-07 3:11 ` [PATCH v1 4/4] powerpc/iommu: fix debugfs name buffer for 64-bit it_index Xixin Liu
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Xixin Liu @ 2026-08-07 3:11 UTC (permalink / raw)
To: linuxppc-dev; +Cc: maddy, mpe, npiggin, chleroy, linux-kernel, liuxixin
Hi,
This series fixes some bugs in powerpc paths found by static review
of linux-next:
1) hv-gpci sysfs hex formatting can overflow the PAGE_SIZE show
buffer; switch to sysfs_emit_at() and return -EFBIG
2) opal-imc debugfs names use char[16] with sprintf for a u32 id
3) pseries energy walks H_BEST_ENERGY cnt and sprintf()s without
page bounds
4) iommu debugfs uses char[10] with %08lx while it_index is
unsigned long
Patches are independent. Please review.
Thanks,
Xixin Liu
---
Xixin Liu (4):
powerpc/perf: hv-gpci: bound sysfs hex formatting to PAGE_SIZE
powerpc/powernv: opal-imc: fix debugfs name buffer size
powerpc/pseries: energy: bound H_BEST_ENERGY cnt and sysfs output
powerpc/iommu: fix debugfs name buffer for 64-bit it_index
arch/powerpc/kernel/iommu.c | 9 +++--
arch/powerpc/perf/hv-gpci.c | 77 +++++++++++++++---------
arch/powerpc/platforms/powernv/opal-imc.c | 7 +++--
arch/powerpc/platforms/pseries/pseries_energy.c | 16 ++++-
4 files changed, 75 insertions(+), 34 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v1 2/4] powerpc/powernv: opal-imc: fix debugfs name buffer size
2026-08-07 3:11 [PATCH v1 0/4] powerpc: assorted fixes (gpci, imc, energy, iommu) Xixin Liu
` (2 preceding siblings ...)
2026-08-07 3:11 ` [PATCH v1 3/4] powerpc/pseries: energy: bound H_BEST_ENERGY cnt and sysfs output Xixin Liu
@ 2026-08-07 3:11 ` Xixin Liu
3 siblings, 0 replies; 5+ messages in thread
From: Xixin Liu @ 2026-08-07 3:11 UTC (permalink / raw)
To: linuxppc-dev; +Cc: maddy, mpe, npiggin, chleroy, linux-kernel, liuxixin
char mode[16]/cmd[16] are too small for sprintf("imc_mode_%d") /
sprintf("imc_cmd_%d") when id is a full u32 (up to 20 bytes including NUL).
id comes from DT "chip-id" as u32. Enlarge the buffers and use snprintf.
Signed-off-by: Xixin Liu <liuxixin@kylinos.cn>
---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/platforms/powernv/opal-imc.c b/arch/powerpc/platforms/powernv/opal-imc.c
index b3fd5c648dea..77de53d47cb6 100644
--- a/arch/powerpc/platforms/powernv/opal-imc.c
+++ b/arch/powerpc/platforms/powernv/opal-imc.c
@@ -51,7 +51,8 @@
struct imc_pmu *pmu_ptr)
{
static u64 loc, *imc_mode_addr, *imc_cmd_addr;
- char mode[16], cmd[16];
+ /* "imc_mode_" / "imc_cmd_" + max u32 decimal + NUL */
+ char mode[20], cmd[20];
u32 cb_offset;
struct imc_mem_info *ptr = pmu_ptr->mem_info;
@@ -63,12 +64,12 @@
while (ptr->vbase != NULL) {
loc = (u64)(ptr->vbase) + cb_offset;
imc_mode_addr = (u64 *)(loc + IMC_CNTL_BLK_MODE_OFFSET);
- sprintf(mode, "imc_mode_%d", (u32)(ptr->id));
+ snprintf(mode, sizeof(mode), "imc_mode_%u", ptr->id);
imc_debugfs_create_x64(mode, 0600, imc_debugfs_parent,
imc_mode_addr);
imc_cmd_addr = (u64 *)(loc + IMC_CNTL_BLK_CMD_OFFSET);
- sprintf(cmd, "imc_cmd_%d", (u32)(ptr->id));
+ snprintf(cmd, sizeof(cmd), "imc_cmd_%u", ptr->id);
imc_debugfs_create_x64(cmd, 0600, imc_debugfs_parent,
imc_cmd_addr);
ptr++;
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-08-07 12:46 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-07 3:11 [PATCH v1 0/4] powerpc: assorted fixes (gpci, imc, energy, iommu) Xixin Liu
2026-08-07 3:11 ` [PATCH v1 4/4] powerpc/iommu: fix debugfs name buffer for 64-bit it_index Xixin Liu
2026-08-07 3:11 ` [PATCH v1 1/4] powerpc/perf: hv-gpci: bound sysfs hex formatting to PAGE_SIZE Xixin Liu
2026-08-07 3:11 ` [PATCH v1 3/4] powerpc/pseries: energy: bound H_BEST_ENERGY cnt and sysfs output Xixin Liu
2026-08-07 3:11 ` [PATCH v1 2/4] powerpc/powernv: opal-imc: fix debugfs name buffer size Xixin Liu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox