Skip to contentSkip to conversation

x86_32: add support for 64 bit __get_user()

PATCH In review Benjamin LaHaise 4 participants 14 messages Mar 9, 2016 – Mar 14, 2016 x86

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 x86_32: add support for 64 bit __get_user()

The existing __get_user() implementation does not support fetching 64 bit values on 32 bit x86. Implement this in a way that does not generate any incorrect warnings as cautioned by Russell King. Test code available at http://www.kvack.org/~bcrl/x86_32-get_user.tar .

arch/x86/include/asm/uaccess.h +31 -6
index a4a30e4..2d0607a 100644
@@ -333,7 +333,23 @@ do {									\
 } while (0)
 
 #ifdef CONFIG_X86_32
-#define __get_user_asm_u64(x, ptr, retval, errret)	(x) = __get_user_bad()
+#define __get_user_asm_u64(x, addr, err, errret)			\
+	asm volatile(ASM_STAC "\n"					\
+		     "1:	movl %2,%%eax\n"			\
+		     "2:	movl %3,%%edx\n"			\
+		     "3: " ASM_CLAC "\n"				\
+		     ".section .fixup,\"ax\"\n"				\
+		     "4:	mov %4,%0\n"				\
+		     "	xorl %%eax,%%eax\n"				\
+		     "	xorl %%edx,%%edx\n"				\
+		     "	jmp 3b\n"					\
+		     ".previous\n"					\
+		     _ASM_EXTABLE(1b, 4b)				\
+		     _ASM_EXTABLE(2b, 4b)				\
+		     : "=r" (err), "=A"(x)				\
+		     : "m" (__m(addr)), "m" __m(((u32 *)(addr)) + 1),	\
+		       "i" (errret), "0" (err))
+
 #define __get_user_asm_ex_u64(x, ptr)			(x) = __get_user_bad()
 #else
 #define __get_user_asm_u64(x, ptr, retval, errret) \
@@ -420,11 +436,20 @@ do {									\
 #define __get_user_nocheck(x, ptr, size)				\
 ({									\
 	int __gu_err;							\
-	unsigned long __gu_val;						\
-	__uaccess_begin();						\
-	__get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT);	\
-	__uaccess_end();						\
-	(x) = (__force __typeof__(*(ptr)))__gu_val;			\
+	if (size == 8) {						\
+		unsigned long __gu_val[2];				\
+		__gu_err = 0;						\
+		__uaccess_begin();					\
+		__get_user_asm_u64(__gu_val, ptr, __gu_err, -EFAULT);	\
+		__uaccess_end();					\
+		(x) = *(__force __typeof__((ptr)))__gu_val;		\
+	} else {							\
+		unsigned long __gu_val;					\
+		__uaccess_begin();					\
+		__get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
+		__uaccess_end();					\
+		(x) = (__force __typeof__(*(ptr)))__gu_val;		\
+	}								\
 	__builtin_expect(__gu_err, 0);					\
 })
 
Signature · 1 line
"Thought is the essence of where you are now."
#1 lore raw
Quoted 54 lines · Benjamin LaHaise

The existing __get_user() implementation does not support fetching 64 bit values on 32 bit x86. Implement this in a way that does not generate any incorrect warnings as cautioned by Russell King. Test code available at http://www.kvack.org/~bcrl/x86_32-get_user.tar .

arch/x86/include/asm/uaccess.h +17 -1
index a4a30e4..2d0607a 100644
@@ -333,7 +333,23 @@ do {									\
 } while (0)
 
 #ifdef CONFIG_X86_32
-#define __get_user_asm_u64(x, ptr, retval, errret)	(x) =
 __get_user_bad()
+#define __get_user_asm_u64(x, addr, err, errret)			\
+	asm volatile(ASM_STAC "\n"					\
+		     "1:	movl %2,%%eax\n"			\
+		     "2:	movl %3,%%edx\n"			\
+		     "3: " ASM_CLAC "\n"				\
+		     ".section .fixup,\"ax\"\n"				\
+		     "4:	mov %4,%0\n"				\
+		     "	xorl %%eax,%%eax\n"				\
+		     "	xorl %%edx,%%edx\n"				\
+		     "	jmp 3b\n"					\
+		     ".previous\n"					\
+		     _ASM_EXTABLE(1b, 4b)				\
+		     _ASM_EXTABLE(2b, 4b)				\
+		     : "=r" (err), "=A"(x)				\
+		     : "m" (__m(addr)), "m" __m(((u32 *)(addr)) + 1),	\
+		       "i" (errret), "0" (err))
+
 #define __get_user_asm_ex_u64(x, ptr)			(x) = __get_user_bad()
 #else

#define __get_user_asm_u64(x, ptr, retval, errret) \

