public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* Evolution of ELF symbol management
@ 2016-10-18  9:26 Florian Weimer
  2016-10-18 16:50 ` Joseph Myers
  2016-11-16 15:55 ` Zack Weinberg
  0 siblings, 2 replies; 19+ messages in thread
From: Florian Weimer @ 2016-10-18  9:26 UTC (permalink / raw)
  To: GNU C Library

In the ancient past, all glibc symbols, including internal ones, were 
public.  Then came symbol versioning, and hidden symbols.

This did not solve all problems.  For static linking, we often have to 
mangle symbols so that an implementation of a function in one standard 
does not implicitly require the application to be conforming to another 
standard (or standard version): the application might define a symbol 
which is reserved by the other standard, and we cannot use this function 
in the implementation.

For essentially the same reason, we need to mangle references in 
non-libc DSOs to libc symbols which are not present in all of the 
standards implied by all symbol references to the non-libc DSO.

Symbol versioning does not help here, for two reasons: We do not provide 
symbol versions for static builds.  For backwards compatibility reasons, 
non-versioned symbols interpose all versioned symbols, irrespective of 
their version (not just the base definition).  The second reason is 
important in practice; it is required for interposing malloc.

I think the above sums up the status quo.  With this message, I want to 
start a discussion why this symbol mangling stops at glibc-internal 
cross-DSO references (or static linking).  Wouldn't other system 
libraries, such as libstdc++, glib, Qt and so on need to do the same 
thing?  After all, if Qt calls foo@GLIBC_2.31, and the main program 
defines foo (which the static linker automatically exports to enable 
interposition), we almost certainly would want Qt to continue to call 
foo@GLIBC_2.31, and not the potentially incompatible implementation of 
foo in the main program.

To keep things simple, I suggest that for all new function symbols, we 
declare __libc_foo in the header file, redirect foo to __libc_foo, 
export both at the same symbol version from the DSO, and make __libc_foo 
a strong definition and foo a weak one.  (We should not add new variable 
symbols.)

For existing symbols, we only do this if we receive reports of conflicts 
causing problems in the field.  In this case, we add __libc_foo and the 
redirect to the header file, and use the current symbol version for the 
__libc_foo export (not the one of foo).

Comments?

Thanks,
Florian

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Evolution of ELF symbol management
  2016-10-18  9:26 Evolution of ELF symbol management Florian Weimer
@ 2016-10-18 16:50 ` Joseph Myers
  2016-10-25 14:32   ` Florian Weimer
  2016-11-16 15:55 ` Zack Weinberg
  1 sibling, 1 reply; 19+ messages in thread
From: Joseph Myers @ 2016-10-18 16:50 UTC (permalink / raw)
  To: Florian Weimer; +Cc: GNU C Library

On Tue, 18 Oct 2016, Florian Weimer wrote:

> I think the above sums up the status quo.  With this message, I want to start
> a discussion why this symbol mangling stops at glibc-internal cross-DSO
> references (or static linking).  Wouldn't other system libraries, such as
> libstdc++, glib, Qt and so on need to do the same thing?  After all, if Qt
> calls foo@GLIBC_2.31, and the main program defines foo (which the static
> linker automatically exports to enable interposition), we almost certainly
> would want Qt to continue to call foo@GLIBC_2.31, and not the potentially
> incompatible implementation of foo in the main program.

We've previously discussed this in the libstdc++ context and I think 
agreed that implementation-namespace versions should be added at least for 
functions used in libstdc++ headers, to allow G++ to stop defining 
_GNU_SOURCE by default 
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=11196> 
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51749> 
<https://sourceware.org/ml/libc-alpha/2012-03/msg00311.html>.  I'd 
consider the namespace issues to apply equally to all language runtime 
libraries - so including any symbols used in libstdc++ but not in the 
headers, for example, and in other language runtimes in GCC where there is 
a meaningful question for the relevant languages of certain C symbol names 
being reserved or not reserved.  Language runtimes also include e.g. 
libdfp (on which basis the printf hooks functionality should be exported 
under implementation-namespace names).

Doing it more systematically for glibc function symbols rather than only 
supporting it for particular privileged language runtimes seems reasonable 
to me.

> To keep things simple, I suggest that for all new function symbols, we declare
> __libc_foo in the header file, redirect foo to __libc_foo, export both at the
> same symbol version from the DSO, and make __libc_foo a strong definition and
> foo a weak one.  (We should not add new variable symbols.)

I take it this is __libc_foo independent of which library contains foo (so 
no __libm_foo, __libpthread_foo etc.)?

There are a few existing __libc_foo exports at public symbol versions.  Do 
all those satisfy the rule that where both foo and __libc_foo exist, the 
latest version of foo and the latest version of __libc_foo are aliases or 
otherwise have the same semantics?  (It would seem very confusing for old 
and new __libc_* symbols to follow different rules in that regard.)

What should be done where the symbol is only added in the implementation 
namespace - symbols for use in redirection for different standard 
versions, macros, inline functions or *_nonshared.a, for example?  Should 
future such symbols also use the __libc_foo namespace (unless there are 
ABI reasons for something else, e.g. the libmvec functions) (so if such a 
practice were implemented before glibc 2.25 came out, __iscanonicall would 
change to __libc_iscanonicall, etc.), or continue being __foo?

What about compilers that do not support redirection?  Right now we have 
many individual #defines in the case where __REDIRECT is not supported.  
If we required support for asm redirection in compilers using the glibc 
headers, it would be possible to define a macro to declare both foo and 
__libc_foo, with the same type and the same attributes (and the same throw 
() information for C++), and do the redirection, all with one macro call.  
Otherwise you get a lot of repetitive boilerplate in headers for every 
such function, since a macro cannot generate a #define of another macro.  
Or you say that compilers without redirection support don't get any of 
these redirections, since they are not semantically required.

(When you're dealing with API issues as well as ABI then the macro 
solution runs into complications with wanting to declare __libc_foo 
unconditionally for use in libstdc++ headers, but foo only when the right 
feature test macros are defined.  Those complications can certainly be 
resolved, e.g. with macros __<something>_GNU to do the declaration whose 
definitions depend on the feature test macros defined, and a first 
solution might well only deal with the ABI issues and leave the API ones 
for later.)

Being able to make all the declarations with a single macro is attractive, 
since right now I'm sure that lots of the declarations in internal 
include/ headers are in fact suboptimal because they are missing 
attributes present on the public declarations.  It would also have the 
potential for defining variants of such macros in future that also do 
*_hidden_proto (for public and internal function names) when building 
glibc.  Recall that *_hidden_* are still needed even for internal function 
names, whether or not those names are exported - if exported, failure to 
use *_hidden_* will be visible through localplt test failures, but if not 
exported, less efficient code is still generated in the caller on 32-bit 
x86 if the function isn't visibly hidden 
<https://sourceware.org/bugzilla/show_bug.cgi?id=18822>.

(In turn, that would allow us to move towards the desired direction of 
eliminating most of the include/ header wrappers so tests build in 
something much more like a normal installed glibc environment.  I think 
it's already understood that declarations that aren't just hidden_proto 
(foo) or declaring __foo for a function foo in the public header ought to 
go in an entirely separate header, not one of those wrappers, and 
appropriate macros for function declarations in installed headers could 
allow eliminating the remaining appropriate contents from the wrappers - 
subject to the issue of the declarations there being for old-style names 
for internal functions, not for __libc_*.)

Features that are de facto required for using glibc headers already 
include (non-exhaustive list):

* C89 or C++98.

* long long.

* Flexible array members - including the ability for a struct with a 
flexible array member to be followed by another member in a containing 
struct, which is not a standard C feature.  (See _G_config.h's _G_iconv_t; 
struct __gconv_info has a flexible array member and is followed by another 
member in a struct.  I don't know if use of a compiler that gets the 
fallback array[1] for a flexible array member would result in any ABI 
issues for a user of glibc, or if the ABI in question is purely internal.)

* Some headers require anonymous structs / unions.

* Various macros in various headers may also require other features such 
as __typeof and statement expressions.

In fact we have evidence 
<https://sourceware.org/ml/libc-alpha/2014-09/msg00017.html> that the 
headers have had problems for a long time for compilers not defining 
__GNUC__, and those include problems relating to redirection.

> For existing symbols, we only do this if we receive reports of conflicts
> causing problems in the field.  In this case, we add __libc_foo and the
> redirect to the header file, and use the current symbol version for the
> __libc_foo export (not the one of foo).

"causing problems in the field" should be broadly interpreted there - to 
allow adding lots of such functions if someone identifies what's needed to 
make the libstdc++ headers or libraries namespace-clean, for example, or 
for fixing the namespace issues described in 
<https://sourceware.org/bugzilla/show_bug.cgi?id=14106>.

What should be done in the case where __foo already has an export at a 
public symbol version (and we have a use for __libc_foo)?  Should we 
arrange for __foo to be declared (with associated redirections) and say 
people should be using that, or add __libc_foo as well?  What about where 
__foo is already exported, but that export is a compat symbol (if there 
are any such cases)?  Making it not a compat symbol would run into needing 
new exports at new versions on platforms postdating the version where it 
was made a compat symbol, and you don't want the API to be __foo on some 
platforms and __libc_foo on others.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Evolution of ELF symbol management
  2016-10-18 16:50 ` Joseph Myers
