2023-01-08 19:54:59

by Maciej W. Rozycki

[permalink] [raw]
Subject: [PATCH] x86: Disable kernel stack offset randomization for !TSC

For x86 kernel stack offset randomization uses the RDTSC instruction,
which causes an invalid opcode exception with hardware that does not
implement this instruction:

process '/sbin/init' started with executable stack
invalid opcode: 0000 [#1]
CPU: 0 PID: 1 Comm: init Not tainted 6.1.0-rc4+ #1
EIP: exit_to_user_mode_prepare+0x90/0xe1
Code: 30 02 00 75 ad 0f ba e3 16 73 05 e8 a7 a5 fc ff 0f ba e3 0e 73 05 e8 3e af fc ff a1 c4 c6 51 c0 85 c0 7e 13 8b 0d ac 01 53 c0 <0f> 31 0f b6 c0 31 c1 89 0d ac 01 53 c0 83 3d 30 ed 62 c0 00 75 33
EAX: 00000001 EBX: 00004000 ECX: 00000000 EDX: 000004ff
ESI: c10253c0 EDI: 00000000 EBP: c1027f98 ESP: c1027f8c
DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068 EFLAGS: 00010002
CR0: 80050033 CR2: bfe8659b CR3: 012e0000 CR4: 00000000
Call Trace:
? rest_init+0x72/0x72
syscall_exit_to_user_mode+0x15/0x27
ret_from_fork+0x10/0x30
EIP: 0xb7f74800
Code: Unable to access opcode bytes at 0xb7f747d6.
EAX: 00000000 EBX: 00000000 ECX: 00000000 EDX: 00000000
ESI: 00000000 EDI: 00000000 EBP: 00000000 ESP: bfe864b0
DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 007b EFLAGS: 00000200
---[ end trace 0000000000000000 ]---
EIP: exit_to_user_mode_prepare+0x90/0xe1
Code: 30 02 00 75 ad 0f ba e3 16 73 05 e8 a7 a5 fc ff 0f ba e3 0e 73 05 e8 3e af fc ff a1 c4 c6 51 c0 85 c0 7e 13 8b 0d ac 01 53 c0 <0f> 31 0f b6 c0 31 c1 89 0d ac 01 53 c0 83 3d 30 ed 62 c0 00 75 33
EAX: 00000001 EBX: 00004000 ECX: 00000000 EDX: 000004ff
ESI: c10253c0 EDI: 00000000 EBP: c1027f98 ESP: c1027f8c
DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068 EFLAGS: 00010002
CR0: 80050033 CR2: b7f747d6 CR3: 012e0000 CR4: 00000000
Kernel panic - not syncing: Fatal exception

Therefore do not offer the option for CPU configurations that do not
guarantee the presence of this instruction.

Signed-off-by: Maciej W. Rozycki <[email protected]>
---
arch/x86/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

linux-x86-randomize-kstack-offset-tsc.diff
Index: linux-macro/arch/x86/Kconfig
===================================================================
--- linux-macro.orig/arch/x86/Kconfig
+++ linux-macro/arch/x86/Kconfig
@@ -186,7 +186,7 @@ config X86
select HAVE_ARCH_USERFAULTFD_WP if X86_64 && USERFAULTFD
select HAVE_ARCH_USERFAULTFD_MINOR if X86_64 && USERFAULTFD
select HAVE_ARCH_VMAP_STACK if X86_64
- select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
+ select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET if X86_TSC
select HAVE_ARCH_WITHIN_STACK_FRAMES
select HAVE_ASM_MODVERSIONS
select HAVE_CMPXCHG_DOUBLE


2023-01-08 20:00:52

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH] x86: Disable kernel stack offset randomization for !TSC

On Sun, Jan 08, 2023 at 07:42:54PM +0000, Maciej W. Rozycki wrote:
> For x86 kernel stack offset randomization uses the RDTSC instruction,
> which causes an invalid opcode exception with hardware that does not
> implement this instruction:

Out of pure curiosity, what hw is that?

Also, I guess the fix should be something like this instead:

---
diff --git a/arch/x86/include/asm/entry-common.h b/arch/x86/include/asm/entry-common.h
index 117903881fe4..57b372ca6ce7 100644
--- a/arch/x86/include/asm/entry-common.h
+++ b/arch/x86/include/asm/entry-common.h
@@ -85,7 +85,8 @@ static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs,
* Therefore, final stack offset entropy will be 5 (x86_64) or
* 6 (ia32) bits.
*/
- choose_random_kstack_offset(rdtsc() & 0xFF);
+ if (cpu_feature_enabled(X86_FEATURE_TSC))
+ choose_random_kstack_offset(rdtsc() & 0xFF);
}
#define arch_exit_to_user_mode_prepare arch_exit_to_user_mode_prepare



--
Regards/Gruss,
Boris.

