GrapheneOS/linux-hardened

Kernel panic after resume from suspend with 4.11.1.a

Opened this issue · 15 comments

I get kernel panic immediately after I resume from suspend with 4.11.1.a. Previous versions didn't have this issue. Vanillia 4.11.1 works ok. Due to nature of this bug I don't have any logs.

Was the last version you tried 4.11.f?

If you can provide the panic traceback, that's what's needed, not logs beyond that.

4.11.f was fine. Log from journalctl ends with suspend. After wake up I have black screen, magic sysrq key doesn't work, I have to do hard reset.

It's probably a bug caught by the fortified strlcpy. Here's a patch on top of 4.11.1.a making it warn instead of using panic, so you should be able to boot and provide the traceback with this from the kernel logs (dmesg) to get the bug fixed:

diff --git a/include/linux/string.h b/include/linux/string.h
index 576a8ff977a1..aa61867411c7 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -172,7 +172,7 @@ static inline const char *kbasename(const char *path)
 #define __FORTIFY_INLINE extern __always_inline __attribute__((gnu_inline))
 #define __RENAME(x) __asm__(#x)
 
-void fortify_panic(const char *name) __noreturn __cold;
+void fortify_panic(const char *name) __cold;
 void __read_overflow(void) __compiletime_error("detected read beyond size of object passed as 1st parameter");
 void __read_overflow2(void) __compiletime_error("detected read beyond size of object passed as 2nd parameter");
 void __write_overflow(void) __compiletime_error("detected write beyond size of object passed as 1st parameter");
diff --git a/lib/string.c b/lib/string.c
index 35aa32602edb..f710ffc5c528 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -955,6 +955,6 @@ EXPORT_SYMBOL(strreplace);
 
 void fortify_panic(const char *name)
 {
-	panic("detected buffer overflow in %s", name);
+	WARN(1, "detected buffer overflow in %s", name);
 }
 EXPORT_SYMBOL(fortify_panic);

It's possible that something else is causing the issue, but it's unlikely. 4.11.f to 4.11.1.a is mostly just the upstream patch, but it also introduced the fortified strlcpy, extra_latent_entropy and some more __ro_after_init and I doubt that the other changes could be causing this.

After I applied patch it won't build.

In file included from ./include/linux/bitmap.h:8:0,
                 from ./include/linux/cpumask.h:11,
                 from ./arch/x86/include/asm/cpumask.h:4,
                 from ./arch/x86/include/asm/msr.h:10,
                 from ./arch/x86/include/asm/processor.h:20,
                 from ./arch/x86/include/asm/cpufeature.h:4,
                 from ./arch/x86/include/asm/thread_info.h:52,
                 from ./include/linux/thread_info.h:25,
                 from ./arch/x86/include/asm/preempt.h:6,
                 from ./include/linux/preempt.h:80,
                 from ./include/linux/spinlock.h:50,
                 from ./include/linux/seqlock.h:35,
                 from ./include/linux/time.h:5,
                 from ./include/linux/stat.h:18,
                 from ./include/linux/module.h:10,
                 from drivers/input/serio/i8042.c:17:
In function ‘memcpy’,
    inlined from ‘i8042_pnp_id_to_string.constprop’ at ./include/linux/string.h:288:3:
./include/linux/string.h:269:4: error: call to ‘__read_overflow2’ declared with attribute error: detected read beyond size of object passed as 2nd parameter
    __read_overflow2();
    ^~~~~~~~~~~~~~~~~~
make[2]: *** [scripts/Makefile.build:300: drivers/input/serio/i8042.o] Error 1
make[1]: *** [scripts/Makefile.build:553: drivers/input/serio] Error 2
make[1]: *** Waiting for unfinished jobs....
  CC [M]  drivers/input/mouse/elan_i2c_smbus.o
  CC [M]  drivers/input/mouse/psmouse-base.o
  CC [M]  net/wireless/scan.o
  CC [M]  drivers/input/mouse/synaptics.o
  CC [M]  net/wireless/nl80211.o
In file included from ./include/linux/bitmap.h:8:0,
                 from ./include/linux/cpumask.h:11,
                 from ./arch/x86/include/asm/cpumask.h:4,
                 from ./arch/x86/include/asm/msr.h:10,
                 from ./arch/x86/include/asm/processor.h:20,
                 from ./arch/x86/include/asm/cpufeature.h:4,
                 from ./arch/x86/include/asm/thread_info.h:52,
                 from ./include/linux/thread_info.h:25,
                 from ./arch/x86/include/asm/preempt.h:6,
                 from ./include/linux/preempt.h:80,
                 from ./include/linux/spinlock.h:50,
                 from ./include/linux/seqlock.h:35,
                 from ./include/linux/time.h:5,
                 from ./include/linux/stat.h:18,
                 from ./include/linux/module.h:10,
                 from drivers/input/mouse/synaptics.c:26:
In function ‘memcpy’,
    inlined from ‘synaptics_pt_create’ at ./include/linux/string.h:288:3,
    inlined from ‘__synaptics_init’ at drivers/input/mouse/synaptics.c:1524:3:
