aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmar Polo <op@omarpolo.com>2024-06-14 12:42:18 +0000
committerOmar Polo <op@omarpolo.com>2024-06-14 12:42:18 +0000
commit23ea79cec6c409d3b98977727b8d5ed857acfd4d (patch)
tree2312cacca075286d6c9e3ac22c02ae246f1f52c7
parentc616a6d6f4299ab0070afdb23aebe46ff4fb2e6a (diff)
propagate prefork value
otherwise the child processes still believet the prefork value is 3 and can end up reading/writing out of bounds when setting up the sockets. Actually, server processes shouldn't create pipes to other servers, but this is left for a follow-up diff. Issue reported by la ninpre, thank you!
-rw-r--r--gmid.c11
-rw-r--r--proc.c13
-rwxr-xr-xregress/regress1
-rw-r--r--regress/tests.sh7
4 files changed, 29 insertions, 3 deletions
diff --git a/gmid.c b/gmid.c
index 5556e1d..3d5f864 100644
--- a/gmid.c
+++ b/gmid.c
@@ -54,7 +54,7 @@ static struct privsep_proc procs[] = {
{ "logger", PROC_LOGGER, main_dispatch_logger, logger },
};
-static const char *opts = "c:D:fI:hnP:T:U:VvX:";
+static const char *opts = "c:D:fI:J:hnP:T:U:VvX:";
static const struct option longopts[] = {
{"help", no_argument, NULL, 'h'},
@@ -240,6 +240,7 @@ main(int argc, char **argv)
int ch, conftest = 0;
int proc_instance = 0;
int proc_id = PROC_PARENT;
+ int nprocs = 0;
int argc0 = argc;
setlocale(LC_CTYPE, "");
@@ -269,6 +270,13 @@ main(int argc, char **argv)
if (errstr != NULL)
fatalx("invalid process instance");
break;
+ case 'J':
+ nprocs = strtonum(optarg, 0, PROC_MAX_INSTANCES,
+ &errstr);
+ if (errstr != NULL)
+ fatalx("invalid process instance");
+ log_warnx("nprocs is %d", nprocs);
+ break;
case 'n':
conftest++;
break;
@@ -320,6 +328,7 @@ main(int argc, char **argv)
if (chroot && strlcpy(conf->chroot, chroot, sizeof(conf->chroot))
>= sizeof(conf->chroot))
fatalx("chroot path too long: %s", chroot);
+ conf->prefork = nprocs;
}
if ((ps = calloc(1, sizeof(*ps))) == NULL)
diff --git a/proc.c b/proc.c
index 82458bc..5b21d6f 100644
--- a/proc.c
+++ b/proc.c
@@ -79,14 +79,17 @@ proc_exec(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc,
unsigned int proc, nargc, i, proc_i, proc_X = 0;
const char **nargv;
struct privsep_proc *p;
- char num[32];
+ char num[32], prefork[32];
int fd;
/* Prepare the new process argv. */
- nargv = calloc(argc + 9, sizeof(char *));
+ nargv = calloc(argc + 11, sizeof(char *));
if (nargv == NULL)
fatal("%s: calloc", __func__);
+ /* Update prefork number */
+ snprintf(prefork, sizeof(prefork), "%d", ps->ps_instances[PROC_SERVER]);
+
/* Copy call argument first. */
nargc = 0;
nargv[nargc++] = argv[0];
@@ -106,6 +109,10 @@ proc_exec(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc,
nargc++;
}
+ /* Set server prefork number */
+ nargv[nargc++] = "-J";
+ nargv[nargc++] = prefork;
+
/* Point process instance arg to stack and copy the original args. */
nargv[nargc++] = "-I";
nargv[nargc++] = num;
@@ -354,6 +361,8 @@ proc_setup(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc)
*/
for (src = 0; src < PROC_MAX; src++) {
/* Allocate destination array for each process */
+ log_debug("allocating %d for proc %d/%d",
+ ps->ps_instances[src], src, PROC_MAX);
if ((ps->ps_pipes[src] = calloc(ps->ps_instances[src],
sizeof(struct privsep_pipes))) == NULL)
fatal("%s: calloc", __func__);
diff --git a/regress/regress b/regress/regress
index 0ace045..82d17a9 100755
--- a/regress/regress
+++ b/regress/regress
@@ -68,6 +68,7 @@ run_test test_log_file
run_test test_ipv4_addr
run_test test_ipv6_addr need_ipv6
run_test test_ipv6_server need_ipv6
+run_test test_high_prefork
# TODO: add test that uses only a TLSv1.2 or TLSv1.3
# TODO: add a test that attempt to serve a non-regular file
diff --git a/regress/tests.sh b/regress/tests.sh
index 4581df0..7648278 100644
--- a/regress/tests.sh
+++ b/regress/tests.sh
@@ -521,3 +521,10 @@ test_ipv6_server() {
fetch /
check_reply "20 text/gemini" "# hello world" || return 1
}
+
+test_high_prefork() {
+ setup_simple_test 'prefork 12'
+
+ fetch /
+ check_reply "20 text/gemini" "# hello world" || return 1
+}