Path: csiph.com!xmission!news.snarked.org!news.linkpendium.com!news.linkpendium.com!panix!usenet.stanford.edu!not-for-mail From: Bob Proulx Newsgroups: gnu.bash.bug Subject: Re: Segfault on recursive trap/kill Date: Sat, 6 Oct 2018 22:44:17 -0600 Lines: 171 Approved: bug-bash@gnu.org Message-ID: References: <8736tj3llu.fsf@gnu.org> <25389056-9fcf-1d31-36d8-13098769a43a@case.edu> <874ldy1vka.fsf@gnu.org> NNTP-Posting-Host: lists.gnu.org Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="9amGYk9869ThD9tj" X-Trace: usenet.stanford.edu 1538887468 9830 208.118.235.17 (7 Oct 2018 04:44:28 GMT) X-Complaints-To: action@cs.stanford.edu Cc: bug-bash@gnu.org To: Mike Gerwitz Envelope-to: bug-bash@gnu.org Mail-Followup-To: Mike Gerwitz , bug-bash@gnu.org Content-Disposition: inline In-Reply-To: <874ldy1vka.fsf@gnu.org> User-Agent: Mutt/1.10.1 (2018-07-13) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 96.88.95.61 X-BeenThere: bug-bash@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Bug reports for the GNU Bourne Again SHell List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Xref: csiph.com gnu.bash.bug:14693 --9amGYk9869ThD9tj Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hi Mike, Mike Gerwitz wrote: > ... but are you saying that terminating with a segfault is the > intended behavior for runaway recursion? Let me give the discussion this way and I think you will be convinced. :-) How is your example any different from a C program? Or Perl, Python, Ruby, and so forth? All of those also allow infinite recursion and the kernel will terminate them with a segfault. Because all of those also allow infinite recursion. A program that executes an infinite recursion would use infinite stack space. But real machines have a finite amount of stack available and therefore die when the stack is exceeded. This following complete C program recurses infinitely. Or at least until the stack is exhausted. At which time it triggers a segfault because it tries to use memory beyond the page mapped stack. int main() { return main(); } $ gcc -o forever forever.c $ ./forever Segmentation fault $ echo $? 139 # Signal 11 + 128 The return value of a simple command is its exit status, or 128+n if the command is terminated by signal n. Would you say that is a bug in the C language? A bug in gcc that compiled it? A bug in the Unix/Linux kernel for memory management that trapped the error? The parent shell that reported the exit code of the program? Or in the program source code? I am hoping that we will all agree that it is a bug in the program source code and not either gcc or the kernel. :-) Shell script code is program source code. Infinite loops or infinite recursion are bugs in the shell script source code not the interpreter that is executing the code as written. This feels to me to be related to The Halting Problem. > As long as there is no exploitable flaw here, then I suppose this isn't > a problem; It's not a privilege escalation. Nor a buffer overflow. Whether this is otherwise exploitable depends upon the surrounding environment usage. > I haven't inspected the code to see if this is an access violation > or if Bash is intentionally signaling SIGSEGV. It is the kernel that manages memory, maps pages, detects page faults, kills the program. The parent bash shell is only reporting the exit code that resulted. The interpreting shell executed the shell script souce code as written. = =20 Other shells are also fun to check: $ dash -c 'trap "kill 0" TERM; kill 0' Segmentation fault $ ash -c 'trap "kill 0" TERM; kill 0' Segmentation fault $ mksh -c 'trap "kill 0" TERM; kill 0' Segmentation fault $ ksh93 -c 'trap "kill 0" TERM; kill 0' $ echo $? 0 $ posh -c 'trap "kill 0" TERM; kill 0' Terminated Terminated Terminated ... Terminated ^C Testing zsh is interesting because it seems to keep the interpreter stack in data space and therefore can consume a large amount of memory if it is available. And then can trap the result of being out of data memory and then kills itself with a SIGTERM. Note that in my testing I have Linux memory overcommit disabled. This finds what look like bugs in posh and ksh93. > it's just that most users assume that a segfault represents a > problem with the program Yes. And here it indicates a bug too. It is indicating a bug in the shell program code which sets up the infinite recursion. Programs should avoid doing that. :-) bash -c 'trap "kill 0" TERM; kill 0' The trap handler was not set back to the default before the program sent the signal to itself. The way to fix this is: $ bash -c 'trap "trap - TERM; kill 0" TERM; kill 0' Terminated $ echo $? 143 # killed on SIGTERM as desired, good If ARG is absent (and a single SIGNAL_SPEC is supplied) or `-', each specified signal is reset to its original value. The proper way for a program to terminate itself upon catching a signal is to set the signal handler back to the default value and then send the signal to itself so that it will be terminated as a result of the signal and therefore the exit status will be set correctly. For example the following is useful boilerplate: unset tmpfile cleanup() { test -n "$tmpfile" && rm -f "$tmpfile" && unset tmpfile } trap "cleanup" EXIT trap "cleanup; trap - HUP; kill -HUP $$" HUP trap "cleanup; trap - INT; kill -INT $$" INT trap "cleanup; trap - QUIT; kill -QUIT $$" QUIT trap "cleanup; trap - TERM; kill -TERM $$" TERM tmpfile=3D$(mktemp) || exit 1 If a program traps a signal then it should restore the default signal handler for that signal and send the signal back to itself. Otherwise the exit code will be incorrect. Otherwise parent programs won't know that the child was killed with a signal. For a highly recommended deep dive into this: https://www.cons.org/cracauer/sigint.html Hope this helps! Bob --9amGYk9869ThD9tj Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEY7Fmg4Qc49wl08brQhr6Jjh/mo4FAlu5jx0ACgkQQhr6Jjh/ mo7nZg/+Le80adq6B8C5FyU6tjV41Y+YOjxgTqPJSmN2dW380OGDURfwW+nuHZ8w IcD6qv2/VPKuSap28A2GUlj+DLmq0UCfmw7YSgrD0dqI/bZmR1EtrhbOogIs4oz6 9osAkjyQsyMes/EGiv8X+iBTOePmzKhgI7iZnXfafJUkU85JP85IAgcuPpOnEisq usnGrZAdei157iFInWV2KQqj/HhE4ch412myjus7TFD0d+5ykKCyqfXRcUqpnDTb Ygx9kE61Vl33II7QJLxa4vwE8U5WWJQSN5lYbF/iGvsJK2HXRquREqpZT2cy8RAh pf197x1OUAibc81Nz+tNjmNhs71A5sk8YLXJ11Ou5eFAL92PB6bkBxxCCp+uoSjD vIftEFXohgks0n5P5AleSLJgSPFobWA6wTpfww4ZJg0mjcD1XVNesnNWGEvPGi8x 0u/QuOvjaavmQvnKDwd2wkD+NKt+VkbGVFo2eksvACq+ZCxGUs4+1RKNgmEsqOR7 UcMtKjSoFgaJoQ6DVSWx5UqT3Fx5e4iHTFAhysgqiFAfKg1+BgoQp9b8OAJt5qYv h+cvJXBDhz73yViQ3JIwj8a2ONMBBQHmOSUzQF8aeDJdrjFNh6I45mVoq2db1hak SJaHZpFutDdwbasp70HWVdh/6GcfP/32HSw7VMF+ARNnjcOyzBM= =EuQg -----END PGP SIGNATURE----- --9amGYk9869ThD9tj--