@@ -141,6 +141,10 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
ret = copy_user_to_xstate(xsave, ubuf);
} else {
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, xsave, 0, -1);
+
+ /* xcomp_bv must be 0 when using uncompacted format */
+ if (!ret && xsave->header.xcomp_bv)
+ ret = -EINVAL;
}
/*
@@ -324,11 +324,16 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
*/
fpu__drop(fpu);
- if (using_compacted_format())
+ if (using_compacted_format()) {
err = copy_user_to_xstate(&fpu->state.xsave, buf_fx);
- else
+ } else {
err = __copy_from_user(&fpu->state.xsave, buf_fx, state_size);
+ /* xcomp_bv must be 0 when using uncompacted format */
+ if (!err && fpu->state.xsave.header.xcomp_bv)
+ err = -EINVAL;
+ }
+
if (err || __copy_from_user(&env, buf, sizeof(env))) {
fpstate_init(&fpu->state);
trace_x86_fpu_init_state(fpu);