Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 18 Apr 2009 15:35:32 +0700 (NOVST)
From:      User & <swp@swp.pp.ru>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   bin/133834: [patch] chat(1): terminate()/fatal() infinity mutual recursion
Message-ID:  <200904180835.n3I8ZWEP056827@swp.pp.ru>
Resent-Message-ID: <200904180910.n3I9A1wB087194@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         133834
>Category:       bin
>Synopsis:       [patch] chat(1): terminate()/fatal() infinity mutual recursion
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Apr 18 09:10:01 UTC 2009
>Closed-Date:
>Last-Modified:
>Originator:     Alexander Mitrokhin
>Release:        FreeBSD 7.1-STABLE i386
>Organization:
Zap-SibTranstelecom
>Environment:
System: FreeBSD swp.pp.ru 7.1-STABLE FreeBSD 7.1-STABLE #1: Sat Jan 10 16:45:33 NOVT 2009 swp@swp.pp.ru:/usr/obj/usr/src/sys/kernconf-freebsd7-20081220-2 i386

>Description:
	I have a small program, which collected data from the switches. It uses telnet 
and chat, to carry out a dialogue. If telnet is completed before the chat will be held 
all of their expectations and answer script, the chat is infinite recursion.
	
>How-To-Repeat:
1. Enable telnetd on localhost.
2. Compile program a.c

#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <libutil.h>

int
main(int argc, char *argv[], char *envp[])
{
        pid_t pid;
        int fd;

        pid = forkpty(&fd, 0, 0, 0);
        if (!pid) {
                execl("/usr/bin/telnet", "telnet", argv[1], 0);
                err(1, "telnet %s", argv[1]);
        }
        if (pid < 0)
                err(1, "forkpty()");
        if (dup2(1, 2) < 0)
                err(1, "dup2(1, 2)");
        if (dup2(fd, 0) < 0)
                err(1, "dup2(fd, 0)");
        if (dup2(fd, 1) < 0)
                err(1, "dup2(fd, 1)");
        close(fd);
        *++argv = "chat";
        execve("/usr/bin/chat", argv, envp);
        err(1, "chat");
}

$ gcc a.c -lutil

3. Run shell command
	./a.out 127.0.0.1 -e 'User' xxx 'Password:' xxxxxxxxxx '$' exit '$' exit

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Trying SRA secure login:
User (root): Password: 
[ SRA accepts you ]

FreeBSD/i386 (swp.pp.ru) (ttypm)

Last login: Sat Apr 18 15:11:52 from localhost
Copyright (c) 1992-2009 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
^IThe Regents of the University of California. All rights reserved.

FreeBSD 7.1-STABLE (kernconf-freebsd7-20081220-2) #1: Sat Jan 10 16:45:33 NOVT 2009

Welcome to FreeBSD!

Before seeking technical support, please use the following resources:

o  Security advisories and updated errata information for all releases are
   at http://www.FreeBSD.org/releases/ - always consult the ERRATA section
   for your release first as it's updated frequently.

o  The Handbook and FAQ documents are at http://www.FreeBSD.org/ and,
   along with the mailing lists, can be searched by going to
   http://www.FreeBSD.org/search/.  If the doc distribution has
   been installed, they're also available formatted in /usr/share/doc.

If you still have a question or problem, please take the output of
`uname -a', along with any relevant error messages, and email it
as a question to the questions@FreeBSD.org mailing list.  If you are
unfamiliar with FreeBSD's directory layout, please refer to the hier(7)
manual page.  If you are not familiar with manual pages, type `man man'.

You may also use sysinstall(8) to re-enter the installation and
configuration utility.  Edit /etc/motd to change this login announcement.

You have new mail.
Need to see the calendar for this month? Simply type "cal".  To see the
whole year, type "cal -y".
^I^I-- Dru <genesis@istar.ca>
[swp@swp ~]$ exit
logout
Connection closed by foreign host.
load: 0.46  cmd: chat 56662 [runnable] 1.55u 0.80s 3% 5236k
load: 0.46  cmd: chat 56662 [runnable] 1.63u 0.83s 3% 5448k
load: 0.46  cmd: chat 56662 [runnable] 1.70u 0.89s 3% 5664k
load: 0.46  cmd: chat 56662 [runnable] 1.76u 0.91s 3% 5836k
load: 0.46  cmd: chat 56662 [runnable] 1.85u 0.94s 3% 6052k
load: 0.46  cmd: chat 56662 [runnable] 1.91u 0.99s 3% 6264k
load: 0.46  cmd: chat 56662 [runnable] 1.98u 1.04s 3% 6480k
^\Quit (core dumped)

