Re: [PATCH v6 1/1] leds: st1202: Add hardware-accelerated blink support

Lee Jones <[email protected]>
Newsgroups org.kernel.vger.linux-leds,dev.linux.lists.sashiko-reviews
Message-ID <[email protected]>
On Thu, 06 Aug 2026, [email protected] wrote:

> Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
> 
> New issues:
> - [High] Hardware blinking destructively overwrites the PWM state of all other active LEDs, forcing them permanently off.
> - [Medium] Hardware blink forces maximum brightness, ignoring user-configured brightness.

Please review, explain or fix the Sashiko review(s).

If this is a set, this request includes the other patches too.

> Pre-existing issues:
> - [High] The driver improperly assigns a sleeping function to the led_cdev->brightness_set callback, causing a 'sleeping in atomic' bug.
> - [High] A dangling fwnode pointer is stored in `led->fwnode` due to a dropped reference count, leading to a UAF upon dereference.
> --
> 
> --- Patch [1]: [PATCH v6 1/1] leds: st1202: Add hardware-accelerated blink support ---
> commit d3cba330dd18edf23569d762b5d09a2ae91bdf35
> Author: Manuel Fombuena <[email protected]>
> 
> leds: st1202: Add hardware-accelerated blink support
> 
> This commit implements blink_set() to enable hardware-accelerated blinking
> via the timer trigger on the ST1202 LED driver. The pattern engine is used
> to produce a two-step sequence with delays clamped to hardware limits.
> 
> > diff --git a/drivers/leds/leds-st1202.c b/drivers/leds/leds-st1202.c
> > index 168df5ecf27b7..ea019d03ad907 100644
> > --- a/drivers/leds/leds-st1202.c
> > +++ b/drivers/leds/leds-st1202.c
> [ ... ]
> > @@ -275,6 +276,89 @@ static int st1202_led_pattern_set(struct led_classdev *ldev,
> [ ... ]
> > +	/* Zero out PWM for all other active channels to prevent them from blinking */
> > +	for (int i = 0; i < ST1202_MAX_LEDS; i++) {
> > +		if (!chip->leds[i].is_active || i == led->led_num)
> > +			continue;
> > +		ret = st1202_pwm_pattern_write(chip, i, 0, LED_OFF);
> 
> [Severity: High]
> Does this loop permanently overwrite the PWM configuration for other active
> LEDs?
> 
> If another LED was previously configured to be statically on, it looks like
> this forces it to be permanently dark. When the hardware blink is stopped,
> the original PWM configurations for these LEDs are never restored, which
> would leave them completely desynchronized from their software
> led_cdev->brightness state.
> 
> > +		if (ret)
> > +			return ret;
> > +		ret = st1202_pwm_pattern_write(chip, i, 1, LED_OFF);
> > +		if (ret)
> > +			return ret;
> > +	}
> [ ... ]
> > +	for (int pattern = 2; pattern < ST1202_MAX_PATTERNS; pattern++) {
> > +		ret = st1202_write_reg(chip, ST1202_PATTERN_DUR + pattern, 0);
> > +		if (ret)
> > +			return ret;
> > +	}
> > +
> > +	ret = st1202_write_reg(chip, ST1202_PATTERN_REP, U8_MAX);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = st1202_write_reg(chip, ST1202_ILED_REG0 + led->led_num, U8_MAX);
> 
> [Severity: Medium]
> Does this force the LED to maximum brightness during a blink, ignoring the
> currently configured led_cdev->brightness or led_cdev->blink_brightness?
> 
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = __st1202_channel_set(chip, led->led_num, true);
> [ ... ]
> > @@ -301,6 +385,7 @@ static int st1202_dt_init(struct st1202_chip *chip)
> >  		led->led_cdev.pattern_set = st1202_led_pattern_set;
> >  		led->led_cdev.pattern_clear = st1202_led_pattern_clear;
> >  		led->led_cdev.default_trigger = "pattern";
> > +		led->led_cdev.blink_set = st1202_blink_set;
> >  		led->led_cdev.brightness_set = st1202_brightness_set;
> 
> [Severity: High]
> This is a pre-existing issue, but does assigning st1202_brightness_set() to
> the non-blocking brightness_set callback cause a "sleeping in atomic" panic?
> 
> The LED subsystem requires that brightness_set not sleep, as it is called
> from atomic contexts like software timers. Looking at
> st1202_brightness_set(), it takes a mutex and performs I2C operations which
> can sleep:
> 
> st1202_brightness_set()
>     guard(mutex)(&chip->lock);
>     ...
>     st1202_write_reg() -> i2c_smbus_write_byte_data()
> 
> Should this be assigned to brightness_set_blocking instead?
> 
> >  		led->led_cdev.brightness_get = st1202_brightness_get;
> >  	}
> 
> [Severity: High]
> This is a pre-existing issue, but I noticed a potential use-after-free
> relating to how led->fwnode is stored earlier in st1202_dt_init().
> 
> The driver iterates over child nodes using
> for_each_available_child_of_node_scoped(), which automatically decrements
> the child node's reference count at the end of each iteration.
> 
> Inside this loop, the fwnode is stored without incrementing its refcount:
> 
>     led->fwnode = of_fwnode_handle(child);
> 
> Since fwnode_handle_get() is not called, does led->fwnode become a dangling
> pointer when the loop finishes? This pointer is later passed to the LED
> core during registration in st1202_probe(), which could cause a UAF if the
> memory is reclaimed.
> 
> -- 
> Sashiko AI review · https://sashiko.dev/#/patchset/GV1PR08MB8497362791595D5C0197701DC5D22@GV1PR08MB8497.eurprd08.prod.outlook.com?part=1

-- 
Lee Jones
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.