[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH 5/5] add setting gs/fsbase
From: |
Samuel Thibault |
Subject: |
Re: [PATCH 5/5] add setting gs/fsbase |
Date: |
Mon, 1 May 2023 03:30:33 +0200 |
User-agent: |
NeoMutt/20170609 (1.8.3) |
Applied, thanks!
Luca Dariz, le mer. 19 avril 2023 21:47:03 +0200, a ecrit:
> * i386/i386/i386asm.sym: add offsets for asm
> * i386/i386/pcb.c: switch FSBASE/GSBASE on context switch and
> implement accessors in thread setstatus/getstatus
> * i386/i386/thread.h: add new state to thread saved state
> * kern/thread.c: add i386_FSGS_BASE_STATE handler
> * x86_64/locore.S: fix fs/gs handling, skipping the base address and
> avoid resetting it by manually re-loading fs/gs
> ---
> i386/i386/i386asm.sym | 2 +
> i386/i386/pcb.c | 39 +++++++++++++++++--
> i386/i386/thread.h | 4 ++
> kern/thread.c | 3 ++
> x86_64/locore.S | 89 ++++++++++++++++++++++++++++++++++---------
> 5 files changed, 116 insertions(+), 21 deletions(-)
>
> diff --git a/i386/i386/i386asm.sym b/i386/i386/i386asm.sym
> index 1b9b40bb..fd0be557 100644
> --- a/i386/i386/i386asm.sym
> +++ b/i386/i386/i386asm.sym
> @@ -108,6 +108,8 @@ offset i386_saved_state r r12
> offset i386_saved_state r r13
> offset i386_saved_state r r14
> offset i386_saved_state r r15
> +offset i386_saved_state r fsbase
> +offset i386_saved_state r gsbase
> #endif
>
> offset i386_interrupt_state i eip
> diff --git a/i386/i386/pcb.c b/i386/i386/pcb.c
> index 61125fe8..8a9e3bf4 100644
> --- a/i386/i386/pcb.c
> +++ b/i386/i386/pcb.c
> @@ -51,6 +51,7 @@
> #include "eflags.h"
> #include "gdt.h"
> #include "ldt.h"
> +#include "msr.h"
> #include "ktss.h"
> #include "pcb.h"
>
> @@ -372,7 +373,10 @@ thread_t switch_context(
> * Load the rest of the user state for the new thread
> */
> switch_ktss(new->pcb);
> -
> +#if defined(__x86_64__) && !defined(USER32)
> + wrmsr(MSR_REG_FSBASE, new->pcb->iss.fsbase);
> + wrmsr(MSR_REG_GSBASE, new->pcb->iss.gsbase);
> +#endif
> return Switch_context(old, continuation, new);
> }
>
> @@ -667,7 +671,23 @@ kern_return_t thread_setstatus(
> return ret;
> break;
> }
> -
> +#if defined(__x86_64__) && !defined(USER32)
> + case i386_FSGS_BASE_STATE:
> + {
> + struct i386_fsgs_base_state *state;
> + if (count < i386_FSGS_BASE_STATE_COUNT)
> + return KERN_INVALID_ARGUMENT;
> +
> + state = (struct i386_fsgs_base_state *) tstate;
> + thread->pcb->iss.fsbase = state->fs_base;
> + thread->pcb->iss.gsbase = state->gs_base;
> + if (thread == current_thread()) {
> + wrmsr(MSR_REG_FSBASE, state->fs_base);
> + wrmsr(MSR_REG_GSBASE, state->gs_base);
> + }
> + break;
> + }
> +#endif
> default:
> return(KERN_INVALID_ARGUMENT);
> }
> @@ -843,7 +863,20 @@ kern_return_t thread_getstatus(
> *count = i386_DEBUG_STATE_COUNT;
> break;
> }
> -
> +#if defined(__x86_64__) && !defined(USER32)
> + case i386_FSGS_BASE_STATE:
> + {
> + struct i386_fsgs_base_state *state;
> + if (*count < i386_FSGS_BASE_STATE_COUNT)
> + return KERN_INVALID_ARGUMENT;
> +
> + state = (struct i386_fsgs_base_state *) tstate;
> + state->fs_base = thread->pcb->iss.fsbase;
> + state->fs_base = thread->pcb->iss.gsbase;
> + *count = i386_FSGS_BASE_STATE_COUNT;
> + break;
> + }
> +#endif
> default:
> return(KERN_INVALID_ARGUMENT);
> }
> diff --git a/i386/i386/thread.h b/i386/i386/thread.h
> index 933b43d8..b5fc5ffb 100644
> --- a/i386/i386/thread.h
> +++ b/i386/i386/thread.h
> @@ -51,6 +51,10 @@
> */
>
> struct i386_saved_state {
> +#ifdef __x86_64__
> + unsigned long fsbase;
> + unsigned long gsbase;
> +#endif
> unsigned long gs;
> unsigned long fs;
> unsigned long es;
> diff --git a/kern/thread.c b/kern/thread.c
> index 392d38f8..f0cea804 100644
> --- a/kern/thread.c
> +++ b/kern/thread.c
> @@ -1472,6 +1472,9 @@ kern_return_t thread_set_state(
> if (flavor == i386_DEBUG_STATE && thread == current_thread())
> /* This state can be set directly for the curren thread. */
> return thread_setstatus(thread, flavor, new_state,
> new_state_count);
> + if (flavor == i386_FSGS_BASE_STATE && thread == current_thread())
> + /* This state can be set directly for the curren thread. */
> + return thread_setstatus(thread, flavor, new_state,
> new_state_count);
> #endif
>
> if (thread == THREAD_NULL || thread == current_thread())
> diff --git a/x86_64/locore.S b/x86_64/locore.S
> index 1b17d921..ba0400a3 100644
> --- a/x86_64/locore.S
> +++ b/x86_64/locore.S
> @@ -34,6 +34,7 @@
> #include <i386/i386/trap.h>
> #include <i386/i386/seg.h>
> #include <i386/i386/ldt.h>
> +#include <i386/i386/msr.h>
> #include <i386/i386/i386asm.h>
> #include <i386/i386/cpu_number.h>
> #include <i386/i386/xen.h>
> @@ -41,6 +42,46 @@
> #define pusha pushq %rax ; pushq %rcx ; pushq %rdx ; pushq %rbx ; subq
> $8,%rsp ; pushq %rbp ; pushq %rsi ; pushq %rdi ; pushq %r8 ; pushq %r9 ;
> pushq %r10 ; pushq %r11 ; pushq %r12 ; pushq %r13 ; pushq %r14 ; pushq %r15
> #define popa popq %r15 ; popq %r14 ; popq %r13 ; popq %r12 ; popq %r11 ;
> popq %r10 ; popq %r9 ; popq %r8 ; popq %rdi ; popq %rsi ; popq %rbp ; addq
> $8,%rsp ; popq %rbx ; popq %rdx ; popq %rcx ; popq %rax
>
> +#ifdef USER32
> +#define PUSH_FSGS \
> + pushq %fs ;\
> + pushq %gs ;\
> + subq $16,%rsp
> +#else
> +#define PUSH_FSGS \
> + subq $32,%rsp
> +#endif
> +
> +#ifdef USER32
> +#define POP_FSGS \
> + popq %gs ;\
> + popq %fs ;\
> + addq $16,%rsp
> +#else
> +#define POP_FSGS \
> + addq $32,%rsp
> +#endif
> +
> +#ifdef USER32
> +#define PUSH_FSGS_ISR \
> + pushq %fs ;\
> + pushq %gs
> +#else
> +#define PUSH_FSGS_ISR \
> + subq $16,%rsp
> +#endif
> +
> +#ifdef USER32
> +#define POP_FSGS_ISR \
> + popq %gs ;\
> + popq %fs
> +#else
> +#define POP_FSGS_ISR \
> + addq $16,%rsp
> +#endif
> +
> +
> +
> /*
> * Fault recovery.
> */
> @@ -405,6 +446,11 @@ push_fs:
> pushq %fs /* restore fs, */
> push_gs:
> pushq %gs /* restore gs. */
> +#ifdef USER32
> +push_gsbase:
> + pushq $0
> + pushq $0
> +#endif
> push_segregs:
> movq %rax,R_TRAPNO(%rsp) /* set trap number */
> movq %rdx,R_ERR(%rsp) /* set error code */
> @@ -470,8 +516,7 @@ trap_push_segs:
> pushq %rax
> movq %es,%rax /* and the segment registers */
> pushq %rax
> - pushq %fs
> - pushq %gs
> + PUSH_FSGS
>
> /* Note that we have to load the segment registers
> even if this is a trap from the kernel,
> @@ -480,9 +525,10 @@ trap_push_segs:
> mov %ss,%ax /* switch to kernel data segment */
> mov %ax,%ds /* (same as kernel stack segment) */
> mov %ax,%es
> +#ifdef USER32
> mov %ax,%fs
> mov %ax,%gs
> -
> +#endif
> trap_set_segs:
> cld /* clear direction flag */
> testl $(EFL_VM),R_EFLAGS(%rsp) /* in V86 mode? */
> @@ -536,10 +582,17 @@ _return_to_user:
> */
>
> _return_from_kernel:
> + addq $16,%rsp /* skip FS/GS base */
> +#ifndef USER32
> +_kret_popl_gs:
> +_kret_popl_fs:
> + addq $16,%rsp /* skip FS/GS selector */
> +#else
> _kret_popl_gs:
> popq %gs /* restore segment registers */
> _kret_popl_fs:
> popq %fs
> +#endif
> _kret_popl_es:
> popq %rax
> movq %rax,%es
> @@ -695,14 +748,15 @@ ENTRY(all_intrs)
> pushq %rdx
> movq %es,%rdx
> pushq %rdx
> - pushq %fs
> - pushq %gs
> + PUSH_FSGS_ISR
> +
> mov %ss,%dx /* switch to kernel segments */
> mov %dx,%ds
> mov %dx,%es
> +#ifdef USER32
> mov %dx,%fs
> mov %dx,%gs
> -
> +#endif
> CPU_NUMBER(%edx)
>
> movq CX(EXT(int_stack_top),%edx),%rcx
> @@ -741,8 +795,7 @@ LEXT(return_to_iret) /* ( label for
> kdb_kintr and hardclock) */
> cmpq $0,CX(EXT(need_ast),%edx)
> jnz ast_from_interrupt /* take it if so */
> 1:
> - pop %gs /* restore segment regs */
> - pop %fs
> + POP_FSGS_ISR
> pop %rdx
> mov %rdx,%es
> pop %rdx
> @@ -796,9 +849,7 @@ stack_overflowed:
> * ss
> */
> ast_from_interrupt:
> - pop %gs /* restore all registers ... */
> - pop %fs
> - pop %rdx
> + POP_FSGS
> mov %rdx,%es
> pop %rdx
> mov %rdx,%ds
> @@ -818,14 +869,15 @@ ast_from_interrupt:
> push %rdx
> mov %es,%rdx
> push %rdx
> - push %fs
> - push %gs
> + PUSH_FSGS
> +
> mov %ss,%dx /* switch to kernel segments */
> mov %dx,%ds
> mov %dx,%es
> +#ifdef USER32
> mov %dx,%fs
> mov %dx,%gs
> -
> +#endif
> CPU_NUMBER(%edx)
> TIME_TRAP_UENTRY
>
> @@ -947,14 +999,12 @@ kdb_from_iret_i: /* on interrupt
> stack */
> push %rdx
> mov %es,%rdx
> push %rdx
> - push %fs
> - push %gs
> + PUSH_FSGS
> movq %rsp,%rdx /* pass regs, */
> movq $0,%rsi /* code, */
> movq $-1,%rdi /* type to kdb */
> call EXT(kdb_trap)
> - pop %gs /* restore segment registers */
> - pop %fs
> + POP_FSGS
> pop %rdx
> mov %rdx,%es
> pop %rdx
> @@ -1039,6 +1089,7 @@ ttd_from_iret_i: /* on interrupt
> stack */
> push %rdx
> push %fs
> push %gs
> + ud2 // TEST it
> movq %rsp,%rdx /* pass regs, */
> movq $0,%rsi /* code, */
> movq $-1,%rdi /* type to kdb */
> @@ -1087,6 +1138,8 @@ syscall_entry_2:
> pushq %rdx
> pushq %fs
> pushq %gs
> + pushq $0 // gsbase
> + pushq $0 // fsbase
>
> mov %ss,%dx /* switch to kernel data segment */
> mov %dx,%ds
> --
> 2.30.2
>
>
--
Samuel
---
Pour une évaluation indépendante, transparente et rigoureuse !
Je soutiens la Commission d'Évaluation de l'Inria.
- Re: [PATCH 5/5] add setting gs/fsbase, (continued)
- Re: [PATCH 5/5] add setting gs/fsbase, Samuel Thibault, 2023/04/22
- Re: [PATCH 5/5] add setting gs/fsbase, Sergey Bugaev, 2023/04/24
- Re: [PATCH 5/5] add setting gs/fsbase, Sergey Bugaev, 2023/04/24
- Re: [PATCH 5/5] add setting gs/fsbase, Luca Dariz, 2023/04/24
- Re: [PATCH 5/5] add setting gs/fsbase, Sergey Bugaev, 2023/04/24
- Re: [PATCH 5/5] add setting gs/fsbase, Samuel Thibault, 2023/04/24
- Re: [PATCH 5/5] add setting gs/fsbase, Sergey Bugaev, 2023/04/25
- Re: [PATCH 5/5] add setting gs/fsbase, Sergey Bugaev, 2023/04/25
- Re: [PATCH 5/5] add setting gs/fsbase, Samuel Thibault, 2023/04/25
- Re: [PATCH 5/5] add setting gs/fsbase, Sergey Bugaev, 2023/04/26
Re: [PATCH 5/5] add setting gs/fsbase,
Samuel Thibault <=
[PATCH 2/5] fix copyoutmsg for 64-bit userspace, Luca Dariz, 2023/04/19
[PATCH 4/5 (v4)] x86_64: add 64-bit syscall entry point, Luca Dariz, 2023/04/19
Re: [PATCH 1/5] fix address fault for 32-on-64-bit syscall, Samuel Thibault, 2023/04/20