arch/x86/include/asm/uaccess.h +7 -5
@@ -420,11 +436,20 @@ do {									\
 #define __get_user_nocheck(x, ptr, size)				\
 ({									\
 	int __gu_err;							\
-	unsigned long __gu_val;						\
-	__uaccess_begin();						\
-	__get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT);	\
-	__uaccess_end();						\
-	(x) = (__force __typeof__(*(ptr)))__gu_val;			\
+	if (size == 8) {						\
+		unsigned long __gu_val[2];				\
+		__gu_err = 0;						\
+		__uaccess_begin();					\
+		__get_user_asm_u64(__gu_val, ptr, __gu_err, -EFAULT);	\
+		__uaccess_end();					\
+		(x) = *(__force __typeof__((ptr)))__gu_val;		\

arch/x86/include/asm/uaccess.h do { \ · line 455

Quoted 10 lines
arch/x86/include/asm/uaccess.h +7 -0
+	} else {							\
+		unsigned long __gu_val;					\
+		__uaccess_begin();					\
+		__get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
+		__uaccess_end();					\
+		(x) = (__force __typeof__(*(ptr)))__gu_val;		\
+	}								\
 	__builtin_expect(__gu_err, 0);					\
 })
 

Weird. I could swear we had already fixed this a few years ago.

Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.
#2 lore raw
Quoted 5 lines · H. Peter Anvin
Quoted 4 lines · Benjamin LaHaise

The existing __get_user() implementation does not support fetching 64 bit values on 32 bit x86. Implement this in a way that does not generate any incorrect warnings as cautioned by Russell King. Test code available at http://www.kvack.org/~bcrl/x86_32-get_user.tar .

...

Quoted 1 line

Weird. I could swear we had already fixed this a few years ago.

That surprised me as well, but Russell raised the fact that the approaches previously tried on 32 bit architectures had caused various incorrect compiler warnings for certain obscure cases -- see the code in test_module.c in that URL that Russell provided to demonstrate the problem across all the corner cases.

-ben

Signature · 1 line
"Thought is the essence of where you are now."
#3 lore raw
Quoted 6 lines · Benjamin LaHaise
Quoted 5 lines · H. Peter Anvin
Quoted 4 lines · Benjamin LaHaise

The existing __get_user() implementation does not support fetching 64 bit values on 32 bit x86. Implement this in a way that does not generate any incorrect warnings as cautioned by Russell King. Test code available at http://www.kvack.org/~bcrl/x86_32-get_user.tar .

Quoted 8 lines

...

Quoted 1 line

Weird. I could swear we had already fixed this a few years ago.

That surprised me as well, but Russell raised the fact that the approaches previously tried on 32 bit architectures had caused various incorrect compiler warnings for certain obscure cases -- see the code in test_module.c in that URL that Russell provided to demonstrate the problem across all the corner cases.

Oh, I see... I implemented it for put but not get... weird. You may want to look at the __inttype() macro defined earlier in this file; it might be useful.

I presume you have already seen:

Quoted 2 lines
Quoted 2 lines

fs/select.c:710: Error: operand type mismatch for movq' fs/select.c:714: Error: incorrect register %cx' used with `q' suffix

fs/select.c:711: Error: operand type mismatch for `movq'

Quoted 1 line
Quoted 1 line

fs/select.c:715: Error: incorrect register %si' used with q' suffix

--
fs/aio.c: Assembler messages:

Quoted 2 lines
Quoted 2 lines

fs/aio.c:1606: Error: operand type mismatch for movq' fs/aio.c:1610: Error: incorrect register %si' used with `q' suffix

... which implies it used 16-bit registers for 64-bit operations when compiling for 64 bits.

-hpa

#4 lore raw
Quoted 16 lines · H. Peter Anvin
Quoted 6 lines · Benjamin LaHaise
Quoted 5 lines · H. Peter Anvin
Quoted 4 lines · Benjamin LaHaise

The existing __get_user() implementation does not support fetching 64 bit values on 32 bit x86. Implement this in a way that does not generate any incorrect warnings as cautioned by Russell King. Test code available at http://www.kvack.org/~bcrl/x86_32-get_user.tar .

Quoted 8 lines

...

Quoted 1 line

Weird. I could swear we had already fixed this a few years ago.

That surprised me as well, but Russell raised the fact that the approaches previously tried on 32 bit architectures had caused various incorrect compiler warnings for certain obscure cases -- see the code in test_module.c in that URL that Russell provided to demonstrate the problem across all the corner cases.

Quoted 3 lines

Oh, I see... I implemented it for put but not get... weird. You may want to look at the __inttype() macro defined earlier in this file; it might be useful.

Ah, interesting. I'll look at that.

Quoted 5 lines

I presume you have already seen:

Quoted 2 lines
Quoted 2 lines

fs/select.c:710: Error: operand type mismatch for movq' fs/select.c:714: Error: incorrect register %cx' used with `q' suffix

fs/select.c:711: Error: operand type mismatch for `movq'

Quoted 8 lines
Quoted 1 line
Quoted 1 line

fs/select.c:715: Error: incorrect register %si' used with q' suffix

--
fs/aio.c: Assembler messages:

Quoted 2 lines
Quoted 2 lines

fs/aio.c:1606: Error: operand type mismatch for movq' fs/aio.c:1610: Error: incorrect register %si' used with `q' suffix

... which implies it used 16-bit registers for 64-bit operations when compiling for 64 bits.

Yup, will respin shortly.

-ben

Signature · 1 line
"Thought is the essence of where you are now."
#5 lore raw

PATCH 1/1 x86_32: add support for 64 bit __get_user() v2

In reply to H. Peter Anvin

The existing __get_user() implementation does not support fetching 64 bit values on 32 bit x86. Implement this in a way that does not generate any incorrect warnings as cautioned by Russell King. Test code available at http://www.kvack.org/~bcrl/x86_32-get_user.tar .

v2: use __inttype() as suggested by H. Peter Anvin, which cleans the code up nicely, and fix things to work on x86_64 as well. Tested on both 32 bit and 64 bit x86.

arch/x86/include/asm/uaccess.h +20 -2
index a4a30e4..1284da2 100644
@@ -333,7 +333,25 @@ do {									\
 } while (0)
 
 #ifdef CONFIG_X86_32
-#define __get_user_asm_u64(x, ptr, retval, errret)	(x) = __get_user_bad()
+#define __get_user_asm_u64(x, ptr, retval, errret)			\
+({									\
+	asm volatile(ASM_STAC "\n"					\
+		     "1:	movl %2,%%eax\n"			\
+		     "2:	movl %3,%%edx\n"			\
+		     "3: " ASM_CLAC "\n"				\
+		     ".section .fixup,\"ax\"\n"				\
+		     "4:	mov %4,%0\n"				\
+		     "	xorl %%eax,%%eax\n"				\
+		     "	xorl %%edx,%%edx\n"				\
+		     "	jmp 3b\n"					\
+		     ".previous\n"					\
+		     _ASM_EXTABLE(1b, 4b)				\
+		     _ASM_EXTABLE(2b, 4b)				\
+		     : "=r" (retval), "=A"(x)				\
+		     : "m" (__m(ptr)), "m" __m(((u32 *)(ptr)) + 1),	\
+		       "i" (errret), "0" (retval));			\
+})
+
 #define __get_user_asm_ex_u64(x, ptr)			(x) = __get_user_bad()
 #else
 #define __get_user_asm_u64(x, ptr, retval, errret) \
@@ -420,7 +438,7 @@ do {									\
 #define __get_user_nocheck(x, ptr, size)				\
 ({									\
 	int __gu_err;							\
-	unsigned long __gu_val;						\
+	__inttype(*(ptr)) __gu_val;					\
 	__uaccess_begin();						\
 	__get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT);	\
 	__uaccess_end();						\
Signature · 1 line
"Thought is the essence of where you are now."
#6 lore raw

Re: [PATCH] x86_32: add support for 64 bit __get_user() v2

reproduce:

Hi Benjamin,

[auto build test WARNING on tip/x86/core]
[also build test WARNING on v4.5-rc7 next-20160309]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Benjamin-LaHaise/x86_32-add-support-for-64-bit-__get_user-v2/20160310-033507
config: i386-tinyconfig (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All warnings (new ones prefixed by >>):

In file included from arch/x86/include/asm/sections.h:5:0,

                    from arch/x86/include/asm/hw_irq.h:26,
                    from include/linux/irq.h:418,
                    from arch/x86/include/asm/hardirq.h:5,
                    from include/linux/hardirq.h:8,
                    from include/linux/memcontrol.h:24,
                    from include/linux/tracehook.h:53,
                    from arch/x86/kernel/ptrace.c:14:
   arch/x86/kernel/ptrace.c: In function 'genregs_set':
>> arch/x86/kernel/ptrace.c:530:28: warning: operation on 'u' may be undefined [-Wsequence-point]
       ret = __get_user(word, u++);
                               ^
   arch/x86/include/asm/uaccess.h:451:51: note: in definition of macro '__m'
    #define __m(x) (*(struct __large_struct __user *)(x))
                                                      ^
>> arch/x86/include/asm/uaccess.h:378:3: note: in expansion of macro '__get_user_asm_u64'
      __get_user_asm_u64(x, ptr, retval, errret);  \
      ^
>> arch/x86/include/asm/uaccess.h:443:2: note: in expansion of macro '__get_user_size'
     __get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
     ^
>> arch/x86/include/asm/uaccess.h:512:2: note: in expansion of macro '__get_user_nocheck'
     __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
     ^
>> arch/x86/kernel/ptrace.c:530:10: note: in expansion of macro '__get_user'
       ret = __get_user(word, u++);
             ^
--
   In file included from lib/bitmap.c:17:0:
   lib/bitmap.c: In function '__bitmap_parse':
>> lib/bitmap.c:377:27: warning: operation on 'ubuf' may be undefined [-Wsequence-point]
        if (__get_user(c, ubuf++))
                              ^
   arch/x86/include/asm/uaccess.h:451:51: note: in definition of macro '__m'
    #define __m(x) (*(struct __large_struct __user *)(x))
                                                      ^
>> arch/x86/include/asm/uaccess.h:378:3: note: in expansion of macro '__get_user_asm_u64'
      __get_user_asm_u64(x, ptr, retval, errret);  \
      ^
>> arch/x86/include/asm/uaccess.h:443:2: note: in expansion of macro '__get_user_size'
     __get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
     ^
>> arch/x86/include/asm/uaccess.h:512:2: note: in expansion of macro '__get_user_nocheck'
     __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
     ^
>> lib/bitmap.c:377:9: note: in expansion of macro '__get_user'
        if (__get_user(c, ubuf++))
            ^
   lib/bitmap.c: In function '__bitmap_parselist':
   lib/bitmap.c:525:27: warning: operation on 'ubuf' may be undefined [-Wsequence-point]
        if (__get_user(c, ubuf++))
                              ^
   arch/x86/include/asm/uaccess.h:451:51: note: in definition of macro '__m'
    #define __m(x) (*(struct __large_struct __user *)(x))
                                                      ^
>> arch/x86/include/asm/uaccess.h:378:3: note: in expansion of macro '__get_user_asm_u64'
      __get_user_asm_u64(x, ptr, retval, errret);  \
      ^
>> arch/x86/include/asm/uaccess.h:443:2: note: in expansion of macro '__get_user_size'
     __get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
     ^
>> arch/x86/include/asm/uaccess.h:512:2: note: in expansion of macro '__get_user_nocheck'
     __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
     ^
   lib/bitmap.c:525:9: note: in expansion of macro '__get_user'
        if (__get_user(c, ubuf++))
            ^

vim +/__get_user_asm_u64 +378 arch/x86/include/asm/uaccess.h

3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  372  		__get_user_asm(x, ptr, retval, "w", "w", "=r", errret);	\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  373  		break;							\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  374  	case 4:								\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  375  		__get_user_asm(x, ptr, retval, "l", "k", "=r", errret);	\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  376  		break;							\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  377  	case 8:								\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25 @378  		__get_user_asm_u64(x, ptr, retval, errret);		\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  379  		break;							\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  380  	default:							\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  381  		(x) = __get_user_bad();					\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  382  	}								\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  383  } while (0)
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  384  
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  385  #define __get_user_asm(x, addr, err, itype, rtype, ltype, errret)	\
11f1a4b9 arch/x86/include/asm/uaccess.h Linus Torvalds    2015-12-17  386  	asm volatile("\n"						\
63bcff2a arch/x86/include/asm/uaccess.h H. Peter Anvin    2012-09-21  387  		     "1:	mov"itype" %2,%"rtype"1\n"		\
11f1a4b9 arch/x86/include/asm/uaccess.h Linus Torvalds    2015-12-17  388  		     "2:\n"						\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  389  		     ".section .fixup,\"ax\"\n"				\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  390  		     "3:	mov %3,%0\n"				\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  391  		     "	xor"itype" %"rtype"1,%"rtype"1\n"		\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  392  		     "	jmp 2b\n"					\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  393  		     ".previous\n"					\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  394  		     _ASM_EXTABLE(1b, 3b)				\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  395  		     : "=r" (err), ltype(x)				\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  396  		     : "m" (__m(addr)), "i" (errret), "0" (err))
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  397  
11f1a4b9 arch/x86/include/asm/uaccess.h Linus Torvalds    2015-12-17  398  /*
11f1a4b9 arch/x86/include/asm/uaccess.h Linus Torvalds    2015-12-17  399   * This doesn't do __uaccess_begin/end - the exception handling
11f1a4b9 arch/x86/include/asm/uaccess.h Linus Torvalds    2015-12-17  400   * around it must do that.
11f1a4b9 arch/x86/include/asm/uaccess.h Linus Torvalds    2015-12-17  401   */
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  402  #define __get_user_size_ex(x, ptr, size)				\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  403  do {									\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  404  	__chk_user_ptr(ptr);						\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  405  	switch (size) {							\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  406  	case 1:								\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  407  		__get_user_asm_ex(x, ptr, "b", "b", "=q");		\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  408  		break;							\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  409  	case 2:								\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  410  		__get_user_asm_ex(x, ptr, "w", "w", "=r");		\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  411  		break;							\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  412  	case 4:								\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  413  		__get_user_asm_ex(x, ptr, "l", "k", "=r");		\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  414  		break;							\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  415  	case 8:								\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  416  		__get_user_asm_ex_u64(x, ptr);				\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  417  		break;							\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  418  	default:							\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  419  		(x) = __get_user_bad();					\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  420  	}								\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  421  } while (0)
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  422  
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  423  #define __get_user_asm_ex(x, addr, itype, rtype, ltype)			\
5e88353d arch/x86/include/asm/uaccess.h H. Peter Anvin    2012-09-21  424  	asm volatile("1:	mov"itype" %1,%"rtype"0\n"		\
5e88353d arch/x86/include/asm/uaccess.h H. Peter Anvin    2012-09-21  425  		     "2:\n"						\
535c0c34 arch/x86/include/asm/uaccess.h H. Peter Anvin    2012-04-20  426  		     _ASM_EXTABLE_EX(1b, 2b)				\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  427  		     : ltype(x) : "m" (__m(addr)))
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  428  
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  429  #define __put_user_nocheck(x, ptr, size)			\
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  430  ({								\
16855f87 arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2008-12-08  431  	int __pu_err;						\
11f1a4b9 arch/x86/include/asm/uaccess.h Linus Torvalds    2015-12-17  432  	__uaccess_begin();					\
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  433  	__put_user_size((x), (ptr), (size), __pu_err, -EFAULT);	\
11f1a4b9 arch/x86/include/asm/uaccess.h Linus Torvalds    2015-12-17  434  	__uaccess_end();					\
a76cf66e arch/x86/include/asm/uaccess.h Andy Lutomirski   2015-10-05  435  	__builtin_expect(__pu_err, 0);				\
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  436  })
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  437  
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  438  #define __get_user_nocheck(x, ptr, size)				\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  439  ({									\
16855f87 arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2008-12-08  440  	int __gu_err;							\
7dd119d0 arch/x86/include/asm/uaccess.h Benjamin LaHaise  2016-03-09  441  	__inttype(*(ptr)) __gu_val;					\
11f1a4b9 arch/x86/include/asm/uaccess.h Linus Torvalds    2015-12-17  442  	__uaccess_begin();						\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25 @443  	__get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT);	\
11f1a4b9 arch/x86/include/asm/uaccess.h Linus Torvalds    2015-12-17  444  	__uaccess_end();						\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  445  	(x) = (__force __typeof__(*(ptr)))__gu_val;			\
a76cf66e arch/x86/include/asm/uaccess.h Andy Lutomirski   2015-10-05  446  	__builtin_expect(__gu_err, 0);					\
3f168221 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  447  })
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  448  
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  449  /* FIXME: this hack is definitely wrong -AK */
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  450  struct __large_struct { unsigned long buf[100]; };
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25 @451  #define __m(x) (*(struct __large_struct __user *)(x))
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  452  
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  453  /*
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  454   * Tell gcc we read from memory instead of writing: this is because
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  455   * we do not write to any memory gcc knows about, so there are no
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  456   * aliasing issues.
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  457   */
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  458  #define __put_user_asm(x, addr, err, itype, rtype, ltype, errret)	\
11f1a4b9 arch/x86/include/asm/uaccess.h Linus Torvalds    2015-12-17  459  	asm volatile("\n"						\
63bcff2a arch/x86/include/asm/uaccess.h H. Peter Anvin    2012-09-21  460  		     "1:	mov"itype" %"rtype"1,%2\n"		\
11f1a4b9 arch/x86/include/asm/uaccess.h Linus Torvalds    2015-12-17  461  		     "2:\n"						\
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  462  		     ".section .fixup,\"ax\"\n"				\
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  463  		     "3:	mov %3,%0\n"				\
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  464  		     "	jmp 2b\n"					\
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  465  		     ".previous\n"					\
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  466  		     _ASM_EXTABLE(1b, 3b)				\
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  467  		     : "=r"(err)					\
dc70ddf4 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  468  		     : ltype(x), "m" (__m(addr)), "i" (errret), "0" (err))
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  469  
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  470  #define __put_user_asm_ex(x, addr, itype, rtype, ltype)			\
5e88353d arch/x86/include/asm/uaccess.h H. Peter Anvin    2012-09-21  471  	asm volatile("1:	mov"itype" %"rtype"0,%1\n"		\
5e88353d arch/x86/include/asm/uaccess.h H. Peter Anvin    2012-09-21  472  		     "2:\n"						\
535c0c34 arch/x86/include/asm/uaccess.h H. Peter Anvin    2012-04-20  473  		     _ASM_EXTABLE_EX(1b, 2b)				\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  474  		     : : ltype(x), "m" (__m(addr)))
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  475  
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  476  /*
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  477   * uaccess_try and catch
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  478   */
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  479  #define uaccess_try	do {						\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  480  	current_thread_info()->uaccess_err = 0;				\
11f1a4b9 arch/x86/include/asm/uaccess.h Linus Torvalds    2015-12-17  481  	__uaccess_begin();						\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  482  	barrier();
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  483  
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  484  #define uaccess_catch(err)						\
11f1a4b9 arch/x86/include/asm/uaccess.h Linus Torvalds    2015-12-17  485  	__uaccess_end();						\
4fc34901 arch/x86/include/asm/uaccess.h Andy Lutomirski   2011-11-07  486  	(err) |= (current_thread_info()->uaccess_err ? -EFAULT : 0);	\
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  487  } while (0)
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  488  
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  489  /**
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  490   * __get_user: - Get a simple variable from user space, with less checking.
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  491   * @x:   Variable to store result.
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  492   * @ptr: Source address, in user space.
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  493   *
b3c395ef arch/x86/include/asm/uaccess.h David Hildenbrand 2015-05-11  494   * Context: User context only. This function may sleep if pagefaults are
b3c395ef arch/x86/include/asm/uaccess.h David Hildenbrand 2015-05-11  495   *          enabled.
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  496   *
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  497   * This macro copies a single simple variable from user space to kernel
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  498   * space.  It supports simple types like char and int, but not larger
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  499   * data types like structures or arrays.
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  500   *
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  501   * @ptr must have pointer-to-simple-variable type, and the result of
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  502   * dereferencing @ptr must be assignable to @x without a cast.
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  503   *
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  504   * Caller must check the pointer with access_ok() before calling this
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  505   * function.
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  506   *
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  507   * Returns zero on success, or -EFAULT on error.
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  508   * On error, the variable @x is set to zero.
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  509   */
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  510  
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  511  #define __get_user(x, ptr)						\
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25 @512  	__get_user_nocheck((x), (ptr), sizeof(*(ptr)))
fe40c0af arch/x86/include/asm/uaccess.h Hiroshi Shimamoto 2009-01-23  513  
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  514  /**
8cb834e9 include/asm-x86/uaccess.h      Glauber Costa     2008-06-25  515   * __put_user: - Write a simple value into user space, with less checking.

:::::: The code at line 378 was first introduced by commit
:::::: 3f168221167ca7a844fde3bf58e1c7ca0bf9741e x86: merge __get_user_asm and its users.

:::::: TO: Glauber Costa <[email protected]>
:::::: CC: Ingo Molnar <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#7 lore raw

PATCH 1/1 x86_32: add support for 64 bit __get_user() v3

In reply to Benjamin LaHaise

The existing __get_user() implementation does not support fetching 64 bit values on 32 bit x86. Implement this in a way that does not generate any incorrect warnings as cautioned by Russell King. Test code available at http://www.kvack.org/~bcrl/x86_32-get_user.tar .

v2: use __inttype() as suggested by H. Peter Anvin, which cleans the code up nicely, and fix things to work on x86_64 as well.

v3: fix undefined behaviour on 32 bit x86 caused by multiple expansion of ptr in the 64 bit case.

arch/x86/include/asm/uaccess.h +21 -2
index a4a30e4..8743552 100644
@@ -333,7 +333,26 @@ do {									\
 } while (0)
 
 #ifdef CONFIG_X86_32
-#define __get_user_asm_u64(x, ptr, retval, errret)	(x) = __get_user_bad()
+#define __get_user_asm_u64(x, ptr, retval, errret)			\
+({									\
+	__typeof__(ptr) __ptr = (ptr);					\
+	asm volatile(ASM_STAC "\n"					\
+		     "1:	movl %2,%%eax\n"			\
+		     "2:	movl %3,%%edx\n"			\
+		     "3: " ASM_CLAC "\n"				\
+		     ".section .fixup,\"ax\"\n"				\
+		     "4:	mov %4,%0\n"				\
+		     "	xorl %%eax,%%eax\n"				\
+		     "	xorl %%edx,%%edx\n"				\
+		     "	jmp 3b\n"					\
+		     ".previous\n"					\
+		     _ASM_EXTABLE(1b, 4b)				\
+		     _ASM_EXTABLE(2b, 4b)				\
+		     : "=r" (retval), "=A"(x)				\
+		     : "m" (__m(__ptr)), "m" __m(((u32 *)(__ptr)) + 1),	\
+		       "i" (errret), "0" (retval));			\
+})
+
 #define __get_user_asm_ex_u64(x, ptr)			(x) = __get_user_bad()
 #else
 #define __get_user_asm_u64(x, ptr, retval, errret) \
@@ -420,7 +439,7 @@ do {									\
 #define __get_user_nocheck(x, ptr, size)				\
 ({									\
 	int __gu_err;							\
-	unsigned long __gu_val;						\
+	__inttype(*(ptr)) __gu_val;					\
 	__uaccess_begin();						\
 	__get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT);	\
 	__uaccess_end();						\
Signature · 1 line
"Thought is the essence of where you are now."
#8 lore raw

Re: [PATCH] x86_32: add support for 64 bit __get_user() v3

Any more comments/feedback on this? Can this be merged for 4.6?

-ben

Quoted 57 lines · Benjamin LaHaise

The existing __get_user() implementation does not support fetching 64 bit values on 32 bit x86. Implement this in a way that does not generate any incorrect warnings as cautioned by Russell King. Test code available at http://www.kvack.org/~bcrl/x86_32-get_user.tar .

v2: use __inttype() as suggested by H. Peter Anvin, which cleans the code up nicely, and fix things to work on x86_64 as well.

v3: fix undefined behaviour on 32 bit x86 caused by multiple expansion of ptr in the 64 bit case.

arch/x86/include/asm/uaccess.h +21 -2
index a4a30e4..8743552 100644
@@ -333,7 +333,26 @@ do {									\
 } while (0)
 
 #ifdef CONFIG_X86_32
-#define __get_user_asm_u64(x, ptr, retval, errret)	(x) = __get_user_bad()
+#define __get_user_asm_u64(x, ptr, retval, errret)			\
+({									\
+	__typeof__(ptr) __ptr = (ptr);					\
+	asm volatile(ASM_STAC "\n"					\
+		     "1:	movl %2,%%eax\n"			\
+		     "2:	movl %3,%%edx\n"			\
+		     "3: " ASM_CLAC "\n"				\
+		     ".section .fixup,\"ax\"\n"				\
+		     "4:	mov %4,%0\n"				\
+		     "	xorl %%eax,%%eax\n"				\
+		     "	xorl %%edx,%%edx\n"				\
+		     "	jmp 3b\n"					\
+		     ".previous\n"					\
+		     _ASM_EXTABLE(1b, 4b)				\
+		     _ASM_EXTABLE(2b, 4b)				\
+		     : "=r" (retval), "=A"(x)				\
+		     : "m" (__m(__ptr)), "m" __m(((u32 *)(__ptr)) + 1),	\
+		       "i" (errret), "0" (retval));			\
+})
+
 #define __get_user_asm_ex_u64(x, ptr)			(x) = __get_user_bad()
 #else
 #define __get_user_asm_u64(x, ptr, retval, errret) \
@@ -420,7 +439,7 @@ do {									\
 #define __get_user_nocheck(x, ptr, size)				\
 ({									\
 	int __gu_err;							\
-	unsigned long __gu_val;						\
+	__inttype(*(ptr)) __gu_val;					\
 	__uaccess_begin();						\
 	__get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT);	\
 	__uaccess_end();						\
Signature · 2 lines
-- 
"Thought is the essence of where you are now."
Signature · 1 line
"Thought is the essence of where you are now."
#9 lore raw

Re: [PATCH] x86_32: add support for 64 bit __get_user() v3

Quoted 1 line · Benjamin LaHaise

Any more comments/feedback on this? Can this be merged for 4.6?

Will get to it once the merge window calms down.

Thanks,

Ingo

#10 lore raw

Re: [PATCH] x86_32: add support for 64 bit __get_user() v2

In reply to Benjamin LaHaise
reproduce:

Hi Benjamin,

[auto build test WARNING on tip/x86/core]
[also build test WARNING on v4.5-rc7 next-20160309]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Benjamin-LaHaise/x86_32-add-support-for-64-bit-__get_user-v2/20160310-033507
config: i386-randconfig-s1-201610 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All warnings (new ones prefixed by >>):

In file included from include/uapi/linux/stddef.h:1:0,
from include/linux/stddef.h:4,
from include/uapi/linux/posix_types.h:4,
from include/uapi/linux/types.h:13,
from include/linux/types.h:5,
from include/linux/thread_info.h:10,
from lib/bitmap.c:9:
lib/bitmap.c: In function '__bitmap_parse':
lib/bitmap.c:377:27: warning: operation on 'ubuf' may be undefined [-Wsequence-point]

        if (__get_user(c, ubuf++))
                              ^
   include/linux/compiler.h:147:28: note: in definition of macro '__trace_if'
     if (__builtin_constant_p((cond)) ? !!(cond) :   \
                               ^
>> lib/bitmap.c:377:5: note: in expansion of macro 'if'
        if (__get_user(c, ubuf++))
        ^
>> arch/x86/include/asm/uaccess.h:351:15: note: in expansion of macro '__m'
           : "m" (__m(ptr)), "m" __m(((u32 *)(ptr)) + 1), \
                  ^
   arch/x86/include/asm/uaccess.h:378:3: note: in expansion of macro '__get_user_asm_u64'
      __get_user_asm_u64(x, ptr, retval, errret);  \
      ^
   arch/x86/include/asm/uaccess.h:443:2: note: in expansion of macro '__get_user_size'
     __get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
     ^
   arch/x86/include/asm/uaccess.h:512:2: note: in expansion of macro '__get_user_nocheck'
     __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
     ^
   lib/bitmap.c:377:9: note: in expansion of macro '__get_user'
        if (__get_user(c, ubuf++))
            ^
   lib/bitmap.c:377:27: warning: operation on 'ubuf' may be undefined [-Wsequence-point]
        if (__get_user(c, ubuf++))
                              ^
   include/linux/compiler.h:147:40: note: in definition of macro '__trace_if'
     if (__builtin_constant_p((cond)) ? !!(cond) :   \
                                           ^
>> lib/bitmap.c:377:5: note: in expansion of macro 'if'
        if (__get_user(c, ubuf++))
        ^
>> arch/x86/include/asm/uaccess.h:351:15: note: in expansion of macro '__m'
           : "m" (__m(ptr)), "m" __m(((u32 *)(ptr)) + 1), \
                  ^
   arch/x86/include/asm/uaccess.h:378:3: note: in expansion of macro '__get_user_asm_u64'
      __get_user_asm_u64(x, ptr, retval, errret);  \
      ^
   arch/x86/include/asm/uaccess.h:443:2: note: in expansion of macro '__get_user_size'
     __get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
     ^
   arch/x86/include/asm/uaccess.h:512:2: note: in expansion of macro '__get_user_nocheck'
     __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
     ^
   lib/bitmap.c:377:9: note: in expansion of macro '__get_user'
        if (__get_user(c, ubuf++))
            ^
   lib/bitmap.c:377:27: warning: operation on 'ubuf' may be undefined [-Wsequence-point]
        if (__get_user(c, ubuf++))
                              ^
   include/linux/compiler.h:158:16: note: in definition of macro '__trace_if'
      ______r = !!(cond);     \
                   ^
>> lib/bitmap.c:377:5: note: in expansion of macro 'if'
        if (__get_user(c, ubuf++))
        ^
>> arch/x86/include/asm/uaccess.h:351:15: note: in expansion of macro '__m'
           : "m" (__m(ptr)), "m" __m(((u32 *)(ptr)) + 1), \
                  ^
   arch/x86/include/asm/uaccess.h:378:3: note: in expansion of macro '__get_user_asm_u64'
      __get_user_asm_u64(x, ptr, retval, errret);  \
      ^
   arch/x86/include/asm/uaccess.h:443:2: note: in expansion of macro '__get_user_size'
     __get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
     ^
   arch/x86/include/asm/uaccess.h:512:2: note: in expansion of macro '__get_user_nocheck'
     __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
     ^
   lib/bitmap.c:377:9: note: in expansion of macro '__get_user'
        if (__get_user(c, ubuf++))
            ^
   lib/bitmap.c: In function '__bitmap_parselist':
   lib/bitmap.c:525:27: warning: operation on 'ubuf' may be undefined [-Wsequence-point]
        if (__get_user(c, ubuf++))
                              ^
   include/linux/compiler.h:147:28: note: in definition of macro '__trace_if'
     if (__builtin_constant_p((cond)) ? !!(cond) :   \
                               ^
   lib/bitmap.c:525:5: note: in expansion of macro 'if'
        if (__get_user(c, ubuf++))
        ^
>> arch/x86/include/asm/uaccess.h:351:15: note: in expansion of macro '__m'
           : "m" (__m(ptr)), "m" __m(((u32 *)(ptr)) + 1), \
                  ^
   arch/x86/include/asm/uaccess.h:378:3: note: in expansion of macro '__get_user_asm_u64'
      __get_user_asm_u64(x, ptr, retval, errret);  \
      ^
   arch/x86/include/asm/uaccess.h:443:2: note: in expansion of macro '__get_user_size'
     __get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
     ^
   arch/x86/include/asm/uaccess.h:512:2: note: in expansion of macro '__get_user_nocheck'
     __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
     ^
   lib/bitmap.c:525:9: note: in expansion of macro '__get_user'
        if (__get_user(c, ubuf++))
            ^
   lib/bitmap.c:525:27: warning: operation on 'ubuf' may be undefined [-Wsequence-point]
        if (__get_user(c, ubuf++))
                              ^
   include/linux/compiler.h:147:40: note: in definition of macro '__trace_if'
     if (__builtin_constant_p((cond)) ? !!(cond) :   \
                                           ^
   lib/bitmap.c:525:5: note: in expansion of macro 'if'
        if (__get_user(c, ubuf++))
        ^
>> arch/x86/include/asm/uaccess.h:351:15: note: in expansion of macro '__m'
           : "m" (__m(ptr)), "m" __m(((u32 *)(ptr)) + 1), \
                  ^
   arch/x86/include/asm/uaccess.h:378:3: note: in expansion of macro '__get_user_asm_u64'
      __get_user_asm_u64(x, ptr, retval, errret);  \
      ^
   arch/x86/include/asm/uaccess.h:443:2: note: in expansion of macro '__get_user_size'
     __get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
     ^
   arch/x86/include/asm/uaccess.h:512:2: note: in expansion of macro '__get_user_nocheck'
     __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
     ^
   lib/bitmap.c:525:9: note: in expansion of macro '__get_user'
        if (__get_user(c, ubuf++))
            ^
   lib/bitmap.c:525:27: warning: operation on 'ubuf' may be undefined [-Wsequence-point]
        if (__get_user(c, ubuf++))
                              ^
   include/linux/compiler.h:158:16: note: in definition of macro '__trace_if'
      ______r = !!(cond);     \
                   ^
   lib/bitmap.c:525:5: note: in expansion of macro 'if'
        if (__get_user(c, ubuf++))
        ^
>> arch/x86/include/asm/uaccess.h:351:15: note: in expansion of macro '__m'
           : "m" (__m(ptr)), "m" __m(((u32 *)(ptr)) + 1), \
                  ^
   arch/x86/include/asm/uaccess.h:378:3: note: in expansion of macro '__get_user_asm_u64'
      __get_user_asm_u64(x, ptr, retval, errret);  \
      ^
   arch/x86/include/asm/uaccess.h:443:2: note: in expansion of macro '__get_user_size'
     __get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
     ^
   arch/x86/include/asm/uaccess.h:512:2: note: in expansion of macro '__get_user_nocheck'
     __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
     ^
   lib/bitmap.c:525:9: note: in expansion of macro '__get_user'
        if (__get_user(c, ubuf++))
            ^

vim +/__m +351 arch/x86/include/asm/uaccess.h

335 #ifdef CONFIG_X86_32
336 #define __get_user_asm_u64(x, ptr, retval, errret) \
337 ({ \
338 asm volatile(ASM_STAC "\n" \

   339			     "1:	movl %2,%%eax\n"			\
   340			     "2:	movl %3,%%edx\n"			\
   341			     "3: " ASM_CLAC "\n"				\
   342			     ".section .fixup,\"ax\"\n"				\
   343			     "4:	mov %4,%0\n"				\
   344			     "	xorl %%eax,%%eax\n"				\
   345			     "	xorl %%edx,%%edx\n"				\
   346			     "	jmp 3b\n"					\
   347			     ".previous\n"					\
   348			     _ASM_EXTABLE(1b, 4b)				\
   349			     _ASM_EXTABLE(2b, 4b)				\
   350			     : "=r" (retval), "=A"(x)				\
 > 351			     : "m" (__m(ptr)), "m" __m(((u32 *)(ptr)) + 1),	\

352 "i" (errret), "0" (retval)); \
353 })
354
355 #define __get_user_asm_ex_u64(x, ptr) (x) = __get_user_bad()
356 #else
357 #define __get_user_asm_u64(x, ptr, retval, errret) \
358 __get_user_asm(x, ptr, retval, "q", "", "=r", errret)
359 #define __get_user_asm_ex_u64(x, ptr) \

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#11 lore raw
In reply to Benjamin LaHaise
reproduce:

Hi Benjamin,

[auto build test ERROR on tip/x86/core]
[also build test ERROR on v4.5-rc7 next-20160309]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Benjamin-LaHaise/x86_32-add-support-for-64-bit-__get_user/20160310-012551
config: x86_64-alldefconfig (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

fs/select.c: Assembler messages:

>> fs/select.c:710: Error: operand type mismatch for `movq'
>> fs/select.c:714: Error: incorrect register `%cx' used with `q' suffix
   fs/select.c:711: Error: operand type mismatch for `movq'
>> fs/select.c:715: Error: incorrect register `%si' used with `q' suffix
--
   fs/aio.c: Assembler messages:
>> fs/aio.c:1606: Error: operand type mismatch for `movq'
>> fs/aio.c:1610: Error: incorrect register `%si' used with `q' suffix

vim +710 fs/select.c

9f72949f David Woodhouse   2006-01-18  704  	size_t sigsetsize = 0;
9f72949f David Woodhouse   2006-01-18  705  	sigset_t __user *up = NULL;
9f72949f David Woodhouse   2006-01-18  706  
9f72949f David Woodhouse   2006-01-18  707  	if (sig) {
9f72949f David Woodhouse   2006-01-18  708  		if (!access_ok(VERIFY_READ, sig, sizeof(void *)+sizeof(size_t))
e110ab94 Al Viro           2006-02-01  709  		    || __get_user(up, (sigset_t __user * __user *)sig)
9f72949f David Woodhouse   2006-01-18 @710  		    || __get_user(sigsetsize,
e110ab94 Al Viro           2006-02-01  711  				(size_t __user *)(sig+sizeof(void *))))
9f72949f David Woodhouse   2006-01-18  712  			return -EFAULT;
9f72949f David Woodhouse   2006-01-18  713  	}
9f72949f David Woodhouse   2006-01-18 @714  
c9da9f21 Heiko Carstens    2009-01-14 @715  	return do_pselect(n, inp, outp, exp, tsp, up, sigsetsize);
9f72949f David Woodhouse   2006-01-18  716  }
9f72949f David Woodhouse   2006-01-18  717  

5d0e5283 Christoph Hellwig 2010-03-10 718 #ifdef __ARCH_WANT_SYS_OLD_SELECT

:::::: The code at line 710 was first introduced by commit
:::::: 9f72949f679df06021c9e43886c9191494fdb007 [PATCH] Add pselect/ppoll system call implementation

:::::: TO: David Woodhouse <[email protected]>
:::::: CC: Linus Torvalds <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#12 lore raw
In reply to Benjamin LaHaise
reproduce:

Hi Benjamin,

[auto build test ERROR on tip/x86/core]
[also build test ERROR on v4.5-rc7 next-20160309]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Benjamin-LaHaise/x86_32-add-support-for-64-bit-__get_user/20160310-012551
config: x86_64-randconfig-s3-03100205 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

kernel/ptrace.c: Assembler messages:
kernel/ptrace.c:1039: Error: operand type mismatch for `movq'

>> kernel/ptrace.c:1043: Error: incorrect register `%cx' used with `q' suffix

kernel/ptrace.c:1040: Error: operand type mismatch for movq' kernel/ptrace.c:1044: Error: incorrect register %cx' used with `q' suffix

vim +1043 kernel/ptrace.c

9fed81dc Namhyung Kim  2010-10-27  1033  		struct iovec __user *uiov = datavp;
2225a122 Suresh Siddha 2010-02-11  1034  
2225a122 Suresh Siddha 2010-02-11  1035  		if (!access_ok(VERIFY_WRITE, uiov, sizeof(*uiov)))
2225a122 Suresh Siddha 2010-02-11  1036  			return -EFAULT;
2225a122 Suresh Siddha 2010-02-11  1037  
2225a122 Suresh Siddha 2010-02-11  1038  		if (__get_user(kiov.iov_base, &uiov->iov_base) ||
2225a122 Suresh Siddha 2010-02-11 @1039  		    __get_user(kiov.iov_len, &uiov->iov_len))
2225a122 Suresh Siddha 2010-02-11  1040  			return -EFAULT;
2225a122 Suresh Siddha 2010-02-11  1041  
2225a122 Suresh Siddha 2010-02-11  1042  		ret = ptrace_regset(child, request, addr, &kiov);
2225a122 Suresh Siddha 2010-02-11 @1043  		if (!ret)
2225a122 Suresh Siddha 2010-02-11  1044  			ret = __put_user(kiov.iov_len, &uiov->iov_len);
2225a122 Suresh Siddha 2010-02-11  1045  		break;
2225a122 Suresh Siddha 2010-02-11  1046  	}

:::::: The code at line 1043 was first introduced by commit
:::::: 2225a122ae26d542bdce523d9d87a4a7ba10e07b ptrace: Add support for generic PTRACE_GETREGSET/PTRACE_SETREGSET

:::::: TO: Suresh Siddha <[email protected]> :::::: CC: H. Peter Anvin <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#13 lore raw
In reply to Benjamin LaHaise
reproduce:

Hi Benjamin,

[auto build test ERROR on tip/x86/core]
[also build test ERROR on v4.5-rc7 next-20160309]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Benjamin-LaHaise/x86_32-add-support-for-64-bit-__get_user/20160310-012551
config: x86_64-randconfig-s0-03100154 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All error/warnings (new ones prefixed by >>):

arch/x86/kernel/ptrace.c: Assembler messages:

>> arch/x86/kernel/ptrace.c:531: Error: operand type mismatch for `movq'
>> arch/x86/kernel/ptrace.c:535: Error: incorrect register `%dx' used with `q' suffix
--
   In file included from include/linux/thread_info.h:11:0,
                    from arch/x86/include/asm/preempt.h:6,
                    from include/linux/preempt.h:59,
                    from include/linux/spinlock.h:50,
                    from include/linux/seqlock.h:35,
                    from include/linux/time.h:5,
                    from include/uapi/linux/timex.h:56,
                    from include/linux/timex.h:56,
                    from include/linux/sched.h:19,
                    from fs/select.c:18:
   fs/select.c: In function 'SyS_pselect6':
>> include/linux/bug.h:33:45: error: unsupported operand size for extended register
    #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
                                                ^
>> include/linux/syscalls.h:108:31: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
    #define __SC_TEST(t, a) (void)BUILD_BUG_ON_ZERO(!__TYPE_IS_LL(t) && sizeof(t) > sizeof(long))
                                  ^
>> include/linux/syscalls.h:93:23: note: in expansion of macro '__SC_TEST'
    #define __MAP1(m,t,a) m(t,a)
                          ^
   include/linux/syscalls.h:94:35: note: in expansion of macro '__MAP1'
    #define __MAP2(m,t,a,...) m(t,a), __MAP1(m,__VA_ARGS__)
                                      ^
   include/linux/syscalls.h:95:35: note: in expansion of macro '__MAP2'
    #define __MAP3(m,t,a,...) m(t,a), __MAP2(m,__VA_ARGS__)
                                      ^
   include/linux/syscalls.h:96:35: note: in expansion of macro '__MAP3'
    #define __MAP4(m,t,a,...) m(t,a), __MAP3(m,__VA_ARGS__)
                                      ^
   include/linux/syscalls.h:97:35: note: in expansion of macro '__MAP4'
    #define __MAP5(m,t,a,...) m(t,a), __MAP4(m,__VA_ARGS__)
                                      ^
>> include/linux/syscalls.h:98:35: note: in expansion of macro '__MAP5'
    #define __MAP6(m,t,a,...) m(t,a), __MAP5(m,__VA_ARGS__)
                                      ^
>> include/linux/syscalls.h:99:22: note: in expansion of macro '__MAP6'
    #define __MAP(n,...) __MAP##n(__VA_ARGS__)
                         ^
   include/linux/syscalls.h:202:3: note: in expansion of macro '__MAP'
      __MAP(x,__SC_TEST,__VA_ARGS__);    \
      ^
   include/linux/syscalls.h:191:2: note: in expansion of macro '__SYSCALL_DEFINEx'
     __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
     ^
   include/linux/syscalls.h:187:36: note: in expansion of macro 'SYSCALL_DEFINEx'
    #define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
                                       ^
>> fs/select.c:700:1: note: in expansion of macro 'SYSCALL_DEFINE6'
    SYSCALL_DEFINE6(pselect6, int, n, fd_set __user *, inp, fd_set __user *, outp,
    ^
>> include/linux/bug.h:33:45: error: unsupported operand size for extended register
    #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
                                                ^
>> include/linux/syscalls.h:108:31: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
    #define __SC_TEST(t, a) (void)BUILD_BUG_ON_ZERO(!__TYPE_IS_LL(t) && sizeof(t) > sizeof(long))
                                  ^
>> include/linux/syscalls.h:93:23: note: in expansion of macro '__SC_TEST'
    #define __MAP1(m,t,a) m(t,a)
                          ^
   include/linux/syscalls.h:94:35: note: in expansion of macro '__MAP1'
    #define __MAP2(m,t,a,...) m(t,a), __MAP1(m,__VA_ARGS__)
                                      ^
   include/linux/syscalls.h:95:35: note: in expansion of macro '__MAP2'
    #define __MAP3(m,t,a,...) m(t,a), __MAP2(m,__VA_ARGS__)
                                      ^
   include/linux/syscalls.h:96:35: note: in expansion of macro '__MAP3'
    #define __MAP4(m,t,a,...) m(t,a), __MAP3(m,__VA_ARGS__)
                                      ^
   include/linux/syscalls.h:97:35: note: in expansion of macro '__MAP4'
    #define __MAP5(m,t,a,...) m(t,a), __MAP4(m,__VA_ARGS__)
                                      ^
>> include/linux/syscalls.h:98:35: note: in expansion of macro '__MAP5'
    #define __MAP6(m,t,a,...) m(t,a), __MAP5(m,__VA_ARGS__)
                                      ^
>> include/linux/syscalls.h:99:22: note: in expansion of macro '__MAP6'
    #define __MAP(n,...) __MAP##n(__VA_ARGS__)
                         ^
   include/linux/syscalls.h:202:3: note: in expansion of macro '__MAP'
      __MAP(x,__SC_TEST,__VA_ARGS__);    \
      ^
   include/linux/syscalls.h:191:2: note: in expansion of macro '__SYSCALL_DEFINEx'
     __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
     ^
   include/linux/syscalls.h:187:36: note: in expansion of macro 'SYSCALL_DEFINEx'
    #define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
                                       ^
>> fs/select.c:700:1: note: in expansion of macro 'SYSCALL_DEFINE6'
    SYSCALL_DEFINE6(pselect6, int, n, fd_set __user *, inp, fd_set __user *, outp,
    ^
>> include/linux/bug.h:33:45: error: unsupported operand size for extended register
    #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
                                                ^
>> include/linux/syscalls.h:108:31: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
    #define __SC_TEST(t, a) (void)BUILD_BUG_ON_ZERO(!__TYPE_IS_LL(t) && sizeof(t) > sizeof(long))
                                  ^
>> include/linux/syscalls.h:93:23: note: in expansion of macro '__SC_TEST'
    #define __MAP1(m,t,a) m(t,a)
                          ^
   include/linux/syscalls.h:94:35: note: in expansion of macro '__MAP1'
    #define __MAP2(m,t,a,...) m(t,a), __MAP1(m,__VA_ARGS__)
                                      ^
   include/linux/syscalls.h:95:35: note: in expansion of macro '__MAP2'
    #define __MAP3(m,t,a,...) m(t,a), __MAP2(m,__VA_ARGS__)
                                      ^
   include/linux/syscalls.h:96:35: note: in expansion of macro '__MAP3'
    #define __MAP4(m,t,a,...) m(t,a), __MAP3(m,__VA_ARGS__)
                                      ^
   include/linux/syscalls.h:97:35: note: in expansion of macro '__MAP4'
    #define __MAP5(m,t,a,...) m(t,a), __MAP4(m,__VA_ARGS__)
                                      ^
>> include/linux/syscalls.h:98:35: note: in expansion of macro '__MAP5'
    #define __MAP6(m,t,a,...) m(t,a), __MAP5(m,__VA_ARGS__)
                                      ^
>> include/linux/syscalls.h:99:22: note: in expansion of macro '__MAP6'
    #define __MAP(n,...) __MAP##n(__VA_ARGS__)
                         ^
   include/linux/syscalls.h:202:3: note: in expansion of macro '__MAP'
      __MAP(x,__SC_TEST,__VA_ARGS__);    \
      ^
   include/linux/syscalls.h:191:2: note: in expansion of macro '__SYSCALL_DEFINEx'
     __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
     ^
   include/linux/syscalls.h:187:36: note: in expansion of macro 'SYSCALL_DEFINEx'
    #define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
                                       ^
>> fs/select.c:700:1: note: in expansion of macro 'SYSCALL_DEFINE6'
    SYSCALL_DEFINE6(pselect6, int, n, fd_set __user *, inp, fd_set __user *, outp,
    ^
>> include/linux/bug.h:33:45: error: unsupported operand size for extended register
    #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
                                                ^
>> include/linux/syscalls.h:108:31: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
    #define __SC_TEST(t, a) (void)BUILD_BUG_ON_ZERO(!__TYPE_IS_LL(t) && sizeof(t) > sizeof(long))
                                  ^
--
   fs/compat.c: In function 'compat_SyS_fcntl64':
>> fs/compat.c:417:1: error: unsupported operand size for extended register
    COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
    ^
>> fs/compat.c:417:1: error: unsupported operand size for extended register
>> fs/compat.c:417:1: error: unsupported operand size for extended register
>> fs/compat.c:417:1: error: unsupported operand size for extended register
>> fs/compat.c:417:1: error: unsupported operand size for extended register
>> fs/compat.c:417:1: error: unsupported operand size for extended register
--
   kernel/ptrace.c: In function 'ptrace_request':
>> kernel/ptrace.c:1058:1: error: unsupported operand size for extended register
    }
    ^
>> kernel/ptrace.c:1058:1: error: unsupported operand size for extended register
>> kernel/ptrace.c:1058:1: error: unsupported operand size for extended register
>> kernel/ptrace.c:1058:1: error: unsupported operand size for extended register
>> kernel/ptrace.c:1058:1: error: unsupported operand size for extended register
>> kernel/ptrace.c:1058:1: error: unsupported operand size for extended register
--
   kernel/signal.c: In function 'do_sigaltstack':
>> kernel/signal.c:3154:1: error: unsupported operand size for extended register
    }
    ^
>> kernel/signal.c:3154:1: error: unsupported operand size for extended register
>> kernel/signal.c:3154:1: error: unsupported operand size for extended register
>> kernel/signal.c:3154:1: error: unsupported operand size for extended register
>> kernel/signal.c:3154:1: error: unsupported operand size for extended register
>> kernel/signal.c:3154:1: error: unsupported operand size for extended register
--
   net/socket.c: In function 'copy_msghdr_from_user':
>> net/socket.c:1873:1: error: unsupported operand size for extended register
    }
    ^
>> net/socket.c:1873:1: error: unsupported operand size for extended register
>> net/socket.c:1873:1: error: unsupported operand size for extended register
>> net/socket.c:1873:1: error: unsupported operand size for extended register
>> net/socket.c:1873:1: error: unsupported operand size for extended register
>> net/socket.c:1873:1: error: unsupported operand size for extended register
>> net/socket.c:1873:1: error: unsupported operand size for extended register
>> net/socket.c:1873:1: error: unsupported operand size for extended register
>> net/socket.c:1873:1: error: unsupported operand size for extended register
>> net/socket.c:1873:1: error: unsupported operand size for extended register
>> net/socket.c:1873:1: error: unsupported operand size for extended register
>> net/socket.c:1873:1: error: unsupported operand size for extended register
>> net/socket.c:1873:1: error: unsupported operand size for extended register
>> net/socket.c:1873:1: error: unsupported operand size for extended register
>> net/socket.c:1873:1: error: unsupported operand size for extended register

vim +531 arch/x86/kernel/ptrace.c

91e7b707 Roland McGrath 2008-01-30  525  		}
91e7b707 Roland McGrath 2008-01-30  526  	} else {
91e7b707 Roland McGrath 2008-01-30  527  		const unsigned long  __user *u = ubuf;
04a1e62c Linus Torvalds 2009-12-17  528  		while (count >= sizeof(*u) && !ret) {
91e7b707 Roland McGrath 2008-01-30  529  			unsigned long word;
91e7b707 Roland McGrath 2008-01-30  530  			ret = __get_user(word, u++);
91e7b707 Roland McGrath 2008-01-30 @531  			if (ret)
91e7b707 Roland McGrath 2008-01-30  532  				break;
91e7b707 Roland McGrath 2008-01-30  533  			ret = putreg(target, pos, word);
91e7b707 Roland McGrath 2008-01-30  534  			count -= sizeof(*u);
91e7b707 Roland McGrath 2008-01-30 @535  			pos += sizeof(*u);
91e7b707 Roland McGrath 2008-01-30  536  		}
91e7b707 Roland McGrath 2008-01-30  537  	}
91e7b707 Roland McGrath 2008-01-30  538  	return ret;

:::::: The code at line 531 was first introduced by commit
:::::: 91e7b707a4776185f91f03bd052aa53af820094e x86: x86 user_regset general regs

:::::: TO: Roland McGrath <[email protected]>
:::::: CC: Ingo Molnar <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation