|
|
Subscribe / Log in / New account

System-call wrappers for glibc

By Jonathan Corbet
September 19, 2019

LPC
The GNU C Library has long had a reputation for being hostile to the addition of wrappers for new Linux system calls; that has resulted in many system calls being unsupported by the library for years. That situation is changing, though. During the Toolchain microconference at the 2019 Linux Plumbers Conference, Maciej Rozycki talked about glibc's new attitude toward system-call wrappers, but also served notice that there is still significant work to do for the addition of any new system call.

Rozycki, who put together the talk with Dmitry Levin, is not the person doing most of this work. He was, instead, "delivering a message from Florian Weimer", who was unable to attend the event.

For those who might appreciate a bit of background: applications running in user space do not call directly into the kernel; instead, they will call a wrapper function that knows how to invoke the system call of interest. If nothing else, the wrapper will place the system-call arguments in the right locations and do whatever is necessary to invoke a trap into kernel mode. In some cases, the interface implemented by the wrapper can be significantly different from what the kernel provides.

The provision of a specialized wrapper is not strictly necessary; an application can always gain access to an unsupported system call by way of the syscall() function. But, as Rozycki began, there are good reasons to not require applications to do that. There is no type-checking of arguments with syscall(), for example. System-call numbers vary from one architecture to the next, even if a Linux kernel is running in both cases, and there can be other ABI differences as well; that makes writing portable [Maciej Rozycki] code with syscall() difficult. Then, there are the difficulties that come with POSIX threads and thread cancellation in particular. It is just better to have proper C-library support for the system calls that applications need to use.

So the intention in the glibc project has shifted from blocking system-call wrappers to accepting them. They can't all come in at once, though; each must clear some obstacles first. These include proper documentation in the glibc manual and, since glibc is a Free Software Foundation project, copyright-assignment paperwork in place. That last requirement led to a discussion on whether requiring copyright on system-call wrappers amounts to a recognition of ABI copyrights in general — surprisingly, no useful conclusions came from that part of the conversation. The final problem with getting wrappers merged, Rozycki said, is common to all free-software projects: a lack of reviewers to look them over.

The project has adopted a policy of not emulating system calls in almost all circumstances. If a given system call is not available, the library will return ENOSYS and be done with it. System-call emulation has proved to be error-prone, so it will only be done in the most trivial of cases. Glibc also requires that wrapper names be architecture-independent, the alternative being a "maintenance nightmare". If possible, the glibc developers want to add support for all architectures in a single release; otherwise keeping track of things gets difficult.

Glibc developers have also learned a lesson that has been felt in kernel circles, even if that lesson is still not always taken to heart: multiplexing system calls are painful to support. They make the checking of argument types difficult or impossible, and the situation is even worse for variadic calls (those which take different numbers of arguments for different operations). One result of this aversion to multiplexing system calls may well be that calls like futex() and bpf() will probably be implemented in glibc as a set of independent wrappers, one for each operation.

There are some specific ABI rules that have been adopted for system-call wrappers. For example, ssize_t or size_t should be used for all buffer sizes, regardless of the type the kernel uses; that helps to make the purpose of the argument clear. Flags should not have a long type, since it's often unclear how the upper 32 bits should be handled on 32-bit machines. Errors should always be returned via errno, except for the POSIX threads calls, which are a perennial exception. The glibc developers also feel that their lives would be easier if each new system call had a separate kernel UAPI header file for its associated types and constants. That allows them to include the required information without bringing in any unrelated declarations.

Rozycki concluded by asking for better cooperation with the C-library projects in general. They should be copied on patches containing ABI changes, for example. I noted that there are often times where C-library developers wish the kernel community had done things differently; how could those be avoided in the future? Members of the audience suggested that more glibc developers should perhaps join the linux-api list. The other suggestion was to "copy Florian on everything".

Levin added that sometimes documentation can be a limiting issue, ironically it can be worse if a new system call comes out of the kernel community with documentation already written. If the author will not assign copyright for that documentation to the FSF for inclusion in the manual, progress can be blocked; the glibc developers will have to find a way to recreate it without copying the original. This struck some in the audience as a self-imposed problem.

