#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
+#include <sys/prctl.h>
void
daemon_resolve_ugid(struct daemon_params *dp)
void daemon_switch_ugid(struct daemon_params *dp)
{
+ // If we want to preserve some caps across UID switch, keep all first, to avoid having to set them twice.
+ if (dp->keep_caps && prctl(PR_SET_KEEPCAPS, 1L) < 0)
+ die("Can not keep caps: %m");
if (dp->want_setgid && setresgid(dp->run_as_gid, dp->run_as_gid, dp->run_as_gid) < 0)
die("Cannot set GID to %d: %m", (int) dp->run_as_gid);
if (dp->want_setgid > 1 && initgroups(dp->run_as_user, dp->run_as_gid) < 0)
die("Cannot initialize groups: %m");
if (dp->want_setuid && setresuid(dp->run_as_uid, dp->run_as_uid, dp->run_as_uid) < 0)
die("Cannot set UID to %d: %m", (int) dp->run_as_uid);
+ if (dp->keep_caps)
+ {
+ cap_t caps = cap_init();
+ if (cap_clear(caps) < 0)
+ die("Couldn't clear capability set: %m");
+ if (cap_set_flag(caps, CAP_EFFECTIVE, dp->keep_cap_count, dp->keep_caps, 1) < 0 ||
+ cap_set_flag(caps, CAP_PERMITTED, dp->keep_cap_count, dp->keep_caps, 1) < 0 ||
+ cap_set_flag(caps, CAP_INHERITABLE, dp->keep_cap_count, dp->keep_caps, 1) < 0)
+ die("Couldn't set capability flags: %m");
+ if (cap_set_proc(caps) < 0)
+ die("Couldn't set capabilities: %m");
+ if (prctl(PR_SET_KEEPCAPS, 0L) < 0)
+ die("Couldn't give up keeping caps: %m");
+ cap_free(caps);
+ }
}
void
#define _UCW_DAEMON_H
#include <sys/types.h>
+#include <sys/capability.h>
#ifdef CONFIG_UCW_CLEAN_ABI
#define daemon_control ucw_daemon_control
const char *pid_file; // A path to PID file (optional)
const char *run_as_user; // User name or "#uid" (optional)
const char *run_as_group; // Group name or "#gid" (optional)
+ const cap_value_t *keep_caps; // Keep these capabilities across UID switch (optional)
+ int keep_cap_count;
// Internal
uid_t run_as_uid;