From 6bc7175f315bd4e2c334d60ee3364cbff63574f1 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 16 May 2020 16:29:23 +0000 Subject: [PATCH] sh: Fix double INTON with vfork The shell maintains a count of the number of times SIGINT processing has been disabled via INTOFF, so SIGINT processing resumes when all disables have enabled again (INTON). If an error occurs in a vfork() child, the processing of the error enables SIGINT processing again, and the INTON in vforkexecshell() causes the count to become negative. As a result, a later INTOFF may not actually disable SIGINT processing. This might cause memory corruption if a SIGINT arrives at an inopportune time. As of r360452, it causes the shell to abort when it would unsafely allocate or free memory in certain ways. Note that various places such as errors in non-special builtins unconditionally reset the count to 0, so the problem might still not always be visible. PR: 246497 Reported by: jbeich MFC after: 2 weeks --- bin/sh/jobs.c | 4 +++- bin/sh/tests/execution/Makefile | 1 + bin/sh/tests/execution/unknown2.0 | 6 ++++++ 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 bin/sh/tests/execution/unknown2.0 diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c index 2475787c1da9..c46e526eab67 100644 --- a/bin/sh/jobs.c +++ b/bin/sh/jobs.c @@ -1008,9 +1008,11 @@ vforkexecshell(struct job *jp, char **argv, char **envp, const char *path, int i pid_t pid; struct jmploc jmploc; struct jmploc *savehandler; + int inton; TRACE(("vforkexecshell(%%%td, %s, %p) called\n", jp - jobtab, argv[0], (void *)pip)); + inton = is_int_on(); INTOFF; flushall(); savehandler = handler; @@ -1045,7 +1047,7 @@ vforkexecshell(struct job *jp, char **argv, char **envp, const char *path, int i setcurjob(jp); #endif } - INTON; + SETINTON(inton); TRACE(("In parent shell: child = %d\n", (int)pid)); return pid; } diff --git a/bin/sh/tests/execution/Makefile b/bin/sh/tests/execution/Makefile index 983db692faff..526541d50994 100644 --- a/bin/sh/tests/execution/Makefile +++ b/bin/sh/tests/execution/Makefile @@ -64,6 +64,7 @@ ${PACKAGE}FILES+= subshell2.0 ${PACKAGE}FILES+= subshell3.0 ${PACKAGE}FILES+= subshell4.0 ${PACKAGE}FILES+= unknown1.0 +${PACKAGE}FILES+= unknown2.0 ${PACKAGE}FILES+= var-assign1.0 .include diff --git a/bin/sh/tests/execution/unknown2.0 b/bin/sh/tests/execution/unknown2.0 new file mode 100644 index 000000000000..d316e01949f6 --- /dev/null +++ b/bin/sh/tests/execution/unknown2.0 @@ -0,0 +1,6 @@ +# $FreeBSD$ + +{ + : $(/var/empty/nosuchtool) + : $(:) +} 2>/dev/null