Skip to content

Commit b57682b

Browse files
brooniectmarinas
authored andcommitted
arm64/signal: Avoid rereading context frame sizes
We need to read the sizes of the signal context frames as part of parsing the overall signal context in parse_user_sigframe(). In the cases where we defer frame specific parsing to other functions those functions (other than the recently added TPIDR2 parser) reread the size and validate the version they read, opening the possibility that the value may change. Avoid this possibility by passing the size read in parse_user_sigframe() through user_ctxs and referring to that. For consistency we move the size check for the TPIDR2 context into the TPIDR2 parsing function. Note that for SVE, ZA and ZT contexts we still read the size again but after this change we no longer use the value, further changes will avoid the read. Signed-off-by: Mark Brown <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]>
1 parent 4e4e930 commit b57682b

File tree

1 file changed

+27
-25
lines changed

1 file changed

+27
-25
lines changed

arch/arm64/kernel/signal.c

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,15 @@ static void __user *apply_user_offset(
172172

173173
struct user_ctxs {
174174
struct fpsimd_context __user *fpsimd;
175+
u32 fpsimd_size;
175176
struct sve_context __user *sve;
177+
u32 sve_size;
176178
struct tpidr2_context __user *tpidr2;
179+
u32 tpidr2_size;
177180
struct za_context __user *za;
181+
u32 za_size;
178182
struct zt_context __user *zt;
183+
u32 zt_size;
179184
};
180185

181186
static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
@@ -199,14 +204,10 @@ static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
199204
static int restore_fpsimd_context(struct user_ctxs *user)
200205
{
201206
struct user_fpsimd_state fpsimd;
202-
__u32 size;
203207
int err = 0;
204208

205209
/* check the size information */
206-
__get_user_error(size, &user->fpsimd->head.size, err);
207-
if (err)
208-
return -EFAULT;
209-
if (size != sizeof(struct fpsimd_context))
210+
if (user->fpsimd_size != sizeof(struct fpsimd_context))
210211
return -EINVAL;
211212

212213
/* copy the FP and status/control registers */
@@ -275,12 +276,12 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
275276
struct user_fpsimd_state fpsimd;
276277
struct sve_context sve;
277278

279+
if (user->sve_size < sizeof(*user->sve))
280+
return -EINVAL;
281+
278282
if (__copy_from_user(&sve, user->sve, sizeof(sve)))
279283
return -EFAULT;
280284

281-
if (sve.head.size < sizeof(*user->sve))
282-
return -EINVAL;
283-
284285
if (sve.flags & SVE_SIG_FLAG_SM) {
285286
if (!system_supports_sme())
286287
return -EINVAL;
@@ -296,7 +297,7 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
296297
if (sve.vl != vl)
297298
return -EINVAL;
298299

299-
if (sve.head.size == sizeof(*user->sve)) {
300+
if (user->sve_size == sizeof(*user->sve)) {
300301
clear_thread_flag(TIF_SVE);
301302
current->thread.svcr &= ~SVCR_SM_MASK;
302303
current->thread.fp_type = FP_STATE_FPSIMD;
@@ -305,7 +306,7 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
305306

306307
vq = sve_vq_from_vl(sve.vl);
307308

308-
if (sve.head.size < SVE_SIG_CONTEXT_SIZE(vq))
309+
if (user->sve_size < SVE_SIG_CONTEXT_SIZE(vq))
309310
return -EINVAL;
310311

311312
/*
@@ -385,7 +386,9 @@ static int restore_tpidr2_context(struct user_ctxs *user)
385386
u64 tpidr2_el0;
386387
int err = 0;
387388

388-
/* Magic and size were validated deciding to call this function */
389+
if (user->tpidr2_size != sizeof(*user->tpidr2))
390+
return -EINVAL;
391+
389392
__get_user_error(tpidr2_el0, &user->tpidr2->tpidr2, err);
390393
if (!err)
391394
current->thread.tpidr2_el0 = tpidr2_el0;
@@ -434,23 +437,23 @@ static int restore_za_context(struct user_ctxs *user)
434437
unsigned int vq;
435438
struct za_context za;
436439

440+
if (user->za_size < sizeof(*user->za))
441+
return -EINVAL;
442+
437443
if (__copy_from_user(&za, user->za, sizeof(za)))
438444
return -EFAULT;
439445

440-
if (za.head.size < sizeof(*user->za))
441-
return -EINVAL;
442-
443446
if (za.vl != task_get_sme_vl(current))
444447
return -EINVAL;
445448

446-
if (za.head.size == sizeof(*user->za)) {
449+
if (user->za_size == sizeof(*user->za)) {
447450
current->thread.svcr &= ~SVCR_ZA_MASK;
448451
return 0;
449452
}
450453

451454
vq = sve_vq_from_vl(za.vl);
452455

453-
if (za.head.size < ZA_SIG_CONTEXT_SIZE(vq))
456+
if (user->za_size < ZA_SIG_CONTEXT_SIZE(vq))
454457
return -EINVAL;
455458

456459
/*
@@ -521,15 +524,15 @@ static int restore_zt_context(struct user_ctxs *user)
521524
if (!thread_za_enabled(&current->thread))
522525
return -EINVAL;
523526

527+
if (user->zt_size != ZT_SIG_CONTEXT_SIZE(1))
528+
return -EINVAL;
529+
524530
if (__copy_from_user(&zt, user->zt, sizeof(zt)))
525531
return -EFAULT;
526532

527533
if (zt.nregs != 1)
528534
return -EINVAL;
529535

530-
if (zt.head.size != ZT_SIG_CONTEXT_SIZE(zt.nregs))
531-
return -EINVAL;
532-
533536
/*
534537
* Careful: we are about __copy_from_user() directly into
535538
* thread.zt_state with preemption enabled, so protection is
@@ -621,6 +624,7 @@ static int parse_user_sigframe(struct user_ctxs *user,
621624
goto invalid;
622625

623626
user->fpsimd = (struct fpsimd_context __user *)head;
627+
user->fpsimd_size = size;
624628
break;
625629

626630
case ESR_MAGIC:
@@ -635,6 +639,7 @@ static int parse_user_sigframe(struct user_ctxs *user,
635639
goto invalid;
636640

637641
user->sve = (struct sve_context __user *)head;
642+
user->sve_size = size;
638643
break;
639644

640645
case TPIDR2_MAGIC:
@@ -644,10 +649,8 @@ static int parse_user_sigframe(struct user_ctxs *user,
644649
if (user->tpidr2)
645650
goto invalid;
646651

647-
if (size != sizeof(*user->tpidr2))
648-
goto invalid;
649-
650652
user->tpidr2 = (struct tpidr2_context __user *)head;
653+
user->tpidr2_size = size;
651654
break;
652655

653656
case ZA_MAGIC:
@@ -658,6 +661,7 @@ static int parse_user_sigframe(struct user_ctxs *user,
658661
goto invalid;
659662

660663
user->za = (struct za_context __user *)head;
664+
user->za_size = size;
661665
break;
662666

663667
case ZT_MAGIC:
@@ -667,10 +671,8 @@ static int parse_user_sigframe(struct user_ctxs *user,
667671
if (user->zt)
668672
goto invalid;
669673

670-
if (size < sizeof(*user->zt))
671-
goto invalid;
672-
673674
user->zt = (struct zt_context __user *)head;
675+
user->zt_size = size;
674676
break;
675677

676678
case EXTRA_MAGIC:

0 commit comments

Comments
 (0)