CVE-2026-46286
Description
Linux kernel's qcom-lpg driver has an array overflow vulnerability when selecting high-resolution values, potentially leading to incorrect chip configuration.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Linux kernel's qcom-lpg driver has an array overflow vulnerability when selecting high-resolution values, potentially leading to incorrect chip configuration.
Vulnerability
The Linux kernel's qcom-lpg driver contains an array overflow vulnerability. The FIELD_GET() macro attempts to read from a 3-bit register to index an array with only 5 values. This can lead to an overflow when selecting high-resolution values.
Exploitation
An attacker would need to trigger the code path that selects high-resolution values. This involves manipulating the 3-bit register that is used as an index into the qcom-lpg driver's array. The exact conditions for triggering this code path are not detailed in the available references.
Impact
If exploited, this vulnerability could lead to the driver reading random data from memory due to the array overflow. This incorrect data could then be used to set up chip values, potentially leading to unexpected behavior or instability in the affected hardware.
Mitigation
This vulnerability has been resolved in the Linux kernel. The fix is available in the stable tree at commit f67a24e75d3251ba42538738120b6b659c0dca7d [1]. Users should update to a kernel version containing this fix.
AI Insight generated on Jun 8, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1Patches
1036ce3094dc50leds: qcom-lpg: Check for array overflow when selecting the high resolution
1 file changed · +6 −2
drivers/leds/rgb/leds-qcom-lpg.c+6 −2 modifieddiff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c index 98c60e971b48f..4c28fb7d4da0f 100644 --- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -1272,7 +1272,12 @@ static int lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, return ret; if (chan->subtype == LPG_SUBTYPE_HI_RES_PWM) { - refclk = lpg_clk_rates_hi_res[FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val)]; + unsigned int clk_idx = FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val); + + if (clk_idx >= ARRAY_SIZE(lpg_clk_rates_hi_res)) + return -EINVAL; + + refclk = lpg_clk_rates_hi_res[clk_idx]; resolution = lpg_pwm_resolution_hi_res[FIELD_GET(PWM_SIZE_HI_RES_MASK, val)]; } else { refclk = lpg_clk_rates[FIELD_GET(PWM_CLK_SELECT_MASK, val)]; -- cgit 1.3-korg
d45963a93c14leds: qcom-lpg: Check for array overflow when selecting the high resolution
1 file changed · +6 −2
drivers/leds/rgb/leds-qcom-lpg.c+6 −2 modifieddiff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c index 016bf468e0941..f6061c47f863d 100644 --- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -1273,7 +1273,12 @@ static int lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, return ret; if (chan->subtype == LPG_SUBTYPE_HI_RES_PWM) { - refclk = lpg_clk_rates_hi_res[FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val)]; + unsigned int clk_idx = FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val); + + if (clk_idx >= ARRAY_SIZE(lpg_clk_rates_hi_res)) + return -EINVAL; + + refclk = lpg_clk_rates_hi_res[clk_idx]; resolution = lpg_pwm_resolution_hi_res[FIELD_GET(PWM_SIZE_HI_RES_MASK, val)]; } else { refclk = lpg_clk_rates[FIELD_GET(PWM_CLK_SELECT_MASK, val)]; -- cgit 1.3-korg
438e357b3cc6leds: qcom-lpg: Check for array overflow when selecting the high resolution
1 file changed · +6 −2
drivers/leds/rgb/leds-qcom-lpg.c+6 −2 modifieddiff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c index a460782dadca4..ce0e61452af27 100644 --- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -1273,7 +1273,12 @@ static int lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, return ret; if (chan->subtype == LPG_SUBTYPE_HI_RES_PWM) { - refclk = lpg_clk_rates_hi_res[FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val)]; + unsigned int clk_idx = FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val); + + if (clk_idx >= ARRAY_SIZE(lpg_clk_rates_hi_res)) + return -EINVAL; + + refclk = lpg_clk_rates_hi_res[clk_idx]; resolution = lpg_pwm_resolution_hi_res[FIELD_GET(PWM_SIZE_HI_RES_MASK, val)]; } else { refclk = lpg_clk_rates[FIELD_GET(PWM_CLK_SELECT_MASK, val)]; -- cgit 1.3-korg
f67a24e75d32leds: qcom-lpg: Check for array overflow when selecting the high resolution
1 file changed · +6 −2
drivers/leds/rgb/leds-qcom-lpg.c+6 −2 modifieddiff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c index 016bf468e0941..f6061c47f863d 100644 --- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -1273,7 +1273,12 @@ static int lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, return ret; if (chan->subtype == LPG_SUBTYPE_HI_RES_PWM) { - refclk = lpg_clk_rates_hi_res[FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val)]; + unsigned int clk_idx = FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val); + + if (clk_idx >= ARRAY_SIZE(lpg_clk_rates_hi_res)) + return -EINVAL; + + refclk = lpg_clk_rates_hi_res[clk_idx]; resolution = lpg_pwm_resolution_hi_res[FIELD_GET(PWM_SIZE_HI_RES_MASK, val)]; } else { refclk = lpg_clk_rates[FIELD_GET(PWM_CLK_SELECT_MASK, val)]; -- cgit 1.3-korg
28a2e047d037leds: qcom-lpg: Check for array overflow when selecting the high resolution
1 file changed · +6 −2
drivers/leds/rgb/leds-qcom-lpg.c+6 −2 modifieddiff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c index 9843fe2e5f9eb..d94c5dd91bdfe 100644 --- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -1043,7 +1043,12 @@ static int lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, return ret; if (chan->subtype == LPG_SUBTYPE_HI_RES_PWM) { - refclk = lpg_clk_rates_hi_res[FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val)]; + unsigned int clk_idx = FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val); + + if (clk_idx >= ARRAY_SIZE(lpg_clk_rates_hi_res)) + return -EINVAL; + + refclk = lpg_clk_rates_hi_res[clk_idx]; resolution = lpg_pwm_resolution_hi_res[FIELD_GET(PWM_SIZE_HI_RES_MASK, val)]; } else { refclk = lpg_clk_rates[FIELD_GET(PWM_CLK_SELECT_MASK, val)]; -- cgit 1.3-korg
f67a24e75d32leds: qcom-lpg: Check for array overflow when selecting the high resolution
1 file changed · +6 −2
drivers/leds/rgb/leds-qcom-lpg.c+6 −2 modifieddiff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c index 016bf468e0941..f6061c47f863d 100644 --- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -1273,7 +1273,12 @@ static int lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, return ret; if (chan->subtype == LPG_SUBTYPE_HI_RES_PWM) { - refclk = lpg_clk_rates_hi_res[FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val)]; + unsigned int clk_idx = FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val); + + if (clk_idx >= ARRAY_SIZE(lpg_clk_rates_hi_res)) + return -EINVAL; + + refclk = lpg_clk_rates_hi_res[clk_idx]; resolution = lpg_pwm_resolution_hi_res[FIELD_GET(PWM_SIZE_HI_RES_MASK, val)]; } else { refclk = lpg_clk_rates[FIELD_GET(PWM_CLK_SELECT_MASK, val)]; -- cgit 1.3-korg
28a2e047d037leds: qcom-lpg: Check for array overflow when selecting the high resolution
1 file changed · +6 −2
drivers/leds/rgb/leds-qcom-lpg.c+6 −2 modifieddiff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c index 9843fe2e5f9eb..d94c5dd91bdfe 100644 --- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -1043,7 +1043,12 @@ static int lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, return ret; if (chan->subtype == LPG_SUBTYPE_HI_RES_PWM) { - refclk = lpg_clk_rates_hi_res[FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val)]; + unsigned int clk_idx = FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val); + + if (clk_idx >= ARRAY_SIZE(lpg_clk_rates_hi_res)) + return -EINVAL; + + refclk = lpg_clk_rates_hi_res[clk_idx]; resolution = lpg_pwm_resolution_hi_res[FIELD_GET(PWM_SIZE_HI_RES_MASK, val)]; } else { refclk = lpg_clk_rates[FIELD_GET(PWM_CLK_SELECT_MASK, val)]; -- cgit 1.3-korg
36ce3094dc50leds: qcom-lpg: Check for array overflow when selecting the high resolution
1 file changed · +6 −2
drivers/leds/rgb/leds-qcom-lpg.c+6 −2 modifieddiff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c index 98c60e971b48f..4c28fb7d4da0f 100644 --- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -1272,7 +1272,12 @@ static int lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, return ret; if (chan->subtype == LPG_SUBTYPE_HI_RES_PWM) { - refclk = lpg_clk_rates_hi_res[FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val)]; + unsigned int clk_idx = FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val); + + if (clk_idx >= ARRAY_SIZE(lpg_clk_rates_hi_res)) + return -EINVAL; + + refclk = lpg_clk_rates_hi_res[clk_idx]; resolution = lpg_pwm_resolution_hi_res[FIELD_GET(PWM_SIZE_HI_RES_MASK, val)]; } else { refclk = lpg_clk_rates[FIELD_GET(PWM_CLK_SELECT_MASK, val)]; -- cgit 1.3-korg
d45963a93c14leds: qcom-lpg: Check for array overflow when selecting the high resolution
1 file changed · +6 −2
drivers/leds/rgb/leds-qcom-lpg.c+6 −2 modifieddiff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c index 016bf468e0941..f6061c47f863d 100644 --- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -1273,7 +1273,12 @@ static int lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, return ret; if (chan->subtype == LPG_SUBTYPE_HI_RES_PWM) { - refclk = lpg_clk_rates_hi_res[FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val)]; + unsigned int clk_idx = FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val); + + if (clk_idx >= ARRAY_SIZE(lpg_clk_rates_hi_res)) + return -EINVAL; + + refclk = lpg_clk_rates_hi_res[clk_idx]; resolution = lpg_pwm_resolution_hi_res[FIELD_GET(PWM_SIZE_HI_RES_MASK, val)]; } else { refclk = lpg_clk_rates[FIELD_GET(PWM_CLK_SELECT_MASK, val)]; -- cgit 1.3-korg
438e357b3cc6leds: qcom-lpg: Check for array overflow when selecting the high resolution
1 file changed · +6 −2
drivers/leds/rgb/leds-qcom-lpg.c+6 −2 modifieddiff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c index a460782dadca4..ce0e61452af27 100644 --- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -1273,7 +1273,12 @@ static int lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, return ret; if (chan->subtype == LPG_SUBTYPE_HI_RES_PWM) { - refclk = lpg_clk_rates_hi_res[FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val)]; + unsigned int clk_idx = FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val); + + if (clk_idx >= ARRAY_SIZE(lpg_clk_rates_hi_res)) + return -EINVAL; + + refclk = lpg_clk_rates_hi_res[clk_idx]; resolution = lpg_pwm_resolution_hi_res[FIELD_GET(PWM_SIZE_HI_RES_MASK, val)]; } else { refclk = lpg_clk_rates[FIELD_GET(PWM_CLK_SELECT_MASK, val)]; -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"The code fails to check if a value read from a register is within the bounds of an array before using it as an index."
Attack vector
An attacker can trigger this vulnerability by providing a value to the `lpg_pwm_get_state` function that, when processed by `FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val)`, results in an index that is out of bounds for the `lpg_clk_rates_hi_res` array. This could lead to reading unintended memory locations and potentially corrupting chip values.
Affected code
The vulnerability exists in the `drivers/leds/rgb/leds-qcom-lpg.c` file within the `lpg_pwm_get_state` function. Specifically, the code uses `FIELD_GET` to extract a value from a register and uses it as an index into the `lpg_clk_rates_hi_res` array without validating if the index is within the array's bounds.
What the fix does
The patch adds a check to ensure that the index obtained from `FIELD_GET(PWM_CLK_SELECT_HI_RES_MASK, val)` is less than the size of the `lpg_clk_rates_hi_res` array. If the index is out of bounds, the function now returns an error code (`-EINVAL`), preventing the use of an invalid index and thus mitigating the risk of reading random data or corrupting chip values.
Generated on Jun 8, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- git.kernel.org/stable/c/28a2e047d03721e0517c67ee726eaa6621c30e5fnvd
- git.kernel.org/stable/c/36ce3094dc50598f38fd961b46688cd533940efcnvd
- git.kernel.org/stable/c/438e357b3cc6cd6900df271e4bc567bfe1142281nvd
- git.kernel.org/stable/c/d45963a93c1495e9f1338fde91d0ebba8fd22474nvd
- git.kernel.org/stable/c/f67a24e75d3251ba42538738120b6b659c0dca7dnvd
News mentions
0No linked articles in our index yet.