Issue
I work on the project where I use syscall structures.
Is structure packing same in kernel space as in user space ? And I also would like to have some trustworthy source, where I can read more about that.
Example for better understanding:
I receive data about syscall in this structure in kernel space.
struct sys_enter_socket_t {
long unusedParams;
int __syscall_nr;
long family;
long type;
long protocol;
};
I save it to char array and send it to user space. In user space I recast it to this structure and work with it. Now on my platform it works fine, but I want to be sure, it will work on other platforms.
Solution
Is structure packing same in kernel space as in user space ?
User-space is about 50 different languages (assembly, C, C++, Pascal, Java, Golang, Ada, MATLAB, ...) each with different rules, sometimes with multiple completely different implementations (e.g. stuff compiled for Windows running under Wine).
Each of these has it's own run-time environment to make it work. For one example, for a function like readdir()
, the C library might (or might not) get completely different structures from the kernel and convert them into whatever makes sense for however the particular C library felt like defining its struct dirent
. Note that this is fundamentally a "good thing" - it means that kernel can change its data structures (e.g. add new fields, increase the size of things like timestamps to fix a "year 2038" problem, etc) without breaking everything in user-space.
In other words, kernel developers say "this is specifically how it is for this kernel (in these conditions)" and every different language run-time in user-space does whatever it needs to do hide the lower level stuff so that nothing else (your program's source code) cares what the kernel developers said.
In user space I recast it to this structure and work with it. Now on my platform it works fine, but I want to be sure, it will work on other platforms.
Compile your program as a 32 bit executable running under a 64-bit kernel; and I think you'll find that (even with the same compiler and linker on the same kernel on the same computer) it does not work.
Specifically; in this case user-space will say that long
is 32 bits and that no padding is necessary, while kernel will say that long
is 64 bits and will add 4 bytes of padding after the int __syscall_nr;
.
To make it easier for different run-time environments to make it work, you could try being explicit, like:
struct sys_enter_socket_t {
uint64_t unusedParams;
uint32_t __syscall_nr;
uint32_t reserved;
uint64_t family;
uint64_t type;
uint64_t protocol;
} __attribute__((packed));
Answered By - Brendan Answer Checked By - Marilyn (WPSolving Volunteer)