>Fix:
$ gdb /usr/bin/chat chat.core 
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-marcel-freebsd"...
Core was generated by `chat'.
Program terminated with signal 3, Quit.
Reading symbols from /lib/libc.so.7...done.
Loaded symbols for /lib/libc.so.7
Reading symbols from /libexec/ld-elf.so.1...done.
oaded symbols for /libexec/ld-elf.so.1
#0  0x4813e0e7 in sendto () from /lib/libc.so.7
n sendto () from /lib/libc.so.7
#1  0x4813ccee in send () from /lib/libc.so.7
#2  0x48137eb7 in vsyslog () from /lib/libc.so.7
#3  0x48137b9e in syslog () from /lib/libc.so.7
#4  0x08049433 in fatal (code=2, fmt=0x804bb40 "Can't restore terminal parameters: %m") at /usr/src/usr.bin/chat/chat.c:429
#5  0x08049832 in terminate (status=2) at /usr/src/usr.bin/chat/chat.c:544
#6  0x08049464 in fatal (code=2, fmt=0x804bb40 "Can't restore terminal parameters: %m") at /usr/src/usr.bin/chat/chat.c:432
#7  0x08049832 in terminate (status=2) at /usr/src/usr.bin/chat/chat.c:544
#8  0x08049464 in fatal (code=2, fmt=0x804bb40 "Can't restore terminal parameters: %m") at /usr/src/usr.bin/chat/chat.c:432
#9  0x08049832 in terminate (status=2) at /usr/src/usr.bin/chat/chat.c:544
...


chat.c
...
/*
 *      Print an error message and terminate.
 */

void
fatal(int code, const char *fmt, ...)
{
    va_list args;

    va_start(args, fmt);
    vfmtmsg(line, sizeof(line), fmt, args);
    if (to_log)
        syslog(LOG_ERR, "%s", line);
    if (to_stderr)
        fprintf(stderr, "%s\n", line);
    terminate(code);
}
...
void terminate(int status)
{
    echo_stderr(-1);
    if (report_file != (char *) 0 && report_fp != (FILE *) NULL) {
/*
 * Allow the last of the report string to be gathered before we terminate.
 */
        if (report_gathering) {
            int c;
            size_t rep_len;

            rep_len = strlen(report_buffer);
            while (rep_len + 1 <= sizeof(report_buffer)) {
                alarm(1);
                c = get_char();
                alarm(0);
                if (c < 0 || iscntrl(c))
                    break;
                report_buffer[rep_len] = c;
                ++rep_len;
            }
            report_buffer[rep_len] = 0;
            fprintf (report_fp, "chat:  %s\n", report_buffer);
        }
        if (verbose)
            fprintf (report_fp, "Closing \"%s\".\n", report_file);
        fclose (report_fp);
        report_fp = (FILE *) NULL;
    }

#if defined(get_term_param)
    if (have_tty_parameters) {
        if (set_term_param (&saved_tty_parameters) < 0)
            fatal(2, "Can't restore terminal parameters: %m");
    }
#endif

    exit(status);
}
...


small fix

Index: chat.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/chat/chat.c,v
retrieving revision 1.21.20.1
diff -u -r1.21.20.1 chat.c
--- chat.c      10 Apr 2008 22:43:25 -0000      1.21.20.1
+++ chat.c      18 Apr 2009 08:32:52 -0000
@@ -431,6 +431,18 @@
        fprintf(stderr, "%s\n", line);
     terminate(code);
 }
+void
+fatalmsg(const char *fmt, ...)
+{
+    va_list args;
+
+    va_start(args, fmt);
+    vfmtmsg(line, sizeof(line), fmt, args);
+    if (to_log)
+       syslog(LOG_ERR, "%s", line);
+    if (to_stderr)
+       fprintf(stderr, "%s\n", line);
+}
 
 int alarmed = 0;
 
@@ -540,8 +552,10 @@
 
 #if defined(get_term_param)
     if (have_tty_parameters) {
-       if (set_term_param (&saved_tty_parameters) < 0)
-           fatal(2, "Can't restore terminal parameters: %m");
+       if (set_term_param (&saved_tty_parameters) < 0) {
+           fatalmsg("Can't restore terminal parameters: %m");
+           status = 2;
+       }
     }
 #endif
 
/swp
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200904180835.n3I8ZWEP056827>