From 61fb657c1b06b8352bf3b3bab6e4ed1d526a6019 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Fri, 2 Dec 2011 10:57:29 -0800 Subject: [PATCH 3/4] Enforce strict permission check in nsswitch.conf(5) and shared libraries being loaded. --- lib/libc/net/nsdispatch.3 | 8 +++++++- lib/libc/net/nsdispatch.c | 30 +++++++++++++++++++++++------- share/man/man5/nsswitch.conf.5 | 9 ++++++++- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/lib/libc/net/nsdispatch.3 b/lib/libc/net/nsdispatch.3 index d1d8d5a..73dc4f7 100644 --- a/lib/libc/net/nsdispatch.3 +++ b/lib/libc/net/nsdispatch.3 @@ -32,7 +32,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 4, 2010 +.Dd December 3, 2011 .Dt NSDISPATCH 3 .Os .Sh NAME @@ -222,6 +222,12 @@ However, these stubs only support the use of the and .Dq Li group databases. +.Pp +This implementation enforces strict check on the configuration file, +.Xr nsswitch.conf 5 +as well as all NSS modules, +allowing them only when they are owned by the superuser, +and not writable by any other users. .Sh SEE ALSO .Xr hesiod 3 , .Xr stdarg 3 , diff --git a/lib/libc/net/nsdispatch.c b/lib/libc/net/nsdispatch.c index 6b7bd02..cbeda44 100644 --- a/lib/libc/net/nsdispatch.c +++ b/lib/libc/net/nsdispatch.c @@ -340,6 +340,7 @@ nss_configure(void) static time_t confmod; struct stat statbuf; int result, isthreaded; + int fd; const char *path; #ifdef NS_CACHING void *handle; @@ -355,20 +356,35 @@ nss_configure(void) if (path == NULL) #endif path = _PATH_NS_CONF; - if (stat(path, &statbuf) != 0) + if ((fd = _open(path, O_RDONLY)) == -1) return (0); - if (statbuf.st_mtime <= confmod) + if (_fstat(fd, &statbuf) != 0) { + _close(fd); return (0); + } + if (statbuf.st_uid != 0 || (statbuf.st_mode & (S_IWGRP | S_IWOTH))) { + nss_log(LOG_ERR, "incorrect permission on %s", path); + _close(fd); + return (0); + } + if (statbuf.st_mtime <= confmod) { + _close(fd); + return (0); + } if (isthreaded) { result = _pthread_mutex_trylock(&conf_lock); - if (result != 0) + if (result != 0) { + _close(fd); return (0); + } (void)_pthread_rwlock_unlock(&nss_lock); result = _pthread_rwlock_wrlock(&nss_lock); - if (result != 0) + if (result != 0) { + _close(fd); goto fin2; + } } - _nsyyin = fopen(path, "r"); + _nsyyin = fdopen(fd, "r"); if (_nsyyin == NULL) goto fin; VECTOR_FREE(_nsmap, &_nsmapsize, sizeof(*_nsmap), @@ -384,7 +400,7 @@ nss_configure(void) confmod = statbuf.st_mtime; #ifdef NS_CACHING - handle = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL); + handle = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL | RTLD_PARANOID); if (handle != NULL) { nss_cache_cycle_prevention_func = dlsym(handle, "_nss_cache_cycle_prevention_function"); @@ -497,7 +513,7 @@ nss_load_module(const char *source, nss_module_register_fn reg_fn) if (snprintf(buf, sizeof(buf), "nss_%s.so.%d", mod.name, NSS_MODULE_INTERFACE_VERSION) >= (int)sizeof(buf)) goto fin; - mod.handle = dlopen(buf, RTLD_LOCAL|RTLD_LAZY); + mod.handle = dlopen(buf, RTLD_LOCAL|RTLD_LAZY|RTLD_PARANOID); if (mod.handle == NULL) { #ifdef _NSS_DEBUG /* This gets pretty annoying since the built-in diff --git a/share/man/man5/nsswitch.conf.5 b/share/man/man5/nsswitch.conf.5 index c28720b..234a983 100644 --- a/share/man/man5/nsswitch.conf.5 +++ b/share/man/man5/nsswitch.conf.5 @@ -33,7 +33,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 4, 2010 +.Dd December 3, 2011 .Dt NSSWITCH.CONF 5 .Os .Sh NAME @@ -357,6 +357,13 @@ However, these stubs only support the use of the and .Dq Li group databases. +.Pp +.Fx Ns 's +.Lb libc +enforces a permission check on the NSS configuration file, +.Pa /etc/nsswitch.conf , +allowing it only when it is owned by the superuser, +and not writable by any other users. .Sh SEE ALSO .Xr nsdispatch 3 , .Xr nscd.conf 5 , -- 1.7.7.2