Merge authors:
Stéphane Graber (stgraber)
Related merge proposals:
https://code.launchpad.net/~stgraber/upstart/upstart-initgroups/+merge/136794
proposed by: Stéphane Graber (stgraber)
review: Approve - James Hunt (jamesodhunt)
------------------------------------------------------------
revno: 1396 [merge]
committer: James Hunt <[email protected]>
branch nick: upstart
timestamp: Wed 2012-12-05 08:56:58 +0000
message:
* Merge of lp:~stgraber/upstart/upstart-initgroups.
modified:
init/job_process.c
init/job_process.h
init/tests/test_job_process.c
--
lp:upstart
https://code.launchpad.net/~upstart-devel/upstart/trunk
Your team Upstart Reviewers is subscribed to branch lp:upstart.
To unsubscribe from this branch go to
https://code.launchpad.net/~upstart-devel/upstart/trunk/+edit-subscription
=== modified file 'init/job_process.c'
--- init/job_process.c 2012-11-21 06:48:08 +0000
+++ init/job_process.c 2012-12-03 20:27:09 +0000
@@ -413,6 +413,8 @@
JobClass *class;
uid_t job_setuid = -1;
gid_t job_setgid = -1;
+ struct passwd *pwd = NULL;
+ struct group *grp = NULL;
nih_assert (job != NULL);
@@ -705,6 +707,11 @@
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CHOWN, 0);
}
+ if (geteuid () == 0 && initgroups (pw->pw_name, pw->pw_gid) < 0) {
+ nih_error_raise_system ();
+ job_process_error_abort (fds[1], JOB_PROCESS_ERROR_INITGROUPS, 0);
+ }
+
if (pw->pw_gid && setgid (pw->pw_gid) < 0) {
nih_error_raise_system ();
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SETGID, 0);
@@ -844,7 +851,6 @@
* session jobs and jobs with a chroot stanza.
*/
if (class->setuid) {
- struct passwd *pwd;
/* Without resetting errno, it's impossible to
* distinguish between a non-existent user and and
* error during lookup */
@@ -867,7 +873,6 @@
}
if (class->setgid) {
- struct group *grp;
errno = 0;
grp = getgrnam (class->setgid);
if (! grp) {
@@ -891,6 +896,35 @@
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CHOWN, 0);
}
+ /* Make sure we always have the needed pwd and grp structs.
+ * Then pass those to initgroups() to setup the user's group list.
+ * Only do that if we're root as initgroups() won't work when non-root. */
+ if (geteuid () == 0) {
+ if (! pwd) {
+ pwd = getpwuid (geteuid ());
+ if (! pwd) {
+ nih_error_raise_system ();
+ job_process_error_abort (fds[1], JOB_PROCESS_ERROR_GETPWUID, 0);
+ }
+ }
+
+ if (! grp) {
+ grp = getgrgid (getegid ());
+ if (! grp) {
+ nih_error_raise_system ();
+ job_process_error_abort (fds[1], JOB_PROCESS_ERROR_GETGRGID, 0);
+ }
+ }
+
+ if (pwd && grp) {
+ if (initgroups (pwd->pw_name, grp->gr_gid) < 0) {
+ nih_error_raise_system ();
+ job_process_error_abort (fds[1], JOB_PROCESS_ERROR_INITGROUPS, 0);
+ }
+ }
+ }
+
+ /* Start dropping privileges */
if (job_setgid != (gid_t) -1 && setgid (job_setgid) < 0) {
nih_error_raise_system ();
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SETGID, 0);
@@ -1142,6 +1176,11 @@
err, _("unable to getpwuid: %s"),
strerror (err->errnum)));
break;
+ case JOB_PROCESS_ERROR_GETGRGID:
+ err->error.message = NIH_MUST (nih_sprintf (
+ err, _("unable to getgrgid: %s"),
+ strerror (err->errnum)));
+ break;
case JOB_PROCESS_ERROR_BAD_SETUID:
err->error.message = NIH_MUST (nih_sprintf (
err, _("unable to find setuid user")));
@@ -1200,6 +1239,11 @@
err, _("unable to allocate memory: %s"),
strerror (err->errnum)));
break;
+ case JOB_PROCESS_ERROR_INITGROUPS:
+ err->error.message = NIH_MUST (nih_sprintf (
+ err, _("unable to initgroups: %s"),
+ strerror (err->errnum)));
+ break;
default:
nih_assert_not_reached ();
}
=== modified file 'init/job_process.h'
--- init/job_process.h 2012-11-07 15:17:58 +0000
+++ init/job_process.h 2012-11-26 19:30:41 +0000
@@ -94,7 +94,9 @@
JOB_PROCESS_ERROR_PTSNAME,
JOB_PROCESS_ERROR_OPENPT_SLAVE,
JOB_PROCESS_ERROR_SIGNAL,
- JOB_PROCESS_ERROR_ALLOC
+ JOB_PROCESS_ERROR_ALLOC,
+ JOB_PROCESS_ERROR_INITGROUPS,
+ JOB_PROCESS_ERROR_GETGRGID
} JobProcessErrorType;
/**
=== modified file 'init/tests/test_job_process.c'
--- init/tests/test_job_process.c 2012-12-04 17:12:46 +0000
+++ init/tests/test_job_process.c 2012-12-05 08:56:58 +0000
@@ -4007,6 +4007,74 @@
}
/************************************************************/
+
+ /* Check that initgroups gets called.
+ * The test will run a job as nobody/nogroup (setuid/setgid) target.
+ *
+ * When run from an unprivileged user, the check will ensure that upstart
+ * fails to start the job (returning -1) as initgroups() is a privileged
+ * call (similar to setuid and setgid).
+ *
+ * When run from a privileged user (root), the check will ensure that
+ * upstart succeeds in dropping privileges, which includes calling
+ * initgroup, setuid and setgid.
+ *
+ * If the test is started by user nobody/nogroup, then it'll succeed as
+ * there's no privilege changes to be done in such case (same uid/gid).
+ */
+ TEST_FEATURE ("with setuid");
+ TEST_HASH_EMPTY (job_classes);
+
+ TEST_NE_P (output, NULL);
+ TEST_ALLOC_FAIL {
+ TEST_ALLOC_SAFE {
+ class = job_class_new (NULL, "test", NULL);
+ class->process[PROCESS_MAIN] = process_new (class);
+ class->process[PROCESS_MAIN]->command = nih_sprintf (
+ class->process[PROCESS_MAIN],
+ "touch %s", filename);
+
+ pwd = getpwnam ("nobody");
+ TEST_NE (pwd, NULL);
+ class->setuid = nih_strdup (class, pwd->pw_name);
+
+ grp = getgrnam ("nogroup");
+ TEST_NE (grp, NULL);
+ class->setgid = nih_strdup (class, grp->gr_name);
+
+ job = job_new (class, "");
+ job->goal = JOB_START;
+ job->state = JOB_SPAWNED;
+
+ output = tmpfile ();
+ }
+
+ TEST_DIVERT_STDERR (output) {
+ ret = job_process_run (job, PROCESS_MAIN);
+ if (geteuid() == 0 || getuid() == pwd->pw_uid) {
+ TEST_EQ (ret, 0);
+ }
+ else {
+ TEST_EQ (ret, -1);
+ }
+ }
+
+ if (geteuid() == 0 || getuid() == pwd->pw_uid) {
+ TEST_NE (job->pid[PROCESS_MAIN], 0);
+
+ waitpid (job->pid[PROCESS_MAIN], NULL, 0);
+ TEST_EQ (stat (filename, &statbuf), 0);
+ }
+ else {
+ TEST_EQ (stat (filename, &statbuf), -1);
+ }
+
+ unlink (filename);
+ nih_free (class);
+
+ }
+
+ /************************************************************/
TEST_FEATURE ("with multiple processes and log");
TEST_HASH_EMPTY (job_classes);
--
upstart-devel mailing list
[email protected]
Modify settings or unsubscribe at:
https://lists.ubuntu.com/mailman/listinfo/upstart-devel