@ 2016-10-25 14:32   ` Florian Weimer
  2016-10-25 15:37     ` Joseph Myers
                       ` (2 more replies)
  0 siblings, 3 replies; 19+ messages in thread
From: Florian Weimer @ 2016-10-25 14:32 UTC (permalink / raw)
  To: Joseph Myers; +Cc: GNU C Library

On 10/18/2016 06:49 PM, Joseph Myers wrote:
> On Tue, 18 Oct 2016, Florian Weimer wrote:
>
>> I think the above sums up the status quo.  With this message, I want to start
>> a discussion why this symbol mangling stops at glibc-internal cross-DSO
>> references (or static linking).  Wouldn't other system libraries, such as
>> libstdc++, glib, Qt and so on need to do the same thing?  After all, if Qt
>> calls foo@GLIBC_2.31, and the main program defines foo (which the static
>> linker automatically exports to enable interposition), we almost certainly
>> would want Qt to continue to call foo@GLIBC_2.31, and not the potentially
>> incompatible implementation of foo in the main program.
>
> We've previously discussed this in the libstdc++ context and I think
> agreed that implementation-namespace versions should be added at least for
> functions used in libstdc++ headers, to allow G++ to stop defining
> _GNU_SOURCE by default
> <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=11196>
> <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51749>
> <https://sourceware.org/ml/libc-alpha/2012-03/msg00311.html>.  I'd
> consider the namespace issues to apply equally to all language runtime
> libraries - so including any symbols used in libstdc++ but not in the
> headers, for example, and in other language runtimes in GCC where there is
> a meaningful question for the relevant languages of certain C symbol names
> being reserved or not reserved.  Language runtimes also include e.g.
> libdfp (on which basis the printf hooks functionality should be exported
> under implementation-namespace names).

Anything providing a plug-in framework is probably a language run-time 
in this sense.

> Doing it more systematically for glibc function symbols rather than only
> supporting it for particular privileged language runtimes seems reasonable
> to me.

Fine.

>> To keep things simple, I suggest that for all new function symbols, we declare
>> __libc_foo in the header file, redirect foo to __libc_foo, export both at the
>> same symbol version from the DSO, and make __libc_foo a strong definition and
>> foo a weak one.  (We should not add new variable symbols.)
>
> I take it this is __libc_foo independent of which library contains foo (so
> no __libm_foo, __libpthread_foo etc.)?

Yes, this was my intent.  I'm not fixated on a particular prefix.  I 
just want to avoid a new discussion for each symbol.

> There are a few existing __libc_foo exports at public symbol versions.  Do
> all those satisfy the rule that where both foo and __libc_foo exist, the
> latest version of foo and the latest version of __libc_foo are aliases or
> otherwise have the same semantics?  (It would seem very confusing for old
> and new __libc_* symbols to follow different rules in that regard.)

I found a few symbols which differs in the exported version.  The 
unprefixed symbol has a regular version, and the prefixed one appears as 
GLIBC_PRIVATE.  These are:

clntudp_bufcreate
fork
longjmp
pread
pwrite
secure_getenv
siglongjmp
system
vfork

__libc_clntudp_bufcreate is GLIBC_PRIVATE and takes an additional 
argument compared to clntudp_bufcreate, so that's a true mismatch.  It's 
used from libnsl.so.

fork, longjmp, siglongjmp, vfork are aliases for the redirection from 
libpthread.  They cannot use the usual __ alias because they define that 
as well.

I don't know why pread, pwrite have __libc_-prefixed aliases instead of 
__-prefixed ones.  I think the goal is namespace-cleanliness, so either 
one would work.

Unfortunately, my current symbol lists do not include symbol values, so 
finding further discrepancies (which have the same version, but 
different values) is not entirely straightforward.  I'll see what I can 
do to get more data (probably using some Perl script; unfortunately 
dlysm is currently broken in the presence of multiple symbol versions).

> What should be done where the symbol is only added in the implementation
> namespace - symbols for use in redirection for different standard
> versions, macros, inline functions or *_nonshared.a, for example?  Should
> future such symbols also use the __libc_foo namespace (unless there are
> ABI reasons for something else, e.g. the libmvec functions) (so if such a
> practice were implemented before glibc 2.25 came out, __iscanonicall would
> change to __libc_iscanonicall, etc.), or continue being __foo?

I have no strong opinion here.  My reason for using __libc_ instead of 
__ was that other libraries use __ for internal symbols.  With __libc_, 
collisions seem even less likely.

> What about compilers that do not support redirection?

I worry more about things like mlnlffigen or SWIG which parse header 
files and attempt to generate bindings from them.  Our current header 
files are already rather difficult to process by such tools, which often 
contain heuristics, in part to avoid implementing full C, in part to get 
some sort of API out of the header file even if parts of it lives in 
preprocessor macros only.

> Right now we have
> many individual #defines in the case where __REDIRECT is not supported.
> If we required support for asm redirection in compilers using the glibc
> headers, it would be possible to define a macro to declare both foo and
> __libc_foo, with the same type and the same attributes (and the same throw
> () information for C++), and do the redirection, all with one macro call.
> Otherwise you get a lot of repetitive boilerplate in headers for every
> such function, since a macro cannot generate a #define of another macro.
> Or you say that compilers without redirection support don't get any of
> these redirections, since they are not semantically required.

Unfortunately, I forgot an important detail:

Even in the __GNUC__ case, we need more than just the declaration.  If 
we just set an asm alias, an interposing definition supplied by the user 
will happily interpose the supposedly-protected alias.

This is less relevant for functions in non-standard headers (which 
applications would not include accidentally), but if we add something to 
<stdio.h> (under _GNU_SOURCE) which is ripe for collisions, we need to 
somehow make sure that a user-defined function of the same name does not 
end up interposing the alias.

The easiest way to do this is to add a function-style macro which 
expends to something that cannot be parsed as part of a function 
definition.  We discussed using inline functions for this, but this 
appraoch was rejected due to standards compliance concerns.  But maybe 
the desire to put all this in a single macro definition will make us 
reconsider.  On the hand, inline functions are particularly hard on some 
wrapper generators.  The internal binding generator of LuaJIT, for 
example, supports asm aliases, but ignores inline functions.

> (When you're dealing with API issues as well as ABI then the macro
> solution runs into complications with wanting to declare __libc_foo
> unconditionally for use in libstdc++ headers, but foo only when the right
> feature test macros are defined.  Those complications can certainly be
> resolved, e.g. with macros __<something>_GNU to do the declaration whose
> definitions depend on the feature test macros defined, and a first
> solution might well only deal with the ABI issues and leave the API ones
> for later.)

Yes, please. :)

> Being able to make all the declarations with a single macro is attractive,
> since right now I'm sure that lots of the declarations in internal
> include/ headers are in fact suboptimal because they are missing
> attributes present on the public declarations.  It would also have the
> potential for defining variants of such macros in future that also do
> *_hidden_proto (for public and internal function names) when building
> glibc.  Recall that *_hidden_* are still needed even for internal function
> names, whether or not those names are exported - if exported, failure to
> use *_hidden_* will be visible through localplt test failures, but if not
> exported, less efficient code is still generated in the caller on 32-bit
> x86 if the function isn't visibly hidden
> <https://sourceware.org/bugzilla/show_bug.cgi?id=18822>.

With consistent internal and external mangling (which was not the goal 
of my proposal, but I can see how it is related), we could compile 
sources within libc and outside, for unit testing purposes.  It would 
also make it easier to avoid linknamespace violations.  But that needs 
new aliases for basically everything.

> In fact we have evidence
> <https://sourceware.org/ml/libc-alpha/2014-09/msg00017.html> that the
> headers have had problems for a long time for compilers not defining
> __GNUC__, and those include problems relating to redirection.

Ugh.

Part of the problem is that we don't have a C89 or C++98 implementation 
with which we can test easily.  I'm not aware of any way to turn GCC or 
Clang into a C89-only or a C++98-only compiler (and you said we'd need 
some extensions anyway).

>> For existing symbols, we only do this if we receive reports of conflicts
>> causing problems in the field.  In this case, we add __libc_foo and the
>> redirect to the header file, and use the current symbol version for the
>> __libc_foo export (not the one of foo).
>
> "causing problems in the field" should be broadly interpreted there - to
> allow adding lots of such functions if someone identifies what's needed to
> make the libstdc++ headers or libraries namespace-clean, for example, or
> for fixing the namespace issues described in
> <https://sourceware.org/bugzilla/show_bug.cgi?id=14106>.

Yes, I would assume this is fine.

> What should be done in the case where __foo already has an export at a
> public symbol version (and we have a use for __libc_foo)?  Should we
> arrange for __foo to be declared (with associated redirections) and say
> people should be using that, or add __libc_foo as well?  What about where
> __foo is already exported, but that export is a compat symbol (if there
> are any such cases)?  Making it not a compat symbol would run into needing
> new exports at new versions on platforms postdating the version where it
> was made a compat symbol, and you don't want the API to be __foo on some
> platforms and __libc_foo on others.

I think this leads to the question whether we should prefer __ over 
__libc_ after all because as part of fixing the glibc-internal 
linknamespace issues, we often added a __ symbol with a public version 
(but sometimes a GLIBC_PRIVATE version as well).  I would prefer if we 
could reuse those symbol names.  I don't think we can switch them to 
__libc_ because they were part of the ABI, although they were not part 
of any header file.

I'm less convinced now in which direction to move.  Unfortunately, this 
has ABI impact, so the consequences are far from trivial.

Maybe we need to take a step back and ask ourselves if we should use 
symbol versioning to address this.  The two blockers I know of are 
purely static links, and the design decision (no doubt for backwards 
compatibility) to interpose versioned symbols with unversioned symbols. 
The latter is difficult to address, but if we could make the change 
somehow, it would enable a nice performance boost in the dynamic linker, 
too.  But it certainly looks like that for the static link case, we only 
have the header files we can tweak to achieve what we want.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Evolution of ELF symbol management
  2016-10-25 14:32   ` Florian Weimer
