summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2023-02-10 18:52:21 +0000
committerCatalin Marinas <catalin.marinas@arm.com>2023-02-10 18:52:21 +0000
commitad4a4d3aff21539263326201d7f5806ea0c1de90 (patch)
tree6d2d64fd9a6087e03b96a38f44a30bd179ae4f29 /arch
parent960046361e719e488de08ad9fcf8f907692161e6 (diff)
parentad678be4238720384fa9e21b9b08b5540ac7ca5d (diff)
downloadlinux-stable-ad4a4d3aff21539263326201d7f5806ea0c1de90.tar.gz
linux-stable-ad4a4d3aff21539263326201d7f5806ea0c1de90.tar.bz2
linux-stable-ad4a4d3aff21539263326201d7f5806ea0c1de90.zip
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
Diffstat (limited to 'arch')
-rw-r--r--arch/arm64/kernel/signal.c121
1 files changed, 61 insertions, 60 deletions
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index ed692284f199..d7b5ed8a9b7f 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -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;
+
+ __get_user_error(user_vl, &(user->sve->vl), err);
+ __get_user_error(flags, &(user->sve->flags), err);
+ if (err)
+ return err;
- if (sve.flags & SVE_SIG_FLAG_SM) {
+ 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 (user->za_size < sizeof(*user->za))
+ return -EINVAL;
+
+ __get_user_error(user_vl, &(user->za->vl), err);
+ if (err)
+ return err;
- if (za.vl != task_get_sme_vl(current))
+ if (user_vl != task_get_sme_vl(current))
return -EINVAL;
- if (za.head.size <= sizeof(*user->za)) {
+ 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)