@@ -388,11 +388,22 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
xsave_hdr = &target->thread.fpu.state->xsave.xsave_hdr;
xsave_hdr->xstate_bv &= pcntxt_mask;
+
+ /* xcomp_bv must be 0 when using uncompacted format */
+ if (!ret && xsave_hdr->xcomp_bv)
+ ret = -EINVAL;
+
/*
* These bits must be zero.
*/
memset(xsave_hdr->reserved, 0, 48);
+ /*
+ * In case of failure, mark all states as init:
+ */
+ if (ret)
+ fpu_finit(&target->thread.fpu);
+
return ret;
}
@@ -394,7 +394,9 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size)
drop_fpu(tsk);
if (__copy_from_user(&fpu->state->xsave, buf_fx, state_size) ||
- __copy_from_user(&env, buf, sizeof(env))) {
+ __copy_from_user(&env, buf, sizeof(env)) ||
+ (state_size > offsetof(struct xsave_struct, xsave_hdr) &&
+ fpu->state->xsave.xsave_hdr.xcomp_bv)) {
fpu_finit(fpu);
err = -1;
} else {