@ 2016-10-25 15:37     ` Joseph Myers
  2016-11-21 15:35       ` Florian Weimer
  2016-10-26 12:17     ` Joseph Myers
  2016-11-20 11:13     ` Mike Frysinger
  2 siblings, 1 reply; 19+ messages in thread
From: Joseph Myers @ 2016-10-25 15:37 UTC (permalink / raw)
  To: Florian Weimer; +Cc: GNU C Library

On Tue, 25 Oct 2016, Florian Weimer wrote:

> > There are a few existing __libc_foo exports at public symbol versions.  Do
> > all those satisfy the rule that where both foo and __libc_foo exist, the
> > latest version of foo and the latest version of __libc_foo are aliases or
> > otherwise have the same semantics?  (It would seem very confusing for old
> > and new __libc_* symbols to follow different rules in that regard.)
> 
> I found a few symbols which differs in the exported version.  The unprefixed
> symbol has a regular version, and the prefixed one appears as GLIBC_PRIVATE.
> These are:
> 
> clntudp_bufcreate
> fork
> longjmp
> pread
> pwrite
> secure_getenv
> siglongjmp
> system
> vfork

My concern is mainly about __libc_* symbols at public versions, not 
GLIBC_PRIVATE, since we can freely change the ABIs for __libc_* at 
GLIBC_PRIVATE if those are confusing.

> > Right now we have
> > many individual #defines in the case where __REDIRECT is not supported.
> > If we required support for asm redirection in compilers using the glibc
> > headers, it would be possible to define a macro to declare both foo and
> > __libc_foo, with the same type and the same attributes (and the same throw
> > () information for C++), and do the redirection, all with one macro call.
> > Otherwise you get a lot of repetitive boilerplate in headers for every
> > such function, since a macro cannot generate a #define of another macro.
> > Or you say that compilers without redirection support don't get any of
> > these redirections, since they are not semantically required.
> 
> Unfortunately, I forgot an important detail:
> 
> Even in the __GNUC__ case, we need more than just the declaration.  If we just
> set an asm alias, an interposing definition supplied by the user will happily
> interpose the supposedly-protected alias.
> 
> This is less relevant for functions in non-standard headers (which
> applications would not include accidentally), but if we add something to
> <stdio.h> (under _GNU_SOURCE) which is ripe for collisions, we need to somehow
> make sure that a user-defined function of the same name does not end up
> interposing the alias.

Same name and type, that is; if the type is wrong and the header 
declaration is visible, a compile-time error will occur.

> The easiest way to do this is to add a function-style macro which expends to
> something that cannot be parsed as part of a function definition.  We
> discussed using inline functions for this, but this appraoch was rejected due
> to standards compliance concerns.  But maybe the desire to put all this in a
> single macro definition will make us reconsider.  On the hand, inline
> functions are particularly hard on some wrapper generators.  The internal
> binding generator of LuaJIT, for example, supports asm aliases, but ignores
> inline functions.

There is always the option of having the installed headers be generated 
files, so the source tree has .h.in files that contain some sort of 
annotations for use by a special glibc-specific preprocessor that does 
things the C preprocessor cannot - converting something that looks like a 
C macro call (say) into function declarations, __REDIRECT calls - and 
function-like macro definitions.  Of course then you need to get those 
headers generated at an early stage in the glibc build.

Or define a new function attribute whose meaning is that the asm 
redirection is disregarded if defining the function, but then user code 
would only be protected against accidental interposition when built with a 
compiler supporting that new attribute.

> I think this leads to the question whether we should prefer __ over __libc_
> after all because as part of fixing the glibc-internal linknamespace issues,
> we often added a __ symbol with a public version (but sometimes a

We shouldn't have added them with public versions, just internally (and 
only at GLIBC_PRIVATE if needed by a separate library from the 
definition).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Evolution of ELF symbol management
  2016-10-25 14:32   ` Florian Weimer
  2016-10-25 15:37     ` Joseph Myers
@ 2016-10-26 12:17     ` Joseph Myers
  2016-11-20 11:13     ` Mike Frysinger
  2 siblings, 0 replies; 19+ messages in thread
From: Joseph Myers @ 2016-10-26 12:17 UTC (permalink / raw)
  To: Florian Weimer; +Cc: GNU C Library

Further consideration of the __libc_* approach:

There are some cases that should never need public aliases: (a) ISO C90 
functions (no aliases needed unless called from macros defined in system 
headers - such macros should properly call C90 functions by aliases in 
case they are shadowed by local variables in the function calling the 
macro; the function names are reserved with file scope / external linkage, 
but not as local variable names); (b) obsolete functions (even if we still 
support linking with a deprecated function because it's in an older 
standard we support, we could say namespace-clean use of it isn't 
supported); (c) if multiple public functions are or should be aliased to 
each other, e.g. for long double = double, we could have just one __libc_* 
alias between them.

> Maybe we need to take a step back and ask ourselves if we should use symbol
> versioning to address this.  The two blockers I know of are purely static
> links, and the design decision (no doubt for backwards compatibility) to
> interpose versioned symbols with unversioned symbols. The latter is difficult
> to address, but if we could make the change somehow, it would enable a nice
> performance boost in the dynamic linker, too.  But it certainly looks like
> that for the static link case, we only have the header files we can tweak to
> achieve what we want.

And symbol versioning cannot help with the API issue of C++ compilations 
being forced to use _GNU_SOURCE because much of the libstdc++ 
implementation is in the headers and wants to use libc features outside 
the libc subset defined in the C++ standard.  That requires public API 
aliases for lots of functions (maybe for constants, types etc. as well).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Evolution of ELF symbol management
  2016-10-18  9:26 Evolution of ELF symbol management Florian Weimer
  2016-10-18 16:50 ` Joseph Myers
@ 2016-11-16 15:55 ` Zack Weinberg
  2016-11-18 15:48   ` Florian Weimer
  1 sibling, 1 reply; 19+ messages in thread
From: Zack Weinberg @ 2016-11-16 15:55 UTC (permalink / raw)
  To: libc-alpha

On 10/18/2016 05:26 AM, Florian Weimer wrote:
> With this message, I want to start a discussion why this symbol
> mangling stops at glibc-internal cross-DSO references (or static
> linking).  Wouldn't other system libraries, such as libstdc++, glib,
> Qt and so on need to do the same thing?  After all, if Qt calls
> foo@GLIBC_2.31, and the main program defines foo (which the static
> linker automatically exports to enable interposition), we almost
> certainly would want Qt to continue to call foo@GLIBC_2.31, and not
> the potentially incompatible implementation of foo in the main
> program.
> 
> To keep things simple, I suggest that for all new function symbols,
> we declare __libc_foo in the header file, redirect foo to
> __libc_foo, export both at the same symbol version from the DSO, and
> make __libc_foo a strong definition and foo a weak one.  (We should
> not add new variable symbols.)
> 
> For existing symbols, we only do this if we receive reports of
> conflicts causing problems in the field.  In this case, we add
> __libc_foo and the redirect to the header file, and use the current
> symbol version for the __libc_foo export (not the one of foo).

I meant to respond to this last month but have not been able to scrape
time away from $DAYJOB until this week.  Apologies.

First, I don't have a problem with adding __libc_* aliases as
non-default but public alternative names, so that third-party libraries
can avoid namespace pollution in static linkage and/or choose to refer
to symbols that are more likely to get resolved to the C library's
export than to a colliding symbol in the main executable.  I'd reserve
that for cases where there is already a demonstrated need, though, such
as libstdc++.  I also don't have a problem with a hypothetical policy
that all new symbols that aren't in the current revisions of C+POSIX
should be given an impl-namespace name as their primary definition, with
the user-namespace name being a weak alias (but still the only name used
in the public headers).

I _do_ have problems with causing these symbols to be used by default.
My main concern is that I think it's tackling the problem in the wrong
place.  If we want to back away from the original principle that the
executable always wins, isn't an expanded version of -Bsymbolic mode
what's _really_ wanted?  That is, an opt-in link-time declaration that
you want all dynamic symbols resolved at load-time to the same library
that provided them at link-time.  Once that exists, we could try to move
slowly in the direction of turning it on by default, along with various
other "yes, fix the bug" linker toggles like -z relro and --as-needed.
Until and unless this possibility has been thoroughly explored and
determined unworkable, I will object to bulk addition of __libc_*
aliases, and to an "all new public prototypes must redirect to a
__libc_* alias" rule.

A secondary reason for not wanting __libc_* aliases to be activated by
default is that it doesn't seem to me that it actually solves the
problem.  Applications that _want_ to interpose are going to shift to
the __libc_* names; depending on what the headers actually do,
applications that don't care (but do define a conflicting symbol) might
wind up shifting to those names by accident.  __REDIRECT doesn't work
without GCC(-compatible) extensions, after all.  (I would not object to
a _documented and enforced_ set of GCC-compatible extensions being a
baseline requirement for use of glibc headers -- but that would need to
happen _first_.)

zw

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Evolution of ELF symbol management
  2016-11-16 15:55 ` Zack Weinberg
