diff mbox series

[v4,04/45] x86: asm: instrument usercopy in get_user() and __put_user_size()

Message ID 20220701142310.2188015-5-glider@google.com (mailing list archive)
State New
Headers show
Series Add KernelMemorySanitizer infrastructure | expand

Commit Message

Alexander Potapenko July 1, 2022, 2:22 p.m. UTC
Use hooks from instrumented.h to notify bug detection tools about
usercopy events in get_user() and put_user_size().

It's still unclear how to instrument put_user(), which assumes that
instrumentation code doesn't clobber RAX.

Signed-off-by: Alexander Potapenko <glider@google.com>
---
Link: https://linux-review.googlesource.com/id/Ia9f12bfe5832623250e20f1859fdf5cc485a2fce
---
 arch/x86/include/asm/uaccess.h | 7 +++++++
 1 file changed, 7 insertions(+)

Comments

kernel test robot July 2, 2022, 3:47 a.m. UTC | #1
Hi Alexander,

I love your patch! Perhaps something to improve:

[auto build test WARNING on masahiroy-kbuild/for-next]
[also build test WARNING on linus/master v5.19-rc4 next-20220701]
[cannot apply to tip/x86/core tip/x86/mm]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/intel-lab-lkp/linux/commits/Alexander-Potapenko/Add-KernelMemorySanitizer-infrastructure/20220701-222712
base:   https://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git for-next
config: i386-randconfig-s002 (https://download.01.org/0day-ci/archive/20220702/202207021129.palrTLrL-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-3) 11.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.4-39-gce1a6720-dirty
        # https://github.com/intel-lab-lkp/linux/commit/0ca0e4029535365a65588446ba55a952ca186079
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Alexander-Potapenko/Add-KernelMemorySanitizer-infrastructure/20220701-222712
        git checkout 0ca0e4029535365a65588446ba55a952ca186079
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=i386 SHELL=/bin/bash arch/x86/kernel/ mm/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
   arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:360:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void const volatile [noderef] __user *ptr @@     got unsigned long long [usertype] * @@
   arch/x86/kernel/signal.c:360:9: sparse:     expected void const volatile [noderef] __user *ptr
   arch/x86/kernel/signal.c:360:9: sparse:     got unsigned long long [usertype] *
   arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
>> arch/x86/kernel/signal.c:360:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __user *to @@     got unsigned long long [usertype] * @@
   arch/x86/kernel/signal.c:360:9: sparse:     expected void [noderef] __user *to
   arch/x86/kernel/signal.c:360:9: sparse:     got unsigned long long [usertype] *
   arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:420:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void const volatile [noderef] __user *ptr @@     got unsigned long long [usertype] * @@
   arch/x86/kernel/signal.c:420:9: sparse:     expected void const volatile [noderef] __user *ptr
   arch/x86/kernel/signal.c:420:9: sparse:     got unsigned long long [usertype] *
   arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:420:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __user *to @@     got unsigned long long [usertype] * @@
   arch/x86/kernel/signal.c:420:9: sparse:     expected void [noderef] __user *to
   arch/x86/kernel/signal.c:420:9: sparse:     got unsigned long long [usertype] *
   arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
   arch/x86/kernel/signal.c:953:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct lockdep_map const *lock @@     got struct lockdep_map [noderef] __rcu * @@
   arch/x86/kernel/signal.c:953:9: sparse:     expected struct lockdep_map const *lock
   arch/x86/kernel/signal.c:953:9: sparse:     got struct lockdep_map [noderef] __rcu *

vim +360 arch/x86/kernel/signal.c

75779f05264b996 arch/x86/kernel/signal.c    Hiroshi Shimamoto 2009-02-27  325  
7e907f48980d666 arch/x86/kernel/signal_32.c Ingo Molnar       2008-03-06  326  static int
235b80226b986da arch/x86/kernel/signal.c    Al Viro           2012-11-09  327  __setup_frame(int sig, struct ksignal *ksig, sigset_t *set,
7e907f48980d666 arch/x86/kernel/signal_32.c Ingo Molnar       2008-03-06  328  	      struct pt_regs *regs)
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  329  {
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  330  	struct sigframe __user *frame;
7e907f48980d666 arch/x86/kernel/signal_32.c Ingo Molnar       2008-03-06  331  	void __user *restorer;
b00d8f8f0b2b392 arch/x86/kernel/signal.c    Al Viro           2020-02-15  332  	void __user *fp = NULL;
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  333  
b00d8f8f0b2b392 arch/x86/kernel/signal.c    Al Viro           2020-02-15  334  	frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fp);
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  335  
5c1f178094631e8 arch/x86/kernel/signal.c    Al Viro           2020-02-15  336  	if (!user_access_begin(frame, sizeof(*frame)))
3d0aedd9538e6be arch/x86/kernel/signal_32.c Hiroshi Shimamoto 2008-09-12  337  		return -EFAULT;
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  338  
5c1f178094631e8 arch/x86/kernel/signal.c    Al Viro           2020-02-15  339  	unsafe_put_user(sig, &frame->sig, Efault);
b00d8f8f0b2b392 arch/x86/kernel/signal.c    Al Viro           2020-02-15  340  	unsafe_put_sigcontext(&frame->sc, fp, regs, set, Efault);
5c1f178094631e8 arch/x86/kernel/signal.c    Al Viro           2020-02-15  341  	unsafe_put_user(set->sig[1], &frame->extramask[0], Efault);
1a3e4ca41c5a389 arch/x86/kernel/signal_32.c Roland McGrath    2008-04-09  342  	if (current->mm->context.vdso)
6f121e548f83674 arch/x86/kernel/signal.c    Andy Lutomirski   2014-05-05  343  		restorer = current->mm->context.vdso +
0a6d1fa0d2b48fb arch/x86/kernel/signal.c    Andy Lutomirski   2015-10-05  344  			vdso_image_32.sym___kernel_sigreturn;
9fbbd4dd17d0712 arch/i386/kernel/signal.c   Andi Kleen        2007-02-13  345  	else
ade1af77129dea6 arch/x86/kernel/signal_32.c Jan Engelhardt    2008-01-30  346  		restorer = &frame->retcode;
235b80226b986da arch/x86/kernel/signal.c    Al Viro           2012-11-09  347  	if (ksig->ka.sa.sa_flags & SA_RESTORER)
235b80226b986da arch/x86/kernel/signal.c    Al Viro           2012-11-09  348  		restorer = ksig->ka.sa.sa_restorer;
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  349  
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  350  	/* Set up to return from userspace.  */
5c1f178094631e8 arch/x86/kernel/signal.c    Al Viro           2020-02-15  351  	unsafe_put_user(restorer, &frame->pretcode, Efault);
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  352  
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  353  	/*
7e907f48980d666 arch/x86/kernel/signal_32.c Ingo Molnar       2008-03-06  354  	 * This is popl %eax ; movl $__NR_sigreturn, %eax ; int $0x80
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  355  	 *
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  356  	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  357  	 * reasons and because gdb uses it as a signature to notice
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  358  	 * signal handler stack frames.
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  359  	 */
5c1f178094631e8 arch/x86/kernel/signal.c    Al Viro           2020-02-15 @360  	unsafe_put_user(*((u64 *)&retcode), (u64 *)frame->retcode, Efault);
5c1f178094631e8 arch/x86/kernel/signal.c    Al Viro           2020-02-15  361  	user_access_end();
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  362  
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  363  	/* Set up registers for signal handler */
65ea5b034990358 arch/x86/kernel/signal_32.c H. Peter Anvin    2008-01-30  364  	regs->sp = (unsigned long)frame;
235b80226b986da arch/x86/kernel/signal.c    Al Viro           2012-11-09  365  	regs->ip = (unsigned long)ksig->ka.sa.sa_handler;
65ea5b034990358 arch/x86/kernel/signal_32.c H. Peter Anvin    2008-01-30  366  	regs->ax = (unsigned long)sig;
92bc2056855b325 arch/x86/kernel/signal_32.c Harvey Harrison   2008-02-08  367  	regs->dx = 0;
92bc2056855b325 arch/x86/kernel/signal_32.c Harvey Harrison   2008-02-08  368  	regs->cx = 0;
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  369  
65ea5b034990358 arch/x86/kernel/signal_32.c H. Peter Anvin    2008-01-30  370  	regs->ds = __USER_DS;
65ea5b034990358 arch/x86/kernel/signal_32.c H. Peter Anvin    2008-01-30  371  	regs->es = __USER_DS;
65ea5b034990358 arch/x86/kernel/signal_32.c H. Peter Anvin    2008-01-30  372  	regs->ss = __USER_DS;
65ea5b034990358 arch/x86/kernel/signal_32.c H. Peter Anvin    2008-01-30  373  	regs->cs = __USER_CS;
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  374  
283828f3c19ceb3 arch/i386/kernel/signal.c   David Howells     2006-01-18  375  	return 0;
b00d8f8f0b2b392 arch/x86/kernel/signal.c    Al Viro           2020-02-15  376  
b00d8f8f0b2b392 arch/x86/kernel/signal.c    Al Viro           2020-02-15  377  Efault:
b00d8f8f0b2b392 arch/x86/kernel/signal.c    Al Viro           2020-02-15  378  	user_access_end();
b00d8f8f0b2b392 arch/x86/kernel/signal.c    Al Viro           2020-02-15  379  	return -EFAULT;
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  380  }
^1da177e4c3f415 arch/i386/kernel/signal.c   Linus Torvalds    2005-04-16  381
kernel test robot July 2, 2022, 10:45 a.m. UTC | #2
Hi Alexander,

