Commit Diff


commit - 5af19830c3bbec71b3db5c2c19335e5e0c7ff76f
commit + 7fff8aa6cb567a62113d9877af5bcb5bb4494111
blob - 0949e7f566972cc9c7250d448a82bbd76ad5b3f2
blob + 463b7ae222bd2bcef0c091b702e42cb5c436dcb8
--- gmid.c
+++ gmid.c
@@ -51,7 +51,7 @@ static struct privsep_proc procs[] = {
 	{ "logger",	PROC_LOGGER,	main_dispatch_logger, logger },
 };
 
-static const char	*opts = "c:D:fI:hnP:T:Vv";
+static const char	*opts = "c:D:fI:hnP:T:U:VvX:";
 
 static const struct option longopts[] = {
 	{"help",	no_argument,		NULL,	'h'},
@@ -169,6 +169,7 @@ main(int argc, char **argv)
 	struct conf *conf;
 	struct privsep *ps;
 	const char *errstr, *title = NULL;
+	const char *user = NULL, *chroot = NULL;
 	size_t i;
 	int ch, conftest = 0;
 	int proc_instance = 0;
@@ -214,12 +215,18 @@ main(int argc, char **argv)
 			if (proc_id == PROC_MAX)
 				fatalx("invalid process name");
 			break;
+		case 'U':
+			user = optarg;
+			break;
 		case 'V':
 			puts("Version: " GMID_STRING);
 			return 0;
 		case 'v':
 			verbose = 1;
 			break;
+		case 'X':
+			chroot = optarg;
+			break;
 		default:
 			usage();
 			return 1;
@@ -231,10 +238,21 @@ main(int argc, char **argv)
 
 	conf = config_new();
 
-	if (parse_conf(conf, config_path) == -1)
-		fatalx("failed to load configuration file");
-	if (*conf->chroot != '\0' && *conf->user == '\0')
-		fatalx("can't chroot without a user to switch to after.");
+	/*
+	 * Only the parent loads the config, the others get user and
+	 * chroot via flags and the rest via imsg.
+	 */
+	if (proc_id == PROC_PARENT) {
+		if (parse_conf(conf, config_path) == -1)
+			fatalx("failed to load configuration file");
+		if (*conf->chroot != '\0' && *conf->user == '\0')
+			fatalx("can't chroot without a user to switch to.");
+	} else {
+		if (user)
+			strlcpy(conf->user, user, sizeof(conf->user));
+		if (chroot)
+			strlcpy(conf->chroot, chroot, sizeof(conf->chroot));
+	}
 
 	if (conftest) {
 		fprintf(stderr, "config OK\n");
blob - 62d3b871144e19c1d91dea27c733c7445939d185
blob + 3060e65789708c425f400e0c13b5fc4a8609f0b3
--- proc.c
+++ proc.c
@@ -89,14 +89,14 @@ void
 proc_exec(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc,
     int debug, int argc, char **argv)
 {
-	unsigned int		 proc, nargc, i, proc_i;
+	unsigned int		 proc, nargc, i, proc_i, proc_X = 0;
 	const char		**nargv;
 	struct privsep_proc	*p;
 	char			 num[32];
 	int			 fd;
 
 	/* Prepare the new process argv. */
-	nargv = calloc(argc + 5, sizeof(char *));
+	nargv = calloc(argc + 9, sizeof(char *));
 	if (nargv == NULL)
 		fatal("%s: calloc", __func__);
 
@@ -108,6 +108,16 @@ proc_exec(struct privsep *ps, struct privsep_proc *pro
 	nargv[nargc++] = "-T";
 	proc_i = nargc;
 	nargc++;
+
+	/* Set user and chroot */
+	if (ps->ps_pw != NULL) {
+		nargv[nargc++] = "-U";
+		nargv[nargc++] = ps->ps_pw->pw_name;
+
+		nargv[nargc++] = "-X";
+		proc_X = nargc;
+		nargc++;
+	}
 
 	/* Point process instance arg to stack and copy the original args. */
 	nargv[nargc++] = "-I";
@@ -120,8 +130,10 @@ proc_exec(struct privsep *ps, struct privsep_proc *pro
 	for (proc = 0; proc < nproc; proc++) {
 		p = &procs[proc];
 
-		/* Update args with process title. */
+		/* Update args with process title and chroot. */
 		nargv[proc_i] = (char *)(uintptr_t)p->p_title;
+		if (proc_X && p->p_chroot != NULL)
+			nargv[proc_X] = p->p_chroot;
 
 		/* Fire children processes. */
 		for (i = 0; i < ps->ps_instances[p->p_id]; i++) {