@ 2016-11-18 15:48   ` Florian Weimer
  2016-11-19 17:25     ` Zack Weinberg
  0 siblings, 1 reply; 19+ messages in thread
From: Florian Weimer @ 2016-11-18 15:48 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: libc-alpha

On 11/16/2016 04:55 PM, Zack Weinberg wrote:

> First, I don't have a problem with adding __libc_* aliases as
> non-default but public alternative names, so that third-party libraries
> can avoid namespace pollution in static linkage and/or choose to refer
> to symbols that are more likely to get resolved to the C library's
> export than to a colliding symbol in the main executable.  I'd reserve
> that for cases where there is already a demonstrated need, though, such
> as libstdc++.  I also don't have a problem with a hypothetical policy
> that all new symbols that aren't in the current revisions of C+POSIX
> should be given an impl-namespace name as their primary definition, with
> the user-namespace name being a weak alias (but still the only name used
> in the public headers).

If we don't declare the library-safe names in headers, how can libraries 
call them?

I also do not want to encourage application or library code to reference 
the implementation namespace at the source code level.  It's ugly, and I 
suspect it encourages implementation namespace pollution once 
programmers are used to it.

> I _do_ have problems with causing these symbols to be used by default.
> My main concern is that I think it's tackling the problem in the wrong
> place.  If we want to back away from the original principle that the
> executable always wins, isn't an expanded version of -Bsymbolic mode
> what's _really_ wanted?

We could cover a lot of ground if we had a new flag on versioned symbol 
definitions which tells the static linker to set a flag on the versioned 
symbol reference, and the dynamic linker would then use this flag to 
ignore unversioned symbols for binding symbols.

(The static linker currently does not add the version of the interposed 
symbol when interposition happens at static link time.)

*However*, this is hardly a complete solution.  It does not cover symbol 
references from public C++ headers because there is no static linker 
invocation that comes between application use of the symbol and the use 
from system headers.

It also does not work for static libraries.  In those cases, we could 
perhaps do some post-processing to add the symbol versions to the .a 
files, but it would still need the interposition protection mentioned 
above *and* changes to how we build static libraries.

> That is, an opt-in link-time declaration that
> you want all dynamic symbols resolved at load-time to the same library
> that provided them at link-time.  Once that exists, we could try to move
> slowly in the direction of turning it on by default, along with various
> other "yes, fix the bug" linker toggles like -z relro and --as-needed.

The build changes I mentioned in the previous paragraph are more 
invasive than just adding a flag to gcc's ld invocation because there is 
currently no such invocation at all.  We could put it into ar or ranlib, 
but that's perhaps too much magic.  A new linking step would be needed.

