* elf/dl-error.c (_dl_signal_error): Store information about use of

real malloc in the catch object.
	(_dl_catch_error): Forward information about malloc use to caller
	in new parameter.
	(_dl_out_of_memory): Make static.
	* elf/dl-deps.c: Adjust callers of _dl_catch_error.
	* elf/dl-libc.c: Likewise.
	* elf/dl-open.c: Likewise.
	* elf/rtld.c: Likewise.
	Add new --audit option.
	* sysdeps/generic/ldsodefs.h: Remove _dl_out_of_memory declaration.
	(rtld_global_ro._dl_signal_error): Add new parameter.
	* include/dlfcn.h (_dl_catch_error): Add new parameter.
	* dlfcn/dlfcn.c (_dlerror_run): Pass additional parameter to
	_dl_catch_error.  Only free if the returned newly value says so.
This commit is contained in:
Ulrich Drepper 2005-06-12 16:29:51 +00:00
parent 6dffebd8b4
commit 74780cf659
8 changed files with 108 additions and 41 deletions

View File

@ -1,3 +1,21 @@
2005-06-12 Ulrich Drepper <drepper@redhat.com>
* elf/dl-error.c (_dl_signal_error): Store information about use of
real malloc in the catch object.
(_dl_catch_error): Forward information about malloc use to caller
in new parameter.
(_dl_out_of_memory): Make static.
* elf/dl-deps.c: Adjust callers of _dl_catch_error.
* elf/dl-libc.c: Likewise.
* elf/dl-open.c: Likewise.
* elf/rtld.c: Likewise.
Add new --audit option.
* sysdeps/generic/ldsodefs.h: Remove _dl_out_of_memory declaration.
(rtld_global_ro._dl_signal_error): Add new parameter.
* include/dlfcn.h (_dl_catch_error): Add new parameter.
* dlfcn/dlfcn.c (_dlerror_run): Pass additional parameter to
_dl_catch_error. Only free if the returned newly value says so.
2005-06-01 Roland McGrath <roland@redhat.com> 2005-06-01 Roland McGrath <roland@redhat.com>
[BZ #959] [BZ #959]

View File

@ -19,6 +19,7 @@
#include <dlfcn.h> #include <dlfcn.h>
#include <libintl.h> #include <libintl.h>
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -40,6 +41,7 @@ struct dl_action_result
{ {
int errcode; int errcode;
int returned; int returned;
bool malloced;
const char *objname; const char *objname;
const char *errstring; const char *errstring;
}; };
@ -154,13 +156,13 @@ _dlerror_run (void (*operate) (void *), void *args)
{ {
/* Free the error string from the last failed command. This can /* Free the error string from the last failed command. This can
happen if `dlerror' was not run after an error was found. */ happen if `dlerror' was not run after an error was found. */
if (strcmp (result->errstring, "out of memory") != 0) if (result->malloced)
free ((char *) result->errstring); free ((char *) result->errstring);
result->errstring = NULL; result->errstring = NULL;
} }
result->errcode = GLRO(dl_catch_error) (&result->objname, &result->errstring, result->errcode = GLRO(dl_catch_error) (&result->objname, &result->errstring,
operate, args); &result->malloced, operate, args);
/* If no error we mark that no error string is available. */ /* If no error we mark that no error string is available. */
result->returned = result->errstring == NULL; result->returned = result->errstring == NULL;

View File

@ -235,16 +235,22 @@ _dl_map_object_deps (struct link_map *map,
{ {
/* Map in the needed object. */ /* Map in the needed object. */
struct link_map *dep; struct link_map *dep;
int err;
/* Recognize DSTs. */ /* Recognize DSTs. */
name = expand_dst (l, strtab + d->d_un.d_val, 0); name = expand_dst (l, strtab + d->d_un.d_val, 0);
/* Store the tag in the argument structure. */ /* Store the tag in the argument structure. */
args.name = name; args.name = name;
err = _dl_catch_error (&objname, &errstring, openaux, &args); bool malloced;
int err = _dl_catch_error (&objname, &errstring, &malloced,
openaux, &args);
if (__builtin_expect (errstring != NULL, 0)) if (__builtin_expect (errstring != NULL, 0))
{ {
char *new_errstring = strdupa (errstring);
if (malloced)
free ((char *) errstring);
errstring = new_errstring;
if (err) if (err)
errno_reason = err; errno_reason = err;
else else
@ -288,8 +294,6 @@ _dl_map_object_deps (struct link_map *map,
if (d->d_tag == DT_AUXILIARY) if (d->d_tag == DT_AUXILIARY)
{ {
int err;
/* Say that we are about to load an auxiliary library. */ /* Say that we are about to load an auxiliary library. */
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS,
0)) 0))
@ -301,13 +305,14 @@ _dl_map_object_deps (struct link_map *map,
/* We must be prepared that the addressed shared /* We must be prepared that the addressed shared
object is not available. */ object is not available. */
err = _dl_catch_error (&objname, &errstring, openaux, bool malloced;
&args); (void) _dl_catch_error (&objname, &errstring, &malloced,
openaux, &args);
if (__builtin_expect (errstring != NULL, 0)) if (__builtin_expect (errstring != NULL, 0))
{ {
/* We are not interested in the error message. */ /* We are not interested in the error message. */
assert (errstring != NULL); assert (errstring != NULL);
if (errstring != _dl_out_of_memory) if (malloced)
free ((char *) errstring); free ((char *) errstring);
/* Simply ignore this error and continue the work. */ /* Simply ignore this error and continue the work. */
@ -316,8 +321,6 @@ _dl_map_object_deps (struct link_map *map,
} }
else else
{ {
int err;
/* Say that we are about to load an auxiliary library. */ /* Say that we are about to load an auxiliary library. */
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS,
0)) 0))
@ -328,10 +331,16 @@ _dl_map_object_deps (struct link_map *map,
? l->l_name : rtld_progname); ? l->l_name : rtld_progname);
/* For filter objects the dependency must be available. */ /* For filter objects the dependency must be available. */
err = _dl_catch_error (&objname, &errstring, openaux, bool malloced;
&args); int err = _dl_catch_error (&objname, &errstring, &malloced,
openaux, &args);
if (__builtin_expect (errstring != NULL, 0)) if (__builtin_expect (errstring != NULL, 0))
{ {
char *new_errstring = strdupa (errstring);
if (malloced)
free ((char *) errstring);
errstring = new_errstring;
if (err) if (err)
errno_reason = err; errno_reason = err;
else else

View File

@ -19,6 +19,7 @@
#include <libintl.h> #include <libintl.h>
#include <setjmp.h> #include <setjmp.h>
#include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@ -30,6 +31,8 @@ struct catch
{ {
const char *objname; /* Object/File name. */ const char *objname; /* Object/File name. */
const char *errstring; /* Error detail filled in here. */ const char *errstring; /* Error detail filled in here. */
bool malloced; /* Nonzero if the string is malloced
by the libc malloc. */
jmp_buf env; /* longjmp here on error. */ jmp_buf env; /* longjmp here on error. */
}; };
@ -44,8 +47,7 @@ struct catch
/* This message we return as a last resort. We define the string in a /* This message we return as a last resort. We define the string in a
variable since we have to avoid freeing it and so have to enable variable since we have to avoid freeing it and so have to enable
a pointer comparison. See below and in dlfcn/dlerror.c. */ a pointer comparison. See below and in dlfcn/dlerror.c. */
const char _dl_out_of_memory[] = "out of memory"; static const char _dl_out_of_memory[] = "out of memory";
rtld_hidden_data_def (_dl_out_of_memory)
/* This points to a function which is called when an continuable error is /* This points to a function which is called when an continuable error is
@ -87,15 +89,27 @@ _dl_signal_error (int errcode, const char *objname, const char *occation,
lcatch->errstring = (char *) malloc (len_objname + len_errstring); lcatch->errstring = (char *) malloc (len_objname + len_errstring);
if (lcatch->errstring != NULL) if (lcatch->errstring != NULL)
/* Make a copy of the object file name and the error string. */ {
lcatch->objname = memcpy (__mempcpy ((char *) lcatch->errstring, /* Make a copy of the object file name and the error string. */
errstring, len_errstring), lcatch->objname = memcpy (__mempcpy ((char *) lcatch->errstring,
objname, len_objname); errstring, len_errstring),
objname, len_objname);
/* If the main executable is relocated it means the libc's malloc
is used. */
#ifdef SHARED
lcatch->malloced = (GL(dl_ns)[LM_ID_BASE]._ns_loaded->l_relocated
!= 0);
#else
lcatch->malloced = true;
#endif
}
else else
{ {
/* This is better than nothing. */ /* This is better than nothing. */
lcatch->objname = ""; lcatch->objname = "";
lcatch->errstring = _dl_out_of_memory; lcatch->errstring = _dl_out_of_memory;
lcatch->malloced = false;
} }
longjmp (lcatch->env, errcode ?: -1); longjmp (lcatch->env, errcode ?: -1);
} }
@ -140,7 +154,7 @@ _dl_signal_cerror (int errcode, const char *objname, const char *occation,
int int
internal_function internal_function
_dl_catch_error (const char **objname, const char **errstring, _dl_catch_error (const char **objname, const char **errstring,
void (*operate) (void *), void *args) bool *mallocedp, void (*operate) (void *), void *args)
{ {
int errcode; int errcode;
struct catch *volatile old; struct catch *volatile old;
@ -162,6 +176,7 @@ _dl_catch_error (const char **objname, const char **errstring,
*catchp = old; *catchp = old;
*objname = NULL; *objname = NULL;
*errstring = NULL; *errstring = NULL;
*mallocedp = false;
return 0; return 0;
} }
@ -169,6 +184,7 @@ _dl_catch_error (const char **objname, const char **errstring,
*catchp = old; *catchp = old;
*objname = c.objname; *objname = c.objname;
*errstring = c.errstring; *errstring = c.errstring;
*mallocedp = c.malloced;
return errcode == -1 ? 0 : errcode; return errcode == -1 ? 0 : errcode;
} }

View File

@ -1,5 +1,5 @@
/* Handle loading and unloading shared objects for internal libc purposes. /* Handle loading and unloading shared objects for internal libc purposes.
Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. Copyright (C) 1999,2000,2001,2002,2004,2005 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Zack Weinberg <zack@rabi.columbia.edu>, 1999. Contributed by Zack Weinberg <zack@rabi.columbia.edu>, 1999.
@ -42,12 +42,13 @@ dlerror_run (void (*operate) (void *), void *args)
{ {
const char *objname; const char *objname;
const char *last_errstring = NULL; const char *last_errstring = NULL;
int result; bool malloced;
(void) GLRO(dl_catch_error) (&objname, &last_errstring, operate, args); (void) GLRO(dl_catch_error) (&objname, &last_errstring, &malloced,
operate, args);
result = last_errstring != NULL; int result = last_errstring != NULL;
if (result && last_errstring != _dl_out_of_memory) if (result && malloced)
free ((char *) last_errstring); free ((char *) last_errstring);
return result; return result;

View File

@ -504,11 +504,6 @@ void *
_dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid, _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
int argc, char *argv[], char *env[]) int argc, char *argv[], char *env[])
{ {
struct dl_open_args args;
const char *objname;
const char *errstring;
int errcode;
if ((mode & RTLD_BINDING_MASK) == 0) if ((mode & RTLD_BINDING_MASK) == 0)
/* One of the flags must be set. */ /* One of the flags must be set. */
_dl_signal_error (EINVAL, file, NULL, N_("invalid mode for dlopen()")); _dl_signal_error (EINVAL, file, NULL, N_("invalid mode for dlopen()"));
@ -543,6 +538,7 @@ no more namespaces available for dlmopen()"));
_dl_signal_error (EINVAL, file, NULL, _dl_signal_error (EINVAL, file, NULL,
N_("invalid target namespace in dlmopen()")); N_("invalid target namespace in dlmopen()"));
struct dl_open_args args;
args.file = file; args.file = file;
args.mode = mode; args.mode = mode;
args.caller_dlopen = caller_dlopen; args.caller_dlopen = caller_dlopen;
@ -552,7 +548,12 @@ no more namespaces available for dlmopen()"));
args.argc = argc; args.argc = argc;
args.argv = argv; args.argv = argv;
args.env = env; args.env = env;
errcode = _dl_catch_error (&objname, &errstring, dl_open_worker, &args);
const char *objname;
const char *errstring;
bool malloced;
int errcode = _dl_catch_error (&objname, &errstring, &malloced,
dl_open_worker, &args);
#ifndef MAP_COPY #ifndef MAP_COPY
/* We must munmap() the cache file. */ /* We must munmap() the cache file. */
@ -603,7 +604,7 @@ no more namespaces available for dlmopen()"));
memcpy (local_errstring, errstring, len_errstring); memcpy (local_errstring, errstring, len_errstring);
} }
if (errstring != _dl_out_of_memory) if (malloced)
free ((char *) errstring); free ((char *) errstring);
assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT); assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);

View File

@ -61,6 +61,9 @@ static void print_missing_version (int errcode, const char *objname,
/* Print the various times we collected. */ /* Print the various times we collected. */
static void print_statistics (hp_timing_t *total_timep); static void print_statistics (hp_timing_t *total_timep);
/* Add audit objects. */
static void process_dl_audit (char *str);
/* This is a list of all the modes the dynamic loader can be in. */ /* This is a list of all the modes the dynamic loader can be in. */
enum mode { normal, list, verify, trace }; enum mode { normal, list, verify, trace };
@ -771,6 +774,7 @@ do_preload (char *fname, struct link_map *main_map, const char *where)
const char *objname; const char *objname;
const char *err_str = NULL; const char *err_str = NULL;
struct map_args args; struct map_args args;
bool malloced;
args.str = fname; args.str = fname;
args.loader = main_map; args.loader = main_map;
@ -779,7 +783,7 @@ do_preload (char *fname, struct link_map *main_map, const char *where)
unsigned int old_nloaded = GL(dl_ns)[LM_ID_BASE]._ns_nloaded; unsigned int old_nloaded = GL(dl_ns)[LM_ID_BASE]._ns_nloaded;
(void) _dl_catch_error (&objname, &err_str, map_doit, &args); (void) _dl_catch_error (&objname, &err_str, &malloced, map_doit, &args);
if (__builtin_expect (err_str != NULL, 0)) if (__builtin_expect (err_str != NULL, 0))
{ {
_dl_error_printf ("\ _dl_error_printf ("\
@ -923,6 +927,14 @@ dl_main (const ElfW(Phdr) *phdr,
{ {
GLRO(dl_inhibit_rpath) = INTUSE(_dl_argv)[2]; GLRO(dl_inhibit_rpath) = INTUSE(_dl_argv)[2];
_dl_skip_args += 2;
_dl_argc -= 2;
INTUSE(_dl_argv) += 2;
}
else if (! strcmp (INTUSE(_dl_argv)[1], "--audit") && _dl_argc > 2)
{
process_dl_audit (INTUSE(_dl_argv)[2]);
_dl_skip_args += 2; _dl_skip_args += 2;
_dl_argc -= 2; _dl_argc -= 2;
INTUSE(_dl_argv) += 2; INTUSE(_dl_argv) += 2;
@ -983,12 +995,14 @@ of this helper program; chances are you did not intend to run this program.\n\
const char *objname; const char *objname;
const char *err_str = NULL; const char *err_str = NULL;
struct map_args args; struct map_args args;
bool malloced;
args.str = rtld_progname; args.str = rtld_progname;
args.loader = NULL; args.loader = NULL;
args.is_preloaded = 0; args.is_preloaded = 0;
args.mode = __RTLD_OPENEXEC; args.mode = __RTLD_OPENEXEC;
(void) _dl_catch_error (&objname, &err_str, map_doit, &args); (void) _dl_catch_error (&objname, &err_str, &malloced, map_doit,
&args);
if (__builtin_expect (err_str != NULL, 0)) if (__builtin_expect (err_str != NULL, 0))
/* We don't free the returned string, the programs stops /* We don't free the returned string, the programs stops
anyway. */ anyway. */
@ -1398,14 +1412,17 @@ ld.so does not support TLS, but program uses it!\n");
const char *objname; const char *objname;
const char *err_str = NULL; const char *err_str = NULL;
(void) _dl_catch_error (&objname, &err_str, dlmopen_doit, &dlmargs); bool malloced;
(void) _dl_catch_error (&objname, &err_str, &malloced, dlmopen_doit,
&dlmargs);
if (__builtin_expect (err_str != NULL, 0)) if (__builtin_expect (err_str != NULL, 0))
{ {
not_loaded: not_loaded:
_dl_error_printf ("\ _dl_error_printf ("\
ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
al->name, err_str); al->name, err_str);
free ((char *) err_str); if (malloced)
free ((char *) err_str);
} }
else else
{ {
@ -1414,7 +1431,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
largs.map = dlmargs.map; largs.map = dlmargs.map;
/* Check whether the interface version matches. */ /* Check whether the interface version matches. */
(void) _dl_catch_error (&objname, &err_str, lookup_doit, &largs); (void) _dl_catch_error (&objname, &err_str, &malloced,
lookup_doit, &largs);
unsigned int (*laversion) (unsigned int); unsigned int (*laversion) (unsigned int);
unsigned int lav; unsigned int lav;
@ -1455,8 +1473,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
do do
{ {
largs.name = cp; largs.name = cp;
(void) _dl_catch_error (&objname, &err_str, lookup_doit, (void) _dl_catch_error (&objname, &err_str, &malloced,
&largs); lookup_doit, &largs);
/* Store the pointer. */ /* Store the pointer. */
if (err_str == NULL && largs.result != NULL) if (err_str == NULL && largs.result != NULL)

View File

@ -1,6 +1,7 @@
#ifndef _DLFCN_H #ifndef _DLFCN_H
#include <dlfcn/dlfcn.h> #include <dlfcn/dlfcn.h>
#include <link.h> /* For ElfW. */ #include <link.h> /* For ElfW. */
#include <stdbool.h>
/* Internally used flag. */ /* Internally used flag. */
#define __RTLD_DLOPEN 0x80000000 #define __RTLD_DLOPEN 0x80000000
@ -67,9 +68,10 @@ extern void *_dl_vsym (void *handle, const char *name, const char *version,
and the error code passed is the return value and *OBJNAME is set to and the error code passed is the return value and *OBJNAME is set to
the object name which experienced the problems. ERRSTRING if nonzero the object name which experienced the problems. ERRSTRING if nonzero
points to a malloc'ed string which the caller has to free after use. points to a malloc'ed string which the caller has to free after use.
ARGS is passed as argument to OPERATE. */ ARGS is passed as argument to OPERATE. MALLOCEDP is set to true only
if the returned string is allocated using the libc's malloc. */
extern int _dl_catch_error (const char **objname, const char **errstring, extern int _dl_catch_error (const char **objname, const char **errstring,
void (*operate) (void *), bool *mallocedp, void (*operate) (void *),
void *args) void *args)
internal_function; internal_function;