RE: [PATCH] x86/ia32: Do not modify the DPL bits for a null selector

From: Li, Xin3
Date: Fri Jul 07 2023 - 18:17:52 EST


> Perhaps something like patch below to make it clear that we are
> normalizing the segment values and forcing that normalization.

"Normalizing" sounds a good term.

> 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)

normalize_usrseg_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;

s/</<=

no?

With this patch it looks that 1,2,3 are no longer valid selector values
in Linux, which seems the right thing to do but I don't know if there is
any side effect.

> +}
> +
> 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