The debugfs buffers in gb_camera (data[PAGE_SIZE], length) are written with sprintf without any bounds checking. The four places in gb_camera_debugfs_capabilities, gb_camera_debugfs_configure_streams and gb_camera_debugfs_flush do:
buffer->length += sprintf(buffer->data + buffer->length, ...); buffer->length = sprintf(buffer->data, ...);
If the formatted data ever grows (e.g., more streams, larger hex dump) or if length is already close to PAGE_SIZE, this will overrun the PAGE_SIZE buffer and corrupt memory. The driver is debugfs-only so the impact is limited, but it is still a real bug and the pattern is repeated in multiple places.
Fix it by using scnprintf with the remaining size:
scnprintf(buffer->data + buffer->length, PAGE_SIZE - buffer->length, ...) scnprintf(buffer->data, PAGE_SIZE, ...)
This is the standard way to write to a fixed-size buffer in the kernel. It guarantees we never write past PAGE_SIZE and will truncate instead of overrunning, which is safe for debugfs output. The return value still accumulates in length, which matches the existing use with simple_read_from_buffer (it will just show truncated output rather than corrupting).
I checked that this exact conversion has not been proposed before: the recent greybus conversions to sysfs_emit (light.c, gbphy.c) and fbtft/vme_tsi148 scnprintf patches do not touch camera.c at all, and a search of lore for "gb_camera_debugfs" shows no prior patch for these four sprintf sites.
No functional change for normal sizes, just makes the code safe if the buffer ever fills up.
Signed-off-by: Vaibhav Agarwal contectforbusiness@proton.me --- drivers/staging/greybus/camera.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 62b55bb28..efc83ceff 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -890,7 +890,8 @@ static ssize_t gb_camera_debugfs_capabilities(struct gb_camera *gcam, for (i = 0; i < size; i += 16) { unsigned int nbytes = min_t(unsigned int, size - i, 16);
- buffer->length += sprintf(buffer->data + buffer->length, + buffer->length += scnprintf(buffer->data + buffer->length, + PAGE_SIZE - buffer->length, "%*ph\n", nbytes, caps + i); }
@@ -973,12 +974,13 @@ static ssize_t gb_camera_debugfs_configure_streams(struct gb_camera *gcam, if (ret < 0) goto done;
- buffer->length = sprintf(buffer->data, "%u;%u;", nstreams, flags); + buffer->length = scnprintf(buffer->data, PAGE_SIZE, "%u;%u;", nstreams, flags);
for (i = 0; i < nstreams; ++i) { struct gb_camera_stream_config *stream = &streams[i];
- buffer->length += sprintf(buffer->data + buffer->length, + buffer->length += scnprintf(buffer->data + buffer->length, + PAGE_SIZE - buffer->length, "%u;%u;%u;%u;%u;%u;%u;", stream->width, stream->height, stream->format, stream->vc, @@ -1046,7 +1048,7 @@ static ssize_t gb_camera_debugfs_flush(struct gb_camera *gcam, if (ret < 0) return ret;
- buffer->length = sprintf(buffer->data, "%u", req_id); + buffer->length = scnprintf(buffer->data, PAGE_SIZE, "%u", req_id);
return len; }