This commit is contained in:
Jakub Jelinek 2004-10-27 21:39:59 +00:00
parent aa85b49673
commit 0b5cfa4e0b
15 changed files with 462 additions and 84 deletions

View File

@ -11,6 +11,9 @@
2004-10-27 Ulrich Drepper <drepper@redhat.com>
* elf/dl-open.c (_dl_open): Don't allow explicitly opening a DSO
into an empty namespace.
* elf/dl-fini.c (_dl_fini): Fix search for map in maps array.
Reverse order of namespaces.
* elf/Makefile: Add rules to build and run tst-dlmopen3.

View File

@ -154,7 +154,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \
tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-align \
$(tests-execstack-$(have-z-execstack)) tst-dlmodcount \
tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2
tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3
# reldep9
test-srcs = tst-pathopt
tests-vis-yes = vismain
@ -770,3 +770,6 @@ $(objpfx)tst-dlmopen1.out: $(objpfx)tst-dlmopen1mod.so
$(objpfx)tst-dlmopen2: $(libdl)
$(objpfx)tst-dlmopen2.out: $(objpfx)tst-dlmopen1mod.so
$(objpfx)tst-dlmopen3: $(libdl)
$(objpfx)tst-dlmopen3.out: $(objpfx)tst-dlmopen1mod.so

View File

