3
3
#include <asm/prctl.h>
4
4
#include <sys/prctl.h>
5
5
#include <sys/mman.h>
6
+ #include <sys/auxv.h>
7
+ #include <elf.h>
8
+ #include <immintrin.h>
6
9
7
10
int arch_prctl (int code , unsigned long * addr );
8
11
12
+ #ifndef HWCAP2_FSGSBASE
13
+ #define HWCAP2_FSGSBASE (1 << 1)
14
+ #endif
15
+
9
16
#define EOSVMOC_MEMORY_PTR_cb_ptr GS_PTR struct eos_vm_oc_control_block* const cb_ptr = ((GS_PTR struct eos_vm_oc_control_block* const)(EOS_VM_OC_CONTROL_BLOCK_OFFSET));
10
17
11
18
int32_t eos_vm_oc_grow_memory (int32_t grow , int32_t max ) {
@@ -37,10 +44,9 @@ int32_t eos_vm_oc_grow_memory(int32_t grow, int32_t max) {
37
44
gs_diff = grow_amount ;
38
45
}
39
46
40
- uint64_t current_gs ;
41
- arch_prctl (ARCH_GET_GS , & current_gs );
47
+ uint64_t current_gs = eos_vm_oc_getgs ();
42
48
current_gs += gs_diff * EOS_VM_OC_MEMORY_STRIDE ;
43
- arch_prctl ( ARCH_SET_GS , ( unsigned long * ) current_gs );
49
+ eos_vm_oc_setgs ( current_gs );
44
50
cb_ptr -> current_linear_memory_pages += grow_amount ;
45
51
cb_ptr -> first_invalid_memory_address += grow_amount * 64 * 1024 ;
46
52
@@ -64,3 +70,56 @@ void* eos_vm_oc_get_bounce_buffer_list() {
64
70
EOSVMOC_MEMORY_PTR_cb_ptr ;
65
71
return cb_ptr -> bounce_buffers ;
66
72
}
73
+
74
+ uint64_t eos_vm_oc_getgs_syscall () {
75
+ uint64_t gs ;
76
+ arch_prctl (ARCH_GET_GS , & gs );
77
+ return gs ;
78
+ }
79
+
80
+ uint64_t __attribute__ ((__target__ ("fsgsbase" ))) eos_vm_oc_getgs_fsgsbase () {
81
+ return _readgsbase_u64 ();
82
+ }
83
+
84
+ void eos_vm_oc_setgs_syscall (uint64_t gs ) {
85
+ arch_prctl (ARCH_SET_GS , (unsigned long * )gs ); //cast to a (unsigned long*) to match local declaration above
86
+ }
87
+
88
+ void __attribute__ ((__target__ ("fsgsbase" ))) eos_vm_oc_setgs_fsgsbase (uint64_t gs ) {
89
+ return _writegsbase_u64 (gs );
90
+ }
91
+
92
+ extern char * * _dl_argv ;
93
+ static int eos_vm_oc_use_fsgsbase () {
94
+ /* ifunc resolvers run _super_ early -- before getenv() is set up even! This is relying on the layout of _dl_argv to be
95
+ _dl_argv
96
+ ↓
97
+ argc, argv[0], ..., argv[argc - 1], NULL, evniron0, environ1, ..., NULL
98
+ */
99
+ const int argc = * (int * )(_dl_argv - 1 );
100
+ char * * my_environ = _dl_argv + argc + 1 ;
101
+ while (* my_environ != NULL ) {
102
+ const char disable_str [] = "SPRING_DISABLE_FSGSBASE" ;
103
+ if (strncmp (* my_environ ++ , disable_str , strlen (disable_str )) == 0 )
104
+ return 0 ;
105
+ }
106
+
107
+ //see linux Documentation/arch/x86/x86_64/fsgs.rst; check that kernel has enabled userspace fsgsbase
108
+ return getauxval (AT_HWCAP2 ) & HWCAP2_FSGSBASE ;
109
+ }
110
+
111
+ uint64_t (* resolve_eos_vm_oc_getgs ())() {
112
+ if (eos_vm_oc_use_fsgsbase ())
113
+ return eos_vm_oc_getgs_fsgsbase ;
114
+ return eos_vm_oc_getgs_syscall ;
115
+ }
116
+
117
+ uint64_t eos_vm_oc_getgs () __attribute__ ((ifunc ("resolve_eos_vm_oc_getgs" )));
118
+
119
+ void (* resolve_eos_vm_oc_setgs ())(uint64_t ) {
120
+ if (eos_vm_oc_use_fsgsbase ())
121
+ return eos_vm_oc_setgs_fsgsbase ;
122
+ return eos_vm_oc_setgs_syscall ;
123
+ }
124
+
125
+ void eos_vm_oc_setgs (uint64_t ) __attribute__ ((ifunc ("resolve_eos_vm_oc_setgs" )));
0 commit comments