X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fnfsdcld%2Fnfsdcld.c;h=e7af4e330c85bcd5e5f2166b3805c67479f1705f;hp=c9f0fb98e02183ddc39d7d119715e1197266912b;hb=623a550b16835685ddca3736a9a00218bd582a2f;hpb=b6a0ab1dfe85b84ab30a1b656a6bc88b9e025434 diff --git a/utils/nfsdcld/nfsdcld.c b/utils/nfsdcld/nfsdcld.c index c9f0fb9..e7af4e3 100644 --- a/utils/nfsdcld/nfsdcld.c +++ b/utils/nfsdcld/nfsdcld.c @@ -34,6 +34,10 @@ #include #include #include +#ifdef HAVE_SYS_CAPABILITY_H +#include +#include +#endif #include "xlog.h" #include "nfslib.h" @@ -46,6 +50,10 @@ #define DEFAULT_CLD_PATH PIPEFS_DIR "/nfsd/cld" +#ifndef CLD_DEFAULT_STORAGEDIR +#define CLD_DEFAULT_STORAGEDIR NFS_STATEDIR "/nfsdcld" +#endif + #define UPCALL_VERSION 1 /* private data structures */ @@ -79,6 +87,47 @@ usage(char *progname) printf("%s [ -hFd ] [ -p pipe ] [ -s dir ]\n", progname); } +static int +cld_set_caps(void) +{ + int ret = 0; +#ifdef HAVE_SYS_CAPABILITY_H + unsigned long i; + cap_t caps; + + if (getuid() != 0) { + xlog(L_ERROR, "Not running as root. Daemon won't be able to " + "open the pipe after dropping capabilities!"); + return -EINVAL; + } + + /* prune the bounding set to nothing */ + for (i = 0; i <= CAP_LAST_CAP; ++i) { + ret = prctl(PR_CAPBSET_DROP, i); + if (ret) { + xlog(L_ERROR, "Unable to prune capability %lu from " + "bounding set: %m", i); + return -errno; + } + } + + /* get a blank capset */ + caps = cap_init(); + if (caps == NULL) { + xlog(L_ERROR, "Unable to get blank capability set: %m"); + return -errno; + } + + /* reset the process capabilities */ + if (cap_set_proc(caps) != 0) { + xlog(L_ERROR, "Unable to set process capabilities: %m"); + ret = -errno; + } + cap_free(caps); +#endif + return ret; +} + #define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX) static int @@ -453,7 +502,7 @@ main(int argc, char **argv) int rc = 0; bool foreground = false; char *progname; - char *storagedir = NULL; + char *storagedir = CLD_DEFAULT_STORAGEDIR; struct cld_client clnt; memset(&clnt, 0, sizeof(clnt)); @@ -502,6 +551,37 @@ main(int argc, char **argv) } } + /* drop all capabilities */ + rc = cld_set_caps(); + if (rc) + goto out; + + /* + * now see if the storagedir is writable by root w/o CAP_DAC_OVERRIDE. + * If it isn't then give the user a warning but proceed as if + * everything is OK. If the DB has already been created, then + * everything might still work. If it doesn't exist at all, then + * assume that the maindb init will be able to create it. Fail on + * anything else. + */ + if (access(storagedir, W_OK) == -1) { + switch (errno) { + case EACCES: + xlog(L_WARNING, "Storage directory %s is not writable. " + "Should be owned by root and writable " + "by owner!", storagedir); + break; + case ENOENT: + /* ignore and assume that we can create dir as root */ + break; + default: + xlog(L_ERROR, "Unexpected error when checking access " + "on %s: %m", storagedir); + rc = -errno; + goto out; + } + } + /* set up storage db */ rc = sqlite_maindb_init(storagedir); if (rc) {