summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/sgs/include/debug.h6
-rw-r--r--usr/src/cmd/sgs/libelf/Makefile.targ4
-rw-r--r--usr/src/cmd/sgs/libelf/common/error.c45
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/liblddbg.msg3
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/libs.c9
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/llib-llddbg4
-rw-r--r--usr/src/cmd/sgs/liblddbg/common/mapfile-vers6
-rw-r--r--usr/src/cmd/sgs/packages/common/SUNWonld-README2
-rw-r--r--usr/src/cmd/sgs/rtld/common/_rtld.h6
-rw-r--r--usr/src/cmd/sgs/rtld/common/analyze.c19
-rw-r--r--usr/src/cmd/sgs/rtld/common/debug.c14
-rw-r--r--usr/src/cmd/sgs/rtld/common/paths.c58
-rw-r--r--usr/src/cmd/sgs/rtld/common/util.c158
13 files changed, 207 insertions, 127 deletions
diff --git a/usr/src/cmd/sgs/include/debug.h b/usr/src/cmd/sgs/include/debug.h
index 0e588be0f1..f8f9e641b6 100644
--- a/usr/src/cmd/sgs/include/debug.h
+++ b/usr/src/cmd/sgs/include/debug.h
@@ -273,7 +273,7 @@ extern uintptr_t Dbg_setup(const char *, Dbg_desc *);
#define Dbg_libs_audit Dbg64_libs_audit
#define Dbg_libs_find Dbg64_libs_find
#define Dbg_libs_found Dbg64_libs_found
-#define Dbg_libs_ignore Dbg64_libs_ignore
+#define Dbg_libs_insecure Dbg64_libs_insecure
#define Dbg_libs_init Dbg64_libs_init
#define Dbg_libs_l Dbg64_libs_l
#define Dbg_libs_path Dbg64_libs_path
@@ -478,7 +478,7 @@ extern uintptr_t Dbg_setup(const char *, Dbg_desc *);
#define Dbg_libs_audit Dbg32_libs_audit
#define Dbg_libs_find Dbg32_libs_find
#define Dbg_libs_found Dbg32_libs_found
-#define Dbg_libs_ignore Dbg32_libs_ignore
+#define Dbg_libs_insecure Dbg32_libs_insecure
#define Dbg_libs_init Dbg32_libs_init
#define Dbg_libs_l Dbg32_libs_l
#define Dbg_libs_path Dbg32_libs_path
@@ -713,7 +713,7 @@ extern void Dbg_got_display(Ofl_desc *, Off, int, Word, size_t);
extern void Dbg_libs_audit(Lm_list *, const char *, const char *);
extern void Dbg_libs_find(Lm_list *, const char *);
extern void Dbg_libs_found(Lm_list *, const char *, int);
-extern void Dbg_libs_ignore(Lm_list *, const char *);
+extern void Dbg_libs_insecure(Lm_list *, const char *, int);
extern void Dbg_libs_init(Lm_list *, List *, List *);
extern void Dbg_libs_l(Lm_list *, const char *, const char *);
extern void Dbg_libs_path(Lm_list *, const char *, uint_t, const char *);
diff --git a/usr/src/cmd/sgs/libelf/Makefile.targ b/usr/src/cmd/sgs/libelf/Makefile.targ
index e5d688a517..6ede755fb4 100644
--- a/usr/src/cmd/sgs/libelf/Makefile.targ
+++ b/usr/src/cmd/sgs/libelf/Makefile.targ
@@ -22,8 +22,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
$(VAR_POUND_2)LIBS += $(LIBRARY)
@@ -138,8 +136,6 @@ pics/xlate.o: xlate.c
native: $(SGSPROTO)/$(DYNLIB)
-native := CPPFLAGS += -DNATIVE_BUILD
-
$(SGSPROTO)/$(DYNLIB): \
pics .WAIT $$(PICS)
$(BUILD.SO)
diff --git a/usr/src/cmd/sgs/libelf/common/error.c b/usr/src/cmd/sgs/libelf/common/error.c
index 21433d05eb..0a55a9efe6 100644
--- a/usr/src/cmd/sgs/libelf/common/error.c
+++ b/usr/src/cmd/sgs/libelf/common/error.c
@@ -24,8 +24,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <thread.h>
#include <pthread.h>
#include <stdlib.h>
@@ -39,7 +37,6 @@
#define ELFERRSHIFT 16
#define SYSERRMASK 0xffff
-
/*
* _elf_err has two values encoded in it, both the _elf_err # and
* the system errno value (if relevant). These values are encoded
@@ -47,57 +44,15 @@
*/
static int _elf_err = 0;
-#if !defined(NATIVE_BUILD)
-
static thread_key_t errkey = THR_ONCE_KEY;
static thread_key_t bufkey = THR_ONCE_KEY;
-#else /* NATIVE_BUILD */
-
-/*
- * This code is here to enable the building of a native version
- * of libelf.so when the build machine has not yet been upgraded
- * to a version of libc that provides thr_keycreate_once().
- * It should be deleted when solaris_nevada ships.
- * The code is not MT-safe in a relaxed memory model.
- */
-
-static thread_key_t errkey = 0;
-static thread_key_t bufkey = 0;
-
-int
-thr_keycreate_once(thread_key_t *keyp, void (*destructor)(void *))
-{
- static mutex_t key_lock = DEFAULTMUTEX;
- thread_key_t key;
- int error;
-
- if (*keyp == 0) {
- mutex_lock(&key_lock);
- if (*keyp == 0) {
- error = thr_keycreate(&key, destructor);
- if (error) {
- mutex_unlock(&key_lock);
- return (error);
- }
- *keyp = key;
- }
- mutex_unlock(&key_lock);
- }
-
- return (0);
-}
-
-#endif /* NATIVE_BUILD */
-
-
const char *
_libelf_msg(Msg mid)
{
return (dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid)));
}
-
void
_elf_seterr(Msg lib_err, int sys_err)
{
diff --git a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg
index ef0190871c..aec5e954ae 100644
--- a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg
+++ b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg
@@ -492,7 +492,8 @@
@ MSG_LIB_ALTER " trying path=%s (auditing supplied alternative)"
@ MSG_LIB_SKIP " skip path=%s (auditing directed)"
@ MSG_LIB_IGNORE " ignore path=%s (insecure directory name)"
-
+@ MSG_LIB_INUSE " use path=%s (implicitly secure, as directory \
+ has already provided dependencies)"
# Mapfile messages
diff --git a/usr/src/cmd/sgs/liblddbg/common/libs.c b/usr/src/cmd/sgs/liblddbg/common/libs.c
index 227a0cce0c..5ccfce723e 100644
--- a/usr/src/cmd/sgs/liblddbg/common/libs.c
+++ b/usr/src/cmd/sgs/liblddbg/common/libs.c
@@ -23,8 +23,6 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include "msg.h"
#include "_debug.h"
#include "libld.h"
@@ -64,12 +62,15 @@ Dbg_libs_found(Lm_list *lml, const char *path, int alter)
}
void
-Dbg_libs_ignore(Lm_list *lml, const char *path)
+Dbg_libs_insecure(Lm_list *lml, const char *path, int usable)
{
if (DBG_NOTCLASS(DBG_C_LIBS))
return;
- dbg_print(lml, MSG_INTL(MSG_LIB_IGNORE), path);
+ if (usable)
+ dbg_print(lml, MSG_INTL(MSG_LIB_INUSE), path);
+ else
+ dbg_print(lml, MSG_INTL(MSG_LIB_IGNORE), path);
}
static void
diff --git a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg
index f2981d8fce..6ab7e7be27 100644
--- a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg
+++ b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg
@@ -166,8 +166,8 @@ void Dbg32_libs_find(Lm_list *, const char *);
void Dbg64_libs_find(Lm_list *, const char *);
void Dbg32_libs_found(Lm_list *, const char *, int);
void Dbg64_libs_found(Lm_list *, const char *, int);
-void Dbg32_libs_ignore(Lm_list *, const char *);
-void Dbg64_libs_ignore(Lm_list *, const char *);
+void Dbg32_libs_insecure(Lm_list *, const char *, int);
+void Dbg64_libs_insecure(Lm_list *, const char *, int);
void Dbg32_libs_init(Lm_list *, List *, List *);
void Dbg64_libs_init(Lm_list *, List *, List *);
void Dbg32_libs_l(Lm_list *, const char *, const char *);
diff --git a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers
index 605e179bfb..102ba73c67 100644
--- a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers
+++ b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers
@@ -38,7 +38,7 @@
# Policy for Shared Library Version Names and Interface Definitions
-SUNWprivate_4.65 {
+SUNWprivate_4.66 {
global:
dbg_desc = NODIRECT; # interposed - ld.so.1(1)
dbg_print = NODIRECT; # interposed - ld(1) and ld.so.1(1)
@@ -166,8 +166,8 @@ SUNWprivate_4.65 {
Dbg64_libs_find;
Dbg32_libs_found;
Dbg64_libs_found;
- Dbg32_libs_ignore;
- Dbg64_libs_ignore;
+ Dbg32_libs_insecure;
+ Dbg64_libs_insecure;
Dbg32_libs_init;
Dbg64_libs_init;
Dbg32_libs_l;
diff --git a/usr/src/cmd/sgs/packages/common/SUNWonld-README b/usr/src/cmd/sgs/packages/common/SUNWonld-README
index f964e166fa..d5ad09bd9d 100644
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README
+++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README
@@ -1376,3 +1376,5 @@ Bugid Risk Synopsis
linking gnu object code
6744003 ld(1) could provide better argument processing diagnostics
PSARC 2008/583 add gld options to ld(1)
+6746674 setuid applications do not find libraries any more because trusted
+ directories behavior changed
diff --git a/usr/src/cmd/sgs/rtld/common/_rtld.h b/usr/src/cmd/sgs/rtld/common/_rtld.h
index ef5c19f602..57764f9526 100644
--- a/usr/src/cmd/sgs/rtld/common/_rtld.h
+++ b/usr/src/cmd/sgs/rtld/common/_rtld.h
@@ -30,8 +30,6 @@
#ifndef __RTLD_H
#define __RTLD_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Common header for run-time linker.
*/
@@ -318,6 +316,7 @@ typedef struct {
#define RT_FL2_PLMSETUP 0x00000400 /* primary link-map set up complete */
#define RT_FL2_BRANDED 0x00000800 /* process is branded */
#define RT_FL2_NOPLM 0x00001000 /* process has no primary link map */
+#define RT_FL2_SETUID 0x00002000 /* ld.so.1 is setuid root */
/*
* Information flags for env_info.
@@ -585,6 +584,7 @@ extern Pnode *hwcap_filtees(Pnode **, Aliste, Lm_cntl *, Dyninfo *,
extern void is_dep_ready(Rt_map *, Rt_map *, int);
extern void is_dep_init(Rt_map *, Rt_map *);
extern int is_move_data(caddr_t);
+extern int is_rtld_setuid();
extern int is_sym_interposer(Rt_map *, Sym *);
extern void ldso_plt_init(Rt_map *);
extern Listnode *list_append(List *, const void *);
@@ -650,6 +650,8 @@ extern Rt_map *setup(char **, auxv_t *, Word, char *, int, char *,
Dyn *, ulong_t, ulong_t, int fd, Phdr *, char *,
char **, int, uid_t, uid_t, gid_t, gid_t, void *,
int, uint_t);
+extern void spavl_insert(const char *);
+extern int spavl_recorded(const char *, avl_index_t *);
extern int tls_assign(Lm_list *, Rt_map *, Phdr *);
extern void tls_modaddrem(Rt_map *, uint_t);
extern int tls_statmod(Lm_list *, Rt_map *);
diff --git a/usr/src/cmd/sgs/rtld/common/analyze.c b/usr/src/cmd/sgs/rtld/common/analyze.c
index f5111d803d..7dcf5b00d0 100644
--- a/usr/src/cmd/sgs/rtld/common/analyze.c
+++ b/usr/src/cmd/sgs/rtld/common/analyze.c
@@ -29,8 +29,6 @@
* All Rights Reserved
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <string.h>
#include <stdio.h>
#include <unistd.h>
@@ -1741,6 +1739,23 @@ load_file(Lm_list *lml, Aliste lmco, Fdesc *fdesc, int *in_nfavl)
remove_so(lml, nlmp);
return (0);
}
+
+ /*
+ * If this is a secure application, record any full path name
+ * directory in which this dependency has been found. This
+ * directory can be deemed safe (as we've already found a
+ * dependency here). This recording provides a fall-back
+ * should another objects $ORIGIN definition expands to this
+ * directory, an expansion that would ordinarily be deemed
+ * insecure.
+ */
+ if (rtld_flags & RT_FL_SECURE) {
+ if (NAME(nlmp)[0] == '/')
+ spavl_insert(NAME(nlmp));
+ if ((NAME(nlmp) != PATHNAME(nlmp)) &&
+ (PATHNAME(nlmp)[0] == '/'))
+ spavl_insert(PATHNAME(nlmp));
+ }
}
/*
diff --git a/usr/src/cmd/sgs/rtld/common/debug.c b/usr/src/cmd/sgs/rtld/common/debug.c
index a58e294246..2168351095 100644
--- a/usr/src/cmd/sgs/rtld/common/debug.c
+++ b/usr/src/cmd/sgs/rtld/common/debug.c
@@ -24,8 +24,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
@@ -61,16 +59,8 @@ dbg_setup(const char *options, Dbg_desc *dbp)
* If we're running secure, only allow debugging if ld.so.1 itself is
* owned by root and has its mode setuid. Fail silently.
*/
- if (rtld_flags & RT_FL_SECURE) {
- struct stat status;
-
- if (stat(NAME(lml_rtld.lm_head), &status) == 0) {
- if ((status.st_uid != 0) ||
- (!(status.st_mode & S_ISUID)))
- return (0);
- } else
- return (0);
- }
+ if ((rtld_flags & RT_FL_SECURE) && (is_rtld_setuid() == 0))
+ return (0);
/*
* As Dbg_setup() will effectively lazy load the necessary support
diff --git a/usr/src/cmd/sgs/rtld/common/paths.c b/usr/src/cmd/sgs/rtld/common/paths.c
index da750728d4..23391d59ab 100644
--- a/usr/src/cmd/sgs/rtld/common/paths.c
+++ b/usr/src/cmd/sgs/rtld/common/paths.c
@@ -29,8 +29,6 @@
* All Rights Reserved
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* PATH setup and search directory functions.
*/
@@ -715,7 +713,7 @@ is_path_secure(char *opath, Rt_map *clmp, uint_t info, uint_t flags)
{
Pnode *sdir = LM_SECURE_DIRS(LIST(clmp)->lm_head);
char buffer[PATH_MAX], *npath;
- Lm_list *lml;
+ Lm_list *lml = LIST(clmp);
/*
* If a pathname originates from a configuration file, use it. The use
@@ -736,20 +734,24 @@ is_path_secure(char *opath, Rt_map *clmp, uint_t info, uint_t flags)
str = strrchr(opath, '/');
/*
- * A simple filename (one containing no "/") is fine, as this
- * will be combined with search paths to determine the complete
- * path. Other paths are checked:
+ * Carry out some initial security checks.
*
+ * . a simple file name (one containing no "/") is fine, as
+ * this file name will be combined with search paths to
+ * determine the complete path.
* . a full path (one starting with "/") is fine, provided
- * it isn't a preload/audit path.
- * . any $ORIGIN expansion
- * . any relative path
+ * this path name isn't a preload/audit path.
+ * . provided $ORIGIN expansion has not been employed, the
+ * above categories of path are deemed secure.
*/
if (((str == 0) || ((*opath == '/') && (str != opath) &&
((info & PN_FLG_EXTLOAD) == 0))) &&
((flags & PN_TKN_ORIGIN) == 0))
return (1);
+ /*
+ * Determine the directory name of the present path.
+ */
if (str == opath)
npath = (char *)MSG_ORIG(MSG_STR_SLASH);
else {
@@ -762,19 +764,47 @@ is_path_secure(char *opath, Rt_map *clmp, uint_t info, uint_t flags)
buffer[size] = '\0';
npath = buffer;
}
+
+ /*
+ * If $ORIGIN processing has been employed, then allow any
+ * directory that has already been used to satisfy other
+ * dependencies, to be used.
+ */
+ if ((flags & PN_TKN_ORIGIN) && spavl_recorded(npath, 0)) {
+ DBG_CALL(Dbg_libs_insecure(lml, npath, 1));
+ return (1);
+ }
+
} else {
/*
* A search path, i.e., RPATH, configuration file path, etc. is
* used as is. Exceptions to this are:
*
- * . LD_LIBRARY_PATH
- * . any $ORIGIN expansion
- * . any relative path
+ * . LD_LIBRARY_PATH.
+ * . any $ORIGIN expansion, unless used by a setuid ld.so.1
+ * to find its own dependencies, or the path name has
+ * already been used to find other dependencies.
+ * . any relative path.
*/
if (((info & LA_SER_LIBPATH) == 0) && (*opath == '/') &&
((flags & PN_TKN_ORIGIN) == 0))
return (1);
+ /*
+ * If $ORIGIN processing is requested, allow a setuid ld.so.1
+ * to use this path for its own dependencies. Allow the
+ * application to use this path name only if the path name has
+ * already been used to locate other dependencies.
+ */
+ if (flags & PN_TKN_ORIGIN) {
+ if ((lml->lm_flags & LML_FLG_RTLDLM) &&
+ is_rtld_setuid())
+ return (1);
+ else if (spavl_recorded(opath, 0)) {
+ DBG_CALL(Dbg_libs_insecure(lml, opath, 1));
+ return (1);
+ }
+ }
npath = (char *)opath;
}
@@ -784,8 +814,6 @@ is_path_secure(char *opath, Rt_map *clmp, uint_t info, uint_t flags)
sdir = sdir->p_next;
}
- lml = LIST(clmp);
-
/*
* The path is insecure, so depending on the caller, provide a
* diagnostic. Preloaded, or audit libraries generate a warning, as
@@ -830,7 +858,7 @@ is_path_secure(char *opath, Rt_map *clmp, uint_t info, uint_t flags)
/*
* Search paths.
*/
- DBG_CALL(Dbg_libs_ignore(lml, opath));
+ DBG_CALL(Dbg_libs_insecure(lml, opath, 0));
if ((lml->lm_flags & LML_FLG_TRC_SEARCH) &&
((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0))
(void) printf(MSG_INTL(MSG_LDD_PTH_IGNORE), opath);
diff --git a/usr/src/cmd/sgs/rtld/common/util.c b/usr/src/cmd/sgs/rtld/common/util.c
index c7671087d7..5f2047bb64 100644
--- a/usr/src/cmd/sgs/rtld/common/util.c
+++ b/usr/src/cmd/sgs/rtld/common/util.c
@@ -29,8 +29,6 @@
* All Rights Reserved
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Utility routines for run-time linker. some are duplicated here from libc
* (with different names) to avoid name space collisions.
@@ -47,6 +45,7 @@
#include <dlfcn.h>
#include <unistd.h>
#include <stdlib.h>
+#include <limits.h>
#include <sys/auxv.h>
#include <debug.h>
#include <conv.h>
@@ -380,6 +379,20 @@ pnavl_compare(const void *n1, const void *n2)
}
/*
+ * Create an AVL tree.
+ */
+static avl_tree_t *
+pnavl_create(size_t size)
+{
+ avl_tree_t *avlt;
+
+ if ((avlt = malloc(sizeof (avl_tree_t))) == NULL)
+ return (NULL);
+ avl_create(avlt, pnavl_compare, size, SGSOFFSETOF(PathNode, pn_avl));
+ return (avlt);
+}
+
+/*
* Determine if a pathname has already been recorded on the full path name
* AVL tree. This tree maintains a node for each path name that ld.so.1 has
* successfully loaded. If the path name does not exist in this AVL tree, then
@@ -390,18 +403,13 @@ Rt_map *
fpavl_recorded(Lm_list *lml, const char *name, avl_index_t *where)
{
FullPathNode fpn, *fpnp;
- avl_tree_t *avlt;
/*
* Create the avl tree if required.
*/
- if ((avlt = lml->lm_fpavl) == NULL) {
- if ((avlt = calloc(sizeof (avl_tree_t), 1)) == 0)
- return (0);
- avl_create(avlt, pnavl_compare, sizeof (FullPathNode),
- SGSOFFSETOF(FullPathNode, fpn_node.pn_avl));
- lml->lm_fpavl = avlt;
- }
+ if ((lml->lm_fpavl == NULL) &&
+ ((lml->lm_fpavl = pnavl_create(sizeof (FullPathNode))) == NULL))
+ return (NULL);
fpn.fpn_node.pn_name = name;
fpn.fpn_node.pn_hash = sgs_str_hash(name);
@@ -439,7 +447,7 @@ fpavl_insert(Lm_list *lml, Rt_map *lmp, const char *name, avl_index_t where)
/*
* Insert new node in tree.
*/
- if ((fpnp = calloc(sizeof (FullPathNode), 1)) == 0)
+ if ((fpnp = calloc(sizeof (FullPathNode), 1)) == NULL)
return (0);
fpnp->fpn_node.pn_name = name;
@@ -487,23 +495,18 @@ int
nfavl_recorded(const char *name, avl_index_t *where)
{
PathNode pn;
- avl_tree_t *avlt;
/*
* Create the avl tree if required.
*/
- if ((avlt = nfavl) == NULL) {
- if ((avlt = calloc(sizeof (avl_tree_t), 1)) == 0)
- return (0);
- avl_create(avlt, pnavl_compare, sizeof (PathNode),
- SGSOFFSETOF(PathNode, pn_avl));
- nfavl = avlt;
- }
+ if ((nfavl == NULL) &&
+ ((nfavl = pnavl_create(sizeof (PathNode))) == NULL))
+ return (0);
pn.pn_name = name;
pn.pn_hash = sgs_str_hash(name);
- if (avl_find(avlt, &pn, where) == NULL)
+ if (avl_find(nfavl, &pn, where) == NULL)
return (0);
return (1);
@@ -538,6 +541,76 @@ nfavl_insert(const char *name, avl_index_t where)
}
}
+static avl_tree_t *spavl = NULL;
+
+/*
+ * Search for a path name within the secure path AVL tree. This tree is used
+ * to maintain a list of directories in which the dependencies of a secure
+ * process have been found. This list provides a fall-back in the case that a
+ * $ORIGIN expansion is deemed insecure, when the expansion results in a path
+ * name that has already provided dependencies.
+ */
+int
+spavl_recorded(const char *name, avl_index_t *where)
+{
+ PathNode pn;
+
+ /*
+ * Create the avl tree if required.
+ */
+ if ((spavl == NULL) &&
+ ((spavl = pnavl_create(sizeof (PathNode))) == NULL))
+ return (0);
+
+ pn.pn_name = name;
+ pn.pn_hash = sgs_str_hash(name);
+
+ if (avl_find(spavl, &pn, where) == NULL)
+ return (0);
+
+ return (1);
+}
+
+/*
+ * Insert the directory name, of a full path name, into the secure path AVL
+ * tree.
+ */
+void
+spavl_insert(const char *name)
+{
+ char buffer[PATH_MAX], *str;
+ size_t size;
+ avl_index_t where;
+ PathNode *pnp;
+
+ /*
+ * Separate the directory name from the path name.
+ */
+ if ((str = strrchr(name, '/')) == name)
+ size = 1;
+ else
+ size = str - name;
+
+ (void) strncpy(buffer, name, size);
+ buffer[size] = '\0';
+
+ /*
+ * Determine whether this directory name is already recorded, or if
+ * not, 'where" will provide the insertion point for the new string.
+ */
+ if (spavl_recorded(buffer, &where))
+ return;
+
+ /*
+ * Insert new node in tree.
+ */
+ if ((pnp = calloc(sizeof (PathNode), 1)) != 0) {
+ pnp->pn_name = strdup(buffer);
+ pnp->pn_hash = sgs_str_hash(buffer);
+ avl_insert(spavl, pnp, where);
+ }
+}
+
/*
* Prior to calling an object, either via a .plt or through dlsym(), make sure
* its .init has fired. Through topological sorting, ld.so.1 attempts to fire
@@ -1034,8 +1107,8 @@ list_append(List *lst, const void *item)
{
Listnode *_lnp;
- if ((_lnp = malloc(sizeof (Listnode))) == 0)
- return (0);
+ if ((_lnp = malloc(sizeof (Listnode))) == NULL)
+ return (NULL);
_lnp->data = (void *)item;
_lnp->next = NULL;
@@ -1109,7 +1182,7 @@ list_delete(List *lst, void *item)
plnp = clnp;
}
- if (clnp == 0)
+ if (clnp == NULL)
return;
if (lst->head == clnp)
@@ -1335,16 +1408,16 @@ lm_move(Lm_list *lml, Aliste nlmco, Aliste plmco, Lm_cntl *nlmc, Lm_cntl *plmc)
* Move the new link-map control list, to the callers link-map control
* list.
*/
- if (plmc->lc_head == 0) {
+ if (plmc->lc_head == NULL) {
plmc->lc_head = nlmc->lc_head;
- PREV(nlmc->lc_head) = 0;
+ PREV(nlmc->lc_head) = NULL;
} else {
NEXT(plmc->lc_tail) = (Link_map *)nlmc->lc_head;
PREV(nlmc->lc_head) = (Link_map *)plmc->lc_tail;
}
plmc->lc_tail = nlmc->lc_tail;
- nlmc->lc_head = nlmc->lc_tail = 0;
+ nlmc->lc_head = nlmc->lc_tail = NULL;
/*
* For backward compatibility with debuggers, the link-map list contains
@@ -2133,10 +2206,10 @@ static int
ld_flags_env(const char *str, Word *lmflags, Word *lmtflags,
uint_t env_flags, int aout)
{
- char *nstr, *sstr, *estr = 0;
+ char *nstr, *sstr, *estr = NULL;
size_t nlen, len;
- if (str == 0)
+ if (str == NULL)
return (0);
/*
@@ -2144,7 +2217,7 @@ ld_flags_env(const char *str, Word *lmflags, Word *lmtflags,
* uppercase and separate tokens with nulls.
*/
len = strlen(str);
- if ((nstr = malloc(len + 1)) == 0)
+ if ((nstr = malloc(len + 1)) == NULL)
return (1);
(void) strcpy(nstr, str);
@@ -2152,7 +2225,7 @@ ld_flags_env(const char *str, Word *lmflags, Word *lmtflags,
int flags;
if ((*sstr != '\0') && (*sstr != ',')) {
- if (estr == 0) {
+ if (estr == NULL) {
if (*sstr == '=')
estr = sstr;
else {
@@ -2183,7 +2256,7 @@ ld_flags_env(const char *str, Word *lmflags, Word *lmtflags,
* the term "(null)" is specifically chosen in case someone
* mistakenly supplies something like LD_FLAGS=library_path.
*/
- if (estr == 0)
+ if (estr == NULL)
estr = (char *)MSG_INTL(MSG_STR_NULL);
/*
@@ -2282,7 +2355,7 @@ ld_str_env(const char *s1, Word *lmflags, Word *lmtflags, uint_t env_flags,
* within a configuration file, these null user settings can be
* used to disable any configuration replaceable definitions.
*/
- if ((s2 = strchr(s1, '=')) == 0) {
+ if ((s2 = strchr(s1, '=')) == NULL) {
len = strlen(s1);
s2 = 0;
} else if (*++s2 == '\0') {
@@ -3179,7 +3252,7 @@ is_path_used(Lm_list *lml, Word unref, int *nl, Pnode *pnp, const char *obj)
* If this pathname originated from an expanded token, use the
* original for any diagnostic output.
*/
- if ((name = pnp->p_oname) == 0)
+ if ((name = pnp->p_oname) == NULL)
name = pnp->p_name;
if (unref == 0) {
@@ -3399,7 +3472,7 @@ leave(Lm_list *lml, int flags)
* case of tearing down a whole link-map list, lml will be null. In
* this case use the main link-map list to test for a notification.
*/
- if (elml == 0)
+ if (elml == NULL)
elml = &lml_main;
if (elml->lm_flags & LML_FLG_DBNOTIF)
rd_event(elml, RD_DLACTIVITY, RT_CONSISTENT);
@@ -3632,6 +3705,23 @@ security(uid_t uid, uid_t euid, gid_t gid, gid_t egid, int auxflags)
}
/*
+ * Determine whether ld.so.1 itself is owned by root and has its mode setuid.
+ */
+int
+is_rtld_setuid()
+{
+ struct stat status;
+
+ if ((rtld_flags2 & RT_FL2_SETUID) ||
+ ((stat(NAME(lml_rtld.lm_head), &status) == 0) &&
+ (status.st_uid == 0) && (status.st_mode & S_ISUID))) {
+ rtld_flags2 |= RT_FL2_SETUID;
+ return (1);
+ }
+ return (0);
+}
+
+/*
* _REENTRANT code gets errno redefined to a function so provide for return
* of the thread errno if applicable. This has no meaning in ld.so.1 which
* is basically singled threaded. Provide the interface for our dependencies.