Merge branch 'for-next/signal' into for-next/core
* for-next/signal: : Signal handling cleanups arm64/signal: Only read new data when parsing the ZT context arm64/signal: Only read new data when parsing the ZA context arm64/signal: Only read new data when parsing the SVE context arm64/signal: Avoid rereading context frame sizes arm64/signal: Make interface for restore_fpsimd_context() consistent arm64/signal: Remove redundant size validation from parse_user_sigframe() arm64/signal: Don't redundantly verify FPSIMD magic
This commit is contained in:
Коммит
ad4a4d3aff
|
@ -170,6 +170,19 @@ static void __user *apply_user_offset(
|
|||
return base + offset;
|
||||
}
|
||||
|
||||
struct user_ctxs {
|
||||
struct fpsimd_context __user *fpsimd;
|
||||
u32 fpsimd_size;
|
||||
struct sve_context __user *sve;
|
||||
u32 sve_size;
|
||||
struct tpidr2_context __user *tpidr2;
|
||||
u32 tpidr2_size;
|
||||
struct za_context __user *za;
|
||||
u32 za_size;
|
||||
struct zt_context __user *zt;
|
||||
u32 zt_size;
|
||||
};
|
||||
|
||||
static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
|
||||
{
|
||||
struct user_fpsimd_state const *fpsimd =
|
||||
|
@ -188,25 +201,20 @@ static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
|
|||
return err ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
static int restore_fpsimd_context(struct fpsimd_context __user *ctx)
|
||||
static int restore_fpsimd_context(struct user_ctxs *user)
|
||||
{
|
||||
struct user_fpsimd_state fpsimd;
|
||||
__u32 magic, size;
|
||||
int err = 0;
|
||||
|
||||
/* check the magic/size information */
|
||||
__get_user_error(magic, &ctx->head.magic, err);
|
||||
__get_user_error(size, &ctx->head.size, err);
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
if (magic != FPSIMD_MAGIC || size != sizeof(struct fpsimd_context))
|
||||
/* check the size information */
|
||||
if (user->fpsimd_size != sizeof(struct fpsimd_context))
|
||||
return -EINVAL;
|
||||
|
||||
/* copy the FP and status/control registers */
|
||||
err = __copy_from_user(fpsimd.vregs, ctx->vregs,
|
||||
err = __copy_from_user(fpsimd.vregs, &(user->fpsimd->vregs),
|
||||
sizeof(fpsimd.vregs));
|
||||
__get_user_error(fpsimd.fpsr, &ctx->fpsr, err);
|
||||
__get_user_error(fpsimd.fpcr, &ctx->fpcr, err);
|
||||
__get_user_error(fpsimd.fpsr, &(user->fpsimd->fpsr), err);
|
||||
__get_user_error(fpsimd.fpcr, &(user->fpsimd->fpcr), err);
|
||||
|
||||
clear_thread_flag(TIF_SVE);
|
||||
current->thread.fp_type = FP_STATE_FPSIMD;
|
||||
|
@ -219,14 +227,6 @@ static int restore_fpsimd_context(struct fpsimd_context __user *ctx)
|
|||
}
|
||||
|
||||
|
||||
struct user_ctxs {
|
||||
struct fpsimd_context __user *fpsimd;
|
||||
struct sve_context __user *sve;
|
||||
struct tpidr2_context __user *tpidr2;
|
||||
struct za_context __user *za;
|
||||
struct zt_context __user *zt;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ARM64_SVE
|
||||
|
||||
static int preserve_sve_context(struct sve_context __user *ctx)
|
||||
|
@ -271,15 +271,20 @@ static int preserve_sve_context(struct sve_context __user *ctx)
|
|||
|
||||
static int restore_sve_fpsimd_context(struct user_ctxs *user)
|
||||
{
|
||||
int err;
|
||||
int err = 0;
|
||||
unsigned int vl, vq;
|
||||
struct user_fpsimd_state fpsimd;
|
||||
struct sve_context sve;
|
||||
u16 user_vl, flags;
|
||||
|
||||
if (__copy_from_user(&sve, user->sve, sizeof(sve)))
|
||||
return -EFAULT;
|
||||
if (user->sve_size < sizeof(*user->sve))
|
||||
return -EINVAL;
|
||||
|
||||
if (sve.flags & SVE_SIG_FLAG_SM) {
|
||||
__get_user_error(user_vl, &(user->sve->vl), err);
|
||||
__get_user_error(flags, &(user->sve->flags), err);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (flags & SVE_SIG_FLAG_SM) {
|
||||
if (!system_supports_sme())
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -291,19 +296,19 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
|
|||
vl = task_get_sve_vl(current);
|
||||
}
|
||||
|
||||
if (sve.vl != vl)
|
||||
if (user_vl != vl)
|
||||
return -EINVAL;
|
||||
|
||||
if (sve.head.size <= sizeof(*user->sve)) {
|
||||
if (user->sve_size == sizeof(*user->sve)) {
|
||||
clear_thread_flag(TIF_SVE);
|
||||
current->thread.svcr &= ~SVCR_SM_MASK;
|
||||
current->thread.fp_type = FP_STATE_FPSIMD;
|
||||
goto fpsimd_only;
|
||||
}
|
||||
|
||||
vq = sve_vq_from_vl(sve.vl);
|
||||
vq = sve_vq_from_vl(vl);
|
||||
|
||||
if (sve.head.size < SVE_SIG_CONTEXT_SIZE(vq))
|
||||
if (user->sve_size < SVE_SIG_CONTEXT_SIZE(vq))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
|
@ -329,7 +334,7 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
|
|||
if (err)
|
||||
return -EFAULT;
|
||||
|
||||
if (sve.flags & SVE_SIG_FLAG_SM)
|
||||
if (flags & SVE_SIG_FLAG_SM)
|
||||
current->thread.svcr |= SVCR_SM_MASK;
|
||||
else
|
||||
set_thread_flag(TIF_SVE);
|
||||
|
@ -383,7 +388,9 @@ static int restore_tpidr2_context(struct user_ctxs *user)
|
|||
u64 tpidr2_el0;
|
||||
int err = 0;
|
||||
|
||||
/* Magic and size were validated deciding to call this function */
|
||||
if (user->tpidr2_size != sizeof(*user->tpidr2))
|
||||
return -EINVAL;
|
||||
|
||||
__get_user_error(tpidr2_el0, &user->tpidr2->tpidr2, err);
|
||||
if (!err)
|
||||
current->thread.tpidr2_el0 = tpidr2_el0;
|
||||
|
@ -428,24 +435,28 @@ static int preserve_za_context(struct za_context __user *ctx)
|
|||
|
||||
static int restore_za_context(struct user_ctxs *user)
|
||||
{
|
||||
int err;
|
||||
int err = 0;
|
||||
unsigned int vq;
|
||||
struct za_context za;
|
||||
u16 user_vl;
|
||||
|
||||
if (__copy_from_user(&za, user->za, sizeof(za)))
|
||||
return -EFAULT;
|
||||
|
||||
if (za.vl != task_get_sme_vl(current))
|
||||
if (user->za_size < sizeof(*user->za))
|
||||
return -EINVAL;
|
||||
|
||||
if (za.head.size <= sizeof(*user->za)) {
|
||||
__get_user_error(user_vl, &(user->za->vl), err);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (user_vl != task_get_sme_vl(current))
|
||||
return -EINVAL;
|
||||
|
||||
if (user->za_size == sizeof(*user->za)) {
|
||||
current->thread.svcr &= ~SVCR_ZA_MASK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
vq = sve_vq_from_vl(za.vl);
|
||||
vq = sve_vq_from_vl(user_vl);
|
||||
|
||||
if (za.head.size < ZA_SIG_CONTEXT_SIZE(vq))
|
||||
if (user->za_size < ZA_SIG_CONTEXT_SIZE(vq))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
|
@ -510,19 +521,19 @@ static int preserve_zt_context(struct zt_context __user *ctx)
|
|||
static int restore_zt_context(struct user_ctxs *user)
|
||||
{
|
||||
int err;
|
||||
struct zt_context zt;
|
||||
u16 nregs;
|
||||
|
||||
/* ZA must be restored first for this check to be valid */
|
||||
if (!thread_za_enabled(¤t->thread))
|
||||
return -EINVAL;
|
||||
|
||||
if (__copy_from_user(&zt, user->zt, sizeof(zt)))
|
||||
return -EFAULT;
|
||||
|
||||
if (zt.nregs != 1)
|
||||
if (user->zt_size != ZT_SIG_CONTEXT_SIZE(1))
|
||||
return -EINVAL;
|
||||
|
||||
if (zt.head.size != ZT_SIG_CONTEXT_SIZE(zt.nregs))
|
||||
if (__copy_from_user(&nregs, &(user->zt->nregs), sizeof(nregs)))
|
||||
return -EFAULT;
|
||||
|
||||
if (nregs != 1)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
|
@ -615,10 +626,8 @@ static int parse_user_sigframe(struct user_ctxs *user,
|
|||
if (user->fpsimd)
|
||||
goto invalid;
|
||||
|
||||
if (size < sizeof(*user->fpsimd))
|
||||
goto invalid;
|
||||
|
||||
user->fpsimd = (struct fpsimd_context __user *)head;
|
||||
user->fpsimd_size = size;
|
||||
break;
|
||||
|
||||
case ESR_MAGIC:
|
||||
|
@ -632,10 +641,8 @@ static int parse_user_sigframe(struct user_ctxs *user,
|
|||
if (user->sve)
|
||||
goto invalid;
|
||||
|
||||
if (size < sizeof(*user->sve))
|
||||
goto invalid;
|
||||
|
||||
user->sve = (struct sve_context __user *)head;
|
||||
user->sve_size = size;
|
||||
break;
|
||||
|
||||
case TPIDR2_MAGIC:
|
||||
|
@ -645,10 +652,8 @@ static int parse_user_sigframe(struct user_ctxs *user,
|
|||
if (user->tpidr2)
|
||||
goto invalid;
|
||||
|
||||
if (size != sizeof(*user->tpidr2))
|
||||
goto invalid;
|
||||
|
||||
user->tpidr2 = (struct tpidr2_context __user *)head;
|
||||
user->tpidr2_size = size;
|
||||
break;
|
||||
|
||||
case ZA_MAGIC:
|
||||
|
@ -658,10 +663,8 @@ static int parse_user_sigframe(struct user_ctxs *user,
|
|||
if (user->za)
|
||||
goto invalid;
|
||||
|
||||
if (size < sizeof(*user->za))
|
||||
goto invalid;
|
||||
|
||||
user->za = (struct za_context __user *)head;
|
||||
user->za_size = size;
|
||||
break;
|
||||
|
||||
case ZT_MAGIC:
|
||||
|
@ -671,10 +674,8 @@ static int parse_user_sigframe(struct user_ctxs *user,
|
|||
if (user->zt)
|
||||
goto invalid;
|
||||
|
||||
if (size < sizeof(*user->zt))
|
||||
goto invalid;
|
||||
|
||||
user->zt = (struct zt_context __user *)head;
|
||||
user->zt_size = size;
|
||||
break;
|
||||
|
||||
case EXTRA_MAGIC:
|
||||
|
@ -793,7 +794,7 @@ static int restore_sigframe(struct pt_regs *regs,
|
|||
if (user.sve)
|
||||
err = restore_sve_fpsimd_context(&user);
|
||||
else
|
||||
err = restore_fpsimd_context(user.fpsimd);
|
||||
err = restore_fpsimd_context(&user);
|
||||
}
|
||||
|
||||
if (err == 0 && system_supports_sme() && user.tpidr2)
|
||||
|
|
Загрузка…
Ссылка в новой задаче