This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: RFC: Treat RTLD_GLOBAL as unique to namespace when used with dlmopen
- From: "Michael Kerrisk (man-pages)" <mtk dot manpages at gmail dot com>
- To: Carlos O'Donell <carlos at redhat dot com>, GNU C Library <libc-alpha at sourceware dot org>
- Cc: mtk dot manpages at gmail dot com
- Date: Fri, 24 Jul 2015 21:43:33 +0200
- Subject: Re: RFC: Treat RTLD_GLOBAL as unique to namespace when used with dlmopen
- Authentication-results: sourceware.org; auth=none
- References: <55A73673 dot 3060104 at redhat dot com> <55B20563 dot 4020900 at gmail dot com> <55B28757 dot 8040502 at redhat dot com>
Hi Carlos,
On 07/24/2015 08:43 PM, Carlos O'Donell wrote:
> On 07/24/2015 05:29 AM, Michael Kerrisk (man-pages) wrote:
>> On 07/16/2015 06:43 AM, Carlos O'Donell wrote:
>>> Michael Kerrisk and I are working on a man page for dlmopen.
>>
>> See below for the current draft of the text describing dlmopen().
>> Note that this text describes how Carlos and I think the API
>> is supposed to behave (at least, I think the text fits with
>> discussions Carlos and I had), and it's also consistent with
>> actual Solaris behavior. The BUGS section describes the
>> points that make dlmopen() unfit for purpose (IIUC).
>>
>> Cheers,
>>
>> Michael
>>
>>
>>
>> SYNOPSIS
>> ....
>> #define _GNU_SOURCE
>> #include <dlfcn.h>
>>
>> void *dlmopen (Lmid_t lmid, const char *filename, int flags);
>>
>> Link with -ldl.
>>
>> DESCRIPTION
>> dlopen()
>> ...
>> dlmopen()
>> This function performs the same task as dlopen()âthe filename and
>> flags arguments, as well as the return value, are the same,
>> except for the differences noted below.
>>
>> The dlmopen() function differs from dlopen() primarily in that it
>> accepts an additional argument, lmid, that specifies the link-map
>> list (also referred to as a namespace) in which the shared object
>> should be loaded. (By comparison, dlopen() adds the dynamically
>> loaded shared object to the same namespace as the shared object
>> from which the dlopen() call is made.) The Lmid_t type is an
>> opaque handle that refers to a namespace.
>>
>> The lmid argument is either the ID of an existing namespace
>> (which can be obtained using the dlinfo(3) RTLD_DI_LMID request)
>> or one of the following special values:
>>
>> LM_ID_BASE
>> Load the shared object in the initial namespace (i.e., the
>> application's namespace).
>>
>> LM_ID_NEWLM
>> Create a new namespace and load the shared object in that
>> namespace. The object must have been correctly linked to
>> reference all of the other shared objects that it
>> requires, since the new namespace is initially empty.
>>
>> If handle is NULL, then the only permitted value for lmid is
>> LM_ID_BASE.
>
> What handle is NULL? If "filename" is NULL?
Yes, sorry s/handle/filename/
> This would be a glibc limitation
> which we plan to fix in 2.23. We should certainly return the handle to the
> base object loaded in the namespace as you suggest, just like the application
> is returned upon dlopen (NULL).
Okay.
>> ....
>>
>> NOTES
>> dlmopen() and namespaces
>> A link-map list defines an isolated namespace for the resolution
>> of symbols by the dynamic linker. Within a namespace, dependent
>> shared objects are implicitly loaded according to the usual
>> rules, and symbol references are likewise resolved according to
>> the usual rules, but such resolution is confined to the definiâ
>> tions provided by the objects that have been (explicitly and
>> implicitly) loaded into the namespace.
>>
>> The dlmopen() function permits object-load isolationâthe ability
>> to load a shared object in a new namespace without exposing the
>> rest of the application to the symbols made available by the new
>> object. Note that the use of the RTLD_LOCAL flag is not suffiâ
>> cient for this purpose, since it prevents a shared object's symâ
>> bols from being available to any other shared object. In some
>> cases, we may want to make the symbols provided by a dynamically
>> loaded shared object available to (a subset of) other shared
>> objects without exposing those symbols to the entire application.
>> This can be achieved by using a separate namespace and the
>> RTLD_GLOBAL flag.
>
> Lastly, RTLD_LOCAL loaded objects may be promoted to RTLD_GLOBAL if they
> are dependencies of another RTLD_GLOBAL loaded object. Therefore RTLD_LOCAL
> is still not sufficient to isolate the loaded shared object without explicit
> control over all object dependencies.
I wrote this up as
The dlmopen() function also can be used to provide better isolaâ
tion than the RTLD_LOCAL flag. In particular, shared objects
laoded with RTLD_LOCAL may be promoted to RTLD_GLOBAL if they are
dependencies of another shared object loaded with RTLD_GLOBAL.
Thus, RTLD_LOCAL is insufficient to isolate a loaded shared
object except in the (uncommon) case where one has explicit conâ
trol over all shared object dependencies.
Look okay?
>> Possible uses of dlmopen() are plugins where the author of the
>> plugin-loading framework can't trust the plugin authors and does
>> not wish any undefined symbols from the plugin framework to be
>> resolved to plugin symbols. Another use is to load the same
>> object more than once. Without the use of dlmopen(), this would
>> require the creation of distinct copies of the shared object
>> file. Using dlmopen(), this can be achieved by loading the same
>> shared object file into different namespaces.
>>
>> The glibc implementation supports a maximum of 16 namespaces.
>>
>> ...
>> BUGS
>> As at glibc 2.21, specifying the RTLD_GLOBAL flag when calling
>> dlmopen() generates an error. Furthermore, specifying
>> RTLD_GLOBAL when calling dlopen() results in a program crash
>> (SIGSEGV) if the call is made from any object loaded in a namesâ
>> pace other than the initial namespace.
>>
>
> Looks good to me. We need dlinfo documented also, which you already know,
> but I wanted to make that explicit in this public discussion.
I think you didn't catch up on all your mail yet ;-).
Cheers,
Michael
--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/