summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
authornectar <nectar@FreeBSD.org>2004-03-30 15:56:15 +0000
committernectar <nectar@FreeBSD.org>2004-03-30 15:56:15 +0000
commit7ec3e333012ba329299be5ca10738792b75cac89 (patch)
tree6dc88cfd8956062abed823d14f63a72bf26ad661 /lib/libc
parentb3ec818746c286dc776ca38f929c2a1feed43c79 (diff)
downloadFreeBSD-src-7ec3e333012ba329299be5ca10738792b75cac89.zip
FreeBSD-src-7ec3e333012ba329299be5ca10738792b75cac89.tar.gz
When a dynamic NSS module is built and linked against a thread
library, it may pull in that thread library at run time. If the process started out single-threaded, this could cause attempts to release locks that do not exist. Guard against this possibility by checking __isthreaded before invoking thread primitives. A similar problem remains if the process is linked against one thread library, but the NSS module is linked against another. This can only be avoided by careful design of the NSS module. Submitted by: Sean McNeil <sean@mcneil.com> (mostly; bugs are mine)
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/include/nss_tls.h2
-rw-r--r--lib/libc/net/nsdispatch.c59
-rw-r--r--lib/libc/net/nss_compat.c5
3 files changed, 43 insertions, 23 deletions
diff --git a/lib/libc/include/nss_tls.h b/lib/libc/include/nss_tls.h
index 999d198..13ab367 100644
--- a/lib/libc/include/nss_tls.h
+++ b/lib/libc/include/nss_tls.h
@@ -75,6 +75,6 @@ name##_getstate(struct name##_state **p) \
return (rv); \
} \
/* allow the macro invocation to end with a semicolon */ \
-typedef int _##name##_bmVjdGFy
+struct _clashproof_bmVjdGFy
#endif /* _NSS_TLS_H_ */
diff --git a/lib/libc/net/nsdispatch.c b/lib/libc/net/nsdispatch.c
index 5361951..7dd9086 100644
--- a/lib/libc/net/nsdispatch.c
+++ b/lib/libc/net/nsdispatch.c
@@ -316,9 +316,11 @@ nss_configure(void)
static pthread_mutex_t conf_lock = PTHREAD_MUTEX_INITIALIZER;
static time_t confmod;
struct stat statbuf;
- int result;
+ int result, isthreaded;
const char *path;
+ result = 0;
+ isthreaded = __isthreaded;
#if defined(_NSS_DEBUG) && defined(_NSS_SHOOT_FOOT)
/* NOTE WELL: THIS IS A SECURITY HOLE. This must only be built
* for debugging purposes and MUST NEVER be used in production.
@@ -331,16 +333,20 @@ nss_configure(void)
return (0);
if (statbuf.st_mtime <= confmod)
return (0);
- result = _pthread_mutex_trylock(&conf_lock);
- if (result != 0)
- return (0);
- (void)_pthread_rwlock_unlock(&nss_lock);
- result = _pthread_rwlock_wrlock(&nss_lock);
- if (result != 0)
- goto fin2;
+ if (isthreaded) {
+ result = _pthread_mutex_trylock(&conf_lock);
+ if (result != 0)
+ return (0);
+ (void)_pthread_rwlock_unlock(&nss_lock);
+ result = _pthread_rwlock_wrlock(&nss_lock);
+ if (result != 0)
+ goto fin2;
+ }
_nsyyin = fopen(path, "r");
- if (_nsyyin == NULL)
+ if (_nsyyin == NULL) {
+ result = errno;
goto fin;
+ }
VECTOR_FREE(_nsmap, &_nsmapsize, sizeof(*_nsmap),
(vector_free_elem)ns_dbt_free);
VECTOR_FREE(_nsmod, &_nsmodsize, sizeof(*_nsmod),
@@ -353,10 +359,14 @@ nss_configure(void)
(void)atexit(nss_atexit);
confmod = statbuf.st_mtime;
fin:
- (void)_pthread_rwlock_unlock(&nss_lock);
- result = _pthread_rwlock_rdlock(&nss_lock);
+ if (isthreaded) {
+ (void)_pthread_rwlock_unlock(&nss_lock);
+ if (result == 0)
+ result = _pthread_rwlock_rdlock(&nss_lock);
+ }
fin2:
- (void)_pthread_mutex_unlock(&conf_lock);
+ if (isthreaded)
+ (void)_pthread_mutex_unlock(&conf_lock);
return (result);
}
@@ -510,12 +520,17 @@ ns_mod_free(ns_mod *mod)
static void
nss_atexit(void)
{
- (void)_pthread_rwlock_wrlock(&nss_lock);
+ int isthreaded;
+
+ isthreaded = __isthreaded;
+ if (isthreaded)
+ (void)_pthread_rwlock_wrlock(&nss_lock);
VECTOR_FREE(_nsmap, &_nsmapsize, sizeof(*_nsmap),
(vector_free_elem)ns_dbt_free);
VECTOR_FREE(_nsmod, &_nsmodsize, sizeof(*_nsmod),
(vector_free_elem)ns_mod_free);
- (void)_pthread_rwlock_unlock(&nss_lock);
+ if (isthreaded)
+ (void)_pthread_rwlock_unlock(&nss_lock);
}
@@ -568,13 +583,16 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database,
const ns_src *srclist;
nss_method method;
void *mdata;
- int serrno, i, result, srclistsize;
+ int isthreaded, serrno, i, result, srclistsize;
+ isthreaded = __isthreaded;
serrno = errno;
- result = _pthread_rwlock_rdlock(&nss_lock);
- if (result != 0) {
- result = NS_UNAVAIL;
- goto fin;
+ if (isthreaded) {
+ result = _pthread_rwlock_rdlock(&nss_lock);
+ if (result != 0) {
+ result = NS_UNAVAIL;
+ goto fin;
+ }
}
result = nss_configure();
if (result != 0) {
@@ -604,7 +622,8 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database,
break;
}
}
- (void)_pthread_rwlock_unlock(&nss_lock);
+ if (isthreaded)
+ (void)_pthread_rwlock_unlock(&nss_lock);
fin:
errno = serrno;
return (result);
diff --git a/lib/libc/net/nss_compat.c b/lib/libc/net/nss_compat.c
index a81ec8a..09a2d4f 100644
--- a/lib/libc/net/nss_compat.c
+++ b/lib/libc/net/nss_compat.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <pthread.h>
#include <pthread_np.h>
#include "un-namespace.h"
+#include "libc_private.h"
struct group;
@@ -60,7 +61,7 @@ static pthread_once_t _term_once_##x = PTHREAD_ONCE_INIT
#define SET_TERMINATOR(x, y) \
do { \
- if (_pthread_main_np()) \
+ if (!__isthreaded || _pthread_main_np()) \
_term_main_##x = (y); \
else { \
(void)_pthread_once(&_term_once_##x, _term_create_##x); \
@@ -69,7 +70,7 @@ do { \
} while (0)
#define CHECK_TERMINATOR(x) \
-(_pthread_main_np() ? \
+(!__isthreaded || _pthread_main_np() ? \
(_term_main_##x) : \
((void)_pthread_once(&_term_once_##x, _term_create_##x), \
_pthread_getspecific(_term_key_##x)))
OpenPOWER on IntegriCloud