Linux kernel and device drivers for NXP i.MX platforms
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: Liem <liem16213@gmail.com>
Cc: imx@lists.linux.dev, Frank.Li@kernel.org
Subject: Re: [PATCH] i2c: imx: Fix slave registration error path and missing NULL check
Date: Thu, 25 Jun 2026 07:26:27 +0000	[thread overview]
Message-ID: <20260625072628.3F6081F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260625071130.93544-1-liem16213@gmail.com>

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:

New issues:
- [Critical] The newly added NULL check in `i2c_imx_slave_event()` conditionally prevents state updates, creating an infinite loop in `i2c_imx_slave_finish_op()`.
- [High] The lockless NULL check of `i2c_imx->slave` in `i2c_imx_slave_event()` introduces a Time-of-Check to Time-of-Use (TOCTOU) race condition.

Pre-existing issues:
- [High] The background `slave_timer` is not synchronously cancelled in `i2c_imx_unreg_slave()`, allowing a suspended device to be accessed.
- [High] The shared IRQ handler accesses hardware registers unconditionally without verifying the runtime PM state, violating PM Subsystem guidelines.
- [High] The runtime suspend callback powers down hardware without calling `synchronize_irq()`, violating PM Subsystem Concurrency rules for shared IRQs.
--

commit acf987bc13c7f8a8bbb96ab3004b61c139d9bb11
Author: Liem <liem16213@gmail.com>

i2c: imx: Fix slave registration error path and missing NULL check

This patch fixes an issue in i2c_imx_reg_slave() by clearing the slave
pointer when pm_runtime_resume_and_get() fails. It also adds a NULL check
in i2c_imx_slave_event() to prevent dereferencing a NULL slave pointer
during slave events.

> diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
> index cf5bacf3a4884..8c44f6bf618c1 100644
> --- a/drivers/i2c/busses/i2c-imx.c
> +++ b/drivers/i2c/busses/i2c-imx.c
> @@ -715,8 +715,10 @@ static void i2c_imx_enable_bus_idle(struct imx_i2c_struct *i2c_imx)
>  static void i2c_imx_slave_event(struct imx_i2c_struct *i2c_imx,
>  				enum i2c_slave_event event, u8 *val)
>  {
> -	i2c_slave_event(i2c_imx->slave, event, val);
> -	i2c_imx->last_slave_event = event;
> +	if (i2c_imx->slave) {
> +		i2c_slave_event(i2c_imx->slave, event, val);

[Severity: High]
Does this introduce a time-of-check to time-of-use race condition?

The slave pointer is read locklessly here, and the compiler could read
i2c_imx->slave twice: once for the if-condition and once to pass as an
argument to i2c_slave_event().

If i2c_imx_unreg_slave() clears the pointer to NULL concurrently from process
context without holding slave_lock:

i2c_imx_unreg_slave() {
    ...
    i2c_imx->slave = NULL;
    ...
}

Could i2c_slave_event() receive and dereference a NULL pointer?

> +		i2c_imx->last_slave_event = event;
> +	}

[Severity: Critical]
Does skipping this state update when the slave is NULL cause an infinite loop
in i2c_imx_slave_finish_op()?

If i2c_imx->slave is cleared concurrently, last_slave_event is never advanced
to I2C_SLAVE_STOP.

i2c_imx_slave_finish_op() iterates based on this state:

i2c_imx_slave_finish_op() {
    ...
    while (i2c_imx->last_slave_event != I2C_SLAVE_STOP) {
        ...
        case I2C_SLAVE_WRITE_REQUESTED:
            ...
            i2c_imx_slave_event(i2c_imx, I2C_SLAVE_STOP, &val);
            break;
    }
}

Will this cause the while loop to spin indefinitely?

[ ... ]

[Severity: High]
This isn't a bug introduced by this patch, but does i2c_imx_unreg_slave()
fail to synchronously cancel the background timer?

It drops the runtime PM reference and disables the clock, but does not cancel
i2c_imx->slave_timer.

If the timer executes asynchronously after the clock is off:

i2c_imx_slave_timeout() {
    ...
    status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
    ...
}

Will reading the hardware register trigger an external abort?

[Severity: High]
This isn't a bug introduced by this patch, but does the shared IRQ handler
access hardware registers unconditionally without verifying the runtime PM
state?

The driver requests a shared IRQ line:

i2c_imx_probe() {
    ...
    ret = request_threaded_irq(irq, i2c_imx_isr, NULL, IRQF_SHARED,
                               pdev->name, i2c_imx);
    ...
}

If another device on the shared IRQ line triggers an interrupt while the I2C
controller is runtime-suspended, the ISR reads from a powered-off IP block:

i2c_imx_isr() {
    ...
    status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
    ...
}

Should the ISR verify the device is active using pm_runtime_get_if_active()?

[Severity: High]
This isn't a bug introduced by this patch, but does the runtime suspend
callback power down hardware without calling synchronize_irq()?

i2c_imx_runtime_suspend() {
    ...
    clk_disable(i2c_imx->clk);
    ...
}

Because the driver requests an IRQ with the IRQF_SHARED flag, PM subsystem
guidelines mandate that synchronize_irq() must be called in the runtime
suspend callback before powering down hardware. This prevents the IRQ
handler from executing mid-flight on another CPU while the clock is being
disabled.

Is a call to synchronize_irq() needed here?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260625071130.93544-1-liem16213@gmail.com?part=1

  reply	other threads:[~2026-06-25  7:26 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-25  7:11 [PATCH] i2c: imx: Fix slave registration error path and missing NULL check Liem
2026-06-25  7:26 ` sashiko-bot [this message]
2026-06-25 11:17 ` Carlos Song (OSS)
2026-06-25 16:02 ` [PATCH v2] i2c: imx: Fix slave registration error path and missing timer cleanup Liem
2026-06-25 16:15   ` sashiko-bot
2026-06-25 16:16   ` Frank Li
2026-06-26  1:55     ` liem
2026-06-26  2:58     ` [PATCH v3 0/2] Fix slave mode corner issues Liem
2026-06-26  2:58       ` [PATCH v3 1/2] i2c: imx: Clear slave pointer on registration error Liem
2026-06-26  6:23         ` Carlos Song (OSS)
2026-06-26  8:30           ` liem
2026-06-29  2:38           ` [PATCH v4 0/2] i2c: imx: Fix slave mode corner issues Liem
2026-06-29  2:38             ` [PATCH v4 1/2] i2c: imx: Fix slave registration race and error handling Liem
2026-06-29  2:55               ` sashiko-bot
2026-06-29  9:30               ` Carlos Song
2026-06-29 14:13               ` Frank Li
2026-06-30  6:49                 ` liem
2026-06-29  2:38             ` [PATCH v4 2/2] i2c: imx: Cancel hrtimer before clearing slave pointer Liem
2026-06-29  2:48               ` sashiko-bot
2026-06-29 14:14               ` Frank Li
2026-06-26  2:58       ` [PATCH v3 " Liem
2026-06-26  6:26         ` Carlos Song (OSS)
  -- strict thread matches above, loose matches on Subject: below --
2026-06-25 15:07 [PATCH] i2c: imx: Fix slave registration error path and missing NULL check liem

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=20260625072628.3F6081F00A3A@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=Frank.Li@kernel.org \
    --cc=imx@lists.linux.dev \
    --cc=liem16213@gmail.com \
    --cc=sashiko-reviews@lists.linux.dev \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox