Re: [PATCH v3] ARM: imx: Fix suspend/resume crash with Clang CFI
Nick Desaulniers <[email protected]> Mon, 20 Jul 2026 09:53:11 -0700
| Newsgroups | dev.linux.lists.llvm,dev.linux.lists.imx,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel,org.kernel.vger.stable |
|---|---|
| Message-ID | <CAKwvOd=eAC-Mz0kZhbHQMFOY=ba=WXDH6X_Zzh6KGfuq5PmJ4A@mail.gmail.com> |
On Sat, Jul 18, 2026 at 4:14 AM Yo'av Moshe <[email protected]> wrote: > > Relocated suspend code in OCRAM lacks compiler-generated CFI type > signatures. When CONFIG_CFI=y is active, the indirect call to > imx6_suspend_in_ocram_fn triggers a strict CFI violation panic. > > To resolve this safely without reducing CFI protection scope: > 1. Create a minimal wrapper function imx6_suspend_in_ocram annotated > with __nocfi to handle the unverified indirect call. > 2. Remove the __nocfi annotation from the main imx6q_suspend_finish > function to preserve full CFI coverage for other indirect calls > in that scope (such as cpu_do_idle() and flush_cache_all()). > 3. Mark global variables ccm_base, suspend_ocram_base, and the > imx6_suspend_in_ocram_fn pointer as __ro_after_init to prevent > them from being used as target vectors for CFI bypass exploits. > > Cc: [email protected] > Signed-off-by: Yo'av Moshe <[email protected]> > --- > Tested on a Kobo Clara HD (i.MX6SLL SoC) running postmarketOS edge. > Before this patch, suspending the device caused an immediate silent > hang requiring a hard-reboot. With this patch applied, suspend and > resume work successfully. > > Differences from v2: > - Restrained __nocfi scope by adding a dedicated, minimal 1-line > wrapper function (imx6_suspend_in_ocram) for the OCRAM call, > avoiding disabling CFI checks for cpu_do_idle() and flush_cache_all(). > - Marked global pointers ccm_base and suspend_ocram_base as > __ro_after_init to fully neutralize Write-What-Where exploit bypasses. > > arch/arm/mach-imx/pm-imx6.c | 13 +++++++++---- > 1 file changed, 9 insertions(+), 4 deletions(-) > > diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c > index a671ca498..3d5b960c5 100644 > --- a/arch/arm/mach-imx/pm-imx6.c > +++ b/arch/arm/mach-imx/pm-imx6.c > @@ -61,9 +61,9 @@ > #define MX6Q_SUSPEND_OCRAM_SIZE 0x1000 > #define MX6_MAX_MMDC_IO_NUM 33 > > -static void __iomem *ccm_base; > -static void __iomem *suspend_ocram_base; > -static void (*imx6_suspend_in_ocram_fn)(void __iomem *ocram_vbase); > +static void __iomem *ccm_base __ro_after_init; > +static void __iomem *suspend_ocram_base __ro_after_init; > +static void (*imx6_suspend_in_ocram_fn)(void __iomem *ocram_vbase) __ro_after_init; Are we able to just put __nocfi on the declaration of `imx6_suspend_in_ocram_fn`, rather than bother with a wrapper (imx6_suspend_in_ocram)? I don't know if that works, but surely you can test that quickly? > > /* > * suspend ocram space layout: > @@ -360,6 +360,11 @@ int imx6_set_lpm(enum mxc_cpu_pwr_mode mode) > return 0; > } > > +static void __nocfi imx6_suspend_in_ocram(void __iomem *ocram_vbase) > +{ > + imx6_suspend_in_ocram_fn(ocram_vbase); > +} > + > static int imx6q_suspend_finish(unsigned long val) > { > if (!imx6_suspend_in_ocram_fn) { > @@ -374,7 +379,7 @@ static int imx6q_suspend_finish(unsigned long val) > if (!((struct imx6_cpu_pm_info *) > suspend_ocram_base)->l2_base.vbase) > flush_cache_all(); > - imx6_suspend_in_ocram_fn(suspend_ocram_base); > + imx6_suspend_in_ocram(suspend_ocram_base); > } > > return 0; > -- > 2.55.0 > -- Thanks, ~Nick Desaulniers