Do not allow system segments (TSS and LDT) from being loaded into segment
registers via sigreturn. Loading these segments into a segment register
normally results in a general protection fault. In the case of sigreturn,
setting CS or SS to a system segment will cause IRET to fault. This
then results in the instruction decoder attempting to use the invalid
segment. This can be avoided by rejecting system segments in the
sigreturn() syscall.
Signed-off-by: Brian Gerst <brgerst@gmail.com>
Reported-By: Michal Luczaj <mhal@rbox.co>
Link: https://lore.kernel.org/lkml/20231206004654.2986026-1-mhal@rbox.co/
---
arch/x86/kernel/signal_32.c | 4 ++++
arch/x86/kernel/signal_64.c | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c
index c12624bc82a3..0e1926b676b0 100644
--- a/arch/x86/kernel/signal_32.c
+++ b/arch/x86/kernel/signal_32.c
@@ -98,7 +98,11 @@ static bool ia32_restore_sigcontext(struct pt_regs *regs,
/* Get CS/SS and force CPL3 */
regs->cs = sc.cs | 0x03;
+ if (!valid_user_selector(regs->cs))
+ return false;
regs->ss = sc.ss | 0x03;
+ if (!valid_user_selector(regs->ss))
+ return false;
regs->flags = (regs->flags & ~FIX_EFLAGS) | (sc.flags & FIX_EFLAGS);
/* disable syscall checks */
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
index 23d8aaf8d9fd..666b147bf43a 100644
--- a/arch/x86/kernel/signal_64.c
+++ b/arch/x86/kernel/signal_64.c
@@ -79,7 +79,11 @@ static bool restore_sigcontext(struct pt_regs *regs,
/* Get CS/SS and force CPL3 */
regs->cs = sc.cs | 0x03;
+ if (!valid_user_selector(regs->cs))
+ return false;
regs->ss = sc.ss | 0x03;
+ if (!valid_user_selector(regs->ss))
+ return false;
regs->flags = (regs->flags & ~FIX_EFLAGS) | (sc.flags & FIX_EFLAGS);
/* disable syscall checks */
--
2.43.0
On Wed, 13 Dec 2023 at 08:34, Brian Gerst <brgerst@gmail.com> wrote:
>
> @@ -98,7 +98,11 @@ static bool ia32_restore_sigcontext(struct pt_regs *regs,
>
> /* Get CS/SS and force CPL3 */
> regs->cs = sc.cs | 0x03;
> + if (!valid_user_selector(regs->cs))
> + return false;
> regs->ss = sc.ss | 0x03;
> + if (!valid_user_selector(regs->ss))
> + return false;
Side note: the SS/CS checks could be stricter than the usual selector tests.
In particular, normal segments can be Null segments. But CS/SS must not be.
Also, since you're now checking the validity, maybe we shouldn't do
the "force cpl3" any more, and just make it an error to try to load a
non-cpl3 segment at sigreturn..
That forcing was literally just because we weren't checking it for sanity...
Linus
On December 13, 2023 10:54:00 AM PST, Linus Torvalds <torvalds@linuxfoundation.org> wrote: >On Wed, 13 Dec 2023 at 08:34, Brian Gerst <brgerst@gmail.com> wrote: >> >> @@ -98,7 +98,11 @@ static bool ia32_restore_sigcontext(struct pt_regs *regs, >> >> /* Get CS/SS and force CPL3 */ >> regs->cs = sc.cs | 0x03; >> + if (!valid_user_selector(regs->cs)) >> + return false; >> regs->ss = sc.ss | 0x03; >> + if (!valid_user_selector(regs->ss)) >> + return false; > >Side note: the SS/CS checks could be stricter than the usual selector tests. > >In particular, normal segments can be Null segments. But CS/SS must not be. > >Also, since you're now checking the validity, maybe we shouldn't do >the "force cpl3" any more, and just make it an error to try to load a >non-cpl3 segment at sigreturn.. > >That forcing was literally just because we weren't checking it for sanity... > > Linus Not to mention that changing a null descriptor to 3 is wrong.
On Sun, 17 Dec 2023 at 13:08, H. Peter Anvin <hpa@zytor.com> wrote:
>
> On December 13, 2023 10:54:00 AM PST, Linus Torvalds <torvalds@linuxfoundation.org> wrote:
]> >Side note: the SS/CS checks could be stricter than the usual selector tests.
> >
> >In particular, normal segments can be Null segments. But CS/SS must not be.
> >
> >Also, since you're now checking the validity, maybe we shouldn't do
> >the "force cpl3" any more, and just make it an error to try to load a
> >non-cpl3 segment at sigreturn..
> >
> >That forcing was literally just because we weren't checking it for sanity...
> >
> > Linus
>
> Not to mention that changing a null descriptor to 3 is wrong.
I don't think it is. All of 0-3 are "Null selectors". The RPL of the
selector simply doesn't matter when the index is zero, afaik.
But we obviously only do this for CS/SS, which can't be (any kind of)
Null selector and iret will GP on them regardless of the RPL in the
selector.
Linus
On December 17, 2023 1:40:53 PM PST, Linus Torvalds <torvalds@linuxfoundation.org> wrote: >On Sun, 17 Dec 2023 at 13:08, H. Peter Anvin <hpa@zytor.com> wrote: >> >> On December 13, 2023 10:54:00 AM PST, Linus Torvalds <torvalds@linuxfoundation.org> wrote: >]> >Side note: the SS/CS checks could be stricter than the usual selector tests. >> > >> >In particular, normal segments can be Null segments. But CS/SS must not be. >> > >> >Also, since you're now checking the validity, maybe we shouldn't do >> >the "force cpl3" any more, and just make it an error to try to load a >> >non-cpl3 segment at sigreturn.. >> > >> >That forcing was literally just because we weren't checking it for sanity... >> > >> > Linus >> >> Not to mention that changing a null descriptor to 3 is wrong. > >I don't think it is. All of 0-3 are "Null selectors". The RPL of the >selector simply doesn't matter when the index is zero, afaik. > >But we obviously only do this for CS/SS, which can't be (any kind of) >Null selector and iret will GP on them regardless of the RPL in the >selector. > > Linus Of course not for CS/SS, but I would agree that if the selector is 0 before the signal it shouldn't mysteriously and asynchronously become 3.
> -----Original Message-----
> From: H. Peter Anvin <hpa@zytor.com>
> Sent: Sunday, December 17, 2023 1:46 PM
> To: Linus Torvalds <torvalds@linuxfoundation.org>
> Cc: Brian Gerst <brgerst@gmail.com>; linux-kernel@vger.kernel.org;
> x86@kernel.org; Ingo Molnar <mingo@kernel.org>; Thomas Gleixner
> <tglx@linutronix.de>; Borislav Petkov <bp@alien8.de>; Peter Zijlstra
> <peterz@infradead.org>; Michal Luczaj <mhal@rbox.co>
> Subject: Re: [PATCH 3/3] x86/sigreturn: Reject system segements
>
> On December 17, 2023 1:40:53 PM PST, Linus Torvalds
> <torvalds@linuxfoundation.org> wrote:
> >On Sun, 17 Dec 2023 at 13:08, H. Peter Anvin <hpa@zytor.com> wrote:
> >>
> >> On December 13, 2023 10:54:00 AM PST, Linus Torvalds
> <torvalds@linuxfoundation.org> wrote:
> >]> >Side note: the SS/CS checks could be stricter than the usual selector tests.
> >> >
> >> >In particular, normal segments can be Null segments. But CS/SS must not be.
> >> >
> >> >Also, since you're now checking the validity, maybe we shouldn't do
> >> >the "force cpl3" any more, and just make it an error to try to load
> >> >a
> >> >non-cpl3 segment at sigreturn..
> >> >
> >> >That forcing was literally just because we weren't checking it for sanity...
> >> >
> >> > Linus
> >>
> >> Not to mention that changing a null descriptor to 3 is wrong.
> >
> >I don't think it is. All of 0-3 are "Null selectors". The RPL of the
> >selector simply doesn't matter when the index is zero, afaik.
> >
> >But we obviously only do this for CS/SS, which can't be (any kind of)
> >Null selector and iret will GP on them regardless of the RPL in the
> >selector.
> >
> > Linus
>
> Of course not for CS/SS, but I would agree that if the selector is 0 before the
> signal it shouldn't mysteriously and asynchronously become 3.
Unfortunately reload_segments() _always_ sets DPL bits of GS/FS/DS/ES
to 3, even for 0. And IRET clears DPL bits when loading a NULL selector
into GS/FS/DS/ES:
https://lore.kernel.org/lkml/20230706052231.2183-1-xin3.li@intel.com/
Thanks!
Xin
© 2016 - 2025 Red Hat, Inc.