@@ -277,38 +277,18 @@ static int copy_user_to_fpregs_zeroing(void __user *buf, u64 xbv, int fx_only)
277
277
return frstor_from_user_sigframe (buf );
278
278
}
279
279
280
- static int __fpu__restore_sig (void __user * buf , void __user * buf_fx , int size )
280
+ static int __fpu_restore_sig (void __user * buf , void __user * buf_fx ,
281
+ bool ia32_fxstate )
281
282
{
282
283
struct user_i387_ia32_struct * envp = NULL ;
283
284
int state_size = fpu_kernel_xstate_size ;
284
- int ia32_fxstate = (buf != buf_fx );
285
285
struct task_struct * tsk = current ;
286
286
struct fpu * fpu = & tsk -> thread .fpu ;
287
287
struct user_i387_ia32_struct env ;
288
288
u64 user_xfeatures = 0 ;
289
289
int fx_only = 0 ;
290
290
int ret = 0 ;
291
291
292
- ia32_fxstate &= (IS_ENABLED (CONFIG_X86_32 ) ||
293
- IS_ENABLED (CONFIG_IA32_EMULATION ));
294
-
295
- if (!buf ) {
296
- fpu__clear_user_states (fpu );
297
- return 0 ;
298
- }
299
-
300
- if (!access_ok (buf , size )) {
301
- ret = - EACCES ;
302
- goto out ;
303
- }
304
-
305
- if (!static_cpu_has (X86_FEATURE_FPU )) {
306
- ret = fpregs_soft_set (current , NULL , 0 ,
307
- sizeof (struct user_i387_ia32_struct ),
308
- NULL , buf );
309
- goto out ;
310
- }
311
-
312
292
if (use_xsave ()) {
313
293
struct _fpx_sw_bytes fx_sw_user ;
314
294
if (unlikely (check_for_xstate (buf_fx , buf_fx , & fx_sw_user ))) {
@@ -391,7 +371,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
391
371
*/
392
372
ret = __copy_from_user (& env , buf , sizeof (env ));
393
373
if (ret )
394
- goto out ;
374
+ return ret ;
395
375
envp = & env ;
396
376
}
397
377
@@ -424,7 +404,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
424
404
425
405
ret = copy_sigframe_from_user_to_xstate (& fpu -> state .xsave , buf_fx );
426
406
if (ret )
427
- goto out ;
407
+ return ret ;
428
408
429
409
sanitize_restored_user_xstate (& fpu -> state , envp , user_xfeatures ,
430
410
fx_only );
@@ -442,10 +422,8 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
442
422
443
423
} else if (use_fxsr ()) {
444
424
ret = __copy_from_user (& fpu -> state .fxsave , buf_fx , state_size );
445
- if (ret ) {
446
- ret = - EFAULT ;
447
- goto out ;
448
- }
425
+ if (ret )
426
+ return - EFAULT ;
449
427
450
428
sanitize_restored_user_xstate (& fpu -> state , envp , user_xfeatures ,
451
429
fx_only );
@@ -462,7 +440,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
462
440
} else {
463
441
ret = __copy_from_user (& fpu -> state .fsave , buf_fx , state_size );
464
442
if (ret )
465
- goto out ;
443
+ return ret ;
466
444
467
445
fpregs_lock ();
468
446
ret = frstor_safe (& fpu -> state .fsave );
@@ -472,10 +450,6 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
472
450
else
473
451
fpregs_deactivate (fpu );
474
452
fpregs_unlock ();
475
-
476
- out :
477
- if (ret )
478
- fpu__clear_user_states (fpu );
479
453
return ret ;
480
454
}
481
455
@@ -490,15 +464,47 @@ static inline int xstate_sigframe_size(void)
490
464
*/
491
465
int fpu__restore_sig (void __user * buf , int ia32_frame )
492
466
{
467
+ unsigned int size = xstate_sigframe_size ();
468
+ struct fpu * fpu = & current -> thread .fpu ;
493
469
void __user * buf_fx = buf ;
494
- int size = xstate_sigframe_size ();
470
+ bool ia32_fxstate = false;
471
+ int ret ;
472
+
473
+ if (unlikely (!buf )) {
474
+ fpu__clear_user_states (fpu );
475
+ return 0 ;
476
+ }
495
477
478
+ ia32_frame &= (IS_ENABLED (CONFIG_X86_32 ) ||
479
+ IS_ENABLED (CONFIG_IA32_EMULATION ));
480
+
481
+ /*
482
+ * Only FXSR enabled systems need the FX state quirk.
483
+ * FRSTOR does not need it and can use the fast path.
484
+ */
496
485
if (ia32_frame && use_fxsr ()) {
497
486
buf_fx = buf + sizeof (struct fregs_state );
498
487
size += sizeof (struct fregs_state );
488
+ ia32_fxstate = true;
499
489
}
500
490
501
- return __fpu__restore_sig (buf , buf_fx , size );
491
+ if (!access_ok (buf , size )) {
492
+ ret = - EACCES ;
493
+ goto out ;
494
+ }
495
+
496
+ if (!IS_ENABLED (CONFIG_X86_64 ) && !cpu_feature_enabled (X86_FEATURE_FPU )) {
497
+ ret = fpregs_soft_set (current , NULL , 0 ,
498
+ sizeof (struct user_i387_ia32_struct ),
499
+ NULL , buf );
500
+ } else {
501
+ ret = __fpu_restore_sig (buf , buf_fx , ia32_fxstate );
502
+ }
503
+
504
+ out :
505
+ if (unlikely (ret ))
506
+ fpu__clear_user_states (fpu );
507
+ return ret ;
502
508
}
503
509
504
510
unsigned long
0 commit comments