From patchwork Fri Nov 11 20:27:36 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 125292 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from acsinet15.oracle.com (acsinet15.oracle.com [141.146.126.227]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "acsinet15.oracle.com", Issuer "VeriSign Class 3 International Server CA - G3" (verified OK)) by ozlabs.org (Postfix) with ESMTPS id 8B3451007D8 for ; Sat, 12 Nov 2011 07:27:51 +1100 (EST) Received: from acsinet22.oracle.com (acsinet22.oracle.com [141.146.126.238]) by acsinet15.oracle.com (Switch-3.4.4/Switch-3.4.4) with ESMTP id pABKRlgm031015 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 11 Nov 2011 20:27:48 GMT Received: from oss.oracle.com (oss.oracle.com [141.146.12.120]) by acsinet22.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id pABKRl4B001505 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 11 Nov 2011 20:27:47 GMT Received: from localhost ([127.0.0.1] helo=oss.oracle.com) by oss.oracle.com with esmtp (Exim 4.63) (envelope-from ) id 1ROxhO-00078o-4H; Fri, 11 Nov 2011 12:27:42 -0800 Received: from rcsinet12.oracle.com ([148.87.113.124]) by oss.oracle.com with esmtp (Exim 4.63) (envelope-from ) id 1ROxhM-00078h-AB for fedfs-utils-devel@oss.oracle.com; Fri, 11 Nov 2011 12:27:40 -0800 Received: from mail-gy0-f171.google.com (mail-gy0-f171.google.com [209.85.160.171]) by rcsinet12.oracle.com (Sentrion-MTA-4.2.0/Sentrion-MTA-4.2.0) with ESMTP id pABKRc8W013987 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=OK) for ; Fri, 11 Nov 2011 20:27:39 GMT Received: by gyg8 with SMTP id 8so4155766gyg.2 for ; Fri, 11 Nov 2011 12:27:38 -0800 (PST) Received: by 10.50.169.1 with SMTP id aa1mr14755027igc.9.1321043257976; Fri, 11 Nov 2011 12:27:37 -0800 (PST) Received: from degas.1015granger.net ([99.26.161.222]) by mx.google.com with ESMTPS id a6sm9544390igc.3.2011.11.11.12.27.37 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 11 Nov 2011 12:27:37 -0800 (PST) From: Chuck Lever To: fedfs-utils-devel@oss.oracle.com Date: Fri, 11 Nov 2011 15:27:36 -0500 Message-ID: <20111111202736.10717.33589.stgit@degas.1015granger.net> In-Reply-To: <20111111202105.10717.28436.stgit@degas.1015granger.net> References: <20111111202105.10717.28436.stgit@degas.1015granger.net> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 Subject: [fedfs-utils] [PATCH 11/12] libnsdb: Eliminate nsdb_create_basedir() X-BeenThere: fedfs-utils-devel@oss.oracle.com X-Mailman-Version: 2.1.9 Precedence: list Reply-To: fedfs-utils Developers List-Id: fedfs-utils Developers List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: fedfs-utils-devel-bounces@oss.oracle.com Errors-To: fedfs-utils-devel-bounces@oss.oracle.com X-Source-IP: acsinet22.oracle.com [141.146.126.238] X-CT-RefId: str=0001.0A090201.4EBD8544.009C:SCFSTAT1119972, ss=1, re=-6.300, fgs=0 X-Auth-Type: Internal IP By having nsdbparams retain cap_dac_override=ep, we can create the state directory after dropping privileges, rather than before. This gives better error reporting when fedfsd or nsdbparams are not run as root, and it also automatically creates the directory with the correct owner and group (the extra passwd look-up and chown(2) is unnecessary). A nice side effect is that the state directory can now be created as needed right in nsdb_init_database() rather than having a separate public function to do it. Thus nsdb_create_basedir() is no longer needed and can be removed. Note that the new behavior is slightly different than the old: nsdb_create_basedir() used to use FEDFS_USER always. Now the directory will get whatever uid and gid might be specified on the fedfsd or nsdbparams command line. This makes the --uid and --gid options behave closer to user expectations. Signed-off-by: Chuck Lever --- src/fedfsd/main.c | 3 -- src/include/nsdb.h | 1 - src/libnsdb/nsdb.c | 58 +++++++++++--------------------------------- src/nsdbparams/Makefile.am | 2 +- src/nsdbparams/delete.c | 3 -- src/nsdbparams/list.c | 3 -- src/nsdbparams/main.c | 58 ++++++++++++++++++++++++++++++++++++++++++-- src/nsdbparams/show.c | 3 -- src/nsdbparams/update.c | 3 -- 9 files changed, 71 insertions(+), 63 deletions(-) diff --git a/src/fedfsd/main.c b/src/fedfsd/main.c index 31718e8..eb7ab48 100644 --- a/src/fedfsd/main.c +++ b/src/fedfsd/main.c @@ -212,9 +212,6 @@ int main(int argc, char **argv) } } - if (!nsdb_create_basedir()) - exit(EXIT_FAILURE); - if (!fedfsd_drop_privileges(uid, gid)) exit(EXIT_FAILURE); diff --git a/src/include/nsdb.h b/src/include/nsdb.h index 9c8383b..2ba1b7a 100644 --- a/src/include/nsdb.h +++ b/src/include/nsdb.h @@ -115,7 +115,6 @@ struct fedfs_fsl { * Locate the cert store */ _Bool nsdb_set_parentdir(const char *parentdir); -_Bool nsdb_create_basedir(void); _Bool nsdb_is_default_parentdir(void); _Bool nsdb_init_database(void); diff --git a/src/libnsdb/nsdb.c b/src/libnsdb/nsdb.c index c81f228..dec2091 100644 --- a/src/libnsdb/nsdb.c +++ b/src/libnsdb/nsdb.c @@ -157,50 +157,6 @@ nsdb_set_parentdir(const char *parentdir) } /** - * Create parent directory - * - * @return true if fedfsd directory exists - * - * Warning: this function must be called as root, and is usually - * invoked before the process has set its umask. - */ -_Bool -nsdb_create_basedir(void) -{ - struct passwd *pw; - _Bool retval; - - retval = false; - if (mkdir(fedfs_base_dirname, FEDFS_BASE_DIRMODE) == -1) { - if (errno == EEXIST) { - xlog(D_CALL, "FedFS base directory exists"); - retval = true; - goto out; - } - xlog(L_ERROR, "Failed to create base dir: %m"); - goto out; - } - - pw = getpwnam(FEDFS_USER); - if (pw == NULL) { - xlog(L_ERROR, "Failed to find %s", FEDFS_USER); - rmdir(fedfs_base_dirname); - goto out; - } - - if (chown(fedfs_base_dirname, pw->pw_uid, pw->pw_gid) == -1) { - xlog(L_ERROR, "Failed to chown base dir: %m"); - rmdir(fedfs_base_dirname); - goto out; - } - - retval = true; - -out: - return retval; -} - -/** * Predicate: Does parent directory refer to default FedFS state directory? * * @return true if active fedfsd directory is same as default @@ -241,6 +197,10 @@ nsdb_create_tables(sqlite3 *db) * Ensure database file and tables exist * * @return true if successful + * + * This must be called with capabilities that allow the base + * directory and database to be created. This is typically + * "cap_dac_override=ep". */ _Bool nsdb_init_database(void) @@ -253,6 +213,16 @@ nsdb_init_database(void) xlog(D_CALL, "%s: Initializing database", __func__); retval = false; + + if (mkdir(fedfs_base_dirname, FEDFS_BASE_DIRMODE) == -1) { + if (errno != EEXIST) { + xlog(L_ERROR, "Failed to create base dir: %m"); + goto out; + } + xlog(D_GENERAL, "%s: Base dir %s exists", + __func__, fedfs_base_dirname); + } + db = fedfs_open_db(fedfs_db_filename, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); if (db == NULL) diff --git a/src/nsdbparams/Makefile.am b/src/nsdbparams/Makefile.am index ddc3cd9..6205e32 100644 --- a/src/nsdbparams/Makefile.am +++ b/src/nsdbparams/Makefile.am @@ -27,7 +27,7 @@ noinst_HEADERS = nsdbparams.h sbin_PROGRAMS = nsdbparams nsdbparams_SOURCES = delete.c list.c main.c show.c update.c LDADD = $(LIBLDAP) $(LIBLBER) \ - $(LIBSQLITE3) $(LIBIDN) $(LIBUUID) \ + $(LIBSQLITE3) $(LIBIDN) $(LIBUUID) $(LIBCAP) \ $(top_builddir)/src/libnsdb/libnsdb.a \ $(top_builddir)/src/libjunction/libjunction.a \ $(top_builddir)/src/libpath/libpath.a \ diff --git a/src/nsdbparams/delete.c b/src/nsdbparams/delete.c index 37f30b1..6b86e3d 100644 --- a/src/nsdbparams/delete.c +++ b/src/nsdbparams/delete.c @@ -199,9 +199,6 @@ nsdbparams_delete(const char *progname, int argc, char **argv) } nsdbname = argv[optind]; - if (!nsdb_create_basedir()) - return EXIT_FAILURE; - if (!nsdbparams_drop_privileges(uid, gid)) return EXIT_FAILURE; diff --git a/src/nsdbparams/list.c b/src/nsdbparams/list.c index e79b896..f877604 100644 --- a/src/nsdbparams/list.c +++ b/src/nsdbparams/list.c @@ -177,9 +177,6 @@ nsdbparams_list(const char *progname, int argc, char **argv) return EXIT_FAILURE; } - if (!nsdb_create_basedir()) - return EXIT_FAILURE; - if (!nsdbparams_drop_privileges(uid, gid)) return EXIT_FAILURE; diff --git a/src/nsdbparams/main.c b/src/nsdbparams/main.c index 91b0372..6e96c1c 100644 --- a/src/nsdbparams/main.c +++ b/src/nsdbparams/main.c @@ -47,6 +47,11 @@ #include "nsdbparams.h" /** + * Capabilies that nsdbparams should retain, in text format. + */ +#define NSDBPARAMS_CAPABILITIES "cap_dac_override=ep" + +/** * Display program synopsis * * @param progname NUL-terminated C string containing name of program @@ -69,6 +74,52 @@ nsdbparams_usage(const char *progname) } /** + * Clear all capabilities but a certain few. + * + * @return true if successful + * + * This permits callers to create directories anywhere, but all other + * capabilities are dropped. + */ +static _Bool +nsdbparams_clear_capabilities(void) +{ + cap_t caps; + char *text; + + caps = cap_from_text(NSDBPARAMS_CAPABILITIES); + if (caps == NULL) { + xlog(L_ERROR, "Failed to allocate capability: %m"); + return false; + } + + if (cap_set_proc(caps) == -1) { + xlog(L_ERROR, "Failed to set capability flags: %m"); + (void)cap_free(caps); + return false; + } + + (void)cap_free(caps); + + caps = cap_get_proc(); + if (caps == NULL) + goto out; + + text = cap_to_text(caps, NULL); + if (text == NULL) + goto out_free; + + xlog(D_CALL, "Process capabilities: %s", text); + (void)cap_free(text); + +out_free: + (void)cap_free(caps); + +out: + return true; +} + +/** * Drop root privileges * * @param uid run as this effective uid @@ -80,6 +131,8 @@ nsdbparams_usage(const char *progname) _Bool nsdbparams_drop_privileges(const uid_t uid, const gid_t gid) { + _Bool result; + (void)umask(S_IWGRP | S_IWOTH); /* @@ -109,10 +162,11 @@ nsdbparams_drop_privileges(const uid_t uid, const gid_t gid) return false; } + result = nsdbparams_clear_capabilities(); + xlog(D_CALL, "%s: Effective UID, GID: %u, %u", __func__, geteuid(), getegid()); - - return true; + return result; } /** diff --git a/src/nsdbparams/show.c b/src/nsdbparams/show.c index ba52521..d95f61c 100644 --- a/src/nsdbparams/show.c +++ b/src/nsdbparams/show.c @@ -189,9 +189,6 @@ nsdbparams_show(const char *progname, int argc, char **argv) } } - if (!nsdb_create_basedir()) - return EXIT_FAILURE; - if (!nsdbparams_drop_privileges(uid, gid)) return EXIT_FAILURE; diff --git a/src/nsdbparams/update.c b/src/nsdbparams/update.c index bde2151..d073552 100644 --- a/src/nsdbparams/update.c +++ b/src/nsdbparams/update.c @@ -333,9 +333,6 @@ nsdbparams_update(const char *progname, int argc, char **argv) goto out; } - if (!nsdb_create_basedir()) - goto out; - if (!nsdbparams_drop_privileges(uid, gid)) goto out;