commit 7fff8aa6cb567a62113d9877af5bcb5bb4494111 from: Omar Polo date: Fri Jun 09 17:50:28 2023 UTC parse the config file only once Don't have all the processes read gmid.conf. The parent needs to do that, and the will send the config to the children (already happening.) The other processes were reading the config anyway to figure out the user and the chroot (if enabled); make the parent pass additional flag to propagate that info. We dissociate a bit from the "usual" proc.c but it's a change worth having. 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++) {