- What are the implications of the linux __user macro?
- 3 Answers 3
- Utilization of Linux Kernel Macros as Functions
- How are linux kernel macros used as functions?
- What is the purpose of hweight macros in the linux kernel?
- Difference of ALIGN() and round_up() macro in the Linux kernel
- Best way to deal with namespace collision of likely/unlikely macros, with boost code
What are the implications of the linux __user macro?
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 __attribute__((noderef, address_space(1)))
Now, after some googling I read that this macro allows one to designate a pointer as belonging to the user address space, and that it should not be dereferenced. I may be missing some obvious facts, but could someone please explain the implications of such a macro? For instance, what is a good example of where this macro would be of use? Again, forgive me if I am missing something obvious. To put this in some context, I came accross the macro while examining some USB code (linux/usbdevice_fs.h). I am only looking for a general understanding of this macros( or others like it) use within the kernel. Thanks for looking!
See do_execve() source for good example. See how argv is used in count(). If you’d simply dereference (*argv[0]) or something, sparse(1) will warn about it. address_space says not all pointers are equal, requiring different (dereference) rules and should not be mixed.
@adobriyan in what header or source file can I find this function? I do not want to grep while filesystem in order to find it. A path will suffice
3 Answers 3
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.
So __attribute__() can use any arbitrary text as an «attribute»? It’s not limited to a fixed set which are meaningful to GCC itself?
@AlexD From the GCC Attribute Syntax Manual: An attribute specifier is of the form __attribute__ ((attribute-list)). An attribute list is a possibly empty comma-separated sequence of attributes, where each attribute is one of the following: 1. Empty. Empty attributes are ignored. **2. An attribute name (which may be an identifier such as unused, or a reserved word such as const).** (. ) . It seems like it could be any identifier you want (using identifier naming conventions).
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.
Utilization of Linux Kernel Macros as Functions
Linux experts utilize a variety of complicated structures to achieve efficiency, simplify complex constructions, and develop architecture-independent code. Given this, is it possible to incorporate macros while still utilizing this complex code?
How are linux kernel macros used as functions?
The heading may appear vulgar, but I am at a loss for words to describe what I am about to share as it is something entirely new to me.
Upon creating my initial kernel module, I utilized a linked list , which incorporated the linux/list.h header file . Within this module, a macro was implemented.
400 /** 401 * list_for_each_entry - iterate over list of given type 402 * @pos: the type * to use as a loop cursor. 403 * @head: the head for your list. 404 * @member: the name of the list_struct within the struct. 405 */ 406 #define list_for_each_entry(pos, head, member) \ 407 for (pos = list_entry((head)->next, typeof(*pos), member); \ 408 prefetch(pos->member.next), &pos->member != (head); \ 409 pos = list_entry(pos->member.next, typeof(*pos), member))
Assuming list_head is the head of the list and list is the list_struct within the struct, this is how I utilized it.
struct thing *ptr; list_for_each_entry(ptr, &list_head, list)< printk(KERN_INFO "contents: %s\n", ptr->something); >
Upon executing dmesg , each item in the list is represented by a single line.
I’m curious about the situation at hand. The use of macros as functions is unfamiliar to me. Can you explain the guidelines for creating a macro that can be invoked in this manner?
I am struggling to comprehend the mechanism behind its functionality and how I can create a similar macro.
The macro does not involve any special process and only expands textually. To view the output, utilize the gcc -E command, which applies in the present scenario.
#define list_for_each_entry(pos, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member); \ prefetch(pos->member.next), &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member)) . struct thing *ptr; list_for_each_entry(ptr, &list_head, list)< printk(KERN_INFO "contents: %s\n", ptr->something); >
struct thing *ptr; for (ptr = list_entry((&list_head)->next, typeof(*ptr), list); prefetch(ptr->list.next), &ptr->list != (&list_head); ptr = list_entry(ptr->list.next, typeof(*ptr), list)) < printk(KERN_INFO "contents: %s\n", ptr->something); >
It’s important to note that I didn’t put in any effort and simply copied and pasted the code, running it through gcc -E while making minor adjustments to the formatting.
As evident from the code, the expansion contains the loop.
To gain a thorough understanding of Linux kernel , a strong foundation in C is necessary. It is recommended to go through a tutorial, such as the one found at http://www.cprogramming.com/tutorial/c-tutorial.html, and work through the material. Linux experts employ various complex and efficient coding techniques, including the use of macros, to create architecture-independent code and abstract complex constructions that are prone to errors. It is important to note that the kernel also utilizes several GCC-only extensions.
Frequent ‘likely-unlikely’ Questions, Q&A for work. Connect and share knowledge within a single location that is structured and easy to search. Learn more Questions …
What is the purpose of hweight macros in the linux kernel?
While examining kernel driver code, I stumbled upon various macros, including hweight8 , hweight16 , hweight32 , and others. Despite my efforts to locate documentation on the purpose and functionality of these macros, I was unable to find any.
The definition of the macros can be located in include/asm-generic/bitops/const_hweight.h.
#define hweight8(w) (__builtin_constant_p(w) ? __const_hweight8(w) : __arch_hweight8(w)) #define hweight16(w) (__builtin_constant_p(w) ? __const_hweight16(w) : __arch_hweight16(w)) #define hweight32(w) (__builtin_constant_p(w) ? __const_hweight32(w) : __arch_hweight32(w)) #define hweight64(w) (__builtin_constant_p(w) ? __const_hweight64(w) : __arch_hweight64(w))
The hweight functions are employed to count the number of bits set to 1 in a byte/word. Though I am not thoroughly aware of the application, I came across a code snippet in the Linux NAND driver that utilizes these functions to verify if a block is erased (comprising all 1 bits) but with a provision for some bits to be flipped.
hweight8(1) --> 1 hweight8(2) --> 1 hweight8(3) --> 2 hweight8(4) --> 1 hweight8(5) --> 2 hweight8(6) --> 2 hweight8(7) --> 3 hweight8(8) --> 1 and so on.
How do you build a Linux Kernel for Android from the, A whole copy of the Linux kernel directory in: How do the likely/unlikely macros in the Linux kernel work and what is their benefit? 1740 . How do I prompt for Yes/No/Cancel input in a Linux shell script? 284. How is the Linux kernel tested? 2432. How to change the output color of echo in Linux. 631. …
Difference of ALIGN() and round_up() macro in the Linux kernel
As I delve into the inner workings of the Linux kernel, I’ve encountered two macros, namely ALIGN() and round_up() . Although they are designed to serve the same purpose of rounding up to the nearest 2^n bytes, they differ in their implementation.
I’m interested to know why they require two macros having distinct implementations but providing identical results.
Additionally, they exist within a shared header file identified as include/linux/kernel.h .
#define __round_mask(x, y) ((__typeof__(x))((y)-1)) #define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1) #define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) #define ALIGN(x, a) __ALIGN_KERNEL((x), (a))
__ALIGN_KERNEL*() used to be in a different header, but it is now incorporated into UAPI. Nonetheless, the primary distinctions, I believe, are:
a) implementation that varies slightly
The author of 9b3be9f99203 («Move round_up/down to kernel.h») had a historical reason for not including the counterpart to ALIGN() . This was later addressed in ed067d4a859f («linux/kernel.h: Add ALIGN_DOWN macro»).
It might be helpful to send an email to LKML and contact the authors of the mentioned commits, such as Kees Cook and others, to request their review.
Linux — How does the command ‘echo «6» >, 1 Answer. Sorted by: 0. Filesystem entries under /proc behave somewhat like function calls. «Writing» a string to the file is like calling a function with the string as an argument. «Reading» from the file is like calling a function with no argument and getting back the return value. The behavior of each «function» is …
Best way to deal with namespace collision of likely/unlikely macros, with boost code
The method named likely is present in the boost::date_time::special_values_parser class. Nevertheless, I am utilizing this class in code that employs the branch-prediction macros likely / unlikely (refer to How do the likely/unlikely macros in the Linux kernel work and what is their benefit?). Is there a feasible solution to use this code while simultaneously utilizing the macros?
Can the macros be utilized in conjunction with this code?
Indeed, macros require operates as a function, as indicated in () . However, unlike regular functions, it expands immediately. To overcome this limitation, a workaround can be implemented.
(boost::date_time::special_values_parser::likely)( /* . */ );
Learning sample of likely() and unlikely() compiler hints, @R. If you think that likely/unlikely can’t give any benefit, you cat open a new Question. But this question was opened upon request from my friend. He is a CS teacher of first-year students and he wanted to show them a likely/unlikely example. He wasn’t able to produce a example, so I asked this q. I …