[PATCH 1/1] params: array: stage element output before concatenation

From: Ren Wei

Date: Thu May 28 2026 - 01:24:22 EST


From: Wyatt Feng <bronzed_45_vested@xxxxxxxxxx>

param_array_get() builds one sysfs string from a parameter array, but
the individual get callbacks are defined to format into a full PAGE_SIZE
buffer. Passing buffer + off directly to those callbacks can overrun the
remaining space once the concatenated output approaches PAGE_SIZE.

Fix this in the array helper by formatting each element into a temporary
PAGE_SIZE buffer before copying only the bytes that still fit into the
sysfs buffer. This keeps the existing callback interface unchanged and
prevents both the element formatter and the final terminator write from
stepping past the end of the page.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@xxxxxxxxxx
Reported-by: Yuan Tan <yuantan098@xxxxxxxxx>
Reported-by: Zhengchuan Liang <zcliangcn@xxxxxxxxx>
Reported-by: Xin Liu <bird@xxxxxxxxxx>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Wyatt Feng <bronzed_45_vested@xxxxxxxxxx>
Signed-off-by: Ren Wei <n05ec@xxxxxxxxxx>
---
kernel/params.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/kernel/params.c b/kernel/params.c
index 74d620bc2521..3573d7bf38da 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -475,22 +475,34 @@ static int param_array_set(const char *val, const struct kernel_param *kp)
static int param_array_get(char *buffer, const struct kernel_param *kp)
{
int i, off, ret;
+ char *elem_buf;
const struct kparam_array *arr = kp->arr;
struct kernel_param p = *kp;

+ elem_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!elem_buf)
+ return -ENOMEM;
+
for (i = off = 0; i < (arr->num ? *arr->num : arr->max); i++) {
/* Replace \n with comma */
if (i)
buffer[off - 1] = ',';
p.arg = arr->elem + arr->elemsize * i;
check_kparam_locked(p.mod);
- ret = arr->ops->get(buffer + off, &p);
+ ret = arr->ops->get(elem_buf, &p);
if (ret < 0)
- return ret;
+ goto out;
+ ret = min(ret, (int)(PAGE_SIZE - 1 - off));
+ if (!ret)
+ break;
+ memcpy(buffer + off, elem_buf, ret);
off += ret;
}
buffer[off] = '\0';
- return off;
+ ret = off;
+out:
+ kfree(elem_buf);
+ return ret;
}

static void param_array_free(void *arg)
--
2.43.7