When to prevent execution of new binaries with old glibc

Joseph Myers joseph@codesourcery.com
Thu Oct 21 17:43:21 GMT 2021


This question has come up in a couple of threads lately, but perhaps 
deserves its own thread.

When should glibc try to ensure that a binary (either a main executable or 
a shared library) built and linked against a newer version of glibc, and 
using some feature that would not work correctly when run with an older 
version of glibc, fails on startup (or shared library load) when run with 
older glibc, rather than failing later or executing incorrectly?

The main mechanism we have for this is symbol versions, although the 
EI_ABIVERSION / libc-abis mechanism might help detect some cases of using 
unsupported ELF features.  We use new symbol versions for new glibc ports, 
newly exported symbols, symbols that have changed semantics in a way 
incompatible with existing binaries, and symbols that have moved from 
another library to libc.

We rarely, however, use such a mechanism in cases where old binaries are 
expected to continue to work OK.  That includes, for example:

* Bug fixes.

* Changed function semantics where the new semantics are a refinement of 
the old semantics (e.g. a new standard imposes stricter requirements on 
the result than an old standard, and glibc changes to implement that).

* Functions taking an enumerated argument (including any case of integers 
from some enumerated list, whether or not using a C enum type) describing 
something about the operation they carry out, where support for a new 
value of that argument is added.  (In some cases, it may be the kernel not 
glibc that adds support for new values of the argument, in which case 
there is nothing much glibc can do.)

* Functions taking a flags argument, where support for a new flag is 
added.  (Again, in some cases it's actually the kernel implementing the 
argument.)

* Functions taking a string argument that they parse, where support for 
some new feature in the string is added and strings using that new feature 
would previously have been considered to result in undefined behavior 
(such as adding new format specifiers for printf, scanf, strftime, 
strptime and strfmon format strings).

In the above cases, it would be possible to use symbol versioning, making 
the new symbol version an alias of the old one, but we don't generally do 
so.  There are also other, possibly rarer, cases where such symbol version 
aliasing can be used for a similar purpose (e.g. the change long ago of 
the return type of various <fenv.h> functions from void to int in C99 TC1, 
where we did use symbol version aliasing on the affected functions).

When, if at all, should we set up symbol version aliases for such issues 
(or use some other mechanism to prevent execution of new binaries with old 
glibc)?  We can take the case of new printf specifiers as an example, 
where HJ has suggested 
<https://sourceware.org/pipermail/libc-alpha/2021-October/132150.html> 
that binaries using such features should have a dependency on the relevant 
glibc version (and in practice that would mean binaries using any affected 
printf-like function, 56 per long double variant, whether they use the new 
formats or not).  But we haven't done that for e.g. strftime/strptime 
changes (and scanf functions have only got new function names because of 
incompatible differences in the handling of formats that were already 
valid before the changes).

-- 
Joseph S. Myers
joseph@codesourcery.com


More information about the Libc-alpha mailing list