lkml.org 
[lkml]   [2004]   [Oct]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patches in this message
    /
    Date
    From
    SubjectRe: ESP corruption bug - what CPUs are affected? (patch attempts)
    Hi,

    Petr Vandrovec wrote:
    >> The reason is that the previous part of the macro
    >> can jump to that part. So how can I divide those?
    > Use real labels instead of numeric local labels.
    OK, I am really sorry for asking such a crap :(

    >> returning to the kernel if fails, should die()
    >> anyway. Is this correct?
    > If you'll first test result of lar, and then
    > you'll do two independent RESTORE_REGS (second
    > setup, instead of doing push + pop), you can reuse
    > RESOTRE_REGS+add $4,%esp+iret return path, including
    > its exception handling.
    Yes, but I was wondering whether we really do
    need an exception handler when returning to
    kernel. There should be no fault there, and
    if there is - it should be an Oops, I think.
    Nevertheless, I did what you said. Perhaps
    something like die_if_kernel() is somewhere
    down the road anyway.

    > Patch looks fine, though you could speedup it a bit as outlined above.
    New patch is attached.

    > Now you have to persuade others that this patch should include patch
    > into the kernel.
    Yes, if not for that anonymous guy, who kept posting
    to me until he finally convinced me that the Ring-0
    approach is not that difficult at all.
    So I tried... It was much more difficult to code
    up, but at the end it looks a little better
    and localized to entry.S completely. OTOH it
    touches the exception handlers, but not too much -
    it adds only 5 insns on the fast path. And the
    code is very fragile, but after I made all the
    magic numbers a #define consts, it actually looks
    not so bad.
    I don't know which patch is really better, so
    I am attaching both.
    Any ideas on which one should I have to continue
    working on and what improvements can be done to
    either one?

    diff -urN linux-2.6.8-pcsp/arch/i386/kernel/entry.S linux-2.6.8-stacks/arch/i386/kernel/entry.S
    --- linux-2.6.8-pcsp/arch/i386/kernel/entry.S 2004-06-10 13:28:35.000000000 +0400
    +++ linux-2.6.8-stacks/arch/i386/kernel/entry.S 2004-10-05 15:12:16.771426456 +0400
    @@ -70,15 +70,22 @@
    CF_MASK = 0x00000001
    TF_MASK = 0x00000100
    IF_MASK = 0x00000200
    -DF_MASK = 0x00000400
    +DF_MASK = 0x00000400
    +IOPL1_MASK = 0x00001000
    +IOPL2_MASK = 0x00002000
    +IOPL_MASK = 0x00003000
    NT_MASK = 0x00004000
    +RF_MASK = 0x00010000
    VM_MASK = 0x00020000
    +AC_MASK = 0x00040000
    +VIF_MASK = 0x00080000
    +VIP_MASK = 0x00100000

    #ifdef CONFIG_PREEMPT
    #define preempt_stop cli
    #else
    #define preempt_stop
    -#define resume_kernel restore_all
    +#define resume_kernel restore_context
    #endif

    #define SAVE_ALL \
    @@ -122,25 +129,6 @@
    .previous


    -#define RESTORE_ALL \
    - RESTORE_REGS \
    - addl $4, %esp; \
    -1: iret; \
    -.section .fixup,"ax"; \
    -2: sti; \
    - movl $(__USER_DS), %edx; \
    - movl %edx, %ds; \
    - movl %edx, %es; \
    - pushl $11; \
    - call do_exit; \
    -.previous; \
    -.section __ex_table,"a";\
    - .align 4; \
    - .long 1b,2b; \
    -.previous
    -
    -
    -
    ENTRY(lcall7)
    pushfl # We get a different stack layout with call
    # gates, which has to be cleaned up later..
    @@ -174,6 +162,15 @@
    jmp do_lcall


    +ENTRY(espfix_trampoline)
    + popl %esp
    +espfix_past_esp:
    +1: iret
    +.section __ex_table,"a"
    + .align 4
    + .long 1b,iret_exc
    +.previous
    +
    ENTRY(ret_from_fork)
    pushl %eax
    call schedule_tail
    @@ -196,8 +193,8 @@
    GET_THREAD_INFO(%ebp)
    movl EFLAGS(%esp), %eax # mix EFLAGS and CS
    movb CS(%esp), %al
    - testl $(VM_MASK | 3), %eax
    - jz resume_kernel # returning to kernel or vm86-space
    + testl $(VM_MASK | 2), %eax
    + jz resume_kernel
    ENTRY(resume_userspace)
    cli # make sure we don't miss an interrupt
    # setting need_resched or sigpending
    @@ -211,7 +208,7 @@
    #ifdef CONFIG_PREEMPT
    ENTRY(resume_kernel)
    cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ?
    - jnz restore_all
    + jnz restore_context
    need_resched:
    movl TI_flags(%ebp), %ecx # need_resched set ?
    testb $_TIF_NEED_RESCHED, %cl
    @@ -293,8 +290,82 @@
    movl TI_flags(%ebp), %ecx
    testw $_TIF_ALLWORK_MASK, %cx # current->work
    jne syscall_exit_work
    +
    restore_all:
    - RESTORE_ALL
    + /* If returning to Ring-3, not to V86, and with
    + * the small stack, try to fix the higher word of
    + * ESP, as the CPU won't restore it from stack.
    + * This is an "official" bug of all the x86-compatible
    + * CPUs, which we can try to work around to make
    + * dosemu happy. */
    + movl EFLAGS(%esp), %eax
    + movb CS(%esp), %al
    + andl $(VM_MASK | 2), %eax
    + /* returning to user-space and not to v86? */
    + cmpl $2, %eax
    + jne restore_context
    + larl OLDSS(%esp), %eax
    + /* returning to "small" stack? */
    + testl $0x00400000, %eax
    + jz 8f # go fixing ESP instead of just to return :(
    +restore_context:
    + RESTORE_REGS
    + addl $4, %esp
    +1: iret
    +.section .fixup,"ax"
    +iret_exc:
    + sti
    + movl $(__USER_DS), %edx
    + movl %edx, %ds
    + movl %edx, %es
    + pushl $11
    + call do_exit
    +.previous
    +.section __ex_table,"a"
    + .align 4
    + .long 1b,iret_exc
    +.previous
    + /* preparing the ESPfix here */
    +#define NMI_STACK_RESERVE 0x800
    + /* reserve some space on stack for the NMI handler */
    +8: RESTORE_REGS
    + subl $(NMI_STACK_RESERVE-4), %esp
    + .rept 5
    + pushl NMI_STACK_RESERVE+16(%esp)
    + .endr
    + subl $24, %esp
    + pushl %eax
    + leal 24(%esp), %eax
    + pushl %ebp
    + preempt_stop
    + GET_THREAD_INFO(%ebp)
    + movl TI_cpu(%ebp), %ebp
    + shll $GDT_SIZE_SHIFT, %ebp
    + /* find GDT of the proper CPU */
    + addl $cpu_gdt_table, %ebp
    + /* patch the base of the ring-1 16bit stack */
    + movw %ax, ((GDT_ENTRY_ESPFIX_SS << GDT_ENTRY_SHIFT) + 2)(%ebp)
    + shrl $16, %eax
    + movb %al, ((GDT_ENTRY_ESPFIX_SS << GDT_ENTRY_SHIFT) + 4)(%ebp)
    + movb %ah, ((GDT_ENTRY_ESPFIX_SS << GDT_ENTRY_SHIFT) + 7)(%ebp)
    + popl %ebp
    + /* push the ESP value to preload on ring-1 */
    + movl 28+12(%esp), %eax
    + movw $4, %ax
    + movl %eax, 4+20(%esp)
    + /* push the iret frame for our ring-1 trampoline */
    + movl $__ESPFIX_SS, 4+16(%esp)
    + movl $0, 4+12(%esp)
    + /* push ring-3 flags only to get the IOPL right */
    + movl 28+8(%esp), %eax
    + andl $IOPL_MASK, %eax
    + /* we need at least IOPL1 to re-enable interrupts */
    + orl $IOPL1_MASK, %eax
    + movl %eax, 4+8(%esp)
    + popl %eax
    + movl $__ESPFIX_CS, 4(%esp)
    + movl $espfix_trampoline, (%esp)
    + iret

    # perform work that needs to be done immediately before resumption
    ALIGN
    @@ -504,7 +575,12 @@
    ENTRY(nmi)
    cmpl $sysenter_entry,(%esp)
    je nmi_stack_fixup
    - pushl %eax
    + cmpl $espfix_past_esp,(%esp)
    + jne 1f
    + /* restart the "popl %esp" */
    + decl (%esp)
    + subw $4, 12(%esp)
    +1: pushl %eax
    movl %esp,%eax
    /* Do not access memory above the end of our stack page,
    * it might not exist.
    @@ -523,7 +599,7 @@
    pushl %edx
    call do_nmi
    addl $8, %esp
    - RESTORE_ALL
    + jmp restore_all

    nmi_stack_fixup:
    FIX_STACK(12,nmi_stack_correct, 1)
    diff -urN linux-2.6.8-pcsp/arch/i386/kernel/head.S linux-2.6.8-stacks/arch/i386/kernel/head.S
    --- linux-2.6.8-pcsp/arch/i386/kernel/head.S 2004-08-10 11:02:36.000000000 +0400
    +++ linux-2.6.8-stacks/arch/i386/kernel/head.S 2004-09-24 13:57:24.000000000 +0400
    @@ -514,8 +514,8 @@
    .quad 0x00009a0000000000 /* 0xc0 APM CS 16 code (16 bit) */
    .quad 0x0040920000000000 /* 0xc8 APM DS data */

    - .quad 0x0000000000000000 /* 0xd0 - unused */
    - .quad 0x0000000000000000 /* 0xd8 - unused */
    + .quad 0x00cfba000000ffff /* 0xd0 - ESPfix 32-bit CS */
    + .quad 0x0000b20000000017 /* 0xd8 - ESPfix 16-bit SS */
    .quad 0x0000000000000000 /* 0xe0 - unused */
    .quad 0x0000000000000000 /* 0xe8 - unused */
    .quad 0x0000000000000000 /* 0xf0 - unused */
    diff -urN linux-2.6.8-pcsp/arch/i386/kernel/traps.c linux-2.6.8-stacks/arch/i386/kernel/traps.c
    --- linux-2.6.8-pcsp/arch/i386/kernel/traps.c 2004-08-10 11:02:36.000000000 +0400
    +++ linux-2.6.8-stacks/arch/i386/kernel/traps.c 2004-09-23 17:54:52.000000000 +0400
    @@ -210,7 +210,7 @@

    esp = (unsigned long) (&regs->esp);
    ss = __KERNEL_DS;
    - if (regs->xcs & 3) {
    + if (regs->xcs & 2) {
    in_kernel = 0;
    esp = regs->esp;
    ss = regs->xss & 0xffff;
    @@ -264,7 +264,7 @@
    char c;
    unsigned long eip;

    - if (regs->xcs & 3)
    + if (regs->xcs & 2)
    goto no_bug; /* Not in kernel */

    eip = regs->eip;
    @@ -335,7 +335,7 @@

    static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
    {
    - if (!(regs->eflags & VM_MASK) && !(3 & regs->xcs))
    + if (!(regs->eflags & VM_MASK) && !(2 & regs->xcs))
    die(str, regs, err);
    }

    @@ -357,7 +357,7 @@
    goto trap_signal;
    }

    - if (!(regs->xcs & 3))
    + if (!(regs->xcs & 2))
    goto kernel_trap;

    trap_signal: {
    @@ -437,7 +437,7 @@
    if (regs->eflags & VM_MASK)
    goto gp_in_vm86;

    - if (!(regs->xcs & 3))
    + if (!(regs->xcs & 2))
    goto gp_in_kernel;

    current->thread.error_code = error_code;
    @@ -614,7 +614,7 @@
    * allowing programs to debug themselves without the ptrace()
    * interface.
    */
    - if ((regs->xcs & 3) == 0)
    + if ((regs->xcs & 2) == 0)
    goto clear_TF_reenable;
    if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE)
    goto clear_TF;
    @@ -630,7 +630,7 @@
    /* If this is a kernel mode trap, save the user PC on entry to
    * the kernel, that's what the debugger can make sense of.
    */
    - info.si_addr = ((regs->xcs & 3) == 0) ? (void *)tsk->thread.eip :
    + info.si_addr = ((regs->xcs & 3) != 3) ? (void *)tsk->thread.eip :
    (void *)regs->eip;
    force_sig_info(SIGTRAP, &info, tsk);

    diff -urN linux-2.6.8-pcsp/arch/i386/mm/extable.c linux-2.6.8-stacks/arch/i386/mm/extable.c
    --- linux-2.6.8-pcsp/arch/i386/mm/extable.c 2004-06-09 15:44:19.000000000 +0400
    +++ linux-2.6.8-stacks/arch/i386/mm/extable.c 2004-09-23 17:54:52.000000000 +0400
    @@ -26,6 +26,11 @@
    }
    #endif

    + if (unlikely(regs->xcs == __ESPFIX_CS))
    + {
    + regs->xcs = __KERNEL_CS;
    + }
    +
    fixup = search_exception_tables(regs->eip);
    if (fixup) {
    regs->eip = fixup->fixup;
    diff -urN linux-2.6.8-pcsp/arch/i386/mm/fault.c linux-2.6.8-stacks/arch/i386/mm/fault.c
    --- linux-2.6.8-pcsp/arch/i386/mm/fault.c 2004-08-10 11:02:37.000000000 +0400
    +++ linux-2.6.8-stacks/arch/i386/mm/fault.c 2004-09-23 17:54:52.000000000 +0400
    @@ -77,7 +77,7 @@
    u32 seg_ar, seg_limit, base, *desc;

    /* The standard kernel/user address space limit. */
    - *eip_limit = (seg & 3) ? USER_DS.seg : KERNEL_DS.seg;
    + *eip_limit = (seg & 2) ? USER_DS.seg : KERNEL_DS.seg;

    /* Unlikely, but must come before segment checks. */
    if (unlikely((regs->eflags & VM_MASK) != 0))
    diff -urN linux-2.6.8-pcsp/include/asm-i386/segment.h linux-2.6.8-stacks/include/asm-i386/segment.h
    --- linux-2.6.8-pcsp/include/asm-i386/segment.h 2004-01-09 09:59:19.000000000 +0300
    +++ linux-2.6.8-stacks/include/asm-i386/segment.h 2004-09-23 17:54:52.000000000 +0400
    @@ -38,8 +38,8 @@
    * 24 - APM BIOS support
    * 25 - APM BIOS support
    *
    - * 26 - unused
    - * 27 - unused
    + * 26 - ESPfix Ring-1 trampoline CS
    + * 27 - ESPfix Ring-1 small SS
    * 28 - unused
    * 29 - unused
    * 30 - unused
    @@ -71,14 +71,21 @@
    #define GDT_ENTRY_PNPBIOS_BASE (GDT_ENTRY_KERNEL_BASE + 6)
    #define GDT_ENTRY_APMBIOS_BASE (GDT_ENTRY_KERNEL_BASE + 11)

    +#define GDT_ENTRY_ESPFIX_CS (GDT_ENTRY_KERNEL_BASE + 14)
    +#define GDT_ENTRY_ESPFIX_SS (GDT_ENTRY_KERNEL_BASE + 15)
    +#define __ESPFIX_CS (GDT_ENTRY_ESPFIX_CS * 8 + 1)
    +#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8 + 1)
    +
    #define GDT_ENTRY_DOUBLEFAULT_TSS 31

    /*
    * The GDT has 32 entries
    */
    -#define GDT_ENTRIES 32
    -
    -#define GDT_SIZE (GDT_ENTRIES * 8)
    +#define GDT_ENTRIES_SHIFT 5
    +#define GDT_ENTRIES (1 << GDT_ENTRIES_SHIFT)
    +#define GDT_ENTRY_SHIFT 3
    +#define GDT_SIZE_SHIFT (GDT_ENTRIES_SHIFT + GDT_ENTRY_SHIFT)
    +#define GDT_SIZE (1 << GDT_SIZE_SHIFT)

    /* Simple and small GDT entries for booting only */
    diff -urN linux-2.6.8-pcsp/arch/i386/kernel/entry.S linux-2.6.8-stacks0/arch/i386/kernel/entry.S
    --- linux-2.6.8-pcsp/arch/i386/kernel/entry.S 2004-06-10 13:28:35.000000000 +0400
    +++ linux-2.6.8-stacks0/arch/i386/kernel/entry.S 2004-10-06 16:29:04.000000000 +0400
    @@ -78,7 +78,7 @@
    #define preempt_stop cli
    #else
    #define preempt_stop
    -#define resume_kernel restore_all
    +#define resume_kernel restore_context
    #endif

    #define SAVE_ALL \
    @@ -122,25 +122,6 @@
    .previous


    -#define RESTORE_ALL \
    - RESTORE_REGS \
    - addl $4, %esp; \
    -1: iret; \
    -.section .fixup,"ax"; \
    -2: sti; \
    - movl $(__USER_DS), %edx; \
    - movl %edx, %ds; \
    - movl %edx, %es; \
    - pushl $11; \
    - call do_exit; \
    -.previous; \
    -.section __ex_table,"a";\
    - .align 4; \
    - .long 1b,2b; \
    -.previous
    -
    -
    -
    ENTRY(lcall7)
    pushfl # We get a different stack layout with call
    # gates, which has to be cleaned up later..
    @@ -197,7 +178,7 @@
    movl EFLAGS(%esp), %eax # mix EFLAGS and CS
    movb CS(%esp), %al
    testl $(VM_MASK | 3), %eax
    - jz resume_kernel # returning to kernel or vm86-space
    + jz resume_kernel
    ENTRY(resume_userspace)
    cli # make sure we don't miss an interrupt
    # setting need_resched or sigpending
    @@ -211,7 +192,7 @@
    #ifdef CONFIG_PREEMPT
    ENTRY(resume_kernel)
    cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ?
    - jnz restore_all
    + jnz restore_context
    need_resched:
    movl TI_flags(%ebp), %ecx # need_resched set ?
    testb $_TIF_NEED_RESCHED, %cl
    @@ -293,8 +274,85 @@
    movl TI_flags(%ebp), %ecx
    testw $_TIF_ALLWORK_MASK, %cx # current->work
    jne syscall_exit_work
    +
    restore_all:
    - RESTORE_ALL
    + /* If returning to Ring-3, not to V86, and with
    + * the small stack, try to fix the higher word of
    + * ESP, as the CPU won't restore it from stack.
    + * This is an "official" bug of all the x86-compatible
    + * CPUs, which we can try to work around to make
    + * dosemu happy. */
    + movl EFLAGS(%esp), %eax
    + movb CS(%esp), %al
    + andl $(VM_MASK | 3), %eax
    + /* returning to user-space and not to v86? */
    + cmpl $3, %eax
    + jne restore_context
    + larl OLDSS(%esp), %eax
    + /* returning to "small" stack? */
    + testl $0x00400000, %eax
    + jz 8f # go fixing ESP instead of just to return :(
    +restore_context:
    + RESTORE_REGS
    + addl $4, %esp
    +1: iret
    +.section .fixup,"ax"
    +iret_exc:
    + sti
    + movl $(__USER_DS), %edx
    + movl %edx, %ds
    + movl %edx, %es
    + pushl $11
    + call do_exit
    +.previous
    +.section __ex_table,"a"
    + .align 4
    + .long 1b,iret_exc
    +.previous
    + /* preparing the ESPfix here */
    +#define FRAME_SIZE_ESTIM 24
    +#define ESPFIX_STACK_RESERVE (FRAME_SIZE_ESTIM * 3)
    +#define SP_ESTIMATE (ESPFIX_STACK_RESERVE - FRAME_SIZE_ESTIM)
    +#define ESPFIX_SWITCH16_OFFS 20
    +#define ESPFIX_SWITCH32_OFFS 28
    +#define ESPFIX_SWITCH16 (ESPFIX_STACK_RESERVE + ESPFIX_SWITCH16_OFFS)
    +#define ESPFIX_SWITCH32 (ESPFIX_STACK_RESERVE + ESPFIX_SWITCH32_OFFS)
    +8: RESTORE_REGS
    + addl $4, %esp
    + .rept 5
    + pushl 16(%esp)
    + .endr
    + pushl %eax
    + pushl %ebp
    + movl $__ESPFIX_SS, ESPFIX_SWITCH16_OFFS+8+4(%esp)
    + movl 8+12(%esp), %eax
    + movw $ESPFIX_STACK_RESERVE, %ax
    + movl %eax, ESPFIX_SWITCH16_OFFS+8(%esp)
    + movl $__KERNEL_DS, ESPFIX_SWITCH32_OFFS+8+4(%esp)
    + leal -FRAME_SIZE_ESTIM+8(%esp), %eax
    + movl %eax, ESPFIX_SWITCH32_OFFS+8(%esp)
    + subl $(ESPFIX_STACK_RESERVE-FRAME_SIZE_ESTIM), %eax
    + cli
    + GET_THREAD_INFO(%ebp)
    + movl TI_cpu(%ebp), %ebp
    + shll $GDT_SIZE_SHIFT, %ebp
    + /* find GDT of the proper CPU */
    + addl $cpu_gdt_table, %ebp
    + /* patch the base of the 16bit stack */
    + movw %ax, ((GDT_ENTRY_ESPFIX_SS << GDT_ENTRY_SHIFT) + 2)(%ebp)
    + shrl $16, %eax
    + movb %al, ((GDT_ENTRY_ESPFIX_SS << GDT_ENTRY_SHIFT) + 4)(%ebp)
    + movb %ah, ((GDT_ENTRY_ESPFIX_SS << GDT_ENTRY_SHIFT) + 7)(%ebp)
    + popl %ebp
    + popl %eax
    +espfix_before_lss:
    + lss ESPFIX_SWITCH16_OFFS(%esp), %esp
    +espfix_after_lss:
    + iret
    +.section __ex_table,"a"
    + .align 4
    + .long espfix_after_lss,iret_exc
    +.previous

    # perform work that needs to be done immediately before resumption
    ALIGN
    @@ -493,6 +551,36 @@
    pushl $do_debug
    jmp error_code

    +/* Check if we are on 16bit stack. Can happen either on iret of ESPFIX,
    + * or in an exception handler after that iret... */
    +#define CHECK_ESPFIX_STACK(label) \
    + pushl %eax; \
    + movl %ss, %eax; \
    + cmpl $__ESPFIX_SS, %eax; \
    + jne label;
    +/* using %es here because NMI can change %ss */
    +#define UNWIND_ESPFIX_STACK \
    + CHECK_ESPFIX_STACK(28f) \
    + pushl %es; \
    + movl %eax, %es; \
    + lss %es:ESPFIX_SWITCH32, %esp; \
    + popl %es; \
    +28: popl %eax;
    +/* have to compensate the difference between real SP and estimated. */
    +#define UNWIND_ESPFIX_STACK_NMI \
    + CHECK_ESPFIX_STACK(28f) \
    + movw $SP_ESTIMATE, %ax; \
    + subw %sp, %ax; \
    + movswl %ax, %eax; \
    + lss %ss:ESPFIX_SWITCH32, %esp; \
    + subl %eax, %esp; \
    + popl %eax; \
    + cmpl $espfix_after_lss, (%esp); \
    + jne nmi_stack_correct; \
    + movl $espfix_before_lss, (%esp); \
    + jmp nmi_stack_correct; \
    +28: popl %eax;
    +
    /*
    * NMI is doubly nasty. It can happen _while_ we're handling
    * a debug fault, and the debug fault hasn't yet been able to
    @@ -502,6 +590,7 @@
    * fault happened on the sysenter path.
    */
    ENTRY(nmi)
    + UNWIND_ESPFIX_STACK_NMI
    cmpl $sysenter_entry,(%esp)
    je nmi_stack_fixup
    pushl %eax
    @@ -523,7 +612,7 @@
    pushl %edx
    call do_nmi
    addl $8, %esp
    - RESTORE_ALL
    + jmp restore_all

    nmi_stack_fixup:
    FIX_STACK(12,nmi_stack_correct, 1)
    @@ -569,14 +658,17 @@
    jmp error_code

    ENTRY(segment_not_present)
    + UNWIND_ESPFIX_STACK
    pushl $do_segment_not_present
    jmp error_code

    ENTRY(stack_segment)
    + UNWIND_ESPFIX_STACK
    pushl $do_stack_segment
    jmp error_code

    ENTRY(general_protection)
    + UNWIND_ESPFIX_STACK
    pushl $do_general_protection
    jmp error_code

    diff -urN linux-2.6.8-pcsp/arch/i386/kernel/head.S linux-2.6.8-stacks0/arch/i386/kernel/head.S
    --- linux-2.6.8-pcsp/arch/i386/kernel/head.S 2004-08-10 11:02:36.000000000 +0400
    +++ linux-2.6.8-stacks0/arch/i386/kernel/head.S 2004-10-05 17:53:46.000000000 +0400
    @@ -514,7 +514,7 @@
    .quad 0x00009a0000000000 /* 0xc0 APM CS 16 code (16 bit) */
    .quad 0x0040920000000000 /* 0xc8 APM DS data */

    - .quad 0x0000000000000000 /* 0xd0 - unused */
    + .quad 0x000092000000ffff /* 0xd0 - ESPfix 16-bit SS */
    .quad 0x0000000000000000 /* 0xd8 - unused */
    .quad 0x0000000000000000 /* 0xe0 - unused */
    .quad 0x0000000000000000 /* 0xe8 - unused */
    diff -urN linux-2.6.8-pcsp/include/asm-i386/segment.h linux-2.6.8-stacks0/include/asm-i386/segment.h
    --- linux-2.6.8-pcsp/include/asm-i386/segment.h 2004-01-09 09:59:19.000000000 +0300
    +++ linux-2.6.8-stacks0/include/asm-i386/segment.h 2004-10-05 17:53:46.000000000 +0400
    @@ -38,7 +38,7 @@
    * 24 - APM BIOS support
    * 25 - APM BIOS support
    *
    - * 26 - unused
    + * 26 - ESPfix small SS
    * 27 - unused
    * 28 - unused
    * 29 - unused
    @@ -71,14 +71,19 @@
    #define GDT_ENTRY_PNPBIOS_BASE (GDT_ENTRY_KERNEL_BASE + 6)
    #define GDT_ENTRY_APMBIOS_BASE (GDT_ENTRY_KERNEL_BASE + 11)

    +#define GDT_ENTRY_ESPFIX_SS (GDT_ENTRY_KERNEL_BASE + 14)
    +#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8)
    +
    #define GDT_ENTRY_DOUBLEFAULT_TSS 31

    /*
    * The GDT has 32 entries
    */
    -#define GDT_ENTRIES 32
    -
    -#define GDT_SIZE (GDT_ENTRIES * 8)
    +#define GDT_ENTRIES_SHIFT 5
    +#define GDT_ENTRIES (1 << GDT_ENTRIES_SHIFT)
    +#define GDT_ENTRY_SHIFT 3
    +#define GDT_SIZE_SHIFT (GDT_ENTRIES_SHIFT + GDT_ENTRY_SHIFT)
    +#define GDT_SIZE (1 << GDT_SIZE_SHIFT)

    /* Simple and small GDT entries for booting only */
    \
     
     \ /
      Last update: 2005-03-22 14:06    [W:3.431 / U:0.084 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site