The header files could contain the symbol version and instruct GCC to 
put it into the header file.  (Even today, it is possible to link 
against specific symbol versions without a custom DSO containing them as 
the default version, but please don't tell anyone.)  But this would 
still need the interposition protection.  I still think this is the most 
promising option, all things considered.

But then we need to step back and ask ourselves: If we have to put the 
versioning information in the header, why do we even need symbol 
versioning?  Why can't we version the interface through its name?

Hence my proposal.

> A secondary reason for not wanting __libc_* aliases to be activated by
> default is that it doesn't seem to me that it actually solves the
> problem.  Applications that _want_ to interpose are going to shift to
> the __libc_* names; depending on what the headers actually do,
> applications that don't care (but do define a conflicting symbol) might
> wind up shifting to those names by accident.

What I would like is a GCC attribute which tells the compiler that the 
declaration must not be completed with a definition in this translation 
unit.  That would make the asm aliases pretty robust because then you 
can only reach the implementation namespace by explicitly referencing it 
in your sources.

Deliberate interposition is much easier if you don't have to worry about 
linker tricks and the unversioned-symbol-interposes-all-versioned-symbol 
issue (which you cannot detect in the interposing DSO).

> __REDIRECT doesn't work
> without GCC(-compatible) extensions, after all.  (I would not object to
> a _documented and enforced_ set of GCC-compatible extensions being a
> baseline requirement for use of glibc headers -- but that would need to
> happen _first_.)

I wouldn't like that, there are many consumers for header files which 
aren't compilers (and would not be forced to implement many GNU extensions).

Thanks,
Florian

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Evolution of ELF symbol management
  2016-11-18 15:48   ` Florian Weimer
@ 2016-11-19 17:25     ` Zack Weinberg
  2016-11-22 15:09       ` Florian Weimer
  0 siblings, 1 reply; 19+ messages in thread
From: Zack Weinberg @ 2016-11-19 17:25 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, Siddhesh Poyarekar

On 11/18/2016 10:48 AM, Florian Weimer wrote:
> On 11/16/2016 04:55 PM, Zack Weinberg wrote:
> 
>> First, I don't have a problem with adding __libc_* aliases as
>> non-default but public alternative names, so that third-party libraries
>> can avoid namespace pollution in static linkage and/or choose to refer
>> to symbols that are more likely to get resolved to the C library's
>> export than to a colliding symbol in the main executable.  I'd reserve
>> that for cases where there is already a demonstrated need, though, such
>> as libstdc++.  I also don't have a problem with a hypothetical policy
>> that all new symbols that aren't in the current revisions of C+POSIX
>> should be given an impl-namespace name as their primary definition, with
>> the user-namespace name being a weak alias (but still the only name used
>> in the public headers).
> 
> If we don't declare the library-safe names in headers, how can libraries
> call them?

We could _declare_ the library-safe names in the headers, just not as
the primaries.  Like how string.h currently declares both bzero and __bzero.

Incidentally, it occurrs to me that the user-namespace name must exist,
for the sake of people using dlsym(RTLD_DEFAULT, "whatever") to access
symbols that they anticipate existing in future revisions of libc
(relative to the one they used at link time).

> I also do not want to encourage application or library code to reference
> the implementation namespace at the source code level.  It's ugly, and I
> suspect it encourages implementation namespace pollution once
> programmers are used to it.

I don't like it either, but how else could a library's headers opt into
these special names on a per-symbol, per-use basis?

Come to think of it, to actually avoid polluting the user namespace, any
library that wants to use these will need a secondary set of libc
headers that declare _only_ the private names.  (This is especially
relevant for C++ with so much code in headers.)  If we don't do that,
the user-namespace libc prototype (which still exists under your plan)
might conflict with an unrelated application definition.

I don't like _that_, because now we have to maintain multiple copies of
the same set of prototypes with different names *in different headers*.
But again, I don't see an alternative in C.  Maybe we could get
'namespace', 'using', and 'extern "C++"' added to C as a GCC extension?
That would _help_.  In fact, that would solve all kinds of problems.
(But we'd have to give up the pretense that our headers work with
anything but GCC.)

>> I _do_ have problems with causing these symbols to be used by default.
>> My main concern is that I think it's tackling the problem in the wrong
>> place.  If we want to back away from the original principle that the
>> executable always wins, isn't an expanded version of -Bsymbolic mode
>> what's _really_ wanted?
> 
> We could cover a lot of ground if we had a new flag on versioned symbol
> definitions which tells the static linker to set a flag on the versioned
> symbol reference, and the dynamic linker would then use this flag to
> ignore unversioned symbols for binding symbols.

I was imagining a new annotation on _all_ undefined symbols in a shared
object, giving the soname of the object that they were satisfied by at
link time.  At load time, 'getrandom!libc.so.6' resolves to the
'getrandom' definition in libc.so.6, ignoring all other definitions of
the same name.  If there are symbol versions involved, only the versions
exported by libc.so.6 are considered.  For instance,
'getrandom!libc.so.6@GLIBC_2.25' cannot be satisfied by
'getrandom@GLIBC_2.25' exported by libmissing-syscalls.so.1.

> (The static linker currently does not add the version of the interposed
> symbol when interposition happens at static link time.)

I don't understand this statement, and that makes me worry that you are
trying to solve a different problem from the one I thought you were
talking about -- a problem that I might not even know exists.  Can you
elaborate, please?  How can a shared object be interposed upon at static
link time?  Its own static link has already happened!

> *However*, this is hardly a complete solution.  It does not cover symbol
> references from public C++ headers because there is no static linker
> invocation that comes between application use of the symbol and the use
> from system headers.

See above.

> It also does not work for static libraries.  In those cases, we could
> perhaps do some post-processing to add the symbol versions to the .a
> files, but it would still need the interposition protection mentioned
> above *and* changes to how we build static libraries.

Yes, to apply my proposal to static libraries, a new linking step would
be needed, functionally the same as the one that already exists for
shared libraries, but with different effects -- either adding a new
archive member with a bunch of annotations, or rewriting all the .o
files with those annotations.

Frankly I don't care very much about static libraries; I'd be fine with
allowing them to continue to work as they do now (it is already the
case, for instance, that the executable can interpose on internal libc
symbols in a static link that are inaccessible to it in a shared link).

> The header files could contain the symbol version and instruct GCC to
> put it into the header file.  (Even today, it is possible to link
> against specific symbol versions without a custom DSO containing them as
> the default version, but please don't tell anyone.)  But this would
> still need the interposition protection.  I still think this is the most
> promising option, all things considered.
> 
> But then we need to step back and ask ourselves: If we have to put the
> versioning information in the header, why do we even need symbol
> versioning?  Why can't we version the interface through its name?
> 
> Hence my proposal.

You keep talking about symbol versioning but, again, I don't understand
how symbol versioning is relevant, and that makes me worry that you're
trying to solve a different problem that I don't even know about.  I
thought the issue here was controlling *which library* provides a
symbol, independent of whether the symbol has versions.

As for what appears in the headers -- again, see above: to solve the
libstdc++/_GNU_SOURCE problem, which I believe I *do* understand, there
needs to be a set of alternative names that libstdc++ headers can
*explicitly* refer to; otherwise we have still polluted the user
namespace.  REDIRECTed declarations do not solve that problem.  In fact,
with my proposed which-library annotations, we could perfectly well
redirect the mangled names to the normal names:

extern ssize_t __libc_getrandom (void *, size_t, unsigned int)
  __asm ("getrandom") __attribute__ ((__bind_to_library ("libc.so.6")));

#ifdef __USE_GNU
extern typeof (__libc_getrandom) getrandom;
#endif

----

All this aside, this discussion is still very brainstormy and that makes
me think that we should *not* yet be supplying mangled names for public
use.  Once we start doing that we are stuck with it forever, after all.
Contrariwise, we *can* always retrofit __libc_* aliases or whatever once
we know what we ought to be doing.

Similarly, this should not be a blocker issue for new 2.25 features. (On
that note, cc:ing Siddhesh with their release manager hat on.)

zw

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Evolution of ELF symbol management
  2016-10-25 14:32   ` Florian Weimer
  2016-10-25 15:37     ` Joseph Myers
  2016-10-26 12:17     ` Joseph Myers
@ 2016-11-20 11:13     ` Mike Frysinger
  2016-11-21 10:12       ` Florian Weimer
  2 siblings, 1 reply; 19+ messages in thread
From: Mike Frysinger @ 2016-11-20 11:13 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Joseph Myers, GNU C Library

[-- Attachment #1: Type: text/plain, Size: 835 bytes --]

On 25 Oct 2016 16:32, Florian Weimer wrote:
> On 10/18/2016 06:49 PM, Joseph Myers wrote:
> > In fact we have evidence
> > <https://sourceware.org/ml/libc-alpha/2014-09/msg00017.html> that the
> > headers have had problems for a long time for compilers not defining
> > __GNUC__, and those include problems relating to redirection.
> 
> Ugh.
> 
> Part of the problem is that we don't have a C89 or C++98 implementation 
> with which we can test easily.  I'm not aware of any way to turn GCC or 
> Clang into a C89-only or a C++98-only compiler (and you said we'd need 
> some extensions anyway).

you mean specifically non-GNU extensions ?  does having gcc-2.95.3 help ?

this might work for x86 systems:
	https://dev.gentoo.org/~vapier/gcc-2.95.3-r10.tbz2
if it helps, i could make it a bit more standalone.
-mike

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Evolution of ELF symbol management
  2016-11-20 11:13     ` Mike Frysinger
@ 2016-11-21 10:12       ` Florian Weimer
  0 siblings, 0 replies; 19+ messages in thread
From: Florian Weimer @ 2016-11-21 10:12 UTC (permalink / raw)
  To: Joseph Myers, GNU C Library

On 11/20/2016 12:13 PM, Mike Frysinger wrote:
> On 25 Oct 2016 16:32, Florian Weimer wrote:
>> On 10/18/2016 06:49 PM, Joseph Myers wrote:
>>> In fact we have evidence
>>> <https://sourceware.org/ml/libc-alpha/2014-09/msg00017.html> that the
>>> headers have had problems for a long time for compilers not defining
>>> __GNUC__, and those include problems relating to redirection.
>>
>> Ugh.
>>
>> Part of the problem is that we don't have a C89 or C++98 implementation
>> with which we can test easily.  I'm not aware of any way to turn GCC or
>> Clang into a C89-only or a C++98-only compiler (and you said we'd need
>> some extensions anyway).
>
> you mean specifically non-GNU extensions ?  does having gcc-2.95.3 help ?

No, because most of the the GNU stuff is already in that version.

I have a 2.7.2 build somewhere, and checked recently that at least some 
of the headers still work with it.  But that doesn't tell us all that 
much about C89 compatibility.

Florian

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Evolution of ELF symbol management
  2016-10-25 15:37     ` Joseph Myers
@ 2016-11-21 15:35       ` Florian Weimer
  0 siblings, 0 replies; 19+ messages in thread
From: Florian Weimer @ 2016-11-21 15:35 UTC (permalink / raw)
  To: Joseph Myers; +Cc: GNU C Library

[-- Attachment #1: Type: text/plain, Size: 3287 bytes --]

On 10/25/2016 05:37 PM, Joseph Myers wrote:
> On Tue, 25 Oct 2016, Florian Weimer wrote:
>
>>> There are a few existing __libc_foo exports at public symbol versions.  Do
>>> all those satisfy the rule that where both foo and __libc_foo exist, the
>>> latest version of foo and the latest version of __libc_foo are aliases or
>>> otherwise have the same semantics?  (It would seem very confusing for old
>>> and new __libc_* symbols to follow different rules in that regard.)
>>
>> I found a few symbols which differs in the exported version.  The unprefixed
>> symbol has a regular version, and the prefixed one appears as GLIBC_PRIVATE.
>> These are:
>>
>> clntudp_bufcreate
>> fork
>> longjmp
>> pread
>> pwrite
>> secure_getenv
>> siglongjmp
>> system
>> vfork
>
> My concern is mainly about __libc_* symbols at public versions, not
> GLIBC_PRIVATE, since we can freely change the ABIs for __libc_* at
> GLIBC_PRIVATE if those are confusing.

I put together the attached Python script to check for collisions.  It 
reports anything that is not UNDEF or GLIBC_PRIVATE and where the 
__libc_-prefixed and non-prefixed symbols have different values.  It 
reports some mismatches in libasan, so I think it works.  It does not 
flag anything for glibc on i386 and x86_64 with current master.

The script has a hard-coded path to elfutils readelf, it needs Mark's 
recent addition of the --symbols=SECTION argument.

So I think we are good on this front.

>> This is less relevant for functions in non-standard headers (which
>> applications would not include accidentally), but if we add something to
>> <stdio.h> (under _GNU_SOURCE) which is ripe for collisions, we need to somehow
>> make sure that a user-defined function of the same name does not end up
>> interposing the alias.
>
> Same name and type, that is; if the type is wrong and the header
> declaration is visible, a compile-time error will occur.

Good point.  We could add artificial transparent unions to arguments to 
make it harder to write a matching definition, even with current GCC 
versions.

> There is always the option of having the installed headers be generated
> files, so the source tree has .h.in files that contain some sort of
> annotations for use by a special glibc-specific preprocessor that does
> things the C preprocessor cannot - converting something that looks like a
> C macro call (say) into function declarations, __REDIRECT calls - and
> function-like macro definitions.  Of course then you need to get those
> headers generated at an early stage in the glibc build.

Interesting idea.

We could generate a different set of such headers of internal glibc user 
if required.  This could allow us to compile more parts of glibc as 
standard C sources, without mangling of public symbols, which would help 
with things like unit testing and fuzz testing.

>> I think this leads to the question whether we should prefer __ over __libc_
>> after all because as part of fixing the glibc-internal linknamespace issues,
>> we often added a __ symbol with a public version (but sometimes a
>
> We shouldn't have added them with public versions, just internally (and
> only at GLIBC_PRIVATE if needed by a separate library from the
> definition).

It's a bit too late for that, unfortunately.

Florian


[-- Attachment #2: glibc-libc-symbols-conflicts.py --]
[-- Type: text/x-python, Size: 2280 bytes --]

#!/usr/bin/python

import collections
import re
import subprocess
import sys

Version = collections.namedtuple("Version", "name default")
Symbol = collections.namedtuple("Symbol", "name version value")

RE_SYMBOL_LINE = re.compile(r"^\d+: ")
RE_SPACES = re.compile(r"\s+")

READELF = "/home/fweimer/src/ext/elfutils/e/src/readelf"

def get_symbols(path):
    p = subprocess.Popen([READELF, "--symbols=.dynsym", "--", path],
                         stdout=subprocess.PIPE)
    for line in p.stdout.readlines():
        line = line.strip()
        if RE_SYMBOL_LINE.match(line):
            split_line = RE_SPACES.split(line)
            # Num(0) Value(1) Size(2) Type(3) Bind(4) Vis(5) Ndx(6) Name(7)
            if len(split_line) < 8:
                continue
            value = int(split_line[1], 16)
            binding = split_line[4]
            ndx = split_line[6]
            name = split_line[7]
            
            if ndx == 'UNDEF':
                continue
            if binding == 'LOCAL':
                continue
            default= False
            if "@@" in name:
                default = True
                name, version = name.split("@@")
            elif "@" in name:
                name, version = name.split("@")
            else:
                version = None
            if version is None:
                yield Symbol(name, None, value)
            else:
                yield Symbol(name, Version(version, default), value)
    if p.wait() != 0:
        raise IOError(
            "readelf failed with exit status {}".format(p.returncode))

def check_file(path):
    with open(path, "rb") as dso:
        if dso.read(4) != "\177ELF":
            return
    
    libc_prefix = {}
    no_prefix = {}
    for sym in get_symbols(path):
        if sym.version and sym.version.name == "GLIBC_PRIVATE":
            continue
        if sym.name.startswith("__libc_"):
            libc_prefix[sym.name] = sym
        else:
            no_prefix[sym.name] = sym

    for np_sym in no_prefix.values():
        libc_sym = libc_prefix.get("__libc_" + np_sym.name, None)
        if libc_sym is None:
            continue
        if libc_sym.value != np_sym.value:
            print path, np_sym, libc_sym

for path in sys.argv[1:]:
    check_file(path)

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Evolution of ELF symbol management
  2016-11-19 17:25     ` Zack Weinberg
@ 2016-11-22 15:09       ` Florian Weimer
  2016-11-22 15:30         ` Andreas Schwab
                           ` (2 more replies)
  0 siblings, 3 replies; 19+ messages in thread
From: Florian Weimer @ 2016-11-22 15:09 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: libc-alpha, Siddhesh Poyarekar

On 11/19/2016 06:25 PM, Zack Weinberg wrote:
> On 11/18/2016 10:48 AM, Florian Weimer wrote:
>> On 11/16/2016 04:55 PM, Zack Weinberg wrote:
>>
>>> First, I don't have a problem with adding __libc_* aliases as
>>> non-default but public alternative names, so that third-party libraries
>>> can avoid namespace pollution in static linkage and/or choose to refer
>>> to symbols that are more likely to get resolved to the C library's
>>> export than to a colliding symbol in the main executable.  I'd reserve
>>> that for cases where there is already a demonstrated need, though, such
>>> as libstdc++.  I also don't have a problem with a hypothetical policy
>>> that all new symbols that aren't in the current revisions of C+POSIX
>>> should be given an impl-namespace name as their primary definition, with
>>> the user-namespace name being a weak alias (but still the only name used
>>> in the public headers).
>>
>> If we don't declare the library-safe names in headers, how can libraries
>> call them?
>
> We could _declare_ the library-safe names in the headers, just not as
> the primaries.  Like how string.h currently declares both bzero and __bzero.

I have no idea at all why __bzero was introduced.  It doesn't look like 
a particularly compelling example (similar to __secure_getenv).  It may 
have been a SunOS thing.

> Incidentally, it occurrs to me that the user-namespace name must exist,
> for the sake of people using dlsym(RTLD_DEFAULT, "whatever") to access
> symbols that they anticipate existing in future revisions of libc
> (relative to the one they used at link time).

There also configure scripts which do

extern char whatever();
main () { whatever(); }

for link testing, without including the appropriate header (perhaps 
deliberately).  That could be considered broken.  I'm not sure.

>> I also do not want to encourage application or library code to reference
>> the implementation namespace at the source code level.  It's ugly, and I
>> suspect it encourages implementation namespace pollution once
>> programmers are used to it.
>
> I don't like it either, but how else could a library's headers opt into
> these special names on a per-symbol, per-use basis?

In general, headers should avoid using libc types, particularly off_t, 
time_t, struct timeval, struct stat, and so on.  But there might be 
exceptions.

For C, it's not clear at all to me whether we need any kind of opt-in 
besides compiling with a particular _*_SOURCE variant (which introduces 
the definition).  We accept that switching to a new glibc version 
requires adjusting source code across the system:

   <https://sourceware.org/ml/libc-alpha/2016-10/msg00307.html>

We can't provide complete source level compatibility on updates, and for 
things compiled with _GNU_SOURCE, it seems to be an explicit non-goal. 
At least that's how I read the previous discussion.

For C++, we might use something based on namespaces to get a clear 
separation.  However, the problem there is that type names and struct 
tags end up in C++ mangled identifiers and thus impact application ABI. 
I have no good idea what to do there.

But to be honest, I was mainly concentrating on function symbols.  I 
understand that other identifiers also present problems.  But with 
those, you can work around issues by reducing the size of translation 
units, at least for C.

> Come to think of it, to actually avoid polluting the user namespace, any
> library that wants to use these will need a secondary set of libc
> headers that declare _only_ the private names.  (This is especially
> relevant for C++ with so much code in headers.)  If we don't do that,
> the user-namespace libc prototype (which still exists under your plan)
> might conflict with an unrelated application definition.

Yes, that's what using a namespace for C++ would achieve.

I'm less convinced we should do this for C.  There is precedent, 
Microsoft did exactly this for the POSIX-inspired interfaces in their 
libc (functions like _open, _close and so on).

> I don't like _that_, because now we have to maintain multiple copies of
> the same set of prototypes with different names *in different headers*.

See Josephs' idea about auto-generating public headers.  It's definitely 
a requirement for this.

> But again, I don't see an alternative in C.

Reducing the size of translation units can be used to sidestep the 
issue, and you can write bridge functions to glue together parts which 
are not directly compatible, providing that there are no symbol clashes 
(which is why I'm particularly interested in symbol collisions).

>>> I _do_ have problems with causing these symbols to be used by default.
>>> My main concern is that I think it's tackling the problem in the wrong
>>> place.  If we want to back away from the original principle that the
>>> executable always wins, isn't an expanded version of -Bsymbolic mode
>>> what's _really_ wanted?
>>
>> We could cover a lot of ground if we had a new flag on versioned symbol
>> definitions which tells the static linker to set a flag on the versioned
>> symbol reference, and the dynamic linker would then use this flag to
>> ignore unversioned symbols for binding symbols.
>
> I was imagining a new annotation on _all_ undefined symbols in a shared
> object, giving the soname of the object that they were satisfied by at
> link time.  At load time, 'getrandom!libc.so.6' resolves to the
> 'getrandom' definition in libc.so.6, ignoring all other definitions of
> the same name.  If there are symbol versions involved, only the versions
> exported by libc.so.6 are considered.  For instance,
> 'getrandom!libc.so.6@GLIBC_2.25' cannot be satisfied by
> 'getrandom@GLIBC_2.25' exported by libmissing-syscalls.so.1.

We still need to support LD_PRELOAD and interposition of arbitrary 
symbols, and not just malloc-related ones, for the benefit of Address 
Sanitizer, fakeroot, cwrap, memstomp and other tools.

This is why hard-coding the DSO name does not seem advisable.

>> (The static linker currently does not add the version of the interposed
>> symbol when interposition happens at static link time.)
>
> I don't understand this statement, and that makes me worry that you are
> trying to solve a different problem from the one I thought you were
> talking about -- a problem that I might not even know exists.  Can you
> elaborate, please?  How can a shared object be interposed upon at static
> link time?  Its own static link has already happened!

When an application is linked against a shared object, if it interposes 
any symbols in it, the symbols becomes exported, so that interposition 
works at run time (otherwise, it could not happen).  You can see an 
example here:

$ nm -Dg malloc/tst-interpose-nothread  | grep ' T '

The application is *not* compiled with -Bdynamic or something like that, 
it happens automatically.

But the symbol version from libc.so.6 is not attached to this symbol 
(“nm” would not show it, but you can check with eu-readelf, for example).

> You keep talking about symbol versioning but, again, I don't understand
> how symbol versioning is relevant,

It's a namespace mechanism for ELF, so it's tempting to use it to 
address this problem as well.

> and that makes me worry that you're
> trying to solve a different problem that I don't even know about.  I
> thought the issue here was controlling *which library* provides a
> symbol, independent of whether the symbol has versions.

I'm not convinced this desirable because of the exceptions I listed 
above.  Both manual name mangling (which I currently prefer) and symbol 
versioning with the no-interpose flag (the one I sketched earlier) would 
support them.  But only name mangling addresses collisions before the 
first static link.

> As for what appears in the headers -- again, see above: to solve the
> libstdc++/_GNU_SOURCE problem, which I believe I *do* understand, there
> needs to be a set of alternative names that libstdc++ headers can
> *explicitly* refer to; otherwise we have still polluted the user
> namespace.  REDIRECTed declarations do not solve that problem.  In fact,
> with my proposed which-library annotations, we could perfectly well
> redirect the mangled names to the normal names:
>
> extern ssize_t __libc_getrandom (void *, size_t, unsigned int)
>   __asm ("getrandom") __attribute__ ((__bind_to_library ("libc.so.6")));
>
> #ifdef __USE_GNU
> extern typeof (__libc_getrandom) getrandom;
> #endif

Yes, I this would work (subject to the existing shortcomings).

> All this aside, this discussion is still very brainstormy and that makes
> me think that we should *not* yet be supplying mangled names for public
> use.  Once we start doing that we are stuck with it forever, after all.
> Contrariwise, we *can* always retrofit __libc_* aliases or whatever once
> we know what we ought to be doing.

I think getrandom is special because the name is rather generic, just 
like some of the new libm names (where we still might have to introduce 
mangling based on feedback from distribution rebuilds; I just don't know 
yet).

Thanks,
Florian

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Evolution of ELF symbol management
  2016-11-22 15:09       ` Florian Weimer
@ 2016-11-22 15:30         ` Andreas Schwab
  2016-11-22 15:39           ` Florian Weimer
  2016-11-22 17:42         ` Joseph Myers
  2016-11-23 14:09         ` Zack Weinberg
  2 siblings, 1 reply; 19+ messages in thread
From: Andreas Schwab @ 2016-11-22 15:30 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Zack Weinberg, libc-alpha, Siddhesh Poyarekar

On Nov 22 2016, Florian Weimer <fweimer@redhat.com> wrote:

> There also configure scripts which do
>
> extern char whatever();
> main () { whatever(); }
>
> for link testing, without including the appropriate header (perhaps
> deliberately).  That could be considered broken.  I'm not sure.

While getting the return type wrong makes it slightly broken, the C
standard does support declaring standard functions on your own, as long
as you don't need special types.

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Evolution of ELF symbol management
  2016-11-22 15:30         ` Andreas Schwab
@ 2016-11-22 15:39           ` Florian Weimer
  2016-11-22 15:48             ` Zack Weinberg
  0 siblings, 1 reply; 19+ messages in thread
From: Florian Weimer @ 2016-11-22 15:39 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Zack Weinberg, libc-alpha, Siddhesh Poyarekar

On 11/22/2016 04:29 PM, Andreas Schwab wrote:
> On Nov 22 2016, Florian Weimer <fweimer@redhat.com> wrote:
>
>> There also configure scripts which do
>>
>> extern char whatever();
>> main () { whatever(); }
>>
>> for link testing, without including the appropriate header (perhaps
>> deliberately).  That could be considered broken.  I'm not sure.
>
> While getting the return type wrong makes it slightly broken, the C
> standard does support declaring standard functions on your own, as long
> as you don't need special types.

Yes, that's true.  Thanks for the reminder.

Florian

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Evolution of ELF symbol management
  2016-11-22 15:39           ` Florian Weimer
@ 2016-11-22 15:48             ` Zack Weinberg
  2016-11-22 15:48               ` Zack Weinberg
  0 siblings, 1 reply; 19+ messages in thread
From: Zack Weinberg @ 2016-11-22 15:48 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Andreas Schwab, GNU C Library, Siddhesh Poyarekar

On Tue, Nov 22, 2016 at 10:39 AM, Florian Weimer <fweimer@redhat.com> wrote:
> On 11/22/2016 04:29 PM, Andreas Schwab wrote:
>>
>> On Nov 22 2016, Florian Weimer <fweimer@redhat.com> wrote:
>>
>>> There also configure scripts which do
>>>
>>> extern char whatever();
>>> main () { whatever(); }
>>>
>>> for link testing, without including the appropriate header (perhaps
>>> deliberately).  That could be considered broken.  I'm not sure.
>>
>> While getting the return type wrong makes it slightly broken, the C
>> standard does support declaring standard functions on your own, as long
>> as you don't need special types.
>
> Yes, that's true.  Thanks for the reminder.

As a practical matter, also, Autoconf has done this for decades and no
one has even sketched a design for a replacement; I think we must
assume we will need to support it for the foreseeable future.

zw

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Evolution of ELF symbol management
  2016-11-22 15:48             ` Zack Weinberg
@ 2016-11-22 15:48               ` Zack Weinberg
  0 siblings, 0 replies; 19+ messages in thread
From: Zack Weinberg @ 2016-11-22 15:48 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Andreas Schwab, GNU C Library, Siddhesh Poyarekar

(I'll respond to the rest of your message later; don't have time today.)

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Evolution of ELF symbol management
  2016-11-22 15:09       ` Florian Weimer
  2016-11-22 15:30         ` Andreas Schwab
@ 2016-11-22 17:42         ` Joseph Myers
  2016-11-23 14:09         ` Zack Weinberg
  2 siblings, 0 replies; 19+ messages in thread
From: Joseph Myers @ 2016-11-22 17:42 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Zack Weinberg, libc-alpha, Siddhesh Poyarekar

On Tue, 22 Nov 2016, Florian Weimer wrote:

> I have no idea at all why __bzero was introduced.  It doesn't look like a

It used to be used in a bits/string2.h definition of memset which 
involved:

  __builtin_constant_p (c) && (c) == '\0'
  ? ({ void *__s = (s); __bzero (__s, n); __s; })
  : memset (s, c, n)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Evolution of ELF symbol management
  2016-11-22 15:09       ` Florian Weimer
  2016-11-22 15:30         ` Andreas Schwab
  2016-11-22 17:42         ` Joseph Myers
@ 2016-11-23 14:09         ` Zack Weinberg
  2016-11-24 10:01           ` Florian Weimer
  2 siblings, 1 reply; 19+ messages in thread
From: Zack Weinberg @ 2016-11-23 14:09 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, Siddhesh Poyarekar

On 11/22/2016 10:09 AM, Florian Weimer wrote:
> On 11/19/2016 06:25 PM, Zack Weinberg wrote:
>> On 11/18/2016 10:48 AM, Florian Weimer wrote:
>>> If we don't declare the library-safe names in headers, how can
>>> libraries call them?
>> 
>> We could _declare_ the library-safe names in the headers, just not
>> as the primaries.  Like how string.h currently declares both bzero
>> and __bzero.
> 
> I have no idea at all why __bzero was introduced.

__bzero was the first case that came to mind where existing headers
declare both a name and a __name for the same function, is all.  I've
been looking at string.h a lot lately.

>>> I also do not want to encourage application or library code to
>>> reference the implementation namespace at the source code level.
>>> It's ugly, and I suspect it encourages implementation namespace
>>> pollution once programmers are used to it.
>> 
>> I don't like it either, but how else could a library's headers opt
>> into these special names on a per-symbol, per-use basis?
> 
> In general, headers should avoid using libc types, particularly
> off_t, time_t, struct timeval, struct stat, and so on.  But there
> might be exceptions.

... I'm not sure why we're suddenly discussing typedef names?

> For C, it's not clear at all to me whether we need any kind of
> opt-in besides compiling with a particular _*_SOURCE variant (which
> introduces the definition).

I am having trouble articulating why I don't like this.  I think it
might be mostly to do with the way new symbols are now different than
old symbols.  I'd be okay with an across-the-board change to symbol
resolution (as discussed below) that made interposition not work by
default, but I'm not okay with the idea of its being supported only for
symbols added before some arbitrary release.

Third-party C libraries don't tend to put nearly as much code in inline
functions, so the need for explicitly-useable __names is lessened there,
I think.

> For C++, we might use something based on namespaces to get a clear 
> separation.  However, the problem there is that type names and
> struct tags end up in C++ mangled identifiers and thus impact
> application ABI. I have no good idea what to do there.

Arguably that's a Good Thing -- a change to what off_t means is an ABI
break whether or not it shows up in symbol names, and _making_ that one
in particular show up in symbol names might solve some of the problems
that lead to _FILE_OFFSET_BITS=64 still not being default for the older
32-bit architectures.

>> Come to think of it, to actually avoid polluting the user
>> namespace, any library that wants to use these will need a
>> secondary set of libc headers that declare _only_ the private
>> names.  (This is especially relevant for C++ with so much code in
>> headers.)  If we don't do that, the user-namespace libc prototype
>> (which still exists under your plan) might conflict with an
>> unrelated application definition.
> 
> Yes, that's what using a namespace for C++ would achieve.
> 
> I'm less convinced we should do this for C.  There is precedent, 
> Microsoft did exactly this for the POSIX-inspired interfaces in
> their libc (functions like _open, _close and so on).

That definitely does cause grief for portable code...

>> I was imagining a new annotation on _all_ undefined symbols in a
>> shared object, giving the soname of the object that they were
>> satisfied by at link time.  At load time, 'getrandom!libc.so.6'
>> resolves to the 'getrandom' definition in libc.so.6, ignoring all
>> other definitions of the same name.  If there are symbol versions
>> involved, only the versions exported by libc.so.6 are considered.
>> For instance, 'getrandom!libc.so.6@GLIBC_2.25' cannot be satisfied
>> by 'getrandom@GLIBC_2.25' exported by libmissing-syscalls.so.1.
> 
> We still need to support LD_PRELOAD and interposition of arbitrary 
> symbols, and not just malloc-related ones, for the benefit of
> Address Sanitizer, fakeroot, cwrap, memstomp and other tools.
> 
> This is why hard-coding the DSO name does not seem advisable.

This argument applies equally to every new symbol we might add, and in
fact to every _intra_-libc call that currently _can't_ be interposed.
So I'm inclined to discount it.

The solution I'm leaning toward involves each library designating a set
of exported symbols, calls to which _can_ be interposed; the default is
not to allow it.  We'd probably have to spend some time figuring out
exactly which of libc's symbols should be interposeable.

> When an application is linked against a shared object, if it
> interposes any symbols in it, the symbols becomes exported, so that
> interposition works at run time (otherwise, it could not happen).
> You can see an example here:
> 
> $ nm -Dg malloc/tst-interpose-nothread  | grep ' T '
> 
> The application is *not* compiled with -Bdynamic or something like
> that, it happens automatically.
> 
> But the symbol version from libc.so.6 is not attached to this symbol 
> (“nm” would not show it, but you can check with eu-readelf, for
> example).

Well, OK, why don't we just fix that?  Is there a good reason why it
_doesn't_ pick up the symbol version?  (I know that for compatibility's
sake an unversioned symbol has to interpose all versions of the same
name, but that wouldn't seem to apply when the versioned symbol was
visible to the static linker.)

>> I thought the issue here was controlling *which library* provides
>> a symbol, independent of whether the symbol has versions.
> 
> I'm not convinced this desirable because of the exceptions I listed 
> above.  Both manual name mangling (which I currently prefer) and
> symbol versioning with the no-interpose flag (the one I sketched
> earlier) would support them.  But only name mangling addresses
> collisions before the first static link.

I hope I've explained clearly enough already why I'm not a fan of manual
name mangling, especially on an ad-hoc or new-symbols-only basis.

>> All this aside, this discussion is still very brainstormy and that
>> makes me think that we should *not* yet be supplying mangled names
>> for public use.  Once we start doing that we are stuck with it
>> forever, after all. Contrariwise, we *can* always retrofit __libc_*
>> aliases or whatever once we know what we ought to be doing.
> 
> I think getrandom is special because the name is rather generic,
> just like some of the new libm names (where we still might have to
> introduce mangling based on feedback from distribution rebuilds; I
> just don't know yet).

We agreed that the unmangled name has to exist, so how about we move
forward by introducing only the unmangled names for the new symbols
currently proposed (getrandom, explicit_bzero), introduce mangling if
necessary based on feedback, and work toward a long-term solution that
can be applied across the board?

zw

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Evolution of ELF symbol management
  2016-11-23 14:09         ` Zack Weinberg
@ 2016-11-24 10:01           ` Florian Weimer
  0 siblings, 0 replies; 19+ messages in thread
From: Florian Weimer @ 2016-11-24 10:01 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: libc-alpha, Siddhesh Poyarekar

On 11/23/2016 03:08 PM, Zack Weinberg wrote:

>> In general, headers should avoid using libc types, particularly
>> off_t, time_t, struct timeval, struct stat, and so on.  But there
>> might be exceptions.
>
> ... I'm not sure why we're suddenly discussing typedef names?

I'm trying to come up with reasons why the usual header file conflict 
avoidance mechanisms would not work.

I mean, if you use C, you pretty much agreed to using separate 
compilation to work around header conflict issues.

>> For C, it's not clear at all to me whether we need any kind of
>> opt-in besides compiling with a particular _*_SOURCE variant (which
>> introduces the definition).
>
> I am having trouble articulating why I don't like this.  I think it
> might be mostly to do with the way new symbols are now different than
> old symbols.  I'd be okay with an across-the-board change to symbol
> resolution (as discussed below) that made interposition not work by
> default, but I'm not okay with the idea of its being supported only for
> symbols added before some arbitrary release.

I prefer the case-by-case approach because it allows us to review ABI 
changes individually.

> Third-party C libraries don't tend to put nearly as much code in inline
> functions, so the need for explicitly-useable __names is lessened there,
> I think.

Right, and separate compilation is available as workaround.

>> For C++, we might use something based on namespaces to get a clear
>> separation.  However, the problem there is that type names and
>> struct tags end up in C++ mangled identifiers and thus impact
>> application ABI. I have no good idea what to do there.
>
> Arguably that's a Good Thing -- a change to what off_t means is an ABI
> break whether or not it shows up in symbol names, and _making_ that one
> in particular show up in symbol names might solve some of the problems
> that lead to _FILE_OFFSET_BITS=64 still not being default for the older
> 32-bit architectures.

Suppose we want to make struct sockaddr_un available to C++ code under a 
namespaced name.  Then C++ code has to use that name.  But this could 
change ABI on the C++ side merely due to name mangling (on top of 
potential type compatibility issues interface with user code).  If we do 
not solve this in some way, I don't think many C++ projects will switch 
to internal names to avoid the header file collision because it's not 
worth the impact on compatibility.

>>> I was imagining a new annotation on _all_ undefined symbols in a
>>> shared object, giving the soname of the object that they were
>>> satisfied by at link time.  At load time, 'getrandom!libc.so.6'
>>> resolves to the 'getrandom' definition in libc.so.6, ignoring all
>>> other definitions of the same name.  If there are symbol versions
>>> involved, only the versions exported by libc.so.6 are considered.
>>> For instance, 'getrandom!libc.so.6@GLIBC_2.25' cannot be satisfied
>>> by 'getrandom@GLIBC_2.25' exported by libmissing-syscalls.so.1.
>>
>> We still need to support LD_PRELOAD and interposition of arbitrary
>> symbols, and not just malloc-related ones, for the benefit of
>> Address Sanitizer, fakeroot, cwrap, memstomp and other tools.
>>
>> This is why hard-coding the DSO name does not seem advisable.
>
> This argument applies equally to every new symbol we might add, and in
> fact to every _intra_-libc call that currently _can't_ be interposed.
> So I'm inclined to discount it.

I think there's a big difference if you have to write new interceptors 
to support newer glibc versions, or if you have to rewrite your whole 
library as an audit module because the ability to interpose the symbols 
you are interested in is gone completely.

> The solution I'm leaning toward involves each library designating a set
> of exported symbols, calls to which _can_ be interposed; the default is
> not to allow it.  We'd probably have to spend some time figuring out
> exactly which of libc's symbols should be interposeable.

It seems to me that interposition of arbitrary symbols is currently part 
of the programming interface.  We didn't plan for things like fakeroot 
and cwrap, but someone created those tools eventually, and they 
apparently address a real need.

>> When an application is linked against a shared object, if it
>> interposes any symbols in it, the symbols becomes exported, so that
>> interposition works at run time (otherwise, it could not happen).
>> You can see an example here:
>>
>> $ nm -Dg malloc/tst-interpose-nothread  | grep ' T '
>>
>> The application is *not* compiled with -Bdynamic or something like
>> that, it happens automatically.
>>
>> But the symbol version from libc.so.6 is not attached to this symbol
>> (“nm” would not show it, but you can check with eu-readelf, for
>> example).
>
> Well, OK, why don't we just fix that?  Is there a good reason why it
> _doesn't_ pick up the symbol version?

I'm not sure if interposition at load time will still happen.  But this 
should be easy to verify.  I'll give it a try.

> We agreed that the unmangled name has to exist, so how about we move
> forward by introducing only the unmangled names for the new symbols
> currently proposed (getrandom, explicit_bzero), introduce mangling if
> necessary based on feedback, and work toward a long-term solution that
> can be applied across the board?

What kind of feedback would trigger mangled names?  Is having a 
real-world application which triggers accidental interposition sufficient?

For getrandom, not using the mangled name by default looks like a 
security bug in the making.  Less so for explict_bzero.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2016-11-24 10:01 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-18  9:26 Evolution of ELF symbol management Florian Weimer
2016-10-18 16:50 ` Joseph Myers
2016-10-25 14:32   ` Florian Weimer
2016-10-25 15:37     ` Joseph Myers
2016-11-21 15:35       ` Florian Weimer
2016-10-26 12:17     ` Joseph Myers
2016-11-20 11:13     ` Mike Frysinger
2016-11-21 10:12       ` Florian Weimer
2016-11-16 15:55 ` Zack Weinberg
2016-11-18 15:48   ` Florian Weimer
2016-11-19 17:25     ` Zack Weinberg
2016-11-22 15:09       ` Florian Weimer
2016-11-22 15:30         ` Andreas Schwab
2016-11-22 15:39           ` Florian Weimer
2016-11-22 15:48             ` Zack Weinberg
2016-11-22 15:48               ` Zack Weinberg
2016-11-22 17:42         ` Joseph Myers
2016-11-23 14:09         ` Zack Weinberg
2016-11-24 10:01           ` Florian Weimer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).