1 // SPDX-License-Identifier: GPL-2.0 2 #define __FRAME_OFFSETS 3 #include <linux/errno.h> 4 #include <linux/string.h> 5 #include <sys/ucontext.h> 6 #include <asm/ptrace.h> 7 /* 8 * musl defines struct sigcontext in <bits/signal.h>. Rename the kernel's 9 * copy to avoid redefinition while keeping the FP-state types available. 10 */ 11 #define sigcontext __kernel_sigcontext 12 #include <asm/sigcontext.h> 13 #undef sigcontext 14 #include <sysdep/ptrace.h> 15 #include <sysdep/mcontext.h> 16 #include <arch.h> 17 18 void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc) 19 { 20 #ifdef __i386__ 21 #define COPY2(X,Y) regs->gp[X] = mc->gregs[REG_##Y] 22 #define COPY(X) regs->gp[X] = mc->gregs[REG_##X] 23 #define COPY_SEG(X) regs->gp[X] = mc->gregs[REG_##X] & 0xffff; 24 #define COPY_SEG_CPL3(X) regs->gp[X] = (mc->gregs[REG_##X] & 0xffff) | 3; 25 COPY_SEG(GS); COPY_SEG(FS); COPY_SEG(ES); COPY_SEG(DS); 26 COPY(EDI); COPY(ESI); COPY(EBP); 27 COPY2(UESP, ESP); /* sic */ 28 COPY(EBX); COPY(EDX); COPY(ECX); COPY(EAX); 29 COPY(EIP); COPY_SEG_CPL3(CS); COPY(EFL); COPY_SEG_CPL3(SS); 30 #undef COPY2 31 #undef COPY 32 #undef COPY_SEG 33 #undef COPY_SEG_CPL3 34 #else 35 #define COPY2(X,Y) regs->gp[X/sizeof(unsigned long)] = mc->gregs[REG_##Y] 36 #define COPY(X) regs->gp[X/sizeof(unsigned long)] = mc->gregs[REG_##X] 37 COPY(R8); COPY(R9); COPY(R10); COPY(R11); 38 COPY(R12); COPY(R13); COPY(R14); COPY(R15); 39 COPY(RDI); COPY(RSI); COPY(RBP); COPY(RBX); 40 COPY(RDX); COPY(RAX); COPY(RCX); COPY(RSP); 41 COPY(RIP); 42 COPY2(EFLAGS, EFL); 43 COPY2(CS, CSGSFS); 44 regs->gp[SS / sizeof(unsigned long)] = mc->gregs[REG_CSGSFS] >> 48; 45 #undef COPY2 46 #undef COPY 47 #endif 48 } 49 50 void mc_set_rip(void *_mc, void *target) 51 { 52 mcontext_t *mc = _mc; 53 54 #ifdef __i386__ 55 mc->gregs[REG_EIP] = (unsigned long)target; 56 #else 57 mc->gregs[REG_RIP] = (unsigned long)target; 58 #endif 59 } 60 61 /* Same thing, but the copy macros are turned around. */ 62 void get_mc_from_regs(struct uml_pt_regs *regs, mcontext_t *mc, int single_stepping) 63 { 64 #ifdef __i386__ 65 #define COPY2(X,Y) mc->gregs[REG_##Y] = regs->gp[X] 66 #define COPY(X) mc->gregs[REG_##X] = regs->gp[X] 67 #define COPY_SEG(X) mc->gregs[REG_##X] = regs->gp[X] & 0xffff; 68 #define COPY_SEG_CPL3(X) mc->gregs[REG_##X] = (regs->gp[X] & 0xffff) | 3; 69 COPY_SEG(GS); COPY_SEG(FS); COPY_SEG(ES); COPY_SEG(DS); 70 COPY(EDI); COPY(ESI); COPY(EBP); 71 COPY2(UESP, ESP); /* sic */ 72 COPY(EBX); COPY(EDX); COPY(ECX); COPY(EAX); 73 COPY(EIP); COPY_SEG_CPL3(CS); COPY(EFL); COPY_SEG_CPL3(SS); 74 #else 75 #define COPY2(X,Y) mc->gregs[REG_##Y] = regs->gp[X/sizeof(unsigned long)] 76 #define COPY(X) mc->gregs[REG_##X] = regs->gp[X/sizeof(unsigned long)] 77 COPY(R8); COPY(R9); COPY(R10); COPY(R11); 78 COPY(R12); COPY(R13); COPY(R14); COPY(R15); 79 COPY(RDI); COPY(RSI); COPY(RBP); COPY(RBX); 80 COPY(RDX); COPY(RAX); COPY(RCX); COPY(RSP); 81 COPY(RIP); 82 COPY2(EFLAGS, EFL); 83 mc->gregs[REG_CSGSFS] = mc->gregs[REG_CSGSFS] & 0xffffffffffffl; 84 mc->gregs[REG_CSGSFS] |= (regs->gp[SS / sizeof(unsigned long)] & 0xffff) << 48; 85 #endif 86 87 if (single_stepping) 88 mc->gregs[REG_EFL] |= X86_EFLAGS_TF; 89 else 90 mc->gregs[REG_EFL] &= ~X86_EFLAGS_TF; 91 } 92 93 #ifdef CONFIG_X86_32 94 struct _xstate_64 { 95 struct _fpstate_64 fpstate; 96 struct _header xstate_hdr; 97 struct _ymmh_state ymmh; 98 /* New processor state extensions go here: */ 99 }; 100 101 /* Not quite the right structures as these contain more information */ 102 int um_i387_from_fxsr(struct _fpstate_32 *i387, 103 const struct _fpstate_64 *fxsave); 104 int um_fxsr_from_i387(struct _fpstate_64 *fxsave, 105 const struct _fpstate_32 *from); 106 #else 107 #define _xstate_64 _xstate 108 #endif 109 110 static struct _fpstate *get_fpstate(struct stub_data *data, 111 mcontext_t *mcontext, 112 int *fp_size) 113 { 114 struct _fpstate *res; 115 116 /* Assume floating point registers are on the same page */ 117 res = (void *)(((unsigned long)mcontext->fpregs & 118 (UM_KERN_PAGE_SIZE - 1)) + 119 (unsigned long)&data->sigstack[0]); 120 121 if ((void *)res + sizeof(struct _fpstate) > 122 (void *)data->sigstack + sizeof(data->sigstack)) 123 return NULL; 124 125 if (res->sw_reserved.magic1 != FP_XSTATE_MAGIC1) { 126 *fp_size = sizeof(struct _fpstate); 127 } else { 128 char *magic2_addr; 129 130 magic2_addr = (void *)res; 131 magic2_addr += res->sw_reserved.extended_size; 132 magic2_addr -= FP_XSTATE_MAGIC2_SIZE; 133 134 /* We still need to be within our stack */ 135 if ((void *)magic2_addr > 136 (void *)data->sigstack + sizeof(data->sigstack)) 137 return NULL; 138 139 /* If we do not read MAGIC2, then we did something wrong */ 140 if (*(__u32 *)magic2_addr != FP_XSTATE_MAGIC2) 141 return NULL; 142 143 /* Remove MAGIC2 from the size, we do not save/restore it */ 144 *fp_size = res->sw_reserved.extended_size - 145 FP_XSTATE_MAGIC2_SIZE; 146 } 147 148 return res; 149 } 150 151 int get_stub_state(struct uml_pt_regs *regs, struct stub_data *data, 152 unsigned long *fp_size_out) 153 { 154 mcontext_t *mcontext; 155 struct _fpstate *fpstate_stub; 156 struct _xstate_64 *xstate_stub; 157 int fp_size, xstate_size; 158 159 /* mctx_offset is verified by wait_stub_done_seccomp */ 160 mcontext = (void *)&data->sigstack[data->mctx_offset]; 161 162 get_regs_from_mc(regs, mcontext); 163 164 fpstate_stub = get_fpstate(data, mcontext, &fp_size); 165 if (!fpstate_stub) 166 return -EINVAL; 167 168 #ifdef CONFIG_X86_32 169 xstate_stub = (void *)&fpstate_stub->_fxsr_env; 170 xstate_size = fp_size - offsetof(struct _fpstate_32, _fxsr_env); 171 #else 172 xstate_stub = (void *)fpstate_stub; 173 xstate_size = fp_size; 174 #endif 175 176 if (fp_size_out) 177 *fp_size_out = xstate_size; 178 179 if (xstate_size > host_fp_size) 180 return -ENOSPC; 181 182 memcpy(®s->fp, xstate_stub, xstate_size); 183 184 /* We do not need to read the x86_64 FS_BASE/GS_BASE registers as 185 * we do not permit userspace to set them directly. 186 */ 187 188 #ifdef CONFIG_X86_32 189 /* Read the i387 legacy FP registers */ 190 if (um_fxsr_from_i387((void *)®s->fp, fpstate_stub)) 191 return -EINVAL; 192 #endif 193 194 return 0; 195 } 196 197 /* Copied because we cannot include regset.h here. */ 198 struct task_struct; 199 struct user_regset; 200 struct membuf { 201 void *p; 202 size_t left; 203 }; 204 205 int fpregs_legacy_get(struct task_struct *target, 206 const struct user_regset *regset, 207 struct membuf to); 208 209 int set_stub_state(struct uml_pt_regs *regs, struct stub_data *data, 210 int single_stepping) 211 { 212 mcontext_t *mcontext; 213 struct _fpstate *fpstate_stub; 214 struct _xstate_64 *xstate_stub; 215 int fp_size, xstate_size; 216 217 /* mctx_offset is verified by wait_stub_done_seccomp */ 218 mcontext = (void *)&data->sigstack[data->mctx_offset]; 219 220 if ((unsigned long)mcontext < (unsigned long)data->sigstack || 221 (unsigned long)mcontext > 222 (unsigned long) data->sigstack + 223 sizeof(data->sigstack) - sizeof(*mcontext)) 224 return -EINVAL; 225 226 get_mc_from_regs(regs, mcontext, single_stepping); 227 228 fpstate_stub = get_fpstate(data, mcontext, &fp_size); 229 if (!fpstate_stub) 230 return -EINVAL; 231 232 #ifdef CONFIG_X86_32 233 xstate_stub = (void *)&fpstate_stub->_fxsr_env; 234 xstate_size = fp_size - offsetof(struct _fpstate_32, _fxsr_env); 235 #else 236 xstate_stub = (void *)fpstate_stub; 237 xstate_size = fp_size; 238 #endif 239 240 memcpy(xstate_stub, ®s->fp, xstate_size); 241 242 #ifdef __i386__ 243 /* 244 * On x86, the GDT entries are updated by arch_set_tls. 245 */ 246 247 /* Store the i387 legacy FP registers which the host will use */ 248 if (um_i387_from_fxsr(fpstate_stub, (void *)®s->fp)) 249 return -EINVAL; 250 #else 251 /* 252 * On x86_64, we need to sync the FS_BASE/GS_BASE registers using the 253 * arch specific data. 254 */ 255 if (data->arch_data.fs_base != regs->gp[FS_BASE / sizeof(unsigned long)]) { 256 data->arch_data.fs_base = regs->gp[FS_BASE / sizeof(unsigned long)]; 257 data->arch_data.sync |= STUB_SYNC_FS_BASE; 258 } 259 if (data->arch_data.gs_base != regs->gp[GS_BASE / sizeof(unsigned long)]) { 260 data->arch_data.gs_base = regs->gp[GS_BASE / sizeof(unsigned long)]; 261 data->arch_data.sync |= STUB_SYNC_GS_BASE; 262 } 263 #endif 264 265 return 0; 266 } 267