https://people.kernel.org/tglx/notes-about-netiquette

2023-01-08 20:38:25

by Maciej W. Rozycki

[permalink] [raw]
Subject: Re: [PATCH] x86: Disable kernel stack offset randomization for !TSC

On Sun, 8 Jan 2023, Borislav Petkov wrote:

> > For x86 kernel stack offset randomization uses the RDTSC instruction,
> > which causes an invalid opcode exception with hardware that does not
> > implement this instruction:
>
> Out of pure curiosity, what hw is that?

processor : 0
vendor_id : GenuineIntel
cpu family : 4
model : 3
model name : 486 DX/2
stepping : 5
fdiv_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 1
wp : yes
flags : fpu vme cpuid
bugs : itlb_multihit
bogomips : 32.35
clflush size : 32
cache_alignment : 32
address sizes : 32 bits physical, 32 bits virtual
power management:

> Also, I guess the fix should be something like this instead:
>
> ---
> diff --git a/arch/x86/include/asm/entry-common.h b/arch/x86/include/asm/entry-common.h
> index 117903881fe4..57b372ca6ce7 100644
> --- a/arch/x86/include/asm/entry-common.h
> +++ b/arch/x86/include/asm/entry-common.h
> @@ -85,7 +85,8 @@ static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs,
> * Therefore, final stack offset entropy will be 5 (x86_64) or
> * 6 (ia32) bits.
> */
> - choose_random_kstack_offset(rdtsc() & 0xFF);
> + if (cpu_feature_enabled(X86_FEATURE_TSC))
> + choose_random_kstack_offset(rdtsc() & 0xFF);

I'll check if that works, thanks for the suggestion.

Maciej

2023-01-08 20:39:47

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH] x86: Disable kernel stack offset randomization for !TSC

On Sun, Jan 08, 2023 at 08:04:14PM +0000, Maciej W. Rozycki wrote:
> processor : 0
> vendor_id : GenuineIntel
> cpu family : 4
> model : 3
> model name : 486 DX/2
> stepping : 5

Real hw?

If so, LOL, amazing that a box like that still even boots.

A modern phone is likely orders of magnitudes more powerful than this relic.

:-)

--
Regards/Gruss,
Boris.

https://people.kernel.org/tglx/notes-about-netiquette

2023-01-08 20:44:11

by Maciej W. Rozycki

[permalink] [raw]
Subject: Re: [PATCH] x86: Disable kernel stack offset randomization for !TSC

On Sun, 8 Jan 2023, Borislav Petkov wrote:

> > processor : 0
> > vendor_id : GenuineIntel
> > cpu family : 4
> > model : 3
> > model name : 486 DX/2
> > stepping : 5
>
> Real hw?
>
> If so, LOL, amazing that a box like that still even boots.

Why? I have slower non-x86 hardware that boots current Linux. This box
at least has 128MiB of RAM (I still look forward to doubling it if I find
the right modules) and boots quite quickly. It's portable (luggable) too.

> A modern phone is likely orders of magnitudes more powerful than this relic.

It doesn't provide the environment to verify that EISA FDDI networking
(defxx.c) continues to operate as expected though.

Maciej

2023-01-14 00:01:09

by Kees Cook

[permalink] [raw]
Subject: Re: [PATCH] x86: Disable kernel stack offset randomization for !TSC

On Sun, Jan 08, 2023 at 08:55:06PM +0100, Borislav Petkov wrote:
> On Sun, Jan 08, 2023 at 07:42:54PM +0000, Maciej W. Rozycki wrote:
> > For x86 kernel stack offset randomization uses the RDTSC instruction,
> > which causes an invalid opcode exception with hardware that does not
> > implement this instruction:
>
> Out of pure curiosity, what hw is that?
>
> Also, I guess the fix should be something like this instead:
>
> ---
> diff --git a/arch/x86/include/asm/entry-common.h b/arch/x86/include/asm/entry-common.h
> index 117903881fe4..57b372ca6ce7 100644
> --- a/arch/x86/include/asm/entry-common.h
> +++ b/arch/x86/include/asm/entry-common.h
> @@ -85,7 +85,8 @@ static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs,
> * Therefore, final stack offset entropy will be 5 (x86_64) or
> * 6 (ia32) bits.
> */
> - choose_random_kstack_offset(rdtsc() & 0xFF);
> + if (cpu_feature_enabled(X86_FEATURE_TSC))
> + choose_random_kstack_offset(rdtsc() & 0xFF);
> }
> #define arch_exit_to_user_mode_prepare arch_exit_to_user_mode_prepare

I think probably the entire feature should just be disabled in early
boot, checking for TSC, and then using:

if (!cpu_feature_enabled(X86_FEATURE_TSC))
static_branch_disable(&randomize_kstack_offset);

I'm not sure the best place to put that where it's early but late enough
that static branches are working...

--
Kees Cook