elf: Do not fail for failed dlmopen on audit modules (BZ #28061)

The dl_main sets the LM_ID_BASE to RT_ADD just before starting to
add load new shared objects.  The state is set to RT_CONSISTENT just
after all objects are loaded.

However if a audit modules tries to dlmopen an inexistent module,
the _dl_open will assert that the namespace is in an inconsistent
state.

This is different than dlopen, since first it will not use
LM_ID_BASE and second _dl_map_object_from_fd is the sole responsible
to set and reset the r_state value.

So the assert on _dl_open can not really be seen if the state is
consistent, since _dt_main resets it.  This patch removes the assert.

Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
This commit is contained in:
Adhemerval Zanella 2021-06-30 17:33:57 -03:00
parent f0e23d34a7
commit 484e672dda
4 changed files with 87 additions and 2 deletions

View file

@ -232,6 +232,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
tst-dl-is_dso tst-ro-dynamic \
tst-audit18 \
tst-audit19b \
tst-audit20 \
tst-audit22 \
tst-rtld-run-static \
# reldep9
@ -383,6 +384,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
tst-auditmod19a \
tst-auditmod19b \
tst-audit19bmod \
tst-auditmod20 \
tst-auditmod22 \
# Most modules build with _ISOMAC defined, but those filtered out
@ -1596,6 +1598,9 @@ $(objpfx)tst-audit19b.out: $(objpfx)tst-auditmod19b.so
$(objpfx)tst-audit19b: $(objpfx)tst-audit19bmod.so
tst-audit19b-ARGS = -- $(host-test-program-cmd)
$(objpfx)tst-audit20.out: $(objpfx)tst-auditmod20.so
tst-audit20-ENV = LD_AUDIT=$(objpfx)tst-auditmod20.so
$(objpfx)tst-audit22.out: $(objpfx)tst-auditmod22.so
tst-audit22-ARGS = -- $(host-test-program-cmd)

View file

@ -914,8 +914,6 @@ no more namespaces available for dlmopen()"));
the flag here. */
}
assert (_dl_debug_update (args.nsid)->r_state == RT_CONSISTENT);
/* Release the lock. */
__rtld_lock_unlock_recursive (GL(dl_load_lock));

25
elf/tst-audit20.c Normal file
View file

@ -0,0 +1,25 @@
/* Check dlopen failure on audit modules.
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
static int
do_test (void)
{
return 0;
}
#include <support/test-driver.c>

57
elf/tst-auditmod20.c Normal file
View file

@ -0,0 +1,57 @@
/* Check dlopen failure on audit modules.
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <dlfcn.h>
#include <link.h>
#include <stdlib.h>
unsigned int
la_version (unsigned int v)
{
return LAV_CURRENT;
}
static void
check (void)
{
{
void *mod = dlopen ("nonexistent.so", RTLD_NOW);
if (mod != NULL)
abort ();
}
{
void *mod = dlmopen (LM_ID_BASE, "nonexistent.so", RTLD_NOW);
if (mod != NULL)
abort ();
}
}
void
la_activity (uintptr_t *cookie, unsigned int flag)
{
if (flag != LA_ACT_CONSISTENT)
return;
check ();
}
void
la_preinit (uintptr_t *cookie)
{
check ();
}