in ,

The Unix C library API can only be reliably used from C, Hacker News

The Unix C library API can only be reliably used from C

December 823,

To fully implement system call origin verification, OpenBSD would like Go to make system calls through the C library instead of directly making system Calls from its own runtime (which it hassome reasons for doing). On the surface, this sounds like only a moderately small issue; sure, it’s a bit awkward, but a language like Go should be able to just make calls to the usual C library functions likeopen ()(and using the C calling ABI). Unfortunately it's not that simple, because very oftenparts of the normal C library API are actually implemented in the C preprocessor. Because of this, the C library API cannot be reliably and generally used without actually writing your own C glue code.

This sounds extreme, so let me illustrate it with everyone’s favorite case oferrno, which you consult to get the error value from a failed system call (and from some failed library calls). As covered in yesterday's entry, in the modern worlderrnomust be implemented so that different threads can have different values ​​for it, because they may be making different system calls at the same time. This requires thread local storage, and generally thread local storage cannot be accessed as a plain variable; it must be accessed through some special tricks supported by the C runtime. So here are the definitions of 'errno' from OpenBSD 6.6 and a current Fedora Linux with glibc:

/ * OpenBSD * / int * __ errno (void); #define errno __ errno ()) / * Fedora glibc * / extern int * __ errno_location (void) __THROW __attribute_const__; # define errno __ errno_location ())

In both of these cases,errnois actually a preprocessor definition. The definitions refer to non-public and undocumented C library functions (that's what the leading double underscores signal) that are not part of the public API. If you compile C code against thiserrnoAPI (by includingerrno.hin your program), it will work, but that's the only officially supported way of doing it. There is no usefulerrnovariable to load in your own language's runtime after a call to, say, theopen ()function, and if you call__ errnoor____ errno_locationin your runtime, you are using a non-public API and it could break tomorrow (although it probably won't). To build a reliable language runtime that sticks to the public C library API, it's not enough to just call exported functions likeopen (); you also need to write and compile your own little C function that just returnserrnoto your runtime.

(There may be other important cases besideserrno); I will leave them to interested parties to find.)

This is not a new issue in Unix, of course. From the beginning of stdio in V7, some of the stdio ‘functions’ were implemented as preprocessor macros instdio.h. But for a long time, people did not insist that the C library was the only officially supported way of making system calls, so you could bypass things like the whole modernerrnomess unless you needed to be Compatible with C code for some reason.

(Before threading came into the Unix picture,errnowas a plain variable and a generally good interface, although not perfect.)

************************ Read More********

What do you think?

Leave a Reply

Your email address will not be published. Required fields are marked *

GIPHY App Key not set. Please check settings

Own Your Website Stats, Hacker News

[FREE]Hacking with Metasploit: Pre Exploitation Techniques