[PATCHv5][PING][BZ #17833] _dl_close_worker() does not release inconsistent objects.
Yury Gribov
y.gribov@samsung.com
Fri Jun 5 08:30:00 GMT 2015
On 05/29/2015 08:38 PM, Pavel Kopyl wrote:
> On 05/29/2015 12:31 AM, Pavel Kopyl wrote:
>> On 05/28/2015 01:06 AM, H.J. Lu wrote:
>>> On Wed, May 27, 2015 at 2:38 PM, Pavel Kopyl <p.kopyl@samsung.com>
>>> wrote:
>>>>>>>> AFAIU DF_1_NODELETE change is necessary. Otherwise unique
>>>>>>>> symbols force
>>>>>>>> library to remain loaded in half-initialized state (with missing
>>>>>>>> dependencies). This usecase is demonstrated by the testcase in
>>>>>>>> patch.
>>>>>>>>
>>>>>>> But unique symbols != DF_1_NODELETE:
>>>>>>
>>>>>> DF_1_NODELETE is set in do_lookup_unique at runtime (Paul, am I
>>>>>> right?):
>>>>>>
>>>>>> enter_unique_sym (entries, size,
>>>>>> new_hash, strtab + sym->st_name, sym, map);
>>>>>>
>>>>>> if (map->l_type == lt_loaded)
>>>>>> /* Make sure we don't unload this object by
>>>>>> setting the appropriate flag. */
>>>>>> ((struct link_map *) map)->l_flags_1 |= DF_1_NODELETE;
>>>>>>
>>>>>> -Y
>>>>> Should we set DF_1_NODELETE when dlopen fails? What happens
>>>>> when dlopen a DF_1_NODELETE fails? Do we keep it in memory
>>>>> even when dopen fails?
>>>>>
>>>> As I know there are following ways how to set DF_1_NODELETE flag for a
>>>> library.
>>>>
>>>> 1. Unique symbols.
>>>> 2, Load with RTLD_NODELETE flag.
>>>> 3. Link with "-z nodelete" option.
>>>>
>>>> As for RTLD_NODELETE, there is no problem: dlopen exits in case of
>>>> error
>>>> before DF_1_NODELETE is set.
>>>> If dlopen fails both in first and third cases this leads to locking
>>>> libraries in half-initialized state. I think this is a bug.
>>>> Suggested patch fixes both usecases.
>>> Assume there is a problem with DF_1_NODELETE, which can be
>>> set explicitly as well as implicitly. Your testcase only covers
>>> implicitly DF_1_NODELETE, not explicitly DF_1_NODELETE.
>>> I think we should verify the status of explicitly DF_1_NODELETE.
>>>
>>> If explicitly DF_1_NODELETE works fine, then we only have a
>>> problem with implicitly DF_1_NODELETE.
>>>
>>> If explicitly DF_1_NODELETE doesn't work, we need to fix it
>>> first and implicitly DF_1_NODELETE may just work.
>>
>> Ok, I prepared the following testcase.
>>
>> tst-nodelete.cc:
>> #include <stdio.h>
>> #include <stdlib.h>
>> #include <dlfcn.h>
>>
>> int
>> main (void)
>> {
>> int ret = 0;
>>
>> /* This is a test for correct handling of dlopen failures for
>> library that
>> is loaded with RTLD_NODELETE flag. The first dlopen should fail
>> because
>> of undefined symbols in shared library. The second dlopen then
>> verifies
>> that library was properly unloaded. */
>> if (dlopen ("./tst-nodeletelib.so", RTLD_NOW | RTLD_NODELETE) != NULL
>> || dlopen ("./tst-nodeletelib.so", RTLD_LAZY | RTLD_NOLOAD) !=
>> NULL)
>> {
>> printf("RTLD_NOLOAD test failed\n");
>> ret = 1;
>> }
>>
>> /* This is a test for correct handling of dlopen failures for
>> library that
>> is linked with '-z nodelete' option and hence has DF_1_NODELETE
>> flag.
>> The first dlopen should fail because of undefined symbols in shared
>> library. The second dlopen then verifies that library was properly
>> unloaded. */
>> if (dlopen ("./tst-znodeletelib.so", RTLD_NOW) != NULL
>> || dlopen ("./tst-znodeletelib.so", RTLD_LAZY | RTLD_NOLOAD) !=
>> NULL)
>> {
>> printf("-z \'nodelete\' test failed\n");
>> ret = 1;
>> }
>>
>> /* This is a test for correct handling of dlopen failures for library
>> with unique symbols. The first dlopen should fail because of
>> undefined
>> symbols in shared library. The second dlopen then verifies that
>> library
>> was properly unloaded. */
>> if (dlopen ("./tst-unique5lib.so", RTLD_NOW) != NULL
>> || dlopen ("./tst-unique5lib.so", RTLD_LAZY | RTLD_NOLOAD) != NULL)
>> {
>> printf("Unique symbols test failed\n");
>> ret = 1;
>> }
>>
>> if (!ret)
>> printf ("SUCCESS\n");
>>
>> return ret;
>> }
>>
>>
>> tst-unique5lib.cc:
>> extern int not_exist (void);
>>
>> inline int make_unique (void)
>> {
>> /* Static variables in inline functions and classes
>> generate STB_GNU_UNIQUE symbols. */
>> static int unique;
>> return ++unique;
>> }
>>
>> int foo (void)
>> {
>> return make_unique () + not_exist ();
>> }
>>
>>
>> tst-nodeletelib.cc:
>> extern int not_exist (void);
>>
>> int foo (void)
>> {
>> return not_exist ();
>> }
>>
>>
>> g++ -o tst-nodelete tst-nodelete.cc -ldl
>> g++ -shared -fPIC -o tst-nodeletelib.so tst-nodeletelib.cc
>> g++ -shared -fPIC -Wl,-z,nodelete -o tst-znodeletelib.so
>> tst-nodeletelib.cc
>> ./tst-nodelete
>> -z 'nodelete' test failed
>> Unique symbols test failed
>>
>>
>> Thus, besides unique symbols we have a problem with explicitly
>> DF_1_NODELETE when library is built with "-Wl,-z,nodelete".
>> I checked that patch fixes this usecase too. Now I'm going to update
>> testcase in make check.
>
> This is new patch with updated testcase.
>
> -Pavel
Ping.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: delete_inconsistent_objs_v5.patch
Type: text/x-patch
Size: 8717 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/libc-alpha/attachments/20150605/7c51c827/attachment.bin>
More information about the Libc-alpha
mailing list