X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=support%2Fnsm%2Ffile.c;fp=support%2Fnsm%2Ffile.c;h=d4692197df8e0853d80d65a2bbf51ade5d4166f0;hp=8796705918545b95007628930999ded4eaae8379;hb=e2446fda6e7cdb1b9462162b81b0e50fd6efaf56;hpb=d16bd0400fc096ec2fed36d5dfa8620b2370e4d1 diff --git a/support/nsm/file.c b/support/nsm/file.c index 8796705..d469219 100644 --- a/support/nsm/file.c +++ b/support/nsm/file.c @@ -67,6 +67,8 @@ #endif #include +#include +#include #include #include @@ -335,6 +337,34 @@ nsm_is_default_parentdir(void) return strcmp(nsm_base_dirname, NSM_DEFAULT_STATEDIR) == 0; } +/* + * Clear all capabilities but CAP_NET_BIND_SERVICE. This permits + * callers to acquire privileged source ports, but all other root + * capabilities are disallowed. + * + * Returns true if successful, or false if some error occurred. + */ +static _Bool +nsm_clear_capabilities(void) +{ + cap_t caps; + + caps = cap_from_text("cap_net_bind_service=ep"); + 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); + return true; +} + /** * nsm_drop_privileges - drop root privileges * @pidfd: file descriptor of a pid file @@ -382,6 +412,14 @@ nsm_drop_privileges(const int pidfd) if (fchown(pidfd, st.st_uid, st.st_gid) == -1) xlog_warn("Failed to change owner of pidfile: %m"); + /* + * Don't clear capabilities when dropping root. + */ + if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) { + xlog(L_ERROR, "prctl(PR_SET_KEEPCAPS) failed: %m"); + return 0; + } + if (setgroups(0, NULL) == -1) { xlog(L_ERROR, "Failed to drop supplementary groups: %m"); return false; @@ -399,7 +437,8 @@ nsm_drop_privileges(const int pidfd) } xlog(D_CALL, "Effective UID, GID: %u, %u", st.st_uid, st.st_gid); - return true; + + return nsm_clear_capabilities(); } /**