summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-06-01 08:49:33 +0200
committerLennart Poettering <lennart@poettering.net>2014-06-01 08:49:33 +0200
commit966bff2660a13c82b70a1e1ac4f1a48bb33d7f7e (patch)
tree46d0b3f2ab28b507665ff70b81ea6c33af88ac16 /src
parent267b3e41df5a2181f2911433539f81de2fa1511a (diff)
timesyncd: split privilege dropping code out of timesyncd so that we can make use of it from other daemons too
This is preparation to make networkd work as unpriviliged user.
Diffstat (limited to 'src')
-rw-r--r--src/shared/capability.c71
-rw-r--r--src/shared/capability.h2
-rw-r--r--src/shared/util.c3
-rw-r--r--src/timesync/timesyncd.c68
4 files changed, 74 insertions, 70 deletions
diff --git a/src/shared/capability.c b/src/shared/capability.c
index b49c51400..69e054b1f 100644
--- a/src/shared/capability.c
+++ b/src/shared/capability.c
@@ -29,12 +29,13 @@
#include <ctype.h>
#include <sys/capability.h>
#include <sys/prctl.h>
+#include "grp.h"
#include "macro.h"
-#include "capability.h"
#include "util.h"
#include "log.h"
#include "fileio.h"
+#include "capability.h"
int have_effective_cap(int value) {
_cleanup_cap_free_ cap_t cap;
@@ -212,3 +213,71 @@ int capability_bounding_set_drop_usermode(uint64_t drop) {
return r;
}
+
+int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilites) {
+
+ _cleanup_cap_free_ cap_t d = NULL;
+ cap_value_t bits[sizeof(keep_capabilites)*8];
+ unsigned i, j = 0;
+ int r;
+
+ /* Unfortunately we cannot leave privilege dropping to PID 1
+ * here, since we want to run as user but want to keep some
+ * capabilities. Since file capabilities have been introduced
+ * this cannot be done across exec() anymore, unless our
+ * binary has the capability configured in the file system,
+ * which we want to avoid. */
+
+ if (setresgid(gid, gid, gid) < 0) {
+ log_error("Failed change group ID: %m");
+ return -errno;
+ }
+
+ if (setgroups(0, NULL) < 0) {
+ log_error("Failed to drop auxiliary groups list: %m");
+ return -errno;
+ }
+
+ if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
+ log_error("Failed to enable keep capabilities flag: %m");
+ return -errno;
+ }
+
+ r = setresuid(uid, uid, uid);
+ if (r < 0) {
+ log_error("Failed change user ID: %m");
+ return -errno;
+ }
+
+ if (prctl(PR_SET_KEEPCAPS, 0) < 0) {
+ log_error("Failed to disable keep capabilities flag: %m");
+ return -errno;
+ }
+
+ r = capability_bounding_set_drop(~keep_capabilites, true);
+ if (r < 0) {
+ log_error("Failed to drop capabilities: %s", strerror(-r));
+ return r;
+ }
+
+ d = cap_init();
+ if (!d)
+ return log_oom();
+
+ for (i = 0; i < sizeof(keep_capabilites)*8; i++)
+ if (keep_capabilites & (1ULL << i))
+ bits[j++] = i;
+
+ if (cap_set_flag(d, CAP_EFFECTIVE, j, bits, CAP_SET) < 0 ||
+ cap_set_flag(d, CAP_PERMITTED, j, bits, CAP_SET) < 0) {
+ log_error("Failed to enable capabilities bits: %m");
+ return -errno;
+ }
+
+ if (cap_set_proc(d) < 0) {
+ log_error("Failed to increase capabilities: %m");
+ return -errno;
+ }
+
+ return 0;
+}
diff --git a/src/shared/capability.h b/src/shared/capability.h
index 64f86410a..3e6d9995f 100644
--- a/src/shared/capability.h
+++ b/src/shared/capability.h
@@ -32,6 +32,8 @@ int have_effective_cap(int value);
int capability_bounding_set_drop(uint64_t drop, bool right_now);
int capability_bounding_set_drop_usermode(uint64_t drop);
+int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilites);
+
DEFINE_TRIVIAL_CLEANUP_FUNC(cap_t, cap_free);
#define _cleanup_cap_free_ _cleanup_(cap_freep)
diff --git a/src/shared/util.c b/src/shared/util.c
index 17b0ae16c..4a3e35f35 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -6480,8 +6480,7 @@ void hexdump(FILE *f, const void *p, size_t s) {
}
}
-int update_reboot_param_file(const char *param)
-{
+int update_reboot_param_file(const char *param) {
int r = 0;
if (param) {
diff --git a/src/timesync/timesyncd.c b/src/timesync/timesyncd.c
index a56bbc30c..27f6b2d22 100644
--- a/src/timesync/timesyncd.c
+++ b/src/timesync/timesyncd.c
@@ -1196,72 +1196,6 @@ static int manager_network_monitor_listen(Manager *m) {
return 0;
}
-static int drop_privileges(uid_t uid, gid_t gid) {
-
- static const cap_value_t bits[] = {
- CAP_SYS_TIME,
- };
-
- _cleanup_cap_free_ cap_t d = NULL;
- int r;
-
- /* Unfortunately we cannot leave privilege dropping to PID 1
- * here, since we want to run as user but want to keep te
- * CAP_SYS_TIME capability. Since file capabilities have been
- * introduced this cannot be done across exec() anymore,
- * unless our binary has the capability configured in the file
- * system, which we want to avoid. */
-
- if (setresgid(gid, gid, gid) < 0) {
- log_error("Failed change group ID: %m");
- return -errno;
- }
-
- if (setgroups(0, NULL) < 0) {
- log_error("Failed to drop auxiliary groups list: %m");
- return -errno;
- }
-
- if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
- log_error("Failed to enable keep capabilities flag: %m");
- return -errno;
- }
-
- r = setresuid(uid, uid, uid);
- if (r < 0) {
- log_error("Failed change user ID: %m");
- return -errno;
- }
-
- if (prctl(PR_SET_KEEPCAPS, 0) < 0) {
- log_error("Failed to disable keep capabilities flag: %m");
- return -errno;
- }
-
- r = capability_bounding_set_drop(~(1ULL << CAP_SYS_TIME), true);
- if (r < 0) {
- log_error("Failed to drop capabilities: %s", strerror(-r));
- return r;
- }
-
- d = cap_init();
- if (!d)
- return log_oom();
-
- if (cap_set_flag(d, CAP_EFFECTIVE, ELEMENTSOF(bits), bits, CAP_SET) < 0 ||
- cap_set_flag(d, CAP_PERMITTED, ELEMENTSOF(bits), bits, CAP_SET) < 0) {
- log_error("Failed to enable capabilities bits: %m");
- return -errno;
- }
-
- if (cap_set_proc(d) < 0) {
- log_error("Failed to increase capabilities: %m");
- return -errno;
- }
-
- return 0;
-}
-
int main(int argc, char *argv[]) {
const char *user = "systemd-timesync";
_cleanup_manager_free_ Manager *m = NULL;
@@ -1291,7 +1225,7 @@ int main(int argc, char *argv[]) {
if (r < 0)
goto out;
- r = drop_privileges(uid, gid);
+ r = drop_privileges(uid, gid, (1ULL << CAP_SYS_TIME));
if (r < 0)
goto out;