diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-10-09 03:02:35 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-10-09 03:02:35 -0400 |
commit | 1236d6bb6e19fc72ffc6bbcdeb1bfefe450e54ee (patch) | |
tree | 47da3feee8e263e8c9352c85cf518e624be3c211 /arch/x86/kernel/fpu/signal.c | |
parent | 750b1a6894ecc9b178c6e3d0a1170122971b2036 (diff) | |
parent | 8a5776a5f49812d29fe4b2d0a2d71675c3facf3f (diff) |
Merge 4.14-rc4 into staging-next
We want the staging/iio fixes in here as well to handle merge issues.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch/x86/kernel/fpu/signal.c')
-rw-r--r-- | arch/x86/kernel/fpu/signal.c | 37 |
1 files changed, 21 insertions, 16 deletions
diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c index 83c23c230b4c..fb639e70048f 100644 --- a/arch/x86/kernel/fpu/signal.c +++ b/arch/x86/kernel/fpu/signal.c | |||
@@ -155,7 +155,8 @@ static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf) | |||
155 | */ | 155 | */ |
156 | int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size) | 156 | int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size) |
157 | { | 157 | { |
158 | struct xregs_state *xsave = ¤t->thread.fpu.state.xsave; | 158 | struct fpu *fpu = ¤t->thread.fpu; |
159 | struct xregs_state *xsave = &fpu->state.xsave; | ||
159 | struct task_struct *tsk = current; | 160 | struct task_struct *tsk = current; |
160 | int ia32_fxstate = (buf != buf_fx); | 161 | int ia32_fxstate = (buf != buf_fx); |
161 | 162 | ||
@@ -170,13 +171,13 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size) | |||
170 | sizeof(struct user_i387_ia32_struct), NULL, | 171 | sizeof(struct user_i387_ia32_struct), NULL, |
171 | (struct _fpstate_32 __user *) buf) ? -1 : 1; | 172 | (struct _fpstate_32 __user *) buf) ? -1 : 1; |
172 | 173 | ||
173 | if (fpregs_active() || using_compacted_format()) { | 174 | if (fpu->initialized || using_compacted_format()) { |
174 | /* Save the live register state to the user directly. */ | 175 | /* Save the live register state to the user directly. */ |
175 | if (copy_fpregs_to_sigframe(buf_fx)) | 176 | if (copy_fpregs_to_sigframe(buf_fx)) |
176 | return -1; | 177 | return -1; |
177 | /* Update the thread's fxstate to save the fsave header. */ | 178 | /* Update the thread's fxstate to save the fsave header. */ |
178 | if (ia32_fxstate) | 179 | if (ia32_fxstate) |
179 | copy_fxregs_to_kernel(&tsk->thread.fpu); | 180 | copy_fxregs_to_kernel(fpu); |
180 | } else { | 181 | } else { |
181 | /* | 182 | /* |
182 | * It is a *bug* if kernel uses compacted-format for xsave | 183 | * It is a *bug* if kernel uses compacted-format for xsave |
@@ -189,7 +190,7 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size) | |||
189 | return -1; | 190 | return -1; |
190 | } | 191 | } |
191 | 192 | ||
192 | fpstate_sanitize_xstate(&tsk->thread.fpu); | 193 | fpstate_sanitize_xstate(fpu); |
193 | if (__copy_to_user(buf_fx, xsave, fpu_user_xstate_size)) | 194 | if (__copy_to_user(buf_fx, xsave, fpu_user_xstate_size)) |
194 | return -1; | 195 | return -1; |
195 | } | 196 | } |
@@ -213,8 +214,11 @@ sanitize_restored_xstate(struct task_struct *tsk, | |||
213 | struct xstate_header *header = &xsave->header; | 214 | struct xstate_header *header = &xsave->header; |
214 | 215 | ||
215 | if (use_xsave()) { | 216 | if (use_xsave()) { |
216 | /* These bits must be zero. */ | 217 | /* |
217 | memset(header->reserved, 0, 48); | 218 | * Note: we don't need to zero the reserved bits in the |
219 | * xstate_header here because we either didn't copy them at all, | ||
220 | * or we checked earlier that they aren't set. | ||
221 | */ | ||
218 | 222 | ||
219 | /* | 223 | /* |
220 | * Init the state that is not present in the memory | 224 | * Init the state that is not present in the memory |
@@ -223,7 +227,7 @@ sanitize_restored_xstate(struct task_struct *tsk, | |||
223 | if (fx_only) | 227 | if (fx_only) |
224 | header->xfeatures = XFEATURE_MASK_FPSSE; | 228 | header->xfeatures = XFEATURE_MASK_FPSSE; |
225 | else | 229 | else |
226 | header->xfeatures &= (xfeatures_mask & xfeatures); | 230 | header->xfeatures &= xfeatures; |
227 | } | 231 | } |
228 | 232 | ||
229 | if (use_fxsr()) { | 233 | if (use_fxsr()) { |
@@ -279,7 +283,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) | |||
279 | if (!access_ok(VERIFY_READ, buf, size)) | 283 | if (!access_ok(VERIFY_READ, buf, size)) |
280 | return -EACCES; | 284 | return -EACCES; |
281 | 285 | ||
282 | fpu__activate_curr(fpu); | 286 | fpu__initialize(fpu); |
283 | 287 | ||
284 | if (!static_cpu_has(X86_FEATURE_FPU)) | 288 | if (!static_cpu_has(X86_FEATURE_FPU)) |
285 | return fpregs_soft_set(current, NULL, | 289 | return fpregs_soft_set(current, NULL, |
@@ -307,28 +311,29 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) | |||
307 | /* | 311 | /* |
308 | * For 32-bit frames with fxstate, copy the user state to the | 312 | * For 32-bit frames with fxstate, copy the user state to the |
309 | * thread's fpu state, reconstruct fxstate from the fsave | 313 | * thread's fpu state, reconstruct fxstate from the fsave |
310 | * header. Sanitize the copied state etc. | 314 | * header. Validate and sanitize the copied state. |
311 | */ | 315 | */ |
312 | struct fpu *fpu = &tsk->thread.fpu; | 316 | struct fpu *fpu = &tsk->thread.fpu; |
313 | struct user_i387_ia32_struct env; | 317 | struct user_i387_ia32_struct env; |
314 | int err = 0; | 318 | int err = 0; |
315 | 319 | ||
316 | /* | 320 | /* |
317 | * Drop the current fpu which clears fpu->fpstate_active. This ensures | 321 | * Drop the current fpu which clears fpu->initialized. This ensures |
318 | * that any context-switch during the copy of the new state, | 322 | * that any context-switch during the copy of the new state, |
319 | * avoids the intermediate state from getting restored/saved. | 323 | * avoids the intermediate state from getting restored/saved. |
320 | * Thus avoiding the new restored state from getting corrupted. | 324 | * Thus avoiding the new restored state from getting corrupted. |
321 | * We will be ready to restore/save the state only after | 325 | * We will be ready to restore/save the state only after |
322 | * fpu->fpstate_active is again set. | 326 | * fpu->initialized is again set. |
323 | */ | 327 | */ |
324 | fpu__drop(fpu); | 328 | fpu__drop(fpu); |
325 | 329 | ||
326 | if (using_compacted_format()) { | 330 | if (using_compacted_format()) { |
327 | err = copyin_to_xsaves(NULL, buf_fx, | 331 | err = copy_user_to_xstate(&fpu->state.xsave, buf_fx); |
328 | &fpu->state.xsave); | ||
329 | } else { | 332 | } else { |
330 | err = __copy_from_user(&fpu->state.xsave, | 333 | err = __copy_from_user(&fpu->state.xsave, buf_fx, state_size); |
331 | buf_fx, state_size); | 334 | |
335 | if (!err && state_size > offsetof(struct xregs_state, header)) | ||
336 | err = validate_xstate_header(&fpu->state.xsave.header); | ||
332 | } | 337 | } |
333 | 338 | ||
334 | if (err || __copy_from_user(&env, buf, sizeof(env))) { | 339 | if (err || __copy_from_user(&env, buf, sizeof(env))) { |
@@ -339,7 +344,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) | |||
339 | sanitize_restored_xstate(tsk, &env, xfeatures, fx_only); | 344 | sanitize_restored_xstate(tsk, &env, xfeatures, fx_only); |
340 | } | 345 | } |
341 | 346 | ||
342 | fpu->fpstate_active = 1; | 347 | fpu->initialized = 1; |
343 | preempt_disable(); | 348 | preempt_disable(); |
344 | fpu__restore(fpu); | 349 | fpu__restore(fpu); |
345 | preempt_enable(); | 350 | preempt_enable(); |