From: Mert Seftali <mertsftl@gmail.com>
To: Lee Jones <lee@kernel.org>, Pavel Machek <pavel@kernel.org>
Cc: Kees Cook <kees@kernel.org>,
"Gustavo A . R . Silva" <gustavoars@kernel.org>,
linux-leds@vger.kernel.org, linux-hardening@vger.kernel.org,
linux-kernel@vger.kernel.org, Mert Seftali <mertsftl@gmail.com>
Subject: [PATCH v3] leds: pwm: Annotate leds[] with __counted_by()
Date: Fri, 10 Jul 2026 09:01:41 +0200 [thread overview]
Message-ID: <20260710070141.37214-1-mertsftl@gmail.com> (raw)
Add the __counted_by() attribute to the flexible array member leds[] in
struct led_pwm_priv so the compiler and runtime (e.g. FORTIFY_SOURCE,
UBSAN_BOUNDS) can bounds-check accesses against num_leds.
For the annotation to be correct, num_leds must equal the number of
allocated elements before leds[] is accessed. Even taking the address
&priv->leds[i] is bounds-checked against num_leds under UBSAN_BOUNDS. The
driver allocates device_get_child_node_count() elements up front, so set
num_leds to that count right after allocation.
While here, pass the led_pwm_data element into led_pwm_add() instead of
the whole led_pwm_priv, so the helper no longer needs to index the array;
the caller walks a led_pwm_data pointer over priv->leds.
No functional change intended.
Suggested-by: Lee Jones <lee@kernel.org>
Signed-off-by: Mert Seftali <mertsftl@gmail.com>
---
Changes in v3:
- v2 followed the review suggestion to pass the element and increment
num_leds in the caller. That is exactly what Sashiko caught: with
__counted_by(num_leds), &priv->leds[num_leds] is bounds-checked, so
incrementing num_leds from 0 as the loop runs trips UBSAN_BOUNDS on
probe. num_leds is now set to the full count up front and the caller
walks a led_pwm_data pointer, which keeps the element-passing and the
dropped index variable, just without the running counter.
Changes in v2 (per Lee Jones review):
- Pass the led_pwm_data element into led_pwm_add() so it drops the priv and
index arguments.
Build-tested only (no PWM-LED hardware). The __counted_by bounds behaviour
that motivated v3 was verified with a standalone UBSAN reproducer on gcc and
clang.
drivers/leds/leds-pwm.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
index 6c1f2f50ff85..d1116a5cb2b2 100644
--- a/drivers/leds/leds-pwm.c
+++ b/drivers/leds/leds-pwm.c
@@ -36,7 +36,7 @@ struct led_pwm_data {
struct led_pwm_priv {
int num_leds;
- struct led_pwm_data leds[];
+ struct led_pwm_data leds[] __counted_by(num_leds);
};
static int led_pwm_set(struct led_classdev *led_cdev,
@@ -81,10 +81,9 @@ static int led_pwm_default_brightness_get(struct fwnode_handle *fwnode,
}
__attribute__((nonnull))
-static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
+static int led_pwm_add(struct device *dev, struct led_pwm_data *led_data,
struct led_pwm *led, struct fwnode_handle *fwnode)
{
- struct led_pwm_data *led_data = &priv->leds[priv->num_leds];
struct led_init_data init_data = { .fwnode = fwnode };
int ret;
@@ -167,12 +166,12 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
}
}
- priv->num_leds++;
return 0;
}
static int led_pwm_create_fwnode(struct device *dev, struct led_pwm_priv *priv)
{
+ struct led_pwm_data *led_data = priv->leds;
struct led_pwm led;
int ret;
@@ -193,7 +192,7 @@ static int led_pwm_create_fwnode(struct device *dev, struct led_pwm_priv *priv)
led.default_state = led_init_default_state_get(fwnode);
- ret = led_pwm_add(dev, priv, &led, fwnode);
+ ret = led_pwm_add(dev, led_data++, &led, fwnode);
if (ret)
return ret;
}
@@ -217,6 +216,8 @@ static int led_pwm_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
+ priv->num_leds = count;
+
ret = led_pwm_create_fwnode(&pdev->dev, priv);
if (ret)
--
2.55.0
next reply other threads:[~2026-07-10 7:01 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-10 7:01 Mert Seftali [this message]
2026-07-10 7:11 ` [PATCH v3] leds: pwm: Annotate leds[] with __counted_by() sashiko-bot
2026-07-10 8:53 ` Mert Seftali
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260710070141.37214-1-mertsftl@gmail.com \
--to=mertsftl@gmail.com \
--cc=gustavoars@kernel.org \
--cc=kees@kernel.org \
--cc=lee@kernel.org \
--cc=linux-hardening@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-leds@vger.kernel.org \
--cc=pavel@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.