Messages in this thread Patch in this message | | | From | Xin Li <> | Subject | [PATCH] x86/ia32: Do not modify the DPL bits for a null selector | Date | Wed, 5 Jul 2023 22:22:31 -0700 |
| |
When a null selector is to be loaded into a segment register, reload_segments() sets its DPL bits to 3. Later when an IRET instruction loads it, it zeros the segment register. The two operations offset each other to actually effect a nop.
Fix it by not modifying the DPL bits for a null selector.
Signed-off-by: Xin Li <xin3.li@intel.com> --- arch/x86/kernel/signal_32.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 9027fc088f97..7796cf84fca2 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -36,22 +36,27 @@ #ifdef CONFIG_IA32_EMULATION #include <asm/ia32_unistd.h> +static inline u16 usrseg(u16 sel) +{ + return sel <= 3 ? sel : sel | 3; +} + static inline void reload_segments(struct sigcontext_32 *sc) { unsigned int cur; savesegment(gs, cur); - if ((sc->gs | 0x03) != cur) - load_gs_index(sc->gs | 0x03); + if (usrseg(sc->gs) != cur) + load_gs_index(usrseg(sc->gs)); savesegment(fs, cur); - if ((sc->fs | 0x03) != cur) - loadsegment(fs, sc->fs | 0x03); + if (usrseg(sc->fs) != cur) + loadsegment(fs, usrseg(sc->fs)); savesegment(ds, cur); - if ((sc->ds | 0x03) != cur) - loadsegment(ds, sc->ds | 0x03); + if (usrseg(sc->ds) != cur) + loadsegment(ds, usrseg(sc->ds)); savesegment(es, cur); - if ((sc->es | 0x03) != cur) - loadsegment(es, sc->es | 0x03); + if (usrseg(sc->es) != cur) + loadsegment(es, usrseg(sc->es)); } #define sigset32_t compat_sigset_t -- 2.34.1
| |