From 13467fd6998f5da4f5b4f172f1af3d9c48d5de8f Mon Sep 17 00:00:00 2001 From: Cunhao Lu <1579567540@qq.com> Date: Fri, 23 Oct 2026 16:21:05 +0800 Subject: gpio: rockchip: Fix debounce arithmetic for GPIO v2 The debounce interval calculations use unsigned long operands. On 32-bit systems, the numerator used to calculate the maximum interval overflows before division, while multiplying the requested interval by the clock rate overflows before it is assigned to a u64. A zero debounce clock rate also causes division by zero. Use 64-bit arithmetic for both calculations and reject a zero clock rate before division. At 32768 Hz, a 1 us request rounds to zero divider periods. Subtracting one then wraps the divider value to ULONG_MAX. Decrement only a nonzero rounded period count so that such requests use the smallest divider value. Fixes: 3bcbd1a85b68 ("gpio/rockchip: support next version gpio controller") Cc: stable@vger.kernel.org Signed-off-by: Cunhao Lu <1579567540@qq.com> Link: https://patch.msgid.link/20261023-fix-rockchip-gpio-v2-debounce-v1-1-f1141bd5b58f@qq.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-rockchip.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c index 77b239a9a601..714604c11d78 100644 --- a/drivers/gpio/gpio-rockchip.c +++ b/drivers/gpio/gpio-rockchip.c @@ -201,20 +201,25 @@ static int rockchip_gpio_set_debounce(struct gpio_chip *gc, { struct rockchip_pin_bank *bank = gpiochip_get_data(gc); const struct rockchip_gpio_regs *reg = bank->gpio_regs; - unsigned long flags, div_reg, freq, max_debounce; + unsigned long flags, div_reg, freq; bool div_debounce_support; unsigned int cur_div_reg; - u64 div; + u64 div, max_debounce; if (bank->gpio_type == GPIO_TYPE_V2 && !IS_ERR(bank->db_clk)) { div_debounce_support = true; freq = clk_get_rate(bank->db_clk); - max_debounce = (GENMASK(23, 0) + 1) * 2 * 1000000 / freq; + if (!freq) + return -EINVAL; + + div = (u64)(GENMASK(23, 0) + 1) * 2 * USEC_PER_SEC; + max_debounce = div64_u64(div, freq); if (debounce > max_debounce) return -EINVAL; - div = debounce * freq; - div_reg = DIV_ROUND_CLOSEST_ULL(div, 2 * USEC_PER_SEC) - 1; + div = (u64)debounce * freq; + div_reg = DIV_ROUND_CLOSEST_ULL(div, 2 * USEC_PER_SEC); + div_reg = div_reg ? div_reg - 1 : 0; } else { div_debounce_support = false; } -- cgit v1.2.3 From baa14758afb3e2828de1f76511edc1de50216f39 Mon Sep 17 00:00:00 2001 From: Guangshuo Li Date: Mon, 26 Oct 2026 19:52:26 +0800 Subject: gpio: brcmstb: fix UAF after IRQ domain setup failure When devm_request_irq() fails in brcmstb_gpio_irq_setup(), the error path removes the IRQ domain but leaves priv->irq_domain non-NULL. The probe error path subsequently calls brcmstb_gpio_remove(), which checks priv->irq_domain and attempts to access the already-freed domain through irq_find_mapping(). It also attempts to remove the domain again, resulting in a use-after-free and potentially further memory corruption. Set priv->irq_domain to NULL after removing it so that the common cleanup path skips the already-freed IRQ domain. This issue was found by our static analysis tool under development. Fixes: 0ba31dc201de ("gpio: brcmstb: consolidate interrupt domains") Cc: stable@vger.kernel.org Signed-off-by: Guangshuo Li Reviewed-by: Florian Fainelli Link: https://patch.msgid.link/20261026115227.41779-1-lgs201920130244@gmail.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-brcmstb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index 44ca798cf832..3b1aaea63951 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -513,6 +513,7 @@ static int brcmstb_gpio_irq_setup(struct platform_device *pdev, out_free_domain: irq_domain_remove(priv->irq_domain); + priv->irq_domain = NULL; return err; } -- cgit v1.2.3