]> www.infradead.org Git - users/jedix/linux-maple.git/commit
x86/ia32: Leave NULL selector values 0~3 unchanged
authorXin Li (Intel) <xin@zytor.com>
Tue, 26 Nov 2024 18:45:28 +0000 (10:45 -0800)
committerIngo Molnar <mingo@kernel.org>
Thu, 27 Feb 2025 21:46:11 +0000 (22:46 +0100)
commitad546940b5991d3e141238cd80a6d1894b767184
tree4cbc013be556612343db2fe141b18574d57d05a6
parent18cdd90aba794333f4c6dce39f5c3fe642af5575
x86/ia32: Leave NULL selector values 0~3 unchanged

The first GDT descriptor is reserved as 'NULL descriptor'.  As bits 0
and 1 of a segment selector, i.e., the RPL bits, are NOT used to index
GDT, selector values 0~3 all point to the NULL descriptor, thus values
0, 1, 2 and 3 are all valid NULL selector values.

When a NULL selector value is to be loaded into a segment register,
reload_segments() sets its RPL bits.  Later IRET zeros ES, FS, GS, and
DS segment registers if any of them is found to have any nonzero NULL
selector value.  The two operations offset each other to actually effect
a nop.

Besides, zeroing of RPL in NULL selector values is an information leak
in pre-FRED systems as userspace can spot any interrupt/exception by
loading a nonzero NULL selector, and waiting for it to become zero.
But there is nothing software can do to prevent it before FRED.

ERETU, the only legit instruction to return to userspace from kernel
under FRED, by design does NOT zero any segment register to avoid this
problem behavior.

As such, leave NULL selector values 0~3 unchanged and close the leak.

Do the same on 32-bit kernel as well.

Signed-off-by: Xin Li (Intel) <xin@zytor.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20241126184529.1607334-1-xin@zytor.com
arch/x86/kernel/signal_32.c