From c59f723a562f9539dfac68c1b306858e35a05cdd Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 7 Sep 2012 18:22:28 +0100 Subject: ARM: 7527/1: uaccess: explicitly check __user pointer when !CPU_USE_DOMAINS The {get,put}_user macros don't perform range checking on the provided __user address when !CPU_HAS_DOMAINS. This patch reworks the out-of-line assembly accessors to check the user address against a specified limit, returning -EFAULT if is is out of range. [will: changed get_user register allocation to match put_user] [rmk: fixed building on older ARM architectures] CRs-Fixed: 504011 Reported-by: Catalin Marinas Signed-off-by: Will Deacon Cc: stable@vger.kernel.org Signed-off-by: Russell King Git-commit: 8404663f81d212918ff85f493649a7991209fa04 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Laura Abbott Conflicts: arch/arm/include/asm/assembler.h arch/arm/lib/getuser.S arch/arm/lib/putuser.S Change-Id: I3818045a136fcdf72deb1371b132e090fd7ed643 Conflicts: arch/arm/lib/getuser.S arch/arm/lib/putuser.S --- arch/arm/include/asm/assembler.h | 16 +++++++------- arch/arm/lib/copy_from_user.S | 9 ++++++++ arch/arm/lib/copy_template.S | 46 ++++++++++++++++++++++++++++++++-------- arch/arm/lib/copy_to_user.S | 9 ++++++++ arch/arm/lib/memcpy.S | 9 ++++++++ 5 files changed, 72 insertions(+), 17 deletions(-) diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 456649e..b7c5d5d 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -299,14 +299,6 @@ usracc ldr, \reg, \ptr, \inc, \cond, \rept, \abort .endm - .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req -#ifndef CONFIG_CPU_USE_DOMAINS - adds \tmp, \addr, #\size - 1 - sbcccs \tmp, \tmp, \limit - bcs \bad -#endif - .endm - /* Utility macro for declaring string literals */ .macro string name:req, string .type \name , #object @@ -315,4 +307,12 @@ .size \name , . - \name .endm + .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req +#ifndef CONFIG_CPU_USE_DOMAINS + adds \tmp, \addr, #\size - 1 + sbcccs \tmp, \tmp, \limit + bcs \bad +#endif + .endm + #endif /* __ASM_ASSEMBLER_H__ */ diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S index 66a477a..54daeae 100644 --- a/arch/arm/lib/copy_from_user.S +++ b/arch/arm/lib/copy_from_user.S @@ -68,6 +68,15 @@ stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8} .endm + .macro cpy8w dst src reg1 reg2 abort + .irp offset, #0, #8, #16, #24 + ldr1w \src, \reg1, \abort + ldr1w \src, \reg2, \abort + strd \reg1, \reg2, [\dst, \offset] + .endr + add \dst, \dst, #32 + .endm + .macro str1b ptr reg cond=al abort str\cond\()b \reg, [\ptr], #1 .endm diff --git a/arch/arm/lib/copy_template.S b/arch/arm/lib/copy_template.S index 805e3f8..f2b5885 100644 --- a/arch/arm/lib/copy_template.S +++ b/arch/arm/lib/copy_template.S @@ -66,6 +66,7 @@ * than one 32bit instruction in Thumb-2) */ +#define PLDSIZE (CONFIG_ARM_PLD_SIZE) enter r4, lr @@ -90,19 +91,46 @@ CALGN( add pc, r4, ip ) PLD( pld [r1, #0] ) -2: PLD( subs r2, r2, #96 ) - PLD( pld [r1, #28] ) + +#if (PLDSIZE == 64) +2: PLD( cmp r2, #32) + PLD( blt .32copy) + +.64copy: + PLD( subs r2, r2, #(PLDSIZE*3+32) ) + PLD( pld [r1, #PLDSIZE-4] ) PLD( blt 4f ) - PLD( pld [r1, #60] ) - PLD( pld [r1, #92] ) + PLD( pld [r1, #PLDSIZE*2-4] ) + PLD( pld [r1, #PLDSIZE*3-4] ) +3: PLD( pld [r1, #PLDSIZE*4-4] ) +4: cpy8w r0, r1, r4, r5, abort=20f + cpy8w r0, r1, r4, r5, abort=20f + subs r2, r2, #PLDSIZE + bge 3b + PLD( cmn r2, #(PLDSIZE*3) ) + PLD( bge 4b ) + + PLD( cmn r2, #(PLDSIZE*4-32) ) + PLD( blt 5f) + +.32copy: + cpy8w r0, r1, r4, r5, abort=20f +#else +2: PLD( subs r2, r2, #(PLDSIZE*3) ) + PLD( pld [r1, #(PLDSIZE-4)] ) + PLD( blt 4f ) + PLD( pld [r1, #(PLDSIZE*2-4)] ) + PLD( pld [r1, #(PLDSIZE*3-4)] ) + +3: PLD( pld [r1, #(PLDSIZE*4-4)] ) +4: ldr8w r1, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f + subs r2, r2, #PLDSIZE + str8w r0, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f -3: PLD( pld [r1, #124] ) -4: ldr8w r1, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f - subs r2, r2, #32 - str8w r0, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f bge 3b - PLD( cmn r2, #96 ) + PLD( cmn r2, #(PLDSIZE*3) ) PLD( bge 4b ) +#endif 5: ands ip, r2, #28 rsb ip, ip, #32 diff --git a/arch/arm/lib/copy_to_user.S b/arch/arm/lib/copy_to_user.S index d066df6..e32788b 100644 --- a/arch/arm/lib/copy_to_user.S +++ b/arch/arm/lib/copy_to_user.S @@ -71,6 +71,15 @@ str1w \ptr, \reg8, \abort .endm + .macro cpy8w dst src reg1 reg2 abort + .irp offset, #0, #8, #16, #24 + ldrd \reg1, \reg2, [\src, \offset] + str1w \dst, \reg1, \abort + str1w \dst, \reg2, \abort + .endr + add \src, \src, #32 + .endm + .macro str1b ptr reg cond=al abort strusr \reg, \ptr, 1, \cond, abort=\abort .endm diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S index a9b9e22..7ffda59 100644 --- a/arch/arm/lib/memcpy.S +++ b/arch/arm/lib/memcpy.S @@ -40,6 +40,15 @@ stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8} .endm + .macro cpy8w dst src reg1 reg2 abort + .irp offset, #0, #8, #16, #24 + ldrd \reg1, \reg2, [\src, \offset] + strd \reg1, \reg2, [\dst, \offset] + .endr + add \src, \src, #32 + add \dst, \dst, #32 + .endm + .macro str1b ptr reg cond=al abort str\cond\()b \reg, [\ptr], #1 .endm -- cgit v1.1