diff options
author | Jakub Jelinek <jakub@redhat.com> | 2006-04-26 20:18:18 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2006-04-26 20:18:18 +0000 |
commit | dd8c67b33fb3d422afebc83c70e51e736669b0ad (patch) | |
tree | 40569cd29262da66f41d0700391b223ad437082e /nscd | |
parent | cb5c27ecf31a91ad8b96aa8d4777a7d7b6b33b62 (diff) | |
download | glibc-dd8c67b33fb3d422afebc83c70e51e736669b0ad.tar glibc-dd8c67b33fb3d422afebc83c70e51e736669b0ad.tar.gz glibc-dd8c67b33fb3d422afebc83c70e51e736669b0ad.tar.bz2 glibc-dd8c67b33fb3d422afebc83c70e51e736669b0ad.zip |
Updated to fedora-glibc-20060426T2000
Diffstat (limited to 'nscd')
-rw-r--r-- | nscd/Makefile | 5 | ||||
-rw-r--r-- | nscd/connections.c | 13 | ||||
-rw-r--r-- | nscd/grpcache.c | 18 | ||||
-rw-r--r-- | nscd/nscd-client.h | 4 | ||||
-rw-r--r-- | nscd/nscd.conf | 5 | ||||
-rw-r--r-- | nscd/nscd.h | 3 | ||||
-rw-r--r-- | nscd/nscd_conf.c | 13 | ||||
-rw-r--r-- | nscd/nscd_helper.c | 10 | ||||
-rw-r--r-- | nscd/pwdcache.c | 17 | ||||
-rw-r--r-- | nscd/selinux.c | 87 | ||||
-rw-r--r-- | nscd/selinux.h | 12 |
11 files changed, 161 insertions, 26 deletions
diff --git a/nscd/Makefile b/nscd/Makefile index 0b35964e7b..9c98018217 100644 --- a/nscd/Makefile +++ b/nscd/Makefile @@ -55,10 +55,13 @@ all-nscd-modules := $(nscd-modules) selinux ifeq (yes,$(have-selinux)) ifeq (yes,$(have-libaudit)) libaudit = -laudit +ifeq (yes,$(have-libcap)) +libcap = -lcap +endif endif nscd-modules += selinux -selinux-LIBS := -lselinux $(libaudit) +selinux-LIBS := -lselinux $(libaudit) $(libcap) # The configure.in check for libselinux and its headers did not use # $SYSINCLUDES. The directory specified by --with-headers usually diff --git a/nscd/connections.c b/nscd/connections.c index 0426e6346f..a52082cba3 100644 --- a/nscd/connections.c +++ b/nscd/connections.c @@ -103,6 +103,7 @@ struct database_dyn dbs[lastdb] = .enabled = 0, .check_file = 1, .persistent = 0, + .propagate = 1, .shared = 0, .max_db_size = DEFAULT_MAX_DB_SIZE, .filename = "/etc/passwd", @@ -119,6 +120,7 @@ struct database_dyn dbs[lastdb] = .enabled = 0, .check_file = 1, .persistent = 0, + .propagate = 1, .shared = 0, .max_db_size = DEFAULT_MAX_DB_SIZE, .filename = "/etc/group", @@ -135,6 +137,7 @@ struct database_dyn dbs[lastdb] = .enabled = 0, .check_file = 1, .persistent = 0, + .propagate = 0, /* Not used. */ .shared = 0, .max_db_size = DEFAULT_MAX_DB_SIZE, .filename = "/etc/hosts", @@ -1859,6 +1862,11 @@ begin_drop_privileges (void) static void finish_drop_privileges (void) { +#if defined HAVE_LIBAUDIT && defined HAVE_LIBCAP + /* We need to preserve the capabilities to connect to the audit daemon. */ + cap_t new_caps = preserve_capabilities (); +#endif + if (setgroups (server_ngroups, server_groups) == -1) { dbg_log (_("Failed to run nscd as user '%s'"), server_user); @@ -1878,6 +1886,11 @@ finish_drop_privileges (void) perror ("setuid"); exit (4); } + +#if defined HAVE_LIBAUDIT && defined HAVE_LIBCAP + /* Remove the temporary capabilities. */ + install_real_capabilities (new_caps); +#endif } /* Handle the HUP signal which will force a dump of the cache */ diff --git a/nscd/grpcache.c b/nscd/grpcache.c index 4bc9977bc4..5a8fba4759 100644 --- a/nscd/grpcache.c +++ b/nscd/grpcache.c @@ -342,10 +342,10 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, marked with FIRST first. Otherwise we end up with dangling "pointers" in case a latter hash entry cannot be added. */ - bool first = req->type == GETGRBYNAME; + bool first = true; /* If the request was by GID, add that entry first. */ - if (req->type != GETGRBYNAME) + if (req->type == GETGRBYGID) { if (cache_add (GETGRBYGID, cp, key_offset, &dataset->head, true, db, owner) < 0) @@ -355,12 +355,14 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, dataset->head.usable = false; goto out; } + + first = false; } /* If the key is different from the name add a separate entry. */ else if (strcmp (key_copy, gr_name) != 0) { if (cache_add (GETGRBYNAME, key_copy, key_len + 1, - &dataset->head, first, db, owner) < 0) + &dataset->head, true, db, owner) < 0) { /* Could not allocate memory. Make sure the data gets discarded. */ @@ -372,11 +374,13 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, } /* We have to add the value for both, byname and byuid. */ - if (__builtin_expect (cache_add (GETGRBYNAME, gr_name, gr_name_len, - &dataset->head, first, db, owner) - == 0, 1)) + if ((req->type == GETGRBYNAME || db->propagate) + && __builtin_expect (cache_add (GETGRBYNAME, gr_name, + gr_name_len, + &dataset->head, first, db, owner) + == 0, 1)) { - if (req->type == GETGRBYNAME) + if (req->type == GETGRBYNAME && db->propagate) (void) cache_add (GETGRBYGID, cp, key_offset, &dataset->head, req->type != GETGRBYNAME, db, owner); } diff --git a/nscd/nscd-client.h b/nscd/nscd-client.h index 98c167eb62..440697f1be 100644 --- a/nscd/nscd-client.h +++ b/nscd/nscd-client.h @@ -1,4 +1,4 @@ -/* Copyright (c) 1998, 1999, 2000, 2003, 2004, 2005 +/* Copyright (c) 1998, 1999, 2000, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. @@ -277,7 +277,7 @@ extern int __nscd_open_socket (const char *key, size_t keylen, /* Get reference of mapping. */ extern struct mapped_database *__nscd_get_map_ref (request_type type, const char *name, - struct locked_map_ptr *mapptr, + volatile struct locked_map_ptr *mapptr, int *gc_cyclep); /* Unmap database. */ diff --git a/nscd/nscd.conf b/nscd/nscd.conf index bde8e36219..4cdcb7dc9e 100644 --- a/nscd/nscd.conf +++ b/nscd/nscd.conf @@ -23,7 +23,8 @@ # check-files <service> <yes|no> # persistent <service> <yes|no> # shared <service> <yes|no> -# max-db-szie <service> <number bytes> +# max-db-size <service> <number bytes> +* auto-propagate <service> <yes|no> # # Currently supported cache names (services): passwd, group, hosts # @@ -47,6 +48,7 @@ persistent passwd yes shared passwd yes max-db-size passwd 33554432 + auto-propagate passwd yes enable-cache group yes positive-time-to-live group 3600 @@ -56,6 +58,7 @@ persistent group yes shared group yes max-db-size group 33554432 + auto-propagate group yes enable-cache hosts yes positive-time-to-live hosts 3600 diff --git a/nscd/nscd.h b/nscd/nscd.h index ed686bea7e..f826c7ada4 100644 --- a/nscd/nscd.h +++ b/nscd/nscd.h @@ -1,4 +1,4 @@ -/* Copyright (c) 1998, 1999, 2000, 2001, 2003, 2004, 2005 +/* Copyright (c) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. @@ -63,6 +63,7 @@ struct database_dyn int check_file; int persistent; int shared; + int propagate; size_t max_db_size; const char *filename; const char *db_filename; diff --git a/nscd/nscd_conf.c b/nscd/nscd_conf.c index 579ddd402f..2048eca886 100644 --- a/nscd/nscd_conf.c +++ b/nscd/nscd_conf.c @@ -1,4 +1,4 @@ -/* Copyright (c) 1998, 2000, 2003, 2004, 2005 Free Software Foundation, Inc. +/* Copyright (c) 1998,2000,2003,2004,2005,2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. @@ -256,6 +256,17 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) else error (0, 0, _("Must specify value for restart-interval option")); } + else if (strcmp (entry, "auto-propagate") == 0) + { + int idx = find_db (arg1); + if (idx >= 0) + { + if (strcmp (arg2, "no") == 0) + dbs[idx].propagate = 0; + else if (strcmp (arg2, "yes") == 0) + dbs[idx].propagate = 1; + } + } else error (0, 0, _("Unknown option: %s %s %s"), entry, arg1, arg2); } diff --git a/nscd/nscd_helper.c b/nscd/nscd_helper.c index fd749446be..1dfe746d7a 100644 --- a/nscd/nscd_helper.c +++ b/nscd/nscd_helper.c @@ -316,17 +316,18 @@ get_mapping (request_type type, const char *key, struct mapped_database * __nscd_get_map_ref (request_type type, const char *name, - struct locked_map_ptr *mapptr, int *gc_cyclep) + volatile struct locked_map_ptr *mapptr, int *gc_cyclep) { struct mapped_database *cur = mapptr->mapped; if (cur == NO_MAPPING) return cur; int cnt = 0; - while (atomic_compare_and_exchange_val_acq (&mapptr->lock, 1, 0) != 0) + while (__builtin_expect (atomic_compare_and_exchange_val_acq (&mapptr->lock, + 1, 0) != 0, 0)) { // XXX Best number of rounds? - if (++cnt > 5) + if (__builtin_expect (++cnt > 5, 0)) return NO_MAPPING; atomic_delay (); @@ -340,7 +341,8 @@ __nscd_get_map_ref (request_type type, const char *name, if (cur == NULL || (cur->head->nscd_certainly_running == 0 && cur->head->timestamp + MAPPING_TIMEOUT < time (NULL))) - cur = get_mapping (type, name, &mapptr->mapped); + cur = get_mapping (type, name, + (struct mapped_database **) &mapptr->mapped); if (__builtin_expect (cur != NO_MAPPING, 1)) { diff --git a/nscd/pwdcache.c b/nscd/pwdcache.c index 2daff79d78..01c223add5 100644 --- a/nscd/pwdcache.c +++ b/nscd/pwdcache.c @@ -338,10 +338,10 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, marked with FIRST first. Otherwise we end up with dangling "pointers" in case a latter hash entry cannot be added. */ - bool first = req->type == GETPWBYNAME; + bool first = true; /* If the request was by UID, add that entry first. */ - if (req->type != GETPWBYNAME) + if (req->type == GETPWBYUID) { if (cache_add (GETPWBYUID, cp, key_offset, &dataset->head, true, db, owner) < 0) @@ -351,12 +351,14 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, dataset->head.usable = false; goto out; } + + first = false; } /* If the key is different from the name add a separate entry. */ else if (strcmp (key_copy, dataset->strdata) != 0) { if (cache_add (GETPWBYNAME, key_copy, key_len + 1, - &dataset->head, first, db, owner) < 0) + &dataset->head, true, db, owner) < 0) { /* Could not allocate memory. Make sure the data gets discarded. */ @@ -368,11 +370,12 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, } /* We have to add the value for both, byname and byuid. */ - if (__builtin_expect (cache_add (GETPWBYNAME, dataset->strdata, - pw_name_len, &dataset->head, first, - db, owner) == 0, 1)) + if ((req->type == GETPWBYNAME || db->propagate) + && __builtin_expect (cache_add (GETPWBYNAME, dataset->strdata, + pw_name_len, &dataset->head, + first, db, owner) == 0, 1)) { - if (req->type == GETPWBYNAME) + if (req->type == GETPWBYNAME && db->propagate) (void) cache_add (GETPWBYUID, cp, key_offset, &dataset->head, req->type != GETPWBYNAME, db, owner); } diff --git a/nscd/selinux.c b/nscd/selinux.c index c59251f1b5..f123d68b93 100644 --- a/nscd/selinux.c +++ b/nscd/selinux.c @@ -28,12 +28,13 @@ #include <stdlib.h> #include <syslog.h> #include <unistd.h> +#include <sys/prctl.h> #include <selinux/av_permissions.h> #include <selinux/avc.h> #include <selinux/flask.h> #include <selinux/selinux.h> #ifdef HAVE_LIBAUDIT -#include <libaudit.h> +# include <libaudit.h> #endif #include "dbg_log.h" @@ -149,6 +150,90 @@ audit_init (void) && errno != EINVAL && errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT) dbg_log (_("Failed opening connection to the audit subsystem: %m")); } + + +# ifdef HAVE_LIBCAP +static const cap_value_t new_cap_list[] = + { CAP_AUDIT_WRITE }; +# define nnew_cap_list (sizeof (new_cap_list) / sizeof (new_cap_list[0])) +static const cap_value_t tmp_cap_list[] = + { CAP_AUDIT_WRITE, CAP_SETUID, CAP_SETGID }; +# define ntmp_cap_list (sizeof (tmp_cap_list) / sizeof (tmp_cap_list[0])) + +cap_t +preserve_capabilities (void) +{ + if (getuid () != 0) + /* Not root, then we cannot preserve anything. */ + return NULL; + + if (prctl (PR_SET_KEEPCAPS, 1) == -1) + { + dbg_log (_("Failed to set keep-capabilities")); + error (EXIT_FAILURE, errno, _("prctl(KEEPCAPS) failed")); + /* NOTREACHED */ + } + + cap_t tmp_caps = cap_init (); + cap_t new_caps; + if (tmp_caps != NULL) + new_caps = cap_init (); + + if (tmp_caps == NULL || new_caps == NULL) + { + if (tmp_caps != NULL) + free_caps (tmp_caps); + + dbg_log (_("Failed to initialize drop of capabilities")); + error (EXIT_FAILURE, 0, _("cap_init failed")); + } + + /* There is no reason why these should not work. */ + cap_set_flag (new_caps, CAP_PERMITTED, nnew_cap_list, new_cap_list, CAP_SET); + cap_set_flag (new_caps, CAP_EFFECTIVE, nnew_cap_list, new_cap_list, CAP_SET); + + cap_set_flag (tmp_caps, CAP_PERMITTED, ntmp_cap_list, tmp_cap_list, CAP_SET); + cap_set_flag (tmp_caps, CAP_EFFECTIVE, ntmp_cap_list, tmp_cap_list, CAP_SET); + + int res = cap_set_proc (tmp_caps); + + cap_free (tmp_caps); + + if (__builtin_expect (res != 0, 0)) + { + cap_free (new_caps); + dbg_log (_("Failed to drop capabilities\n")); + error (EXIT_FAILURE, 0, _("cap_set_proc failed")); + } + + return new_caps; +} + +void +install_real_capabilities (cap_t new_caps) +{ + /* If we have no capabilities there is nothing to do here. */ + if (new_caps == NULL) + return; + + if (cap_set_proc (new_caps)) + { + cap_free (new_caps); + dbg_log (_("Failed to drop capabilities")); + error (EXIT_FAILURE, 0, _("cap_set_proc failed")); + /* NOTREACHED */ + } + + cap_free (new_caps); + + if (prctl (PR_SET_KEEPCAPS, 0) == -1) + { + dbg_log (_("Failed to unset keep-capabilities")); + error (EXIT_FAILURE, errno, _("prctl(KEEPCAPS) failed")); + /* NOTREACHED */ + } +} +# endif /* HAVE_LIBCAP */ #endif /* HAVE_LIBAUDIT */ /* Determine if we are running on an SELinux kernel. Set selinux_enabled diff --git a/nscd/selinux.h b/nscd/selinux.h index b9eb053aa0..9ce0628486 100644 --- a/nscd/selinux.h +++ b/nscd/selinux.h @@ -1,5 +1,5 @@ /* Header for nscd SELinux access controls. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Matthew Rickard <mjricka@epoch.ncsc.mil>, 2004. @@ -22,6 +22,9 @@ #define _SELINUX_H 1 #include "nscd.h" +#ifdef HAVE_LIBCAP +# include <sys/capabilities.h> +#endif #ifdef HAVE_SELINUX /* Global variable to tell if the kernel has SELinux support. */ @@ -42,6 +45,13 @@ extern int nscd_request_avc_has_perm (int fd, request_type req); extern void nscd_avc_cache_stats (struct avc_cache_stats *cstats); /* Display statistics on AVC usage. */ extern void nscd_avc_print_stats (struct avc_cache_stats *cstats); + +# ifdef HAVE_LIBCAP +/* Preserve capabilities to connect to connnect to the audit daemon. */ +extern cap_t preserve_capabilities (void); +/* Install final capabilities. */ +extern void install_real_capabilities (cap_t new_caps); +# endif #else # define selinux_enabled 0 # define nscd_avc_init() (void) 0 |