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.
This commit is contained in:
Omar Polo 2023-06-09 17:50:28 +00:00
parent 5af19830c3
commit 7fff8aa6cb
2 changed files with 38 additions and 8 deletions

28
gmid.c
View File

@ -51,7 +51,7 @@ static struct privsep_proc procs[] = {
{ "logger", PROC_LOGGER, main_dispatch_logger, logger }, { "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[] = { static const struct option longopts[] = {
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
@ -169,6 +169,7 @@ main(int argc, char **argv)
struct conf *conf; struct conf *conf;
struct privsep *ps; struct privsep *ps;
const char *errstr, *title = NULL; const char *errstr, *title = NULL;
const char *user = NULL, *chroot = NULL;
size_t i; size_t i;
int ch, conftest = 0; int ch, conftest = 0;
int proc_instance = 0; int proc_instance = 0;
@ -214,12 +215,18 @@ main(int argc, char **argv)
if (proc_id == PROC_MAX) if (proc_id == PROC_MAX)
fatalx("invalid process name"); fatalx("invalid process name");
break; break;
case 'U':
user = optarg;
break;
case 'V': case 'V':
puts("Version: " GMID_STRING); puts("Version: " GMID_STRING);
return 0; return 0;
case 'v': case 'v':
verbose = 1; verbose = 1;
break; break;
case 'X':
chroot = optarg;
break;
default: default:
usage(); usage();
return 1; return 1;
@ -231,10 +238,21 @@ main(int argc, char **argv)
conf = config_new(); conf = config_new();
if (parse_conf(conf, config_path) == -1) /*
fatalx("failed to load configuration file"); * Only the parent loads the config, the others get user and
if (*conf->chroot != '\0' && *conf->user == '\0') * chroot via flags and the rest via imsg.
fatalx("can't chroot without a user to switch to after."); */
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) { if (conftest) {
fprintf(stderr, "config OK\n"); fprintf(stderr, "config OK\n");

18
proc.c
View File

@ -89,14 +89,14 @@ void
proc_exec(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc, proc_exec(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc,
int debug, int argc, char **argv) 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; const char **nargv;
struct privsep_proc *p; struct privsep_proc *p;
char num[32]; char num[32];
int fd; int fd;
/* Prepare the new process argv. */ /* Prepare the new process argv. */
nargv = calloc(argc + 5, sizeof(char *)); nargv = calloc(argc + 9, sizeof(char *));
if (nargv == NULL) if (nargv == NULL)
fatal("%s: calloc", __func__); fatal("%s: calloc", __func__);
@ -109,6 +109,16 @@ proc_exec(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc,
proc_i = nargc; proc_i = nargc;
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. */ /* Point process instance arg to stack and copy the original args. */
nargv[nargc++] = "-I"; nargv[nargc++] = "-I";
nargv[nargc++] = num; nargv[nargc++] = num;
@ -120,8 +130,10 @@ proc_exec(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc,
for (proc = 0; proc < nproc; proc++) { for (proc = 0; proc < nproc; proc++) {
p = &procs[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; 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. */ /* Fire children processes. */
for (i = 0; i < ps->ps_instances[p->p_id]; i++) { for (i = 0; i < ps->ps_instances[p->p_id]; i++) {