At the end of session, Christian Brauner said that getting changes into glibc used to be a painful process, but that has changed in recent years. Even the infamous gettid() system call, the subject of a years-long, acrimonious enhancement request, has now been merged, to the amazement of many. The glibc community is now interacting much more with the kernel community, a change that, hopefully, will continue over time and be echoed on the kernel side.

[Your editor thanks the Linux Foundation, LWN's travel sponsor, for supporting his travel to this event.]

Index entries for this article
KernelSystem calls
ConferenceLinux Plumbers Conference/2019


to post comments

System-call wrappers for glibc

Posted Sep 20, 2019 0:41 UTC (Fri) by quotemstr (subscriber, #45331) [Link] (6 responses)

I've long been of the opinion that the kernel should avoid multiplexing system calls. I've said repeatedly on lkml that system calls are not expensive and that multiplexers are pointless. Maybe I'll finally get some traction now?

System-call wrappers for glibc

Posted Sep 20, 2019 3:14 UTC (Fri) by pj (subscriber, #4506) [Link]

Even with normal APIs, it's a design issue of whether to have one call with a boolean flag or two calls that ends up boiling down to aesthetics at some point.

System-call wrappers for glibc

Posted Sep 20, 2019 6:05 UTC (Fri) by NHO (guest, #104320) [Link]

Ain't we running out of syscall numbers?

System-call wrappers for glibc

Posted Sep 20, 2019 6:31 UTC (Fri) by epa (subscriber, #39769) [Link] (2 responses)

If the multiplex call is wrapped by the C library then you can have a separate C function for each mode, each one with a sane and type-safe interface. System calls are a finite resource but C library interfaces are not. However, if you take the view that the C library should provide exactly the interface given by the kernel, a messy system call will result in messy user code.

System-call wrappers for glibc

Posted Sep 20, 2019 6:47 UTC (Fri) by mfuzzey (subscriber, #57966) [Link] (1 responses)

I would say the kernel and the glibc developers should work together *before* new syscalls are set in stone to, as far as possible, come up with a design that suites everyone and makes the wrappers simpler.

That may not be possible in every case for technical reasons but I think up to recently it was more of lack of communication between the kernel and glibc developers that caused most problems rather than specific technical issues.

System-call wrappers for glibc

Posted Sep 20, 2019 7:58 UTC (Fri) by jani (subscriber, #74547) [Link]

FWIW, this is what we try to do in the graphics subsystem for uapi. The userspace part needs to be agreed on and basically ready to merge in the relevant userspace upstream projects before the kernel part lands.

Details at https://www.kernel.org/doc/html/latest/gpu/drm-uapi.html#...

System-call wrappers for glibc

Posted Sep 20, 2019 17:58 UTC (Fri) by fw (subscriber, #26023) [Link]

I suspect that it's a side-effect that wiring up even completely architecture-independent system calls across all architectures used to be very complicated, so that system call additions tended to be spread across many kernel releases. With a multiplexer, you only have to go through the process once. Likewise for adding the system call wrapper to glibc.

Truly problematic are only system calls for which the intended implementation uses va_list in some way. The increased type safety may be worthwhile for separate functions, and it generally increases source portability once rarely used types change (e.g. file offsets with fcntl, times with futex). But that seems to be difficult to predict.

System-call wrappers for glibc

Posted Sep 20, 2019 15:26 UTC (Fri) by hrw (subscriber, #44826) [Link]

If you want to see how different system call numbers can be you can take a look at my syscalls table.

I generate it around every -rc1 kernel release and often at final one.

linux-abi list: typo?

Posted Sep 20, 2019 17:54 UTC (Fri) by fw (subscriber, #26023) [Link] (1 responses)

I assume that “linux-abi list” is a typo for “linux-api list”. (If not, that might explain something.)

linux-abi list: typo?

Posted Sep 20, 2019 19:08 UTC (Fri) by corbet (editor, #1) [Link]

Yes, of course; it's been fixed.


Copyright © 2019, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds