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:
Catalin Marinas 2023-02-10 18:52:21 +00:00
Родитель 960046361e ad678be423
Коммит ad4a4d3aff
1 изменённых файлов: 62 добавлений и 61 удалений

Просмотреть файл

@ -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(&current->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)