summaryrefslogtreecommitdiff
path: root/arch/arm64/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/kernel/signal.c')
-rw-r--r--arch/arm64/kernel/signal.c52
1 files changed, 27 insertions, 25 deletions
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 49321871783d..567e8e5b6998 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -172,10 +172,15 @@ static void __user *apply_user_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)
@@ -199,14 +204,10 @@ static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
static int restore_fpsimd_context(struct user_ctxs *user)
{
struct user_fpsimd_state fpsimd;
- __u32 size;
int err = 0;
/* check the size information */
- __get_user_error(size, &user->fpsimd->head.size, err);
- if (err)
- return -EFAULT;
- if (size != sizeof(struct fpsimd_context))
+ if (user->fpsimd_size != sizeof(struct fpsimd_context))
return -EINVAL;
/* copy the FP and status/control registers */
@@ -275,12 +276,12 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
struct user_fpsimd_state fpsimd;
struct sve_context sve;
+ if (user->sve_size < sizeof(*user->sve))
+ return -EINVAL;
+
if (__copy_from_user(&sve, user->sve, sizeof(sve)))
return -EFAULT;
- if (sve.head.size < sizeof(*user->sve))
- return -EINVAL;
-
if (sve.flags & SVE_SIG_FLAG_SM) {
if (!system_supports_sme())
return -EINVAL;
@@ -296,7 +297,7 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
if (sve.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;
@@ -305,7 +306,7 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
vq = sve_vq_from_vl(sve.vl);
- if (sve.head.size < SVE_SIG_CONTEXT_SIZE(vq))
+ if (user->sve_size < SVE_SIG_CONTEXT_SIZE(vq))
return -EINVAL;
/*
@@ -385,7 +386,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;
@@ -434,23 +437,23 @@ static int restore_za_context(struct user_ctxs *user)
unsigned int vq;
struct za_context za;
+ if (user->za_size < sizeof(*user->za))
+ return -EINVAL;
+
if (__copy_from_user(&za, user->za, sizeof(za)))
return -EFAULT;
- if (za.head.size < sizeof(*user->za))
- return -EINVAL;
-
if (za.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);
- if (za.head.size < ZA_SIG_CONTEXT_SIZE(vq))
+ if (user->za_size < ZA_SIG_CONTEXT_SIZE(vq))
return -EINVAL;
/*
@@ -521,15 +524,15 @@ static int restore_zt_context(struct user_ctxs *user)
if (!thread_za_enabled(&current->thread))
return -EINVAL;
+ if (user->zt_size != ZT_SIG_CONTEXT_SIZE(1))
+ return -EINVAL;
+
if (__copy_from_user(&zt, user->zt, sizeof(zt)))
return -EFAULT;
if (zt.nregs != 1)
return -EINVAL;
- if (zt.head.size != ZT_SIG_CONTEXT_SIZE(zt.nregs))
- return -EINVAL;
-
/*
* Careful: we are about __copy_from_user() directly into
* thread.zt_state with preemption enabled, so protection is
@@ -621,6 +624,7 @@ static int parse_user_sigframe(struct user_ctxs *user,
goto invalid;
user->fpsimd = (struct fpsimd_context __user *)head;
+ user->fpsimd_size = size;
break;
case ESR_MAGIC:
@@ -635,6 +639,7 @@ static int parse_user_sigframe(struct user_ctxs *user,
goto invalid;
user->sve = (struct sve_context __user *)head;
+ user->sve_size = size;
break;
case TPIDR2_MAGIC:
@@ -644,10 +649,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,6 +661,7 @@ static int parse_user_sigframe(struct user_ctxs *user,
goto invalid;
user->za = (struct za_context __user *)head;
+ user->za_size = size;
break;
case ZT_MAGIC:
@@ -667,10 +671,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: