x86: limit the fs segment to the pointer size
authorMasahiro Yamada <masahiroy@kernel.org>
Wed, 8 Jan 2020 11:13:42 +0000 (20:13 +0900)
committerBin Meng <bmeng.cn@gmail.com>
Mon, 3 Feb 2020 17:19:26 +0000 (01:19 +0800)
The fs segment is only used to get the global data pointer.
If it is accessed beyond sizeof(new_gd->arch.gd_addr), it is a bug.

To specify the byte-granule limit size, drop the G bit, so the
flag field is 0x8093 instead of 0xc093, and set the limit field
to sizeof(new_gd->arch.gd_addr) - 1.

Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Tested-by: Bin Meng <bmeng.cn@gmail.com>
[bmeng: fixed the comments about FS segement]
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
arch/x86/cpu/i386/cpu.c

index 1592b2c9d3b3a503251af4317b6541db89721e29..c8da7f10e9b611739b821d5d4c004b3acfc482f0 100644 (file)
@@ -136,10 +136,14 @@ void arch_setup_gd(gd_t *new_gd)
        /* DS: data, read/write, 4 GB, base 0 */
        gdt_addr[X86_GDT_ENTRY_32BIT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff);
 
-       /* FS: data, read/write, 4 GB, base (Global Data Pointer) */
+       /*
+        * FS: data, read/write, sizeof (Global Data Pointer),
+        * base (Global Data Pointer)
+        */
        new_gd->arch.gd_addr = new_gd;
-       gdt_addr[X86_GDT_ENTRY_32BIT_FS] = GDT_ENTRY(0xc093,
-                    (ulong)&new_gd->arch.gd_addr, 0xfffff);
+       gdt_addr[X86_GDT_ENTRY_32BIT_FS] = GDT_ENTRY(0x8093,
+                                       (ulong)&new_gd->arch.gd_addr,
+                                       sizeof(new_gd->arch.gd_addr) - 1);
 
        /* 16-bit CS: code, read/execute, 64 kB, base 0 */
        gdt_addr[X86_GDT_ENTRY_16BIT_CS] = GDT_ENTRY(0x009b, 0, 0x0ffff);