diff options
Diffstat (limited to 'arch/arm64/kernel/signal.c')
-rw-r--r-- | arch/arm64/kernel/signal.c | 52 |
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(¤t->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: |