aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGilad Arnold <garnold@google.com>2015-09-01 17:26:21 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2015-09-01 17:26:21 +0000
commit18f2fc496305e80e9e1c63e36ac41ebbe995994c (patch)
tree0a5a172e84b8845a863d74058b6f3f64abef8734
parent6418bbed7fb53edf19467c19514ad6d2708c1ad7 (diff)
parentaab9382297008c1d1b7cef361159a44885d52af0 (diff)
downloadtlsdate-18f2fc496305e80e9e1c63e36ac41ebbe995994c.tar.gz
am aab93822: Support for dropping privileges with supplementary groups.
* commit 'aab9382297008c1d1b7cef361159a44885d52af0': Support for dropping privileges with supplementary groups.
-rw-r--r--init/tlsdated.rc2
-rw-r--r--src/tlsdate-helper-plan9.c4
-rw-r--r--src/tlsdate-helper.c4
-rw-r--r--src/tlsdate.h1
-rw-r--r--src/tlsdated.c31
-rw-r--r--src/util-plan9.c6
-rw-r--r--src/util-plan9.h3
-rw-r--r--src/util.c38
-rw-r--r--src/util.h3
9 files changed, 72 insertions, 20 deletions
diff --git a/init/tlsdated.rc b/init/tlsdated.rc
index c36b920..2418255 100644
--- a/init/tlsdated.rc
+++ b/init/tlsdated.rc
@@ -1,5 +1,5 @@
# Init file for starting tlsdated on Android.
-service tlsdated /system/bin/tlsdated -v -l -s -U -- /system/bin/tlsdate -v -C /system/etc/security/cacerts -l
+service tlsdated /system/bin/tlsdated -v -l -s -G dbus -- /system/bin/tlsdate -v -C /system/etc/security/cacerts -l
class main
# This daemon needs to start as root and drops privileges early on.
user root
diff --git a/src/tlsdate-helper-plan9.c b/src/tlsdate-helper-plan9.c
index 3c532aa..c245a6b 100644
--- a/src/tlsdate-helper-plan9.c
+++ b/src/tlsdate-helper-plan9.c
@@ -1109,7 +1109,7 @@ main(int argc, char **argv)
/* We are not going to set the clock, thus no need to stay root */
if (0 == setclock && 0 == timewarp)
{
- drop_privs_to (UNPRIV_USER, UNPRIV_GROUP);
+ drop_privs_to (UNPRIV_USER, UNPRIV_GROUP, NULL);
}
/*
XXX: KILL ME
@@ -1171,7 +1171,7 @@ main(int argc, char **argv)
die ("fork failed: %s\n", strerror (errno));
if (0 == ssl_child)
{
- drop_privs_to (UNPRIV_USER, UNPRIV_GROUP);
+ drop_privs_to (UNPRIV_USER, UNPRIV_GROUP, NULL);
run_ssl (time_map, leap);
/*
XXX: should be a pipe close
diff --git a/src/tlsdate-helper.c b/src/tlsdate-helper.c
index 9322517..d923efd 100644
--- a/src/tlsdate-helper.c
+++ b/src/tlsdate-helper.c
@@ -1276,7 +1276,7 @@ main(int argc, char **argv)
if (0 == setclock && 0 == timewarp)
{
verb ("V: attemping to drop administrator privileges");
- drop_privs_to (UNPRIV_USER, UNPRIV_GROUP);
+ drop_privs_to (UNPRIV_USER, UNPRIV_GROUP, NULL);
}
// We cast the mmap value to remove this error when compiling with g++:
@@ -1337,7 +1337,7 @@ main(int argc, char **argv)
die ("fork failed: %s", strerror (errno));
if (0 == ssl_child)
{
- drop_privs_to (UNPRIV_USER, UNPRIV_GROUP);
+ drop_privs_to (UNPRIV_USER, UNPRIV_GROUP, NULL);
run_ssl (time_map, leap, http);
(void) munmap (time_map, sizeof (uint32_t));
_exit (0);
diff --git a/src/tlsdate.h b/src/tlsdate.h
index 52305eb..97d4fec 100644
--- a/src/tlsdate.h
+++ b/src/tlsdate.h
@@ -111,6 +111,7 @@ struct opts
{
const char *user;
const char *group;
+ char *supp_groups;
int max_tries;
int min_steady_state_interval;
int wait_between_tries;
diff --git a/src/tlsdated.c b/src/tlsdated.c
index a4af628..aa852ac 100644
--- a/src/tlsdated.c
+++ b/src/tlsdated.c
@@ -42,6 +42,8 @@
#include "src/dbus.h"
#include "src/platform.h"
+
+static const char kTlsdatedOpts[] = "hwrpt:d:T:D:c:a:lsvbm:j:f:x:Uu:g:G:";
const char *kCacheDir = DEFAULT_DAEMON_CACHEDIR;
int
@@ -102,6 +104,7 @@ usage (const char *progn)
printf (" -U don't use DBus if supported\n");
printf (" -u <user> user to change to\n");
printf (" -g <grp> group to change to\n");
+ printf (" -G <grps> comma-separated list of supplementary groups\n");
printf (" -v be verbose\n");
printf (" -b use verbose debugging\n");
printf (" -x <h> set proxy for subprocs to h\n");
@@ -117,6 +120,7 @@ set_conf_defaults (struct opts *opts)
};
opts->user = UNPRIV_USER;
opts->group = UNPRIV_GROUP;
+ opts->supp_groups = NULL;
opts->max_tries = MAX_TRIES;
opts->min_steady_state_interval = STEADY_STATE_INTERVAL;
opts->wait_between_tries = WAIT_BETWEEN_TRIES;
@@ -145,7 +149,7 @@ void
parse_argv (struct opts *opts, int argc, char *argv[])
{
int opt;
- while ((opt = getopt (argc, argv, "hwrpt:d:T:D:c:a:lsvbm:j:f:x:Uu:g:")) != -1)
+ while ((opt = getopt (argc, argv, kTlsdatedOpts)) != -1)
{
switch (opt)
{
@@ -209,6 +213,9 @@ parse_argv (struct opts *opts, int argc, char *argv[])
case 'g':
opts->group = optarg;
break;
+ case 'G':
+ opts->supp_groups = optarg;
+ break;
case 'h':
default:
usage (argv[0]);
@@ -220,6 +227,21 @@ parse_argv (struct opts *opts, int argc, char *argv[])
/* Validate arguments */
}
+static const char **
+parse_supp_groups (char *arg)
+{
+ size_t i;
+ char *scan;
+ const char **supp_groups;
+
+ for (i = 1, scan = arg; (scan = strchr (scan, ',')); i++, scan++) ;
+ supp_groups = (const char **) calloc (i + 1, sizeof (const char *));
+ if (!supp_groups)
+ die ("Failed to allocate memory for supplementary group names\n");
+ for (i = 0; (supp_groups[i] = strsep (&arg, ",")); i++) ;
+ return supp_groups;
+}
+
static
void add_source_to_conf (struct opts *opts, char *host, char *port, char *proxy)
{
@@ -446,6 +468,8 @@ cleanup_main (struct state *state)
int API
main (int argc, char *argv[], char *envp[])
{
+ const char **supp_groups = NULL;
+
initalize_syslog ();
struct state state;
/* TODO(wad) EVENT_BASE_FLAG_PRECISE_TIMER | EVENT_BASE_FLAG_PRECISE_TIMER */
@@ -498,7 +522,9 @@ main (int argc, char *argv[], char *envp[])
platform->rtc_close (&state.hwclock);
}
/* drop privileges before touching any untrusted data */
- drop_privs_to (state.opts.user, state.opts.group);
+ if (state.opts.supp_groups)
+ supp_groups = parse_supp_groups (state.opts.supp_groups);
+ drop_privs_to (state.opts.user, state.opts.group, supp_groups);
/* register a signal handler to save time at shutdown */
if (state.opts.should_save_disk)
{
@@ -598,6 +624,7 @@ main (int argc, char *argv[], char *envp[])
event_base_dispatch (base);
verb ("tlsdated event dispatch terminating gracefully");
out:
+ free (supp_groups);
return cleanup_main (&state);
}
#endif /* !TLSDATED_MAIN */
diff --git a/src/util-plan9.c b/src/util-plan9.c
index 77d2077..84b68fc 100644
--- a/src/util-plan9.c
+++ b/src/util-plan9.c
@@ -61,7 +61,7 @@ void API logat(int isverbose, const char *fmt, ...)
void
-drop_privs_to (const char *user, const char *group)
+drop_privs_to (const char *user, const char *group, const char **supp_groups)
{
#if !_PLAN9_SOURCE
@@ -70,6 +70,10 @@ drop_privs_to (const char *user, const char *group)
struct passwd *pw;
struct group *gr;
+ /* TODO(garnold) Implement supplementary group support. */
+ if (supp_groups)
+ die ("Supplementary groups not supported\n");
+
if (0 != getuid ())
return; /* not running as root to begin with; should (!) be harmless to continue
without dropping to 'nobody' (setting time will fail in the end) */
diff --git a/src/util-plan9.h b/src/util-plan9.h
index 7453235..62f2329 100644
--- a/src/util-plan9.h
+++ b/src/util-plan9.h
@@ -36,6 +36,7 @@ extern void logat(int isverbose, const char *fmt, ...);
static inline int min(int x, int y) { return x < y ? x : y; }
-void drop_privs_to (const char *user, const char *group);
+void drop_privs_to (const char *user, const char *group,
+ const char **supp_groups);
#endif /* !UTIL_H */
diff --git a/src/util.c b/src/util.c
index 9833ee3..5a0acb9 100644
--- a/src/util.c
+++ b/src/util.c
@@ -148,33 +148,39 @@ void enable_seccomp(void)
#endif
}
+static gid_t
+get_unpriv_gid (const char *group)
+{
+ struct group *gr = getgrnam (group);
+ if (NULL == gr)
+ die ("Failed to obtain GID for `%s'\n", group);
+ if (0 == gr->gr_gid)
+ die ("GID for `%s' is 0, refusing to run SSL\n", group);
+ return gr->gr_gid;
+}
+
void
-drop_privs_to (const char *user, const char *group)
+drop_privs_to (const char *user, const char *group, const char **supp_groups)
{
uid_t uid;
gid_t gid;
struct passwd *pw;
- struct group *gr;
+ size_t num_supp, i;
if (0 != getuid ())
return; /* not running as root to begin with; should (!) be harmless to continue
without dropping to 'nobody' (setting time will fail in the end) */
pw = getpwnam (user);
- gr = getgrnam (group);
if (NULL == pw)
die ("Failed to obtain UID for `%s'\n", user);
- if (NULL == gr)
- die ("Failed to obtain GID for `%s'\n", group);
uid = pw->pw_uid;
if (0 == uid)
die ("UID for `%s' is 0, refusing to run SSL\n", user);
- gid = pw->pw_gid;
- if (0 == gid || 0 == gr->gr_gid)
- die ("GID for `%s' is 0, refusing to run SSL\n", user);
- if (pw->pw_gid != gr->gr_gid)
+ gid = get_unpriv_gid (group);
+ if (pw->pw_gid != gid)
die ("GID for `%s' is not `%s' as expected, refusing to run SSL\n",
user, group);
- if (0 != initgroups ( (const char *) user, gr->gr_gid))
+ if (0 != initgroups ( (const char *) user, gid))
die ("Unable to initgroups for `%s' in group `%s' as expected\n",
user, group);
#ifdef HAVE_SETRESGID
@@ -184,6 +190,18 @@ drop_privs_to (const char *user, const char *group)
if (0 != (setgid (gid) | setegid (gid)))
die ("Failed to setgid: %s\n", strerror (errno));
#endif
+ if (supp_groups)
+ {
+ for (num_supp = 0; supp_groups[num_supp]; num_supp++) ;
+ gid_t *supp_gids = (gid_t *) calloc (num_supp, sizeof (gid_t));
+ if (!supp_gids)
+ die ("Failed to allocate memory for supplementary GIDs\n");
+ for (i = 0; i < num_supp; i++)
+ supp_gids[i] = get_unpriv_gid (supp_groups[i]);
+ if (0 != setgroups (num_supp, supp_gids))
+ die ("Failed to setgroups: %s\n", strerror (errno));
+ free (supp_gids);
+ }
#ifdef HAVE_SETRESUID
if (0 != setresuid (uid, uid, uid))
die ("Failed to setresuid: %s\n", strerror (errno));
diff --git a/src/util.h b/src/util.h
index eaceeeb..7166aa9 100644
--- a/src/util.h
+++ b/src/util.h
@@ -63,7 +63,8 @@ static inline int min (int x, int y)
return x < y ? x : y;
}
-void drop_privs_to (const char *user, const char *group);
+void drop_privs_to (const char *user, const char *group,
+ const char **supp_groups);
void no_new_privs (void);
const char *sync_type_str (int sync_type);