Skip to content

Commit dde6f22

Browse files
James Hogangregkh
authored andcommitted
metag/usercopy: Add early abort to copy_to_user
commit fb8ea062a8f2e85256e13f55696c5c5f0dfdcc8b upstream. When copying to userland on Meta, if any faults are encountered immediately abort the copy instead of continuing on and repeatedly faulting, and worse potentially copying further bytes successfully to subsequent valid pages. Fixes: 373cd78 ("metag: Memory handling") Reported-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: linux-metag@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent ae781de commit dde6f22

1 file changed

Lines changed: 20 additions & 0 deletions

File tree

arch/metag/lib/usercopy.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,23 +538,31 @@ unsigned long __copy_user(void __user *pdst, const void *psrc,
538538
if ((unsigned long) src & 1) {
539539
__asm_copy_to_user_1(dst, src, retn);
540540
n--;
541+
if (retn)
542+
return retn + n;
541543
}
542544
if ((unsigned long) dst & 1) {
543545
/* Worst case - byte copy */
544546
while (n > 0) {
545547
__asm_copy_to_user_1(dst, src, retn);
546548
n--;
549+
if (retn)
550+
return retn + n;
547551
}
548552
}
549553
if (((unsigned long) src & 2) && n >= 2) {
550554
__asm_copy_to_user_2(dst, src, retn);
551555
n -= 2;
556+
if (retn)
557+
return retn + n;
552558
}
553559
if ((unsigned long) dst & 2) {
554560
/* Second worst case - word copy */
555561
while (n >= 2) {
556562
__asm_copy_to_user_2(dst, src, retn);
557563
n -= 2;
564+
if (retn)
565+
return retn + n;
558566
}
559567
}
560568

@@ -569,6 +577,8 @@ unsigned long __copy_user(void __user *pdst, const void *psrc,
569577
while (n >= 8) {
570578
__asm_copy_to_user_8x64(dst, src, retn);
571579
n -= 8;
580+
if (retn)
581+
return retn + n;
572582
}
573583
}
574584
if (n >= RAPF_MIN_BUF_SIZE) {
@@ -581,18 +591,24 @@ unsigned long __copy_user(void __user *pdst, const void *psrc,
581591
while (n >= 8) {
582592
__asm_copy_to_user_8x64(dst, src, retn);
583593
n -= 8;
594+
if (retn)
595+
return retn + n;
584596
}
585597
}
586598
#endif
587599

588600
while (n >= 16) {
589601
__asm_copy_to_user_16(dst, src, retn);
590602
n -= 16;
603+
if (retn)
604+
return retn + n;
591605
}
592606

593607
while (n >= 4) {
594608
__asm_copy_to_user_4(dst, src, retn);
595609
n -= 4;
610+
if (retn)
611+
return retn + n;
596612
}
597613

598614
switch (n) {
@@ -609,6 +625,10 @@ unsigned long __copy_user(void __user *pdst, const void *psrc,
609625
break;
610626
}
611627

628+
/*
629+
* If we get here, retn correctly reflects the number of failing
630+
* bytes.
631+
*/
612632
return retn;
613633
}
614634
EXPORT_SYMBOL(__copy_user);

0 commit comments

Comments
 (0)