I was hoping someone could explain the nuances of the __user macro used in the linux kernel source.
First of all, the macro:
# define __user
It allows tools like sparse to tell kernel developers that they're possibly using an untrusted pointer (or a pointer that may be invalid in the current virtual address mapping) improperly.
I think __user marks user space pointers and tells the developer/system not to trust it. If user gives you "invalid" pointer, then kernel tries to reference it (note that kernel can reference everywhere) and it can corrupt it's own space.
For example in "read"(in you usbdevice_fs.h) should provide you a (__user) buffer to write the result to. So you have to use copy_to_user, but not memcopy, strcpy or anything like this.
Note: This is not formal definition/description, but the only part I'm aware of.
The __user
macro is defined with some other macros like __force
/__kernel
etc in the compiler.h header file. They are actually not of any use to traditional compilers, including GCC/ICC etc. But it's useful for kernel static analysis tools like sparse (more information here: Sparse - Linux Kernel Newbies). When you mention the macros like __user
/__kernel
/__force
etc, it keeps special meaning for sparse. In the Linux kernel mailing list, Linus Torvalds explains the use of it like this:
This is important to remember: for gcc, the sparse annotations are meaningless. They can still be useful just to tell the programmer that "hey, that pointer you got wasn't a normal pointer" in a fairly readable manner, but in the end, unless you use sparse, they don't actually do anything.
HOWEVER. When you do use parse, it is another matter entirely. For "sparse", that "__iomem" has lots of meaning:
# define __iomem __attribute__((noderef, address_space(2)))
ie "iomem" means two separate things: it means that sparse should complain
if the pointer is ever dereferenced (it's a "noderef" pointer) directly, and it's in "address space 2" as opposed to the normal address space (0).
Now, that means that sparse will complain if such a pointer is ever passed into a function that wants a regular pointer (because it is not a normal pointer, and you obviously shouldn't do things like "strcmp()" etc on it), and sparse will also complain if you try to cast it to another pointer in another address space.