Headline
CVE-2010-3856: Andreas Schwab - [PATCH] Require suid bit on audit objects in privileged programs
ld.so in the GNU C Library (aka glibc or libc6) before 2.11.3, and 2.12.x before 2.12.2, does not properly restrict use of the LD_AUDIT environment variable to reference dynamic shared objects (DSOs) as audit objects, which allows local users to gain privileges by leveraging an unsafe DSO located in a trusted library directory, as demonstrated by libpcprofile.so.
This is the mail archive of the [email protected] mailing list for the glibc project.
Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.
Index Nav:
[Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav:
[Date Prev] [Date Next]
[Thread Prev] [Thread Next]
Other format:
[Raw text]
- From: Andreas Schwab <schwab at redhat dot com>
- To: libc-hacker at sourceware dot org
- Date: Fri, 22 Oct 2010 19:17:20 +0200
- Subject: [PATCH] Require suid bit on audit objects in privileged programs
2010-10-22 Andreas Schwab [email protected]
\* include/dlfcn.h (\_\_RTLD\_SECURE): Define.
\* elf/dl-load.c (\_dl\_map\_object): Remove preloaded parameter. Use
mode & \_\_RTLD\_SECURE instead.
(open\_path): Rename preloaded parameter to secure.
\* sysdeps/generic/ldsodefs.h (\_dl\_map\_object): Adjust declaration.
\* elf/dl-open.c (dl\_open\_worker): Adjust call to \_dl\_map\_object.
\* elf/dl-deps.c (openaux): Likewise.
\* elf/rtld.c (struct map\_args): Remove is\_preloaded.
(map\_doit): Don't use it.
(dl\_main): Likewise.
(do\_preload): Use \_\_RTLD\_SECURE instead of is\_preloaded.
(dlmopen\_doit): Add \_\_RTLD\_SECURE to mode bits.
elf/dl-deps.c | 2 ± elf/dl-load.c | 20 ++++++++++±-------- elf/dl-open.c | 2 ± elf/rtld.c | 16 ++++++±-------- include/dlfcn.h | 1 + sysdeps/generic/ldsodefs.h | 6 +±— 6 files changed, 23 insertions(+), 24 deletions(-)
diff --git a/elf/dl-deps.c b/elf/dl-deps.c index e5b9cdf…1cab2d1 100644 — a/elf/dl-deps.c +++ b/elf/dl-deps.c @@ -62,7 +62,7 @@ openaux (void *a) { struct openaux_args *args = (struct openaux_args *) a;
- args->aux = _dl_map_object (args->map, args->name, 0,
- args->aux = _dl_map_object (args->map, args->name, (args->map->l_type == lt_executable ? lt_library : args->map->l_type), args->trace_mode, args->open_mode, diff --git a/elf/dl-load.c b/elf/dl-load.c index 776f7e4…9ab3520 100644 — a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1808,7 +1808,7 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader, if MAY_FREE_DIRS is true. */
static int -open_path (const char *name, size_t namelen, int preloaded, +open_path (const char *name, size_t namelen, int secure, struct r_search_path_struct *sps, char **realname, struct filebuf *fbp, struct link_map *loader, int whatcode, bool *found_other_class) @@ -1890,7 +1890,7 @@ open_path (const char *name, size_t namelen, int preloaded, /* Remember whether we found any existing directory. */ here_any |= this_dir->status[cnt] != nonexisting;
if (fd != -1 && \_\_builtin\_expect (preloaded, 0)
if (fd != -1 && \_\_builtin\_expect (secure, 0) && INTUSE(\_\_libc\_enable\_secure)) { /\* This is an extra security effort to make sure nobody can
@@ -1959,7 +1959,7 @@ open_path (const char *name, size_t namelen, int preloaded,
struct link_map * internal_function -_dl_map_object (struct link_map *loader, const char *name, int preloaded, +_dl_map_object (struct link_map *loader, const char *name, int type, int trace_mode, int mode, Lmid_t nsid) { int fd; @@ -2063,7 +2063,8 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded, for (l = loader; l; l = l->l_loader) if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, “RPATH”)) {
fd = open\_path (name, namelen, preloaded, &l->l\_rpath\_dirs,
fd = open\_path (name, namelen, mode & \_\_RTLD\_SECURE,
&l->l\_rpath\_dirs, &realname, &fb, loader, LA\_SER\_RUNPATH, &found\_other\_class); if (fd != -1)
@@ -2078,14 +2079,15 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded, && main_map != NULL && main_map->l_type != lt_loaded && cache_rpath (main_map, &main_map->l_rpath_dirs, DT_RPATH, “RPATH”))
fd = open\_path (name, namelen, preloaded, &main\_map->l\_rpath\_dirs,
fd = open\_path (name, namelen, mode & \_\_RTLD\_SECURE,
&main\_map->l\_rpath\_dirs, &realname, &fb, loader ?: main\_map, LA\_SER\_RUNPATH, &found\_other\_class);
}
/\* Try the LD\_LIBRARY\_PATH environment variable. \*/ if (fd == -1 && env\_path\_list.dirs != (void \*) -1)
- fd = open_path (name, namelen, preloaded, &env_path_list,
- fd = open_path (name, namelen, mode & __RTLD_SECURE, &env_path_list, &realname, &fb, loader ?: GL(dl_ns)[LM_ID_BASE]._ns_loaded, LA_SER_LIBPATH, &found_other_class); @@ -2094,12 +2096,12 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded, if (fd == -1 && loader != NULL && cache_rpath (loader, &loader->l_runpath_dirs, DT_RUNPATH, “RUNPATH”))
- fd = open_path (name, namelen, preloaded,
fd = open_path (name, namelen, mode & __RTLD_SECURE, &loader->l_runpath_dirs, &realname, &fb, loader, LA_SER_RUNPATH, &found_other_class);
if (fd == -1
&& (\_\_builtin\_expect (! preloaded, 1)
{ /* Check the list of libraries in the file /etc/ld.so.cache, @@ -2165,7 +2167,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded, && ((l = loader ?: GL(dl_ns)[nsid]._ns_loaded) == NULL || __builtin_expect (!(l->l_flags_1 & DF_1_NODEFLIB), 1)) && rtld_search_dirs.dirs != (void *) -1)&& (\_\_builtin\_expect (! (mode & \_\_RTLD\_SECURE), 1) || ! INTUSE(\_\_libc\_enable\_secure)))
- fd = open_path (name, namelen, preloaded, &rtld_search_dirs,
fd = open_path (name, namelen, mode & __RTLD_SECURE, &rtld_search_dirs, &realname, &fb, l, LA_SER_DEFAULT, &found_other_class);
/* Add another newline when we are tracing the library loading. */ diff --git a/elf/dl-open.c b/elf/dl-open.c index c394b3f…cf8e8cc 100644 — a/elf/dl-open.c +++ b/elf/dl-open.c @@ -223,7 +223,7 @@ dl_open_worker (void *a)
/* Load the named object. */ struct link_map *new;
- args->map = new = _dl_map_object (call_map, file, 0, lt_loaded, 0,
args->map = new = _dl_map_object (call_map, file, lt_loaded, 0, mode | __RTLD_CALLMAP, args->nsid);
/* If the pointer returned is NULL this means the RTLD_NOLOAD flag is diff --git a/elf/rtld.c b/elf/rtld.c index 201c9cf…4a8cee8 100644 — a/elf/rtld.c +++ b/elf/rtld.c @@ -587,7 +587,6 @@ struct map_args /* Argument to map_doit. */ char *str; struct link_map *loader;
- int is_preloaded; int mode; /* Return value of map_doit. */ struct link_map *map; @@ -625,16 +624,17 @@ static void map_doit (void *a) { struct map_args *args = (struct map_args *) a;
- args->map = _dl_map_object (args->loader, args->str,
args->is\_preloaded, lt\_library, 0, args->mode,
LM\_ID\_BASE);
- args->map = _dl_map_object (args->loader, args->str, lt_library, 0,
args->mode, LM\_ID\_BASE);
}
static void dlmopen_doit (void *a) { struct dlmopen_args *args = (struct dlmopen_args *) a;
- args->map = _dl_open (args->fname, RTLD_LAZY | __RTLD_DLOPEN | __RTLD_AUDIT,
- args->map = _dl_open (args->fname,
(RTLD\_LAZY | \_\_RTLD\_DLOPEN | \_\_RTLD\_AUDIT
| \_\_RTLD\_SECURE), dl\_main, LM\_ID\_NEWLM, \_dl\_argc, INTUSE(\_dl\_argv), \_\_environ);
} @@ -804,8 +804,7 @@ do_preload (char *fname, struct link_map *main_map, const char *where)
args.str = fname; args.loader = main_map;
- args.is_preloaded = 1;
- args.mode = 0;
args.mode = __RTLD_SECURE;
unsigned int old_nloaded = GL(dl_ns)[LM_ID_BASE]._ns_nloaded;
@@ -1050,7 +1049,6 @@ of this helper program; chances are you did not intend to run this program.\n\
args.str = rtld\_progname;
args.loader = NULL;
args.is\_preloaded = 0; args.mode = \_\_RTLD\_OPENEXEC; (void) \_dl\_catch\_error (&objname, &err\_str, &malloced, map\_doit, &args);
@@ -1062,7 +1060,7 @@ of this helper program; chances are you did not intend to run this program.\n\ else { HP_TIMING_NOW (start);
\_dl\_map\_object (NULL, rtld\_progname, 0, lt\_library, 0,
\_dl\_map\_object (NULL, rtld\_progname, lt\_library, 0, \_\_RTLD\_OPENEXEC, LM\_ID\_BASE); HP\_TIMING\_NOW (stop);
diff --git a/include/dlfcn.h b/include/dlfcn.h index a67426d…af92483 100644 — a/include/dlfcn.h +++ b/include/dlfcn.h @@ -9,6 +9,7 @@ #define __RTLD_OPENEXEC 0x20000000 #define __RTLD_CALLMAP 0x10000000 #define __RTLD_AUDIT 0x08000000 +#define __RTLD_SECURE 0x04000000 /* Apply additional security checks. */
#define __LM_ID_CALLER -2
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index fcc943b…fa4b6b2 100644 — a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -824,11 +824,9 @@ extern void _dl_receive_error (receiver_fct fct, void (*operate) (void *),
/* Open the shared object NAME and map in its segments. LOADER’s DT_RPATH is used in searching for NAME.
- If the object is already opened, returns its existing map.
- For preloaded shared objects PRELOADED is set to a non-zero
- value to allow additional security checks. */
- If the object is already opened, returns its existing map. */ extern struct link_map *_dl_map_object (struct link_map *loader,
const char \*name, int preloaded,
const char \*name, int type, int trace\_mode, int mode, Lmid\_t nsid) internal\_function attribute\_hidden;
– 1.7.2.3
– Andreas Schwab, [email protected] GPG Key fingerprint = D4E8 DBE3 3813 BB5D FA84 5EC7 45C6 250E 6F00 984E “And now for something completely different.”
- Follow-Ups:
- Re: [PATCH] Require suid bit on audit objects in privileged programs
- From: Roland McGrath
- Re: [PATCH] Require suid bit on audit objects in privileged programs
Index Nav:
[Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav:
[Date Prev] [Date Next]
[Thread Prev] [Thread Next]
Related news
The PKCS#11 feature in ssh-agent in OpenSSH versions prior to 9.3p2 has an insufficiently trustworthy search path, leading to remote code execution if an agent is forwarded to an attacker-controlled system.
libffi requests an executable stack allowing attackers to more easily trigger arbitrary code execution by overwriting the stack. Please note that libffi is used by a number of other libraries. It was previously stated that this affects libffi version 3.2.1 but this appears to be incorrect. libffi prior to version 3.1 on 32 bit x86 systems was vulnerable, and upstream is believed to have fixed this issue in version 3.1.