From owner-freebsd-bugs Fri Jul 7 19: 0: 8 2000 Delivered-To: freebsd-bugs@freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (Postfix) with ESMTP id E3EEB37B574 for ; Fri, 7 Jul 2000 19:00:00 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.9.3/8.9.2) id TAA80679; Fri, 7 Jul 2000 19:00:01 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from palrel1.hp.com (palrel1.hp.com [156.153.255.242]) by hub.freebsd.org (Postfix) with ESMTP id EC20F37B552 for ; Fri, 7 Jul 2000 18:53:33 -0700 (PDT) (envelope-from joelh@beastie.mayfield.hp.com) Received: from beastie.mayfield.hp.com (beastie.mayfield.hp.com [15.37.242.90]) by palrel1.hp.com (Postfix) with ESMTP id D0291CB9 for ; Fri, 7 Jul 2000 18:53:33 -0700 (PDT) Received: (from joelh@localhost) by beastie.mayfield.hp.com (8.9.3/8.9.3) id WAA07069; Fri, 7 Jul 2000 22:42:10 -0700 (PDT) (envelope-from joelh) Message-Id: <200007080542.WAA07069@beastie.mayfield.hp.com> Date: Fri, 7 Jul 2000 22:42:10 -0700 (PDT) From: joelh@gnu.org Reply-To: joelh@gnu.org To: FreeBSD-gnats-submit@freebsd.org X-Send-Pr-Version: 3.2 Subject: bin/19773: [PATCH] telnet infinite loop depending on how fds are closed Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >Number: 19773 >Category: bin >Synopsis: [PATCH] telnet infinite loop depending on how fds are closed >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Jul 07 19:00:01 PDT 2000 >Closed-Date: >Last-Modified: >Originator: Joel Ray Holveck >Release: FreeBSD 4.0-STABLE i386 >Organization: none >Environment: FreeBSD 4.0, Pentium 90, nothing extraordinary here that seems relevant >Description: The telnet client can get into an infinite loop if the pipe going to stdout and stderr is closed before the pipe going to stdin. This is because, on a SIGPIPE, it will assume that the remote has closed its connection. It longjmp()'s out of the signal handler, and reports this to the user on stdout or stderr (not sure which, doesn't really matter), generating another SIGPIPE. Now, that SIGPIPE will try the same longjmp. telnet tries to report again, gets another SIGPIPE... ad infinitum. >How-To-Repeat: Compile and run the following program. (I'm not sure how necessary the sleeps are, and this has a few minor bugs, but it demonstrates the problem.) After the process closes the pipe from "me->telnet", then the telnet process (find it with top or ps, sorry) will go into the aforementioned infinite loop. Note that the telnet sticks around after the calling program exits; find it with top or ps and kill it yourself. #include #include int main(int argc, char *argv[]) { int topipe[2]; int frompipe[2]; pipe(&topipe); pipe(&frompipe); if (!fork()) { close(topipe[1]); close(frompipe[0]); dup2(topipe[0], 0); dup2(frompipe[1], 1); dup2(frompipe[1], 2); execlp("/usr/bin/telnet", "telnet", "localhost", NULL); abort(); } close(topipe[0]); close(frompipe[1]); printf("forked\n"); sleep(5); printf("closing telnet->me\n"); close(frompipe[0]); sleep(3); printf("closing me->telnet\n"); close(topipe[1]); sleep(2); printf("bye\n"); exit(0); } >Fix: Here's the fix for crypto/telnet/telnet/sys_bsd.c. I haven't looked at the other telnets, but I would assume they would be similar. Caveat: I've tested this precisely twice. --- sys_bsd.c.orig Fri Jul 7 21:35:57 2000 +++ sys_bsd.c Fri Jul 7 21:50:59 2000 @@ -941,9 +941,17 @@ void sys_telnet_init() { + struct sigaction act; (void) signal(SIGINT, intr); (void) signal(SIGQUIT, intr2); - (void) signal(SIGPIPE, deadpeer); + /* We only want deadpeer to be called once, 'cause if there's a broken + * pipe on stdout, we can't handle a SIGPIPE while reporting the + * dropped connection. + */ + act.sa_handler = deadpeer; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESETHAND; + (void) sigaction(SIGPIPE, &act, NULL); #ifdef SIGWINCH (void) signal(SIGWINCH, sendwin); #endif >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message