@ -42,23 +42,18 @@ _dl_fini (void)
using `dlopen' there are possibly several other modules with its
dependencies to be taken into account. Therefore we have to start
determining the order of the modules once again from the beginning. */
unsigned int i;
unsigned int nloaded;
struct link_map *l;
struct link_map **maps = NULL;
size_t maps_size = 0;
/* We First run the destructors of the main namespaces, then the
other ones. The order should not matter since the namespace
content is supposed to be independent. But we can have auditing
code in a auxiliaty namespace and we want it to monitor the
destructors. */
for (Lmid_t cnt = 0; cnt < DL_NNS; ++cnt)
/* We run the destructors of the main namespaces last. As for the
other namespaces, we pick run the destructors in them in reverse
order of the namespace ID. */
for (Lmid_t cnt = DL_NNS - 1; cnt >= 0; --cnt)
{
/* Protect against concurrent loads and unloads. */
__rtld_lock_lock_recursive (GL(dl_load_lock));
nloaded = GL(dl_ns)[cnt]._ns_nloaded;
unsigned int nloaded = GL(dl_ns)[cnt]._ns_nloaded;
/* XXX Could it be (in static binaries) that there is no object
loaded? */
@ -79,20 +74,20 @@ _dl_fini (void)
nloaded * sizeof (struct link_map *));
}
unsigned int i;
struct link_map *l;
for (l = GL(dl_ns)[cnt]._ns_loaded, i = 0; l != NULL; l = l->l_next)
{
assert (i < nloaded);
/* Do not handle ld.so in secondary namespaces. */
if (l == l->l_real)
{
assert (i < nloaded);
/* Do not handle ld.so in secondary namespaces. */
if (l == l->l_real)
{
maps[i++] = l;
maps[i++] = l;
/* Bump l_opencount of all objects so that they are not
dlclose()ed from underneath us. */
++l->l_opencount;
}
}
/* Bump l_opencount of all objects so that they are not
dlclose()ed from underneath us. */
++l->l_opencount;
}
assert (cnt != LM_ID_BASE || i == nloaded);
assert (cnt == LM_ID_BASE || i == nloaded || i == nloaded - 1);
unsigned int nmaps = i;
@ -105,46 +100,23 @@ _dl_fini (void)
/* The main executable always comes first. */
l = l->l_next;
for (; l != NULL; l = l->l_next)
{
unsigned int j;
unsigned int k;
/* Do not handle ld.so in secondary namespaces. */
if (l == l->l_real)
{
/* Find the place in the 'maps' array. */
unsigned int j;
for (j = cnt == LM_ID_BASE ? 1 : 0; maps[j] != l; ++j)
assert (j < nmaps);
/* Find the place in the 'maps' array. */
for (j = 1; maps[j] != l; ++j)
;
/* Find all object for which the current one is a dependency and
move the found object (if necessary) in front. */
for (k = j + 1; k < nmaps; ++k)
{
struct link_map **runp = maps[k]->l_initfini;
if (runp != NULL)
{
while (*runp != NULL)
if (*runp == l)
{
struct link_map *here = maps[k];
/* Move it now. */
memmove (&maps[j] + 1,
&maps[j],
(k - j) * sizeof (struct link_map *));
maps[j++] = here;
break;
}
else
++runp;
}
if (__builtin_expect (maps[k]->l_reldeps != NULL, 0))
{
unsigned int m = maps[k]->l_reldepsact;
struct link_map **relmaps = maps[k]->l_reldeps;
while (m-- > 0)
{
if (relmaps[m] == l)
/* Find all object for which the current one is a dependency
and move the found object (if necessary) in front. */
for (unsigned int k = j + 1; k < nmaps; ++k)
{
struct link_map **runp = maps[k]->l_initfini;
if (runp != NULL)
{
while (*runp != NULL)
if (*runp == l)
{
struct link_map *here = maps[k];
@ -152,14 +124,37 @@ _dl_fini (void)
memmove (&maps[j] + 1,
&maps[j],
(k - j) * sizeof (struct link_map *));
maps[j] = here;
maps[j++] = here;
break;
}
}
}
}
}
else
++runp;
}
if (__builtin_expect (maps[k]->l_reldeps != NULL, 0))
{
unsigned int m = maps[k]->l_reldepsact;
struct link_map **relmaps = maps[k]->l_reldeps;
while (m-- > 0)
{
if (relmaps[m] == l)
{
struct link_map *here = maps[k];
/* Move it now. */
memmove (&maps[j] + 1,
&maps[j],
(k - j) * sizeof (struct link_map *));
maps[j] = here;
break;
}
}
}
}
}
}
/* We do not rely on the linked list of loaded object anymore from

View File

@ -570,6 +570,12 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid)
no more namespaces available for dlmopen()"));
}
}
/* Never allow loading a DSO in a namespace which is empty. Such
direct placements is only causing problems. */
else if (nsid != LM_ID_BASE && nsid != __LM_ID_CALLER
&& GL(dl_ns)[nsid]._ns_nloaded == 0)
GLRO(dl_signal_error) (EINVAL, file, NULL,
N_("invalid target namespace in dlmopen()"));
args.file = file;
args.mode = mode;

View File

@ -3,6 +3,16 @@
#include <gnu/lib-names.h>
static int cnt;
static void
__attribute ((constructor))
constr (void)
{
++cnt;
}
int
foo (Lmid_t ns2)
{
@ -34,5 +44,16 @@ foo (Lmid_t ns2)
return 1;
}
if (cnt == 0)
{
puts ("constructor did not run");
return 1;
}
else if (cnt != 1)
{
puts ("constructor did not run exactly once");
return 1;
}
return 0;
}

23
elf/tst-dlmopen3.c Normal file
View File

@ -0,0 +1,23 @@
#include <dlfcn.h>
#include <stdio.h>
#include <gnu/lib-names.h>
static int
do_test (void)
{
void *h = dlmopen (LM_ID_NEWLM, "$ORIGIN/tst-dlmopen1mod.so", RTLD_LAZY);
if (h == NULL)
{
printf ("cannot get handle for %s: %s\n",
"tst-dlmopen1mod.so", dlerror ());
return 1;
}
/* Do not unload. */
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -1,4 +1,4 @@
%define glibcrelease 73
%define glibcrelease 74
%define auxarches i586 i686 athlon sparcv9 alphaev6
%define prelinkarches noarch
%define nptlarches i386 i686 athlon x86_64 ia64 s390 s390x sparcv9 ppc ppc64
@ -1256,6 +1256,14 @@ rm -f *.filelist*
%endif
%changelog
* Wed Oct 27 2004 Jakub Jelinek <jakub@redhat.com> 2.3.3-74
- fix <netinet/udp.h> header
- fix globfree (#137176)
- fix exiting if there are dlmopened libraries in namespaces
other than main one not closed yet
- export again _res_opcodes and __p_{class,type}_syms from
libresolv.so that were lost in -69
* Thu Oct 21 2004 Jakub Jelinek <jakub@redhat.com> 2.3.3-73
- remove setaltroot and key{_add,_request,ctl} also from Versions
- back out _sys_errlist changes

View File

@ -98,6 +98,9 @@ libresolv_hidden_proto (__ns_name_unpack)
libresolv_hidden_proto (__ns_get16)
libresolv_hidden_proto (__ns_get32)
extern const char *_res_opcodes[];
libresolv_hidden_proto (_res_opcodes)
#endif
#endif

View File

@ -82,7 +82,7 @@ tests := tstgetopt testfnm runtests runptests \
bug-regex21 bug-regex22 bug-regex23 tst-nice tst-nanosleep \
transbug tst-rxspencer tst-pcre tst-boost \
bug-ga1 tst-vfork1 tst-vfork2 tst-waitid \
tst-getaddrinfo2 bug-glob1
tst-getaddrinfo2 bug-glob1 bug-glob2
xtests := bug-ga2
ifeq (yes,$(build-shared))
test-srcs := globtest
@ -101,7 +101,7 @@ generated := $(addprefix wordexp-test-result, 1 2 3 4 5 6 7 8 9 10) \
bug-regex21-mem bug-regex21.mtrace \
tst-rxspencer-mem tst-rxspencer.mtrace tst-getconf.out \
tst-pcre-mem tst-pcre.mtrace tst-boost-mem tst-boost.mtrace \
bug-ga2.mtrace bug-ga2-mem
bug-ga2.mtrace bug-ga2-mem bug-glob2.mtrace bug-glob2-mem
include ../Rules
@ -194,7 +194,8 @@ tests: $(objpfx)annexc.out
ifeq (no,$(cross-compiling))
tests: $(objpfx)bug-regex2-mem $(objpfx)bug-regex14-mem \
$(objpfx)bug-regex21-mem $(objpfx)tst-rxspencer-mem \
$(objpfx)tst-pcre-mem $(objpfx)tst-boost-mem $(objpfx)tst-getconf.out
$(objpfx)tst-pcre-mem $(objpfx)tst-boost-mem $(objpfx)tst-getconf.out \
$(objpfx)bug-glob2-mem
xtests: $(objpfx)bug-ga2-mem
endif
@ -251,3 +252,8 @@ $(objpfx)bug-ga2-mem: $(objpfx)bug-ga2.out
$(common-objpfx)malloc/mtrace $(objpfx)bug-ga2.mtrace > $@
bug-ga2-ENV = MALLOC_TRACE=$(objpfx)bug-ga2.mtrace
bug-glob2-ENV = MALLOC_TRACE=$(objpfx)bug-glob2.mtrace
$(objpfx)bug-glob2-mem: $(objpfx)bug-glob2.out
$(common-objpfx)malloc/mtrace $(objpfx)bug-glob2.mtrace > $@

303
posix/bug-glob2.c Normal file
View File

@ -0,0 +1,303 @@
/* Test glob memory management.
for the filesystem access functions.
Copyright (C) 2001, 2002, 2004 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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <error.h>
#include <dirent.h>
#include <glob.h>
#include <mcheck.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
// #define DEBUG
#ifdef DEBUG
# define PRINTF(fmt, args...) \
do \
{ \
int save_errno = errno; \
printf (fmt, ##args); \
errno = save_errno; \
} while (0)
#else
# define PRINTF(fmt, args...)
#endif
static struct
{
const char *name;
int level;
int type;
mode_t mode;
} filesystem[] =
{
{ ".", 1, DT_DIR, 0755 },
{ "..", 1, DT_DIR, 0755 },
{ "dir", 1, DT_DIR, 0755 },
{ ".", 2, DT_DIR, 0755 },
{ "..", 2, DT_DIR, 0755 },
{ "readable", 2, DT_DIR, 0755 },
{ ".", 3, DT_DIR, 0755 },
{ "..", 3, DT_DIR, 0755 },
{ "a", 3, DT_REG, 0644 },
{ "unreadable", 2, DT_DIR, 0111 },
{ ".", 3, DT_DIR, 0111 },
{ "..", 3, DT_DIR, 0755 },
{ "a", 3, DT_REG, 0644 },
{ "zz-readable", 2, DT_DIR, 0755 },
{ ".", 3, DT_DIR, 0755 },
{ "..", 3, DT_DIR, 0755 },
{ "a", 3, DT_REG, 0644 }
};
#define nfiles (sizeof (filesystem) / sizeof (filesystem[0]))
typedef struct
{
int level;
int idx;
struct dirent d;
char room_for_dirent[NAME_MAX];
} my_DIR;
static long int
find_file (const char *s)
{
int level = 1;
long int idx = 0;
if (strcmp (s, ".") == 0)
return 0;
if (s[0] == '.' && s[1] == '/')
s += 2;
while (*s != '\0')
{
char *endp = strchrnul (s, '/');
PRINTF ("looking for %.*s, level %d\n", (int) (endp - s), s, level);
while (idx < nfiles && filesystem[idx].level >= level)
{
if (filesystem[idx].level == level
&& memcmp (s, filesystem[idx].name, endp - s) == 0
&& filesystem[idx].name[endp - s] == '\0')
break;
++idx;
}
if (idx == nfiles || filesystem[idx].level < level)
{
errno = ENOENT;
return -1;
}
if (*endp == '\0')
return idx + 1;
if (filesystem[idx].type != DT_DIR
&& (idx + 1 >= nfiles
|| filesystem[idx].level >= filesystem[idx + 1].level))
{
errno = ENOTDIR;
return -1;
}
++idx;
s = endp + 1;
++level;
}
errno = ENOENT;
return -1;
}
static void *
my_opendir (const char *s)
{
long int idx = find_file (s);
my_DIR *dir;
if (idx == -1)
{
PRINTF ("my_opendir(\"%s\") == NULL (%m)\n", s);
return NULL;
}
if ((filesystem[idx].mode & 0400) == 0)
{
errno = EACCES;
PRINTF ("my_opendir(\"%s\") == NULL (%m)\n", s);
return NULL;
}
dir = (my_DIR *) malloc (sizeof (my_DIR));
if (dir == NULL)
{
printf ("cannot allocate directory handle: %m\n");
exit (EXIT_FAILURE);
}
dir->level = filesystem[idx].level;
dir->idx = idx;
PRINTF ("my_opendir(\"%s\") == { level: %d, idx: %ld }\n",
s, filesystem[idx].level, idx);
return dir;
}
static struct dirent *
my_readdir (void *gdir)
{
my_DIR *dir = gdir;
if (dir->idx == -1)
{
PRINTF ("my_readdir ({ level: %d, idx: %ld }) = NULL\n",
dir->level, (long int) dir->idx);
return NULL;
}
while (dir->idx < nfiles && filesystem[dir->idx].level > dir->level)
++dir->idx;
if (dir->idx == nfiles || filesystem[dir->idx].level < dir->level)
{
dir->idx = -1;
PRINTF ("my_readdir ({ level: %d, idx: %ld }) = NULL\n",
dir->level, (long int) dir->idx);
return NULL;
}
dir->d.d_ino = dir->idx;
#ifdef _DIRENT_HAVE_D_TYPE
dir->d.d_type = filesystem[dir->idx].type;
#endif
strcpy (dir->d.d_name, filesystem[dir->idx].name);
#ifdef _DIRENT_HAVE_D_TYPE
PRINTF ("my_readdir ({ level: %d, idx: %ld }) = { d_ino: %ld, d_type: %d, d_name: \"%s\" }\n",
dir->level, (long int) dir->idx, dir->d.d_ino, dir->d.d_type,
dir->d.d_name);
#else
PRINTF ("my_readdir ({ level: %d, idx: %ld }) = { d_ino: %ld, d_name: \"%s\" }\n",
dir->level, (long int) dir->idx, dir->d.d_ino,
dir->d.d_name);
#endif
++dir->idx;
return &dir->d;
}
static void
my_closedir (void *dir)
{
PRINTF ("my_closedir ()\n");
free (dir);
}
/* We use this function for lstat as well since we don't have any. */
static int
my_stat (const char *name, struct stat *st)
{
long int idx = find_file (name);
if (idx == -1)
{
PRINTF ("my_stat (\"%s\", ...) = -1 (%m)\n", name);
return -1;
}
memset (st, '\0', sizeof (*st));
if (filesystem[idx].type == DT_UNKNOWN)
st->st_mode = DTTOIF (idx + 1 < nfiles
&& filesystem[idx].level < filesystem[idx + 1].level
? DT_DIR : DT_REG) | filesystem[idx].mode;
else
st->st_mode = DTTOIF (filesystem[idx].type) | filesystem[idx].mode;
PRINTF ("my_stat (\"%s\", { st_mode: %o }) = 0\n", name, st->st_mode);
return 0;
}
static void
init_glob_altdirfuncs (glob_t *pglob)
{
pglob->gl_closedir = my_closedir;
pglob->gl_readdir = my_readdir;
pglob->gl_opendir = my_opendir;
pglob->gl_lstat = my_stat;
pglob->gl_stat = my_stat;
}
int
do_test (void)
{
mtrace ();
glob_t gl;
memset (&gl, 0, sizeof (gl));
init_glob_altdirfuncs (&gl);
if (glob ("dir/*able/*", GLOB_ERR | GLOB_ALTDIRFUNC, NULL, &gl)
!= GLOB_ABORTED)
{
puts ("glob did not fail with GLOB_ABORTED");
exit (EXIT_FAILURE);
}
globfree (&gl);
memset (&gl, 0, sizeof (gl));
init_glob_altdirfuncs (&gl);
gl.gl_offs = 3;
if (glob ("dir2/*", GLOB_DOOFFS, NULL, &gl) != GLOB_NOMATCH)
{
puts ("glob did not fail with GLOB_NOMATCH");
exit (EXIT_FAILURE);
}
globfree (&gl);
muntrace ();
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -39,7 +39,7 @@ static const char rcsid[] = "$BINDId: res_data.c,v 8.17 1999/10/13 17:11:31 vixi
#include <string.h>
#include <unistd.h>
const char *_res_opcodes[] attribute_hidden = {
const char *_res_opcodes[] = {
"QUERY",
"IQUERY",
"CQUERYM",
@ -57,6 +57,7 @@ const char *_res_opcodes[] attribute_hidden = {
"ZONEINIT",
"ZONEREF",
};
libresolv_hidden_data_def (_res_opcodes)
#ifdef BIND_UPDATE
const char *_res_sectioncodes[] attribute_hidden = {

View File

@ -118,7 +118,6 @@ static const char rcsid[] = "$BINDId: res_debug.c,v 8.34 2000/02/29 05:30:55 vix
# define SPRINTF(x) sprintf x
#endif
extern const char *_res_opcodes[] attribute_hidden;
extern const char *_res_sectioncodes[] attribute_hidden;
/*
@ -349,7 +348,9 @@ p_fqname(const u_char *cp, const u_char *msg, FILE *file) {
* that C_ANY is a qclass but not a class. (You can ask for records of class
* C_ANY, but you can't have any records of that class in the database.)
*/
const struct res_sym __p_class_syms[] attribute_hidden = {
extern const struct res_sym __p_class_syms[];
libresolv_hidden_proto (__p_class_syms)
const struct res_sym __p_class_syms[] = {
{C_IN, "IN"},
{C_CHAOS, "CHAOS"},
{C_HS, "HS"},
@ -358,6 +359,7 @@ const struct res_sym __p_class_syms[] attribute_hidden = {
{C_NONE, "NONE"},
{C_IN, (char *)0}
};
libresolv_hidden_data_def (__p_class_syms)
/*
* Names of message sections.
@ -401,7 +403,9 @@ const struct res_sym __p_cert_syms[] attribute_hidden = {
* that T_ANY is a qtype but not a type. (You can ask for records of type
* T_ANY, but you can't have any records of that type in the database.)
*/
const struct res_sym __p_type_syms[] attribute_hidden = {
extern const struct res_sym __p_type_syms[];
libresolv_hidden_proto (__p_type_syms)
const struct res_sym __p_type_syms[] = {
{ns_t_a, "A", "address"},
{ns_t_ns, "NS", "name server"},
{ns_t_md, "MD", "mail destination (deprecated)"},
@ -448,6 +452,7 @@ const struct res_sym __p_type_syms[] attribute_hidden = {
{ns_t_any, "ANY", "\"any\""},
{0, NULL, NULL}
};
libresolv_hidden_data_def (__p_type_syms)
/*
* Names of DNS rcodes.

View File

@ -88,8 +88,6 @@ static const char rcsid[] = "$BINDId: res_mkquery.c,v 8.12 1999/10/13 16:39:40 v
# endif
#endif
extern const char *_res_opcodes[];
/*
* Form all types of queries.
* Returns the size of the result or -1.

View File

@ -1135,6 +1135,7 @@ globfree (pglob)
if (pglob->gl_pathv[pglob->gl_offs + i] != NULL)
free ((__ptr_t) pglob->gl_pathv[pglob->gl_offs + i]);
free ((__ptr_t) pglob->gl_pathv);
pglob->gl_pathv = NULL;
}
}
#if defined _LIBC && !defined globfree

View File

@ -54,21 +54,23 @@
/* UDP header as specified by RFC 768, August 1980. */
#ifdef __FAVOR_BSD
struct udphdr
{
uint16_t uh_sport; /* source port */
uint16_t uh_dport; /* destination port */
uint16_t uh_ulen; /* udp length */
uint16_t uh_sum; /* udp checksum */
u_int16_t uh_sport; /* source port */
u_int16_t uh_dport; /* destination port */
u_int16_t uh_ulen; /* udp length */
u_int16_t uh_sum; /* udp checksum */
};
#else
struct udphdr
{
uint16_t source;
uint16_t dest;
uint16_t len;
uint16_t check;
u_int16_t source;
u_int16_t dest;
u_int16_t len;
u_int16_t check;
};
#endif