On Thu, May 28, 2020 at 4:09 PM Joel Fernandes joel@joelfernandes.org wrote:
So no, this patch is fundamentally wrong. It negates the whole point of having a uapi header at all.
Sorry, I naively assumed that headers in 'include/uapi/' are safe to include from userspace. I feel terrible.
Well, they "kind of" are safe to include.
It's just that normally they are meant for system integrators to include as part of the system header files. So they are designed not to be safe for normal programs, but for library writers.
And to make things more confusing, sometimes people _do_ include kernel header files directly, just because they want to get features that either haven't been exposed by the system libraries, or because the system libraries copied the uapi header files for an older version of the kernel, and you want the shiny new feature, so...
And some of those header files are easier to do that with than others...
The problem is <sched.h> still does not get us 'struct sched_attr' even though the manpage of sched_setattr(2) says including <sched.h> is all that's needed.
Ouch. But clearly you get it from -somewhere- since it then complains about the double declaration.
Strange.
Also, even if glibc included 'include/uapi/linux/sched/types.h' to get struct sched_attr's definition, we would run into the same issue I reported right? The 'struct sched_param' is already defined by glibc, and this header redefines it.
That's kind of the point: glibc sets up whatever system headers it wants. The uapi ones are there to _help_ it, but it's not like glibc _has_ to use them.
In fact, traditionally we didn't have any uapi header files at all, and we just expected the system libraries to scrape them and make their own private copies.
The uapi headers are _meant_ to make that easier, and to allow system headers to then co-exists with the inevitable "I need to get newer headers because I'm using a bleeding edge feature that glibc isn't exposing" crowd.
Put another way: a very non-portable programs _could_ include the uapi headers directly, if the system library headers were set up that way.
More commonly, what bleeding edge people do when the system header files don't play nice, is to just build their very own libraries and copy the bleeding-edge features directly from the kernel. So you'll find things like
#ifndef __NR_clone3 #define __NR_clone3 435 #endif
syscall(__NR_clone3, ...);
in user space that wants to use the clone3 system call, but knows that it hasn't made it into the glibc headers yet, so the program just forced the local knowledge of it.
That's obviously generally easier to do with macro defines like the above, exactly because you can trivially _test_ whether they've been exposed or not.
So yes, this is a horrid mess.
But the *intent* is that the uapi header files should be things that system library implementations can just use directly, and then the "special" users could mix-and-match if everything is wonderful.
Which it seldom is.
But that's why putting those interface declarations inside a #ifdef __KERNEL__ would completely destroy the whole point.
Linus