Messages in this thread Patch in this message | | | From | "Eric W. Biederman" <> | Date | Fri, 07 Jul 2023 12:28:13 -0500 | Subject | Re: [PATCH] x86/ia32: Do not modify the DPL bits for a null selector |
| |
"Li, Xin3" <xin3.li@intel.com> writes:
>> Thus 3 as a selector is the same as 0, and it doesn't matter to change it or not. But >> when IRET sees an invalid segment register in ES, FS, GS, and DS, it sets it to 0, >> making 0 a preferred null selector value. > > To clarify, an invalid segment register value includes NULL selector values.
Perhaps something like patch below to make it clear that we are normalizing the segment values and forcing that normalization.
I am a bit confused why this code is not the same for ia32 and ia32_emulation. I would think the normalization at least should apply to the 32bit case as well.
Eric
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 9027fc088f97..e5f3978388fd 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -36,22 +36,47 @@ #ifdef CONFIG_IA32_EMULATION #include <asm/ia32_unistd.h> +static inline unsigned int normalize_seg_index(unsigned int index) +{ + /* + * Convert the segment index into normalized form. + * + * For the indexes 0,1,2,3 always use the value of 0, as IRET + * forces this form for the nul segment. + * + * Otherwise set both DPL bits to force it to be a userspace + * ring 3 segment index. + */ + return (index < 3) ? 0 : index | 3; +} + static inline void reload_segments(struct sigcontext_32 *sc) { - unsigned int cur; + unsigned int new, cur; + new = normalize_seg_index(sc->gs); savesegment(gs, cur); - if ((sc->gs | 0x03) != cur) - load_gs_index(sc->gs | 0x03); + cur = normalize_seg_index(cur); + if (new != cur) + load_gs_index(new); + + new = normalize_seg_index(sc->fs); savesegment(fs, cur); - if ((sc->fs | 0x03) != cur) - loadsegment(fs, sc->fs | 0x03); + cur = normalize_seg_index(cur); + if (new != cur) + loadsegment(fs, new); + + new = normalize_seg_index(sc->ds); savesegment(ds, cur); - if ((sc->ds | 0x03) != cur) - loadsegment(ds, sc->ds | 0x03); + cur = normalize_seg_index(cur); + if (new != cur) + loadsegment(ds, new); + + new = normalize_seg_index(sc->es); savesegment(es, cur); - if ((sc->es | 0x03) != cur) - loadsegment(es, sc->es | 0x03); + cur = normalize_seg_index(cur); + if (new != cur) + loadsegment(es, new); } #define sigset32_t compat_sigset_t
| |