x86/mm: Rework address range check in get_user() and put_user()
[linux-2.6-block.git] / arch / x86 / lib / putuser.S
index 32125224fccaadfb45863679bca5c5e7cba85009..3062d09a776d5018039904aa60238ce71918e018 100644 (file)
  * as they get called from within inline assembly.
  */
 
-#ifdef CONFIG_X86_5LEVEL
-#define LOAD_TASK_SIZE_MINUS_N(n) \
-       ALTERNATIVE __stringify(mov $((1 << 47) - 4096 - (n)),%rbx), \
-                   __stringify(mov $((1 << 56) - 4096 - (n)),%rbx), X86_FEATURE_LA57
-#else
-#define LOAD_TASK_SIZE_MINUS_N(n) \
-       mov $(TASK_SIZE_MAX - (n)),%_ASM_BX
-#endif
+.macro check_range size:req
+.if IS_ENABLED(CONFIG_X86_64)
+       mov %rcx, %rbx
+       sar $63, %rbx
+       or %rbx, %rcx
+.else
+       cmp $TASK_SIZE_MAX-\size+1, %ecx
+       jae .Lbad_put_user
+.endif
+.endm
 
 .text
 SYM_FUNC_START(__put_user_1)
-       LOAD_TASK_SIZE_MINUS_N(0)
-       cmp %_ASM_BX,%_ASM_CX
-       jae .Lbad_put_user
+       check_range size=1
        ASM_STAC
 1:     movb %al,(%_ASM_CX)
        xor %ecx,%ecx
@@ -66,9 +66,7 @@ SYM_FUNC_END(__put_user_nocheck_1)
 EXPORT_SYMBOL(__put_user_nocheck_1)
 
 SYM_FUNC_START(__put_user_2)
-       LOAD_TASK_SIZE_MINUS_N(1)
-       cmp %_ASM_BX,%_ASM_CX
-       jae .Lbad_put_user
+       check_range size=2
        ASM_STAC
 3:     movw %ax,(%_ASM_CX)
        xor %ecx,%ecx
@@ -88,9 +86,7 @@ SYM_FUNC_END(__put_user_nocheck_2)
 EXPORT_SYMBOL(__put_user_nocheck_2)
 
 SYM_FUNC_START(__put_user_4)
-       LOAD_TASK_SIZE_MINUS_N(3)
-       cmp %_ASM_BX,%_ASM_CX
-       jae .Lbad_put_user
+       check_range size=4
        ASM_STAC
 5:     movl %eax,(%_ASM_CX)
        xor %ecx,%ecx
@@ -110,9 +106,7 @@ SYM_FUNC_END(__put_user_nocheck_4)
 EXPORT_SYMBOL(__put_user_nocheck_4)
 
 SYM_FUNC_START(__put_user_8)
-       LOAD_TASK_SIZE_MINUS_N(7)
-       cmp %_ASM_BX,%_ASM_CX
-       jae .Lbad_put_user
+       check_range size=8
        ASM_STAC
 7:     mov %_ASM_AX,(%_ASM_CX)
 #ifdef CONFIG_X86_32
@@ -144,15 +138,15 @@ SYM_CODE_START_LOCAL(.Lbad_put_user_clac)
        RET
 SYM_CODE_END(.Lbad_put_user_clac)
 
-       _ASM_EXTABLE_UA(1b, .Lbad_put_user_clac)
-       _ASM_EXTABLE_UA(2b, .Lbad_put_user_clac)
-       _ASM_EXTABLE_UA(3b, .Lbad_put_user_clac)
-       _ASM_EXTABLE_UA(4b, .Lbad_put_user_clac)
-       _ASM_EXTABLE_UA(5b, .Lbad_put_user_clac)
-       _ASM_EXTABLE_UA(6b, .Lbad_put_user_clac)
-       _ASM_EXTABLE_UA(7b, .Lbad_put_user_clac)
-       _ASM_EXTABLE_UA(9b, .Lbad_put_user_clac)
+       _ASM_EXTABLE(1b, .Lbad_put_user_clac)
+       _ASM_EXTABLE(2b, .Lbad_put_user_clac)
+       _ASM_EXTABLE(3b, .Lbad_put_user_clac)
+       _ASM_EXTABLE(4b, .Lbad_put_user_clac)
+       _ASM_EXTABLE(5b, .Lbad_put_user_clac)
+       _ASM_EXTABLE(6b, .Lbad_put_user_clac)
+       _ASM_EXTABLE(7b, .Lbad_put_user_clac)
+       _ASM_EXTABLE(9b, .Lbad_put_user_clac)
 #ifdef CONFIG_X86_32
-       _ASM_EXTABLE_UA(8b, .Lbad_put_user_clac)
-       _ASM_EXTABLE_UA(10b, .Lbad_put_user_clac)
+       _ASM_EXTABLE(8b, .Lbad_put_user_clac)
+       _ASM_EXTABLE(10b, .Lbad_put_user_clac)
 #endif