./include/linux/string.h:269:4: error: call to ‘__read_overflow2’ declared with attribute error: detected read beyond size of object passed as 2nd parameter
    __read_overflow2();
    ^~~~~~~~~~~~~~~~~~
In function ‘memcpy’,
    inlined from ‘synaptics_pt_create’ at ./include/linux/string.h:288:3,
    inlined from ‘__synaptics_init’ at drivers/input/mouse/synaptics.c:1524:3:
./include/linux/string.h:269:4: error: call to ‘__read_overflow2’ declared with attribute error: detected read beyond size of object passed as 2nd parameter
    __read_overflow2();
    ^~~~~~~~~~~~~~~~~~
  CC [M]  drivers/input/mouse/focaltech.o
make[3]: *** [scripts/Makefile.build:294: drivers/input/mouse/synaptics.o] Error 1
make[3]: *** Waiting for unfinished jobs....
  CC [M]  net/wireless/mlme.o
make[2]: *** [scripts/Makefile.build:553: drivers/input/mouse] Error 2
make[1]: *** [scripts/Makefile.build:553: drivers/input] Error 2
make: *** [Makefile:1002: drivers] Error 2
make: *** Waiting for unfinished jobs....
  CC [M]  net/wireless/ibss.o
  CC [M]  net/wireless/sme.o
  CC [M]  net/wireless/chan.o
  CC [M]  net/wireless/ethtool.o
In file included from ./include/linux/bitmap.h:8:0,
                 from ./include/linux/cpumask.h:11,
                 from ./arch/x86/include/asm/cpumask.h:4,
                 from ./arch/x86/include/asm/msr.h:10,
                 from ./arch/x86/include/asm/processor.h:20,
                 from ./arch/x86/include/asm/cpufeature.h:4,
                 from ./arch/x86/include/asm/thread_info.h:52,
                 from ./include/linux/thread_info.h:25,
                 from ./arch/x86/include/asm/preempt.h:6,
                 from ./include/linux/preempt.h:80,
                 from ./include/linux/spinlock.h:50,
                 from ./include/linux/rcupdate.h:38,
                 from ./include/linux/rculist.h:10,
                 from ./include/linux/pid.h:4,
                 from ./include/linux/sched.h:13,
                 from ./include/linux/utsname.h:5,
                 from net/wireless/ethtool.c:1:
In function ‘memcpy’,
    inlined from ‘cfg80211_get_drvinfo’ at ./include/linux/string.h:288:3:
./include/linux/string.h:269:4: error: call to ‘__read_overflow2’ declared with attribute error: detected read beyond size of object passed as 2nd parameter
    __read_overflow2();
    ^~~~~~~~~~~~~~~~~~
make[2]: *** [scripts/Makefile.build:294: net/wireless/ethtool.o] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [scripts/Makefile.build:553: net/wireless] Error 2
make: *** [Makefile:1002: net] Error 2
==> ERROR: A failure occurred in build().
    Aborting...

I recommend disabling CONFIG_FORTIFY_SOURCE until the next release unless you want to fix upstream strlcpy overflows yourself, since that was just added.

Try 4.11.1.b with the same patch applied to make fortify non-fatal:

diff --git a/include/linux/string.h b/include/linux/string.h
index 576a8ff977a1..aa61867411c7 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -172,7 +172,7 @@ static inline const char *kbasename(const char *path)
 #define __FORTIFY_INLINE extern __always_inline __attribute__((gnu_inline))
 #define __RENAME(x) __asm__(#x)
 
-void fortify_panic(const char *name) __noreturn __cold;
+void fortify_panic(const char *name) __cold;
 void __read_overflow(void) __compiletime_error("detected read beyond size of object passed as 1st parameter");
 void __read_overflow2(void) __compiletime_error("detected read beyond size of object passed as 2nd parameter");
 void __write_overflow(void) __compiletime_error("detected write beyond size of object passed as 1st parameter");
diff --git a/lib/string.c b/lib/string.c
index 35aa32602edb..f710ffc5c528 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -955,6 +955,6 @@ EXPORT_SYMBOL(strreplace);
 
 void fortify_panic(const char *name)
 {
-	panic("detected buffer overflow in %s", name);
+	WARN(1, "detected buffer overflow in %s", name);
 }
 EXPORT_SYMBOL(fortify_panic);

If necessary, change error to warning, but I don't think it will be necessary now.

And if it "works", it should produce a warning traceback when you resume from suspend where it did the panic before, which is an upstream bug to fix.

It builds now but still panics after resume. Disabling CONFIG_FORTIFY_SOURCE didn't help.

Try a clean build of the 4.11.f patch with 4.11.1 then to confirm that it wasn't an issue in that patch. There were only a couple of changes since that patch, so it will be easy for you to narrow down the precise cause.

And make sure that you're doing clean builds, with the configuration regenerated via make config to make sure it contains what you expect.

Can you give some more information about the environment you're running it in? Real hardware or a virtual machine (and in that case, which?)?

Lets leave this issue for @duroduro's issue, which may not be related to something you're running into.

Ok, the change at fault is reverted and will be included in the next release soon (4.11.1.c).

Please file similar issues as new bugs if they still occur after 4.11.1.c.