I love your patch! Yet something to improve:

[auto build test ERROR on masahiroy-kbuild/for-next]
[also build test ERROR on linus/master v5.19-rc4 next-20220701]
[cannot apply to tip/x86/core tip/x86/mm]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/intel-lab-lkp/linux/commits/Alexander-Potapenko/Add-KernelMemorySanitizer-infrastructure/20220701-222712
base:   https://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git for-next
config: i386-randconfig-a011 (https://download.01.org/0day-ci/archive/20220702/202207021844.0J4s1Gjz-lkp@intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project a9119143a2d1f4d0d0bc1fe0d819e5351b4e0deb)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/0ca0e4029535365a65588446ba55a952ca186079
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Alexander-Potapenko/Add-KernelMemorySanitizer-infrastructure/20220701-222712
        git checkout 0ca0e4029535365a65588446ba55a952ca186079
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=i386 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> arch/x86/math-emu/reg_ld_str.c:1043:3: error: address of bit-field requested
                   FPU_get_user(instruction_address.selector,
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/x86/math-emu/fpu_system.h:127:36: note: expanded from macro 'FPU_get_user'
   #define FPU_get_user(x,y) do { if (get_user((x),(y))) FPU_abort; } while (0)
                                  ~~~~^~~~~~~~~~~~~~~~~~
   arch/x86/include/asm/uaccess.h:131:43: note: expanded from macro 'get_user'
   #define get_user(x,ptr) ({ might_fault(); do_get_user_call(get_user,x,ptr); })
                                             ^
   arch/x86/include/asm/uaccess.h:103:43: note: expanded from macro 'do_get_user_call'
           instrument_copy_from_user_before((void *)&(x), ptr, sizeof(*(ptr))); \
                                                    ^
   include/linux/compiler.h:56:47: note: expanded from macro 'if'
   #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
                              ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/compiler.h:58:52: note: expanded from macro '__trace_if_var'
   #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
                                                      ^~~~
>> arch/x86/math-emu/reg_ld_str.c:1043:3: error: address of bit-field requested
                   FPU_get_user(instruction_address.selector,
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/x86/math-emu/fpu_system.h:127:36: note: expanded from macro 'FPU_get_user'
   #define FPU_get_user(x,y) do { if (get_user((x),(y))) FPU_abort; } while (0)
                                  ~~~~^~~~~~~~~~~~~~~~~~
   arch/x86/include/asm/uaccess.h:131:43: note: expanded from macro 'get_user'
   #define get_user(x,ptr) ({ might_fault(); do_get_user_call(get_user,x,ptr); })
                                             ^
   arch/x86/include/asm/uaccess.h:109:42: note: expanded from macro 'do_get_user_call'
           instrument_copy_from_user_after((void *)&(x), ptr, sizeof(*(ptr)), 0); \
                                                   ^
   include/linux/compiler.h:56:47: note: expanded from macro 'if'
   #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
                              ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/compiler.h:58:52: note: expanded from macro '__trace_if_var'
   #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
                                                      ^~~~
>> arch/x86/math-emu/reg_ld_str.c:1043:3: error: address of bit-field requested
                   FPU_get_user(instruction_address.selector,
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/x86/math-emu/fpu_system.h:127:36: note: expanded from macro 'FPU_get_user'
   #define FPU_get_user(x,y) do { if (get_user((x),(y))) FPU_abort; } while (0)
                                  ~~~~^~~~~~~~~~~~~~~~~~
   arch/x86/include/asm/uaccess.h:131:43: note: expanded from macro 'get_user'
   #define get_user(x,ptr) ({ might_fault(); do_get_user_call(get_user,x,ptr); })
                                             ^
   arch/x86/include/asm/uaccess.h:103:43: note: expanded from macro 'do_get_user_call'
           instrument_copy_from_user_before((void *)&(x), ptr, sizeof(*(ptr))); \
                                                    ^
   include/linux/compiler.h:56:47: note: expanded from macro 'if'
   #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
                              ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/compiler.h:58:61: note: expanded from macro '__trace_if_var'
   #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
                                                               ^~~~
>> arch/x86/math-emu/reg_ld_str.c:1043:3: error: address of bit-field requested
                   FPU_get_user(instruction_address.selector,
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/x86/math-emu/fpu_system.h:127:36: note: expanded from macro 'FPU_get_user'
   #define FPU_get_user(x,y) do { if (get_user((x),(y))) FPU_abort; } while (0)
                                  ~~~~^~~~~~~~~~~~~~~~~~
   arch/x86/include/asm/uaccess.h:131:43: note: expanded from macro 'get_user'
   #define get_user(x,ptr) ({ might_fault(); do_get_user_call(get_user,x,ptr); })
                                             ^
   arch/x86/include/asm/uaccess.h:109:42: note: expanded from macro 'do_get_user_call'
           instrument_copy_from_user_after((void *)&(x), ptr, sizeof(*(ptr)), 0); \
                                                   ^
   include/linux/compiler.h:56:47: note: expanded from macro 'if'
   #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
                              ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/compiler.h:58:61: note: expanded from macro '__trace_if_var'
   #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
                                                               ^~~~
>> arch/x86/math-emu/reg_ld_str.c:1043:3: error: address of bit-field requested
                   FPU_get_user(instruction_address.selector,
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/x86/math-emu/fpu_system.h:127:36: note: expanded from macro 'FPU_get_user'
   #define FPU_get_user(x,y) do { if (get_user((x),(y))) FPU_abort; } while (0)
                                  ~~~~^~~~~~~~~~~~~~~~~~
   arch/x86/include/asm/uaccess.h:131:43: note: expanded from macro 'get_user'
   #define get_user(x,ptr) ({ might_fault(); do_get_user_call(get_user,x,ptr); })
                                             ^
   arch/x86/include/asm/uaccess.h:103:43: note: expanded from macro 'do_get_user_call'
           instrument_copy_from_user_before((void *)&(x), ptr, sizeof(*(ptr))); \
                                                    ^
   include/linux/compiler.h:56:47: note: expanded from macro 'if'
   #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
                              ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/compiler.h:58:86: note: expanded from macro '__trace_if_var'
   #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
                                                                       ~~~~~~~~~~~~~~~~~^~~~~
   include/linux/compiler.h:69:3: note: expanded from macro '__trace_if_value'
           (cond) ?                                        \
            ^~~~
>> arch/x86/math-emu/reg_ld_str.c:1043:3: error: address of bit-field requested
                   FPU_get_user(instruction_address.selector,
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/x86/math-emu/fpu_system.h:127:36: note: expanded from macro 'FPU_get_user'
   #define FPU_get_user(x,y) do { if (get_user((x),(y))) FPU_abort; } while (0)
                                  ~~~~^~~~~~~~~~~~~~~~~~
   arch/x86/include/asm/uaccess.h:131:43: note: expanded from macro 'get_user'
   #define get_user(x,ptr) ({ might_fault(); do_get_user_call(get_user,x,ptr); })
                                             ^
   arch/x86/include/asm/uaccess.h:109:42: note: expanded from macro 'do_get_user_call'
           instrument_copy_from_user_after((void *)&(x), ptr, sizeof(*(ptr)), 0); \
                                                   ^
   include/linux/compiler.h:56:47: note: expanded from macro 'if'
   #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
                              ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/compiler.h:58:86: note: expanded from macro '__trace_if_var'
   #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
                                                                       ~~~~~~~~~~~~~~~~~^~~~~
   include/linux/compiler.h:69:3: note: expanded from macro '__trace_if_value'
           (cond) ?                                        \
            ^~~~
   arch/x86/math-emu/reg_ld_str.c:1047:3: error: address of bit-field requested
                   FPU_get_user(operand_address.selector,
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/x86/math-emu/fpu_system.h:127:36: note: expanded from macro 'FPU_get_user'
   #define FPU_get_user(x,y) do { if (get_user((x),(y))) FPU_abort; } while (0)
                                  ~~~~^~~~~~~~~~~~~~~~~~
   arch/x86/include/asm/uaccess.h:131:43: note: expanded from macro 'get_user'
   #define get_user(x,ptr) ({ might_fault(); do_get_user_call(get_user,x,ptr); })
                                             ^
   arch/x86/include/asm/uaccess.h:103:43: note: expanded from macro 'do_get_user_call'
           instrument_copy_from_user_before((void *)&(x), ptr, sizeof(*(ptr))); \
                                                    ^
   include/linux/compiler.h:56:47: note: expanded from macro 'if'
   #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
                              ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/compiler.h:58:52: note: expanded from macro '__trace_if_var'
   #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
                                                      ^~~~
   arch/x86/math-emu/reg_ld_str.c:1047:3: error: address of bit-field requested
                   FPU_get_user(operand_address.selector,
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/x86/math-emu/fpu_system.h:127:36: note: expanded from macro 'FPU_get_user'
   #define FPU_get_user(x,y) do { if (get_user((x),(y))) FPU_abort; } while (0)
                                  ~~~~^~~~~~~~~~~~~~~~~~
   arch/x86/include/asm/uaccess.h:131:43: note: expanded from macro 'get_user'
   #define get_user(x,ptr) ({ might_fault(); do_get_user_call(get_user,x,ptr); })
                                             ^
   arch/x86/include/asm/uaccess.h:109:42: note: expanded from macro 'do_get_user_call'
           instrument_copy_from_user_after((void *)&(x), ptr, sizeof(*(ptr)), 0); \
                                                   ^
   include/linux/compiler.h:56:47: note: expanded from macro 'if'
   #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
                              ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/compiler.h:58:52: note: expanded from macro '__trace_if_var'
   #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
                                                      ^~~~
   arch/x86/math-emu/reg_ld_str.c:1047:3: error: address of bit-field requested
                   FPU_get_user(operand_address.selector,
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/x86/math-emu/fpu_system.h:127:36: note: expanded from macro 'FPU_get_user'
   #define FPU_get_user(x,y) do { if (get_user((x),(y))) FPU_abort; } while (0)
                                  ~~~~^~~~~~~~~~~~~~~~~~
   arch/x86/include/asm/uaccess.h:131:43: note: expanded from macro 'get_user'
   #define get_user(x,ptr) ({ might_fault(); do_get_user_call(get_user,x,ptr); })
                                             ^
   arch/x86/include/asm/uaccess.h:103:43: note: expanded from macro 'do_get_user_call'
           instrument_copy_from_user_before((void *)&(x), ptr, sizeof(*(ptr))); \
                                                    ^
   include/linux/compiler.h:56:47: note: expanded from macro 'if'
   #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
                              ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/compiler.h:58:61: note: expanded from macro '__trace_if_var'
   #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
                                                               ^~~~
   arch/x86/math-emu/reg_ld_str.c:1047:3: error: address of bit-field requested
                   FPU_get_user(operand_address.selector,
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/x86/math-emu/fpu_system.h:127:36: note: expanded from macro 'FPU_get_user'
   #define FPU_get_user(x,y) do { if (get_user((x),(y))) FPU_abort; } while (0)
                                  ~~~~^~~~~~~~~~~~~~~~~~
   arch/x86/include/asm/uaccess.h:131:43: note: expanded from macro 'get_user'
   #define get_user(x,ptr) ({ might_fault(); do_get_user_call(get_user,x,ptr); })
                                             ^
   arch/x86/include/asm/uaccess.h:109:42: note: expanded from macro 'do_get_user_call'
           instrument_copy_from_user_after((void *)&(x), ptr, sizeof(*(ptr)), 0); \
                                                   ^
   include/linux/compiler.h:56:47: note: expanded from macro 'if'
   #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
                              ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/compiler.h:58:61: note: expanded from macro '__trace_if_var'
   #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
                                                               ^~~~
   arch/x86/math-emu/reg_ld_str.c:1047:3: error: address of bit-field requested
                   FPU_get_user(operand_address.selector,
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/x86/math-emu/fpu_system.h:127:36: note: expanded from macro 'FPU_get_user'
   #define FPU_get_user(x,y) do { if (get_user((x),(y))) FPU_abort; } while (0)
                                  ~~~~^~~~~~~~~~~~~~~~~~
   arch/x86/include/asm/uaccess.h:131:43: note: expanded from macro 'get_user'
   #define get_user(x,ptr) ({ might_fault(); do_get_user_call(get_user,x,ptr); })


vim +1043 arch/x86/math-emu/reg_ld_str.c

^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1026  
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1027  u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user *s)
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1028  {
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1029  	unsigned short tag_word = 0;
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1030  	u_char tag;
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1031  	int i;
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1032  
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1033  	if ((addr_modes.default_mode == VM86) ||
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1034  	    ((addr_modes.default_mode == PM16)
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1035  	     ^ (addr_modes.override.operand_size == OP_SIZE_PREFIX))) {
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1036  		RE_ENTRANT_CHECK_OFF;
96d4f267e40f950 arch/x86/math-emu/reg_ld_str.c  Linus Torvalds 2019-01-03  1037  		FPU_access_ok(s, 0x0e);
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1038  		FPU_get_user(control_word, (unsigned short __user *)s);
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1039  		FPU_get_user(partial_status, (unsigned short __user *)(s + 2));
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1040  		FPU_get_user(tag_word, (unsigned short __user *)(s + 4));
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1041  		FPU_get_user(instruction_address.offset,
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1042  			     (unsigned short __user *)(s + 6));
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30 @1043  		FPU_get_user(instruction_address.selector,
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1044  			     (unsigned short __user *)(s + 8));
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1045  		FPU_get_user(operand_address.offset,
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1046  			     (unsigned short __user *)(s + 0x0a));
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1047  		FPU_get_user(operand_address.selector,
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1048  			     (unsigned short __user *)(s + 0x0c));
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1049  		RE_ENTRANT_CHECK_ON;
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1050  		s += 0x0e;
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1051  		if (addr_modes.default_mode == VM86) {
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1052  			instruction_address.offset
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1053  			    += (instruction_address.selector & 0xf000) << 4;
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1054  			operand_address.offset +=
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1055  			    (operand_address.selector & 0xf000) << 4;
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1056  		}
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1057  	} else {
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1058  		RE_ENTRANT_CHECK_OFF;
96d4f267e40f950 arch/x86/math-emu/reg_ld_str.c  Linus Torvalds 2019-01-03  1059  		FPU_access_ok(s, 0x1c);
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1060  		FPU_get_user(control_word, (unsigned short __user *)s);
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1061  		FPU_get_user(partial_status, (unsigned short __user *)(s + 4));
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1062  		FPU_get_user(tag_word, (unsigned short __user *)(s + 8));
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1063  		FPU_get_user(instruction_address.offset,
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1064  			     (unsigned long __user *)(s + 0x0c));
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1065  		FPU_get_user(instruction_address.selector,
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1066  			     (unsigned short __user *)(s + 0x10));
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1067  		FPU_get_user(instruction_address.opcode,
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1068  			     (unsigned short __user *)(s + 0x12));
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1069  		FPU_get_user(operand_address.offset,
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1070  			     (unsigned long __user *)(s + 0x14));
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1071  		FPU_get_user(operand_address.selector,
3d0d14f983b55a5 arch/x86/math-emu/reg_ld_str.c  Ingo Molnar    2008-01-30  1072  			     (unsigned long __user *)(s + 0x18));
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1073  		RE_ENTRANT_CHECK_ON;
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1074  		s += 0x1c;
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1075  	}
^1da177e4c3f415 arch/i386/math-emu/reg_ld_str.c Linus Torvalds 2005-04-16  1076
kernel test robot July 2, 2022, 1:09 p.m. UTC | #3
Hi Alexander,

I love your patch! Perhaps something to improve:

[auto build test WARNING on masahiroy-kbuild/for-next]
[also build test WARNING on linus/master v5.19-rc4 next-20220701]
[cannot apply to tip/x86/core tip/x86/mm]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/intel-lab-lkp/linux/commits/Alexander-Potapenko/Add-KernelMemorySanitizer-infrastructure/20220701-222712
base:   https://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git for-next
config: i386-randconfig-s002
compiler: gcc-11 (Debian 11.3.0-3) 11.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.4-39-gce1a6720-dirty
        # https://github.com/intel-lab-lkp/linux/commit/0ca0e4029535365a65588446ba55a952ca186079
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Alexander-Potapenko/Add-KernelMemorySanitizer-infrastructure/20220701-222712
        git checkout 0ca0e4029535365a65588446ba55a952ca186079
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=i386 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
   kernel/signal.c: note: in included file (through arch/x86/include/uapi/asm/signal.h, arch/x86/include/asm/signal.h, include/uapi/linux/signal.h, ...):
   include/uapi/asm-generic/signal-defs.h:83:29: sparse: sparse: multiple address spaces given
   kernel/signal.c:195:31: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:195:31: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:195:31: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:198:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:198:33: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:198:33: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:480:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:480:9: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:480:9: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:484:34: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:484:34: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:484:34: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:517:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:517:9: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:517:9: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:520:36: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:520:36: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:520:36: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:542:53: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected struct k_sigaction *ka @@     got struct k_sigaction [noderef] __rcu * @@
   kernel/signal.c:542:53: sparse:     expected struct k_sigaction *ka
   kernel/signal.c:542:53: sparse:     got struct k_sigaction [noderef] __rcu *
   include/uapi/asm-generic/signal-defs.h:83:29: sparse: sparse: multiple address spaces given
   kernel/signal.c:698:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:698:33: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:698:33: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:700:31: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:700:31: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:700:31: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:765:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct lockdep_map const *lock @@     got struct lockdep_map [noderef] __rcu * @@
   kernel/signal.c:765:9: sparse:     expected struct lockdep_map const *lock
   kernel/signal.c:765:9: sparse:     got struct lockdep_map [noderef] __rcu *
   kernel/signal.c:890:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct lockdep_map const *lock @@     got struct lockdep_map [noderef] __rcu * @@
   kernel/signal.c:890:9: sparse:     expected struct lockdep_map const *lock
   kernel/signal.c:890:9: sparse:     got struct lockdep_map [noderef] __rcu *
   kernel/signal.c:1086:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct lockdep_map const *lock @@     got struct lockdep_map [noderef] __rcu * @@
   kernel/signal.c:1086:9: sparse:     expected struct lockdep_map const *lock
   kernel/signal.c:1086:9: sparse:     got struct lockdep_map [noderef] __rcu *
   kernel/signal.c:1267:29: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void const volatile [noderef] __user *ptr @@     got unsigned char * @@
   kernel/signal.c:1267:29: sparse:     expected void const volatile [noderef] __user *ptr
   kernel/signal.c:1267:29: sparse:     got unsigned char *
>> kernel/signal.c:1267:29: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void const [noderef] __user *from @@     got unsigned char * @@
   kernel/signal.c:1267:29: sparse:     expected void const [noderef] __user *from
   kernel/signal.c:1267:29: sparse:     got unsigned char *
>> kernel/signal.c:1267:29: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void const [noderef] __user *from @@     got unsigned char * @@
   kernel/signal.c:1267:29: sparse:     expected void const [noderef] __user *from
   kernel/signal.c:1267:29: sparse:     got unsigned char *
   kernel/signal.c:1328:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:1328:9: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:1328:9: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:1329:16: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct k_sigaction *action @@     got struct k_sigaction [noderef] __rcu * @@
   kernel/signal.c:1329:16: sparse:     expected struct k_sigaction *action
   kernel/signal.c:1329:16: sparse:     got struct k_sigaction [noderef] __rcu *
   kernel/signal.c:1349:34: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:1349:34: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:1349:34: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:1938:36: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:1938:36: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:1938:36: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:2048:44: sparse: sparse: cast removes address space '__rcu' of expression
   kernel/signal.c:2067:65: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct task_struct *tsk @@     got struct task_struct [noderef] __rcu *parent @@
   kernel/signal.c:2067:65: sparse:     expected struct task_struct *tsk
   kernel/signal.c:2067:65: sparse:     got struct task_struct [noderef] __rcu *parent
   kernel/signal.c:2068:40: sparse: sparse: cast removes address space '__rcu' of expression
   kernel/signal.c:2086:14: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct sighand_struct *psig @@     got struct sighand_struct [noderef] __rcu *[noderef] __rcu sighand @@
   kernel/signal.c:2086:14: sparse:     expected struct sighand_struct *psig
   kernel/signal.c:2086:14: sparse:     got struct sighand_struct [noderef] __rcu *[noderef] __rcu sighand
   kernel/signal.c:2115:53: sparse: sparse: incorrect type in argument 3 (different address spaces) @@     expected struct task_struct *t @@     got struct task_struct [noderef] __rcu *parent @@
   kernel/signal.c:2115:53: sparse:     expected struct task_struct *t
   kernel/signal.c:2115:53: sparse:     got struct task_struct [noderef] __rcu *parent
   kernel/signal.c:2116:34: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected struct task_struct *parent @@     got struct task_struct [noderef] __rcu *parent @@
   kernel/signal.c:2116:34: sparse:     expected struct task_struct *parent
   kernel/signal.c:2116:34: sparse:     got struct task_struct [noderef] __rcu *parent
   kernel/signal.c:2145:24: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct task_struct *parent @@     got struct task_struct [noderef] __rcu *parent @@
   kernel/signal.c:2145:24: sparse:     expected struct task_struct *parent
   kernel/signal.c:2145:24: sparse:     got struct task_struct [noderef] __rcu *parent
   kernel/signal.c:2148:24: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct task_struct *parent @@     got struct task_struct [noderef] __rcu *real_parent @@
   kernel/signal.c:2148:24: sparse:     expected struct task_struct *parent
   kernel/signal.c:2148:24: sparse:     got struct task_struct [noderef] __rcu *real_parent
   kernel/signal.c:2181:17: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct sighand_struct *sighand @@     got struct sighand_struct [noderef] __rcu *sighand @@
   kernel/signal.c:2181:17: sparse:     expected struct sighand_struct *sighand
   kernel/signal.c:2181:17: sparse:     got struct sighand_struct [noderef] __rcu *sighand
   kernel/signal.c:2221:41: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:2221:41: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:2221:41: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:2223:39: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:2223:39: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:2223:39: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:2280:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:2280:33: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:2280:33: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:2315:31: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:2315:31: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:2315:31: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:2355:31: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:2355:31: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:2355:31: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:2357:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:2357:33: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:2357:33: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:2457:41: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:2457:41: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:2457:41: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:2541:41: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:2541:41: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:2541:41: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:2553:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:2553:33: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:2553:33: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:2588:52: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct task_struct *tsk @@     got struct task_struct [noderef] __rcu *parent @@
   kernel/signal.c:2588:52: sparse:     expected struct task_struct *tsk
   kernel/signal.c:2588:52: sparse:     got struct task_struct [noderef] __rcu *parent
   kernel/signal.c:2590:49: sparse: sparse: cast removes address space '__rcu' of expression
   kernel/signal.c:2628:49: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected struct sighand_struct *sighand @@     got struct sighand_struct [noderef] __rcu *sighand @@
   kernel/signal.c:2628:49: sparse:     expected struct sighand_struct *sighand
   kernel/signal.c:2628:49: sparse:     got struct sighand_struct [noderef] __rcu *sighand
   kernel/signal.c:2957:27: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:2957:27: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:2957:27: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:2977:29: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:2977:29: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:2977:29: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:3044:27: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:3044:27: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:3044:27: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:3046:29: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:3046:29: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:3046:29: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:3197:31: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:3197:31: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:3197:31: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:3200:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:3200:33: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:3200:33: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:3589:27: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:3589:27: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:3589:27: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:3601:37: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:3601:37: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:3601:37: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:3606:35: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:3606:35: sparse:     expected struct spinlock [usertype] *lock
   kernel/signal.c:3606:35: sparse:     got struct spinlock [noderef] __rcu *
   kernel/signal.c:3611:29: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/signal.c:3611:29: sparse:     expected struct spinlock [usertype] *lock

vim +1267 kernel/signal.c

7978b567d31555 Sukadev Bhattiprolu 2009-04-02  1254  
4aaefee589f97b Al Viro             2012-11-05  1255  static void print_fatal_signal(int signr)
45807a1df9f51d Ingo Molnar         2007-07-15  1256  {
4aaefee589f97b Al Viro             2012-11-05  1257  	struct pt_regs *regs = signal_pt_regs();
747800efbe8b98 Wang Xiaoqiang      2016-05-23  1258  	pr_info("potentially unexpected fatal signal %d.\n", signr);
45807a1df9f51d Ingo Molnar         2007-07-15  1259  
ca5cd877ae699e Al Viro             2007-10-29  1260  #if defined(__i386__) && !defined(__arch_um__)
747800efbe8b98 Wang Xiaoqiang      2016-05-23  1261  	pr_info("code at %08lx: ", regs->ip);
45807a1df9f51d Ingo Molnar         2007-07-15  1262  	{
45807a1df9f51d Ingo Molnar         2007-07-15  1263  		int i;
45807a1df9f51d Ingo Molnar         2007-07-15  1264  		for (i = 0; i < 16; i++) {
45807a1df9f51d Ingo Molnar         2007-07-15  1265  			unsigned char insn;
45807a1df9f51d Ingo Molnar         2007-07-15  1266  
b45c6e76bc2c72 Andi Kleen          2010-01-08 @1267  			if (get_user(insn, (unsigned char *)(regs->ip + i)))
b45c6e76bc2c72 Andi Kleen          2010-01-08  1268  				break;
747800efbe8b98 Wang Xiaoqiang      2016-05-23  1269  			pr_cont("%02x ", insn);
45807a1df9f51d Ingo Molnar         2007-07-15  1270  		}
45807a1df9f51d Ingo Molnar         2007-07-15  1271  	}
747800efbe8b98 Wang Xiaoqiang      2016-05-23  1272  	pr_cont("\n");
45807a1df9f51d Ingo Molnar         2007-07-15  1273  #endif
3a9f84d354ce1e Ed Swierk           2009-01-26  1274  	preempt_disable();
45807a1df9f51d Ingo Molnar         2007-07-15  1275  	show_regs(regs);
3a9f84d354ce1e Ed Swierk           2009-01-26  1276  	preempt_enable();
45807a1df9f51d Ingo Molnar         2007-07-15  1277  }
45807a1df9f51d Ingo Molnar         2007-07-15  1278
Marco Elver July 7, 2022, 10:13 a.m. UTC | #4
On Fri, 1 Jul 2022 at 16:23, Alexander Potapenko <glider@google.com> wrote:
>
> Use hooks from instrumented.h to notify bug detection tools about
> usercopy events in get_user() and put_user_size().
>
> It's still unclear how to instrument put_user(), which assumes that
> instrumentation code doesn't clobber RAX.

do_put_user_call() has a comment about KASAN clobbering %ax, doesn't
this also apply to KMSAN? If not, could we have a <asm/instrumented.h>
that provides helpers to push registers on the stack and pop them back
on return?

Also it seems the test robot complained about this patch.

> Signed-off-by: Alexander Potapenko <glider@google.com>
> ---
> Link: https://linux-review.googlesource.com/id/Ia9f12bfe5832623250e20f1859fdf5cc485a2fce
> ---
>  arch/x86/include/asm/uaccess.h | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
> index 913e593a3b45f..1a8b5a234474f 100644
> --- a/arch/x86/include/asm/uaccess.h
> +++ b/arch/x86/include/asm/uaccess.h
> @@ -5,6 +5,7 @@
>   * User space memory access functions
>   */
>  #include <linux/compiler.h>
> +#include <linux/instrumented.h>
>  #include <linux/kasan-checks.h>
>  #include <linux/string.h>
>  #include <asm/asm.h>
> @@ -99,11 +100,13 @@ extern int __get_user_bad(void);
>         int __ret_gu;                                                   \
>         register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX);            \
>         __chk_user_ptr(ptr);                                            \
> +       instrument_copy_from_user_before((void *)&(x), ptr, sizeof(*(ptr))); \
>         asm volatile("call __" #fn "_%P4"                               \
>                      : "=a" (__ret_gu), "=r" (__val_gu),                \
>                         ASM_CALL_CONSTRAINT                             \
>                      : "0" (ptr), "i" (sizeof(*(ptr))));                \
>         (x) = (__force __typeof__(*(ptr))) __val_gu;                    \
> +       instrument_copy_from_user_after((void *)&(x), ptr, sizeof(*(ptr)), 0); \
>         __builtin_expect(__ret_gu, 0);                                  \
>  })
>
> @@ -248,7 +251,9 @@ extern void __put_user_nocheck_8(void);
>
>  #define __put_user_size(x, ptr, size, label)                           \
>  do {                                                                   \
> +       __typeof__(*(ptr)) __pus_val = x;                               \
>         __chk_user_ptr(ptr);                                            \
> +       instrument_copy_to_user(ptr, &(__pus_val), size);               \
>         switch (size) {                                                 \
>         case 1:                                                         \
>                 __put_user_goto(x, ptr, "b", "iq", label);              \
> @@ -286,6 +291,7 @@ do {                                                                        \
>  #define __get_user_size(x, ptr, size, label)                           \
>  do {                                                                   \
>         __chk_user_ptr(ptr);                                            \
> +       instrument_copy_from_user_before((void *)&(x), ptr, size);      \
>         switch (size) {                                                 \
>         case 1: {                                                       \
>                 unsigned char x_u8__;                                   \
> @@ -305,6 +311,7 @@ do {                                                                        \
>         default:                                                        \
>                 (x) = __get_user_bad();                                 \
>         }                                                               \
> +       instrument_copy_from_user_after((void *)&(x), ptr, size, 0);    \
>  } while (0)
>
>  #define __get_user_asm(x, addr, itype, ltype, label)                   \
> --
> 2.37.0.rc0.161.g10f37bed90-goog
>
Alexander Potapenko July 15, 2022, 2:03 p.m. UTC | #5
On Sat, Jul 2, 2022 at 5:47 AM kernel test robot <lkp@intel.com> wrote:
>
> Hi Alexander,
>
> I love your patch! Perhaps something to improve:
>
> [auto build test WARNING on masahiroy-kbuild/for-next]
> [also build test WARNING on linus/master v5.19-rc4 next-20220701]
> [cannot apply to tip/x86/core tip/x86/mm]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch]
>
> url:    https://github.com/intel-lab-lkp/linux/commits/Alexander-Potapenko/Add-KernelMemorySanitizer-infrastructure/20220701-222712
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git for-next
> config: i386-randconfig-s002 (https://download.01.org/0day-ci/archive/20220702/202207021129.palrTLrL-lkp@intel.com/config)
> compiler: gcc-11 (Debian 11.3.0-3) 11.3.0
> reproduce:
>         # apt-get install sparse
>         # sparse version: v0.6.4-39-gce1a6720-dirty
>         # https://github.com/intel-lab-lkp/linux/commit/0ca0e4029535365a65588446ba55a952ca186079
>         git remote add linux-review https://github.com/intel-lab-lkp/linux
>         git fetch --no-tags linux-review Alexander-Potapenko/Add-KernelMemorySanitizer-infrastructure/20220701-222712
>         git checkout 0ca0e4029535365a65588446ba55a952ca186079
>         # save the config file
>         mkdir build_dir && cp config build_dir/.config
>         make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=i386 SHELL=/bin/bash arch/x86/kernel/ mm/
>
> If you fix the issue, kindly add following tag where applicable
> Reported-by: kernel test robot <lkp@intel.com>
>
>
> sparse warnings: (new ones prefixed by >>)
>    arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:360:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void const volatile [noderef] __user *ptr @@     got unsigned long long [usertype] * @@
>    arch/x86/kernel/signal.c:360:9: sparse:     expected void const volatile [noderef] __user *ptr
>    arch/x86/kernel/signal.c:360:9: sparse:     got unsigned long long [usertype] *
>    arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
> >> arch/x86/kernel/signal.c:360:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __user *to @@     got unsigned long long [usertype] * @@
>    arch/x86/kernel/signal.c:360:9: sparse:     expected void [noderef] __user *to
>    arch/x86/kernel/signal.c:360:9: sparse:     got unsigned long long [usertype] *
>    arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:360:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:420:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void const volatile [noderef] __user *ptr @@     got unsigned long long [usertype] * @@
>    arch/x86/kernel/signal.c:420:9: sparse:     expected void const volatile [noderef] __user *ptr
>    arch/x86/kernel/signal.c:420:9: sparse:     got unsigned long long [usertype] *
>    arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:420:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __user *to @@     got unsigned long long [usertype] * @@
>    arch/x86/kernel/signal.c:420:9: sparse:     expected void [noderef] __user *to
>    arch/x86/kernel/signal.c:420:9: sparse:     got unsigned long long [usertype] *
>    arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:420:9: sparse: sparse: cast removes address space '__user' of expression
>    arch/x86/kernel/signal.c:953:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct lockdep_map const *lock @@     got struct lockdep_map [noderef] __rcu * @@
>    arch/x86/kernel/signal.c:953:9: sparse:     expected struct lockdep_map const *lock
>    arch/x86/kernel/signal.c:953:9: sparse:     got struct lockdep_map [noderef] __rcu *

Looks like sparse is complaining about the missing __user attribute in the cast:
============================================
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 9c7265b524c73..437de52e2ecaa 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -357,7 +357,7 @@ __setup_frame(int sig, struct ksignal *ksig, sigset_t *set,
         * reasons and because gdb uses it as a signature to notice
         * signal handler stack frames.
         */
-       unsafe_put_user(*((u64 *)&retcode), (u64 *)frame->retcode, Efault);
+       unsafe_put_user(*((u64 *)&retcode), (__user u64
*)frame->retcode, Efault);
        user_access_end();

        /* Set up registers for signal handler */
============================================

The only reason it blames KMSAN patches is because those add yet
another hook inside unsafe_put_user() that expects a __user pointer.
Alexander Potapenko July 15, 2022, 4:44 p.m. UTC | #6
On Sat, Jul 2, 2022 at 12:46 PM kernel test robot <lkp@intel.com> wrote:
>
> Hi Alexander,
>
> I love your patch! Yet something to improve:
>
> [auto build test ERROR on masahiroy-kbuild/for-next]
> [also build test ERROR on linus/master v5.19-rc4 next-20220701]
> [cannot apply to tip/x86/core tip/x86/mm]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch]
>
> url:    https://github.com/intel-lab-lkp/linux/commits/Alexander-Potapenko/Add-KernelMemorySanitizer-infrastructure/20220701-222712
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git for-next
> config: i386-randconfig-a011 (https://download.01.org/0day-ci/archive/20220702/202207021844.0J4s1Gjz-lkp@intel.com/config)
> compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project a9119143a2d1f4d0d0bc1fe0d819e5351b4e0deb)
> reproduce (this is a W=1 build):
>         wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # https://github.com/intel-lab-lkp/linux/commit/0ca0e4029535365a65588446ba55a952ca186079
>         git remote add linux-review https://github.com/intel-lab-lkp/linux
>         git fetch --no-tags linux-review Alexander-Potapenko/Add-KernelMemorySanitizer-infrastructure/20220701-222712
>         git checkout 0ca0e4029535365a65588446ba55a952ca186079
>         # save the config file
>         mkdir build_dir && cp config build_dir/.config
>         COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=i386 SHELL=/bin/bash
>
> If you fix the issue, kindly add following tag where applicable
> Reported-by: kernel test robot <lkp@intel.com>

Uh oh, this is a very good catch.

> All errors (new ones prefixed by >>):
>
> >> arch/x86/math-emu/reg_ld_str.c:1043:3: error: address of bit-field requested
>                    FPU_get_user(instruction_address.selector,
>                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>    arch/x86/math-emu/fpu_system.h:127:36: note: expanded from macro 'FPU_get_user'
>    #define FPU_get_user(x,y) do { if (get_user((x),(y))) FPU_abort; } while (0)
>                                   ~~~~^~~~~~~~~~~~~~~~~~
>    arch/x86/include/asm/uaccess.h:131:43: note: expanded from macro 'get_user'
>    #define get_user(x,ptr) ({ might_fault(); do_get_user_call(get_user,x,ptr); })
>                                              ^
>    arch/x86/include/asm/uaccess.h:103:43: note: expanded from macro 'do_get_user_call'
>            instrument_copy_from_user_before((void *)&(x), ptr, sizeof(*(ptr))); \
>                                                     ^
>    include/linux/compiler.h:56:47: note: expanded from macro 'if'
>    #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
>                               ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
>    include/linux/compiler.h:58:52: note: expanded from macro '__trace_if_var'
>    #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
>                                                       ^~~~
> >> arch/x86/math-emu/reg_ld_str.c:1043:3: error: address of bit-field requested
>                    FPU_get_user(instruction_address.selector,
>                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Actually `x` in get_user(x, ptr) and put_user(x, ptr) is not
guaranteed to be addressable (e.g. in this case it is a bitfield).
We can copy the values to a local var, like it's done in __put_user_size:

254         __typeof__(*(ptr)) __pus_val = x;                               \
255         __chk_user_ptr(ptr);                                            \
256         instrument_copy_to_user(ptr, &(__pus_val), size);               \

, but this won't help KASAN or KCSAN detect the bugs accessing x.
Perhaps a better solution would be to declare instrument_get_user()
and instrument_put_user(), which will unpoison/check the values for
KMSAN and do nothing for other tools.
Alexander Potapenko Aug. 7, 2022, 5:33 p.m. UTC | #7
On Thu, Jul 7, 2022 at 12:13 PM Marco Elver <elver@google.com> wrote:
>
> On Fri, 1 Jul 2022 at 16:23, Alexander Potapenko <glider@google.com> wrote:
> >
> > Use hooks from instrumented.h to notify bug detection tools about
> > usercopy events in get_user() and put_user_size().
> >
> > It's still unclear how to instrument put_user(), which assumes that
> > instrumentation code doesn't clobber RAX.
>
> do_put_user_call() has a comment about KASAN clobbering %ax, doesn't
> this also apply to KMSAN? If not, could we have a <asm/instrumented.h>
> that provides helpers to push registers on the stack and pop them back
> on return?

In fact, yes, it is rather simple to not clobber %ax.
A more important aspect of instrumenting get_user()/put_user() is to
always evaluate `x` and `ptr` only once, because sometimes these
macros get called like `put_user(v, sp++)`.
I might have confused the effects of evaluating sp++ twice with some
register clobbering.

> Also it seems the test robot complained about this patch.
Will fix in v5.
>
> > Signed-off-by: Alexander Potapenko <glider@google.com>
> > ---
> > Link: https://linux-review.googlesource.com/id/Ia9f12bfe5832623250e20f1859fdf5cc485a2fce
> > ---
> >  arch/x86/include/asm/uaccess.h | 7 +++++++
> >  1 file changed, 7 insertions(+)
> >
> > diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
> > index 913e593a3b45f..1a8b5a234474f 100644
> > --- a/arch/x86/include/asm/uaccess.h
> > +++ b/arch/x86/include/asm/uaccess.h
> > @@ -5,6 +5,7 @@
> >   * User space memory access functions
> >   */
> >  #include <linux/compiler.h>
> > +#include <linux/instrumented.h>
> >  #include <linux/kasan-checks.h>
> >  #include <linux/string.h>
> >  #include <asm/asm.h>
> > @@ -99,11 +100,13 @@ extern int __get_user_bad(void);
> >         int __ret_gu;                                                   \
> >         register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX);            \
> >         __chk_user_ptr(ptr);                                            \
> > +       instrument_copy_from_user_before((void *)&(x), ptr, sizeof(*(ptr))); \
> >         asm volatile("call __" #fn "_%P4"                               \
> >                      : "=a" (__ret_gu), "=r" (__val_gu),                \
> >                         ASM_CALL_CONSTRAINT                             \
> >                      : "0" (ptr), "i" (sizeof(*(ptr))));                \
> >         (x) = (__force __typeof__(*(ptr))) __val_gu;                    \
> > +       instrument_copy_from_user_after((void *)&(x), ptr, sizeof(*(ptr)), 0); \
> >         __builtin_expect(__ret_gu, 0);                                  \
> >  })
> >
> > @@ -248,7 +251,9 @@ extern void __put_user_nocheck_8(void);
> >
> >  #define __put_user_size(x, ptr, size, label)                           \
> >  do {                                                                   \
> > +       __typeof__(*(ptr)) __pus_val = x;                               \
> >         __chk_user_ptr(ptr);                                            \
> > +       instrument_copy_to_user(ptr, &(__pus_val), size);               \
> >         switch (size) {                                                 \
> >         case 1:                                                         \
> >                 __put_user_goto(x, ptr, "b", "iq", label);              \
> > @@ -286,6 +291,7 @@ do {                                                                        \
> >  #define __get_user_size(x, ptr, size, label)                           \
> >  do {                                                                   \
> >         __chk_user_ptr(ptr);                                            \
> > +       instrument_copy_from_user_before((void *)&(x), ptr, size);      \
> >         switch (size) {                                                 \
> >         case 1: {                                                       \
> >                 unsigned char x_u8__;                                   \
> > @@ -305,6 +311,7 @@ do {                                                                        \
> >         default:                                                        \
> >                 (x) = __get_user_bad();                                 \
> >         }                                                               \
> > +       instrument_copy_from_user_after((void *)&(x), ptr, size, 0);    \
> >  } while (0)
> >
> >  #define __get_user_asm(x, addr, itype, ltype, label)                   \
> > --
> > 2.37.0.rc0.161.g10f37bed90-goog
> >
diff mbox series

Patch

diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 913e593a3b45f..1a8b5a234474f 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -5,6 +5,7 @@ 
  * User space memory access functions
  */
 #include <linux/compiler.h>
+#include <linux/instrumented.h>
 #include <linux/kasan-checks.h>
 #include <linux/string.h>
 #include <asm/asm.h>
@@ -99,11 +100,13 @@  extern int __get_user_bad(void);
 	int __ret_gu;							\
 	register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX);		\
 	__chk_user_ptr(ptr);						\
+	instrument_copy_from_user_before((void *)&(x), ptr, sizeof(*(ptr))); \
 	asm volatile("call __" #fn "_%P4"				\
 		     : "=a" (__ret_gu), "=r" (__val_gu),		\
 			ASM_CALL_CONSTRAINT				\
 		     : "0" (ptr), "i" (sizeof(*(ptr))));		\
 	(x) = (__force __typeof__(*(ptr))) __val_gu;			\
+	instrument_copy_from_user_after((void *)&(x), ptr, sizeof(*(ptr)), 0); \
 	__builtin_expect(__ret_gu, 0);					\
 })
 
@@ -248,7 +251,9 @@  extern void __put_user_nocheck_8(void);
 
 #define __put_user_size(x, ptr, size, label)				\
 do {									\
+	__typeof__(*(ptr)) __pus_val = x;				\
 	__chk_user_ptr(ptr);						\
+	instrument_copy_to_user(ptr, &(__pus_val), size);		\
 	switch (size) {							\
 	case 1:								\
 		__put_user_goto(x, ptr, "b", "iq", label);		\
@@ -286,6 +291,7 @@  do {									\
 #define __get_user_size(x, ptr, size, label)				\
 do {									\
 	__chk_user_ptr(ptr);						\
+	instrument_copy_from_user_before((void *)&(x), ptr, size);	\
 	switch (size) {							\
 	case 1:	{							\
 		unsigned char x_u8__;					\
@@ -305,6 +311,7 @@  do {									\
 	default:							\
 		(x) = __get_user_bad();					\
 	}								\
+	instrument_copy_from_user_after((void *)&(x), ptr, size, 0);	\
 } while (0)
 
 #define __get_user_asm(x, addr, itype, ltype, label)			\