The incoming message size from the device header (header.size) is
trusted without checking that it is at least the size of the message
header itself, but a value smaller than sizeof(struct gb_operation_msg_hdr)
underflows request_size in gb_operation_create_incoming(), wraps around
in gb_operation_message_alloc(), and results in a tiny buffer that is
then written past its end in gb_operation_message_init().
Reject undersized messages before parsing the message header.
Fixes: d37b1db13f8b ("greybus: refactor gb_connection_recv()")
Reported-by: syzbot+2fd6aefc361af86911d5(a)syzkaller.appspotmail.com
Link: https://syzkaller.appspot.com/bug?extid=2fd6aefc361af86911d5
Cc: stable(a)vger.kernel.org
Signed-off-by: Adriano Cordova <adrianox(a)gmail.com>
---
drivers/greybus/operation.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/greybus/operation.c b/drivers/greybus/operation.c
index 7e12ffb2dd..df6daee4fb 100644
--- a/drivers/greybus/operation.c
+++ b/drivers/greybus/operation.c
@@ -1047,6 +1047,14 @@ void gb_connection_recv(struct gb_connection *connection,
/* Use memcpy as data may be unaligned */
memcpy(&header, data, sizeof(header));
msg_size = le16_to_cpu(header.size);
+ if (msg_size < sizeof(header)) {
+ dev_err_ratelimited(dev,
+ "%s: malformed message 0x%04x of type 0x%02x received (%zu < %zu)\n",
+ connection->name,
+ le16_to_cpu(header.operation_id),
+ header.type, msg_size, sizeof(header));
+ return;
+ }
if (size < msg_size) {
dev_err_ratelimited(dev,
"%s: incomplete message 0x%04x of type 0x%02x received (%zu < %zu)\n",
--
2.51.0
Per Documentation/filesystems/sysfs.rst, new implementations of
show() methods should only use sysfs_emit() or sysfs_emit_at()
when formatting the value to be returned to user space, since it
is aware of the sysfs PAGE_SIZE buffer and includes sanity checks
that sprintf() lacks.
This fixes fade_in_show() and fade_out_show() (both generated by
the gb_lights_fade_attr() macro) and color_show().
Signed-off-by: Tomasz Unger <tomasz.unger(a)yahoo.pl>
---
Verified with checkpatch.pl - no errors or warnings.
Compiled the gb-light module successfully with CONFIG_GREYBUS_LIGHT=m
and CONFIG_LEDS_CLASS_FLASH=m (both previously disabled).
greybus.ko, led-class-flash.ko and gb-light.ko all load without
errors in a QEMU environment (verified via insmod and lsmod, dmesg
shows no errors). This confirms the modules load cleanly but does
not exercise the changed sysfs show() code paths, which would
require an actual Greybus light device bound to the driver.
---
drivers/staging/greybus/light.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c
index cab02b5da867..2689f9a7524a 100644
--- a/drivers/staging/greybus/light.c
+++ b/drivers/staging/greybus/light.c
@@ -173,7 +173,7 @@ static ssize_t fade_##__dir##_show(struct device *dev, \
struct led_classdev *cdev = dev_get_drvdata(dev); \
struct gb_channel *channel = get_channel_from_cdev(cdev); \
\
- return sprintf(buf, "%u\n", channel->fade_##__dir); \
+ return sysfs_emit(buf, "%u\n", channel->fade_##__dir); \
} \
\
static ssize_t fade_##__dir##_store(struct device *dev, \
@@ -220,7 +220,7 @@ static ssize_t color_show(struct device *dev, struct device_attribute *attr,
struct led_classdev *cdev = dev_get_drvdata(dev);
struct gb_channel *channel = get_channel_from_cdev(cdev);
- return sprintf(buf, "0x%08x\n", channel->color);
+ return sysfs_emit(buf, "0x%08x\n", channel->color);
}
static ssize_t color_store(struct device *dev, struct device_attribute *attr,
---
base-commit: 8d3ae59288f1e7d58d76558a6ee96d533bc5019f
change-id: 20260819-greybus-light-sysfs-emit-4b8beab74fcc
Best regards,
--
Tomasz Unger <tomasz.unger(a)yahoo.pl>
Per Documentation/filesystems/sysfs.rst, new implementations of
show() methods should only use sysfs_emit() or sysfs_emit_at()
when formatting the value to be returned to user space, since it
is aware of the sysfs PAGE_SIZE buffer and includes sanity checks
that sprintf() lacks.
Signed-off-by: Tomasz Unger <tomasz.unger(a)yahoo.pl>
---
Verified with checkpatch.pl - no errors or warnings.
Compiled the gb-gbphy module successfully with CONFIG_GREYBUS=m
and CONFIG_GREYBUS_BRIDGED_PHY=m (both previously disabled).
Both greybus.ko and gb-gbphy.ko load without errors in a QEMU
environment (verified via insmod and lsmod). This confirms the
modules load cleanly but does not exercise the changed sysfs
show() code path, which would require an actual Greybus device
(or a userspace simulator such as gbsim) bound to the driver.
---
drivers/staging/greybus/gbphy.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/greybus/gbphy.c b/drivers/staging/greybus/gbphy.c
index bdb0f5164a6f..bb9a5b538e6e 100644
--- a/drivers/staging/greybus/gbphy.c
+++ b/drivers/staging/greybus/gbphy.c
@@ -31,7 +31,7 @@ static ssize_t protocol_id_show(struct device *dev,
{
struct gbphy_device *gbphy_dev = to_gbphy_dev(dev);
- return sprintf(buf, "0x%02x\n", gbphy_dev->cport_desc->protocol_id);
+ return sysfs_emit(buf, "0x%02x\n", gbphy_dev->cport_desc->protocol_id);
}
static DEVICE_ATTR_RO(protocol_id);
---
base-commit: 8d3ae59288f1e7d58d76558a6ee96d533bc5019f
change-id: 20260818-greybus-gbphy-sysfs-emit-69739912458e
Best regards,
--
Tomasz Unger <tomasz.unger(a)yahoo.pl>
gb_lights_channel_config() builds the LED classdev name with kasprintf()
and stores it in cdev->name for every channel during the configuration
phase, which runs before the channel is registered.
That name was only released by __gb_lights_led_unregister(), i.e. only for
a normal LED channel that was actually registered. It was therefore leaked
in two cases:
- a channel that is configured but never registered, e.g.
channel_attr_groups_set() fails, the flash configuration fails, or a
later channel in the same light fails to configure and the whole light
is torn down; the release path calls gb_lights_channel_unregister()
(which returns early because the channel is not registered) and then
gb_lights_channel_free();
- a flash, torch or indicator channel, whose unregister path
(__gb_lights_flash_led_unregister()) never releases cdev->name at all,
so the name leaks even on a successful teardown.
cdev->name is a configuration-phase allocation, like channel->color_name
and channel->mode_name. Free it in gb_lights_channel_free() next to
those, since that runs unconditionally on every teardown path, and drop
the special case free from __gb_lights_led_unregister().
gb_lights_channel_unregister() is only ever called from
gb_lights_channel_release(), immediately followed by
gb_lights_channel_free(), so the name is still released on the registered
path and is freed exactly once.
Commit 04820da21050 ("staging: greybus: light: Release memory obtained by
kasprintf") fixed the leak for the registered normal-LED path only; this
covers the remaining cases.
Fixes: 2870b52bae4c ("greybus: lights: add lights implementation")
Assisted-by: Claude:claude-opus-4
Signed-off-by: Cong Nguyen <congnt264(a)gmail.com>
---
Changes in v2:
- Add Assisted-by: tag to document AI assistance, per
Documentation/process/coding-assistants.rst (Greg KH).
- No functional change.
drivers/staging/greybus/light.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c
index cab02b5da867..1ecca479b5f4 100644
--- a/drivers/staging/greybus/light.c
+++ b/drivers/staging/greybus/light.c
@@ -905,8 +905,6 @@ static void __gb_lights_led_unregister(struct gb_channel *channel)
return;
led_classdev_unregister(cdev);
- kfree(cdev->name);
- cdev->name = NULL;
channel->led = NULL;
}
@@ -1063,6 +1061,9 @@ static int gb_lights_light_register(struct gb_light *light)
static void gb_lights_channel_free(struct gb_channel *channel)
{
+ struct led_classdev *cdev = get_channel_cdev(channel);
+
+ kfree(cdev->name);
kfree(channel->attrs);
kfree(channel->attr_group);
kfree(channel->attr_groups);
--
2.25.1