[Nagiosplug-devel] [ nagiosplug-Patches-1075725 ] PATCH for netutils.c (HEAD): fix SEGV when connect fails.

SourceForge.net noreply at sourceforge.net
Sun Dec 5 16:46:04 CET 2004


Patches item #1075725, was opened at 2004-11-30 02:34
Message generated for change (Comment added) made by stanleyhopcroft
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=397599&aid=1075725&group_id=29880

Category: Bugfix
Group: None
Status: Open
Resolution: None
Priority: 5
Submitted By: Stanley Hopcroft (stanleyhopcroft)
Assigned to: Benoit Mortier (opensides)
Summary: PATCH for netutils.c (HEAD): fix SEGV when connect fails.

Initial Comment:
The HEAD netutils SEGVs after a connect() fails when it
calls freeaddrinfo(res) on a null pointer.

eg 
pc09011> gdb -c check_tcp.core check_tcp
GNU gdb 4.18 (FreeBSD)
Copyright 1998 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-unknown-freebsd"...Deprecated bfd_read called at
/usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/dbxread.c
line 2627 in elfstab_build_psymtabs
Deprecated bfd_read called at
/usr/src/gnu/usr.bin/binutils/gdb/../../../../contrib/gdb/gdb/dbxread.c
line 933 in fill_symbuf

Core was generated by `check_tcp'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /usr/lib/libssl.so.3...done.
Reading symbols from /usr/lib/libcrypto.so.3...done.
Reading symbols from /usr/lib/libc.so.4...done.
Reading symbols from /usr/libexec/ld-elf.so.1...done.
#0  0x281e54bc in freeaddrinfo () from /usr/lib/libc.so.4
(gdb) bt
#0  0x281e54bc in freeaddrinfo () from /usr/lib/libc.so.4
#1  0x804afb8 in my_connect (host_name=0xbfbffc9d
"xena", port=993, sd=0x8053290, proto=6) at netutils.c:263
#2  0x804ae66 in my_tcp_connect (host_name=0xbfbffc9d
"xena", port=993, sd=0x8053290) at netutils.c:193
#3  0x804a8d2 in connect_SSL () at check_tcp.c:561
#4  0x8049e1b in main (argc=3, argv=0xbfbffba4) at
check_tcp.c:241
(gdb) 

Here is a patch.

Unless you tell me otherwise, I will commit it.

pc09011> diff -u netutils.c.orig netutils.c
--- netutils.c.orig     Tue Nov 30 13:15:18 2004
+++ netutils.c  Tue Nov 30 13:13:21 2004
@@ -213,7 +213,7 @@
 my_connect (const char *host_name, int port, int *sd,
int proto)
 {
        struct addrinfo hints;
-       struct addrinfo *res;
+       struct addrinfo *res, *res0;
        char port_str[6];
        int result;
 
@@ -223,13 +223,14 @@
        hints.ai_socktype = (proto == IPPROTO_UDP) ?
SOCK_DGRAM : SOCK_STREAM;
 
        snprintf (port_str, sizeof (port_str), "%d", port);
-       result = getaddrinfo (host_name, port_str,
&hints, &res);
+       result = getaddrinfo (host_name, port_str,
&hints, &res0);
 
        if (result != 0) {
                printf ("%s\n", gai_strerror (result));
                return STATE_UNKNOWN;
        }
        else {
+               res = res0;
                while (res) {
                        /* attempt to create a socket */
                        *sd = socket (res->ai_family,
(proto == IPPROTO_UDP) ?
@@ -260,7 +261,7 @@
                        close (*sd);
                        res = res->ai_next;
                }
-               freeaddrinfo (res);
+               freeaddrinfo (res0);
        }
 
        if (result == 0)

The problem is that the while (res) loop is _not_
exited after a connection failure but updates res with
res->ai_next  ((a NULL pointer eventually) and then
goes on to free it.

On this system (FreeBSD 4.10), errno is 61
(ECONNREFUSED) after the connection failure, ais it
should be but the break in the switch statement doesn't
cause the exit of the while loop before res is updated.

Here is a single step through it
(gdb) s
220             memset (&hints, 0, sizeof (hints));
(gdb) 
221             hints.ai_family = address_family;
(gdb) 
222             hints.ai_protocol = proto;
(gdb) 
223             hints.ai_socktype = (proto ==
IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
(gdb) 
225             snprintf (port_str, sizeof (port_str),
"%d", port);
(gdb) 
226             result = getaddrinfo (host_name,
port_str, &hints, &res);
(gdb) 
228             if (result != 0) {
(gdb) 
233                     while (res) {
(gdb) 
235                             *sd = socket
(res->ai_family, (proto == IPPROTO_UDP) ?
(gdb) 
238                             if (*sd < 0) {
(gdb) 
245                             result = connect (*sd,
res->ai_addr, res->ai_addrlen);
(gdb) 
247                             if (result == 0) {
(gdb) 
252                             if (result < 0) {
(gdb) 
253                                     switch (errno) {
(gdb) 
255                                            
was_refused = TRUE;
(gdb) 
260                             close (*sd);
(gdb) 
261                             res = res->ai_next;
(gdb) q
The program is running.  Exit anyway? (y or n) y
pc09011> 


To sum up, I am not convinced that the code is broken
(maybe a better way is adding another break near the
switch statement.

Your comments are welcome.









----------------------------------------------------------------------

>Comment By: Stanley Hopcroft (stanleyhopcroft)
Date: 2004-12-06 00:45

Message:
Logged In: YES 
user_id=395628

Patch applied to CVS.

Works Ok with FreeBSD and Linux 2.2.



----------------------------------------------------------------------

Comment By: Benoit Mortier (opensides)
Date: 2004-12-06 00:20

Message:
Logged In: YES 
user_id=388184

hi, 
 
can you attach your patch to this report thanks, i will look at it 
 
Bye 

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=397599&aid=1075725&group_id=29880




More information about the Devel mailing list