Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 15 May 2001 23:03:54 -0700
From:      "Brian O'Shea" <boshea@ricochet.net>
To:        Matthew Emmerton <matt@gsicomp.on.ca>
Cc:        John Indra <john@office.naver.co.id>, freebsd-questions@FreeBSD.ORG, freebsd-current@FreeBSD.ORG
Subject:   Re: My network is dead because of this program :(
Message-ID:  <20010515230354.A62767@shaolin.hq.netapp.com>
In-Reply-To: <00b401c0ddb2$23b2c710$1200a8c0@gsicomp.on.ca>; from matt@gsicomp.on.ca on Tue, May 15, 2001 at 10:44:32PM -0400
References:  <20010516092035.A79109@office.naver.co.id> <00b401c0ddb2$23b2c710$1200a8c0@gsicomp.on.ca>

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

--3uo+9/B/ebqu+fSQ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Tue, May 15, 2001 at 10:44:32PM -0400, Matthew Emmerton wrote:
[...]
> > After going to single user mode, cause I can't kill the offending
> > program once it is running in multiuser mode (even kill -9 won't
> > work ...

Probably because the program is forking and you can't kill it's children
fast enough.

> > Can anyone help me trace what the program does? And how can I
> > prevent the program to DoS my network interface? Even when the
> > program is started by unprivileged user, it works, it DoS my network
> > interface. Is this a bug?
[...]

Unfortunately it looks like the program forks, does it's thing, and then
each child forks too.  There is a call to sleep probably to introduce a
delay so that things don't go completely crazy right away, but processes
build up exponentially with each child process forking, so eventually
resources get exhausted.  Take a look at the attachment for more
details.

-brian

-- 
Brian O'Shea
<boshea@ricochet.net>

--3uo+9/B/ebqu+fSQ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="x.disasm"

It looks like the program basically does this, in pseudo-code:

main()
{
    int      pid;

    while (1) {
        pid = fork();

        if (pid == 0) {     /* child process */
            socketpair();   /* get two AF_LOCAL sockets */

            setsockopt();   /* set receive buffer size on one socket */
            setsockopt();   /* set send buffer size on other socket */

            fcntl();        /* set non-blocking I/O on both sockets */
            fcntl();

            write();        /* write some data from one socket to the other */
            write();
        }

        /* else we're in the parent, or fork() failed */

        sleep();            /* sleep a while */
    }

    return;
}



(gdb) disassemble main
Dump of assembler code for function main:
0x804865c <main>:	push   %ebp
0x804865d <main+1>:	mov    %esp,%ebp
0x804865f <main+3>:	sub    $0x32018,%esp
0x8048665 <main+9>:	nop    


We're probably in an infinite loop here.

0x8048666 <main+10>:	movl   $0x0,0xfffffff4(%ebp)
0x804866d <main+17>:	lea    0x0(%esi),%esi
0x8048670 <main+20>:	cmpl   $0x12,0xfffffff4(%ebp)
0x8048674 <main+24>:	jle    0x8048678 <main+28>
0x8048676 <main+26>:	jmp    0x8048690 <main+52>


The first thing we do in the loop is call fork().

0x8048678 <main+28>:	call   0x80484c0 <fork>


Then we check its return value.

0x804867d <main+33>:	mov    %eax,%eax
0x804867f <main+35>:	test   %eax,%eax
0x8048681 <main+37>:	je     0x8048688 <main+44>
0x8048683 <main+39>:	jmp    0x8048690 <main+52>
0x8048685 <main+41>:	lea    0x0(%esi),%esi


It looks like the parent calls fork in a loop.  The child processes that
it creates continue.

0x8048688 <main+44>:	incl   0xfffffff4(%ebp)
0x804868b <main+47>:	jmp    0x8048670 <main+20>
0x804868d <main+49>:	lea    0x0(%esi),%esi
0x8048690 <main+52>:	add    $0xfffffff4,%esp


Sleep for 5 seconds ...

0x8048693 <main+55>:	push   $0x5
0x8048695 <main+57>:	call   0x8048490 <sleep>
0x804869a <main+62>:	add    $0x10,%esp



0x804869d <main+65>:	lea    0x0(%esi),%esi
0x80486a0 <main+68>:	jmp    0x80486a8 <main+76>
0x80486a2 <main+70>:	jmp    0x80487ac <main+336>
0x80486a7 <main+75>:	nop    


Child calls socketpair with the following arguments:

    int socketpair(int domain, int type, int protocol, int *sv)
    int      domain   = 0x1     (AF_LOCAL)
    int      type     = 0x1     (SOCK_STREAM)
    int      protocol = 0x0     (typically 0 for AF_LOCAL)
    int     *sv       = address of an array of two file descriptors


Push arguments to socketpair onto stack and call socketpair again:

0x80486a8 <main+76>:	lea    0xfffffff8(%ebp),%eax
0x80486ab <main+79>:	push   %eax
0x80486ac <main+80>:	push   $0x0
0x80486ae <main+82>:	push   $0x1
0x80486b0 <main+84>:	push   $0x1
0x80486b2 <main+86>:	call   0x80484e0 <socketpair>
0x80486b7 <main+91>:	add    $0x10,%esp
0x80486ba <main+94>:	mov    %eax,%eax

Note: It's strange that the address family is AF_LOCAL.  I wouldn't think
this would cause the problems that you are seeing with the xl0 device,
unless AF_LOCAL sockets consume some of the same resources that this driver
also consumes, and thus starves it of those resources.  I don't know enough
about FreeBSD to tell.


Looks like we're checking the return value of socketpair.
The value 0xffffffff is -1, which is what socketpair returns if it fails.

0x80486bc <main+96>:	cmp    $0xffffffff,%eax

0x80486bf <main+99>:	jne    0x80486c8 <main+108>
0x80486c1 <main+101>:	jmp    0x80487ac <main+336>

If it fails, jumps ahead to a call to pause (below at main+336)


0x80486c6 <main+106>:	mov    %esi,%esi
0x80486c8 <main+108>:	movl   $0x32000,0xfffffff4(%ebp)
0x80486cf <main+115>:	add    $0xfffffff4,%esp


Push arguments to setsockopt onto stack and call setsockopt:

0x80486d2 <main+118>:	push   $0x4
0x80486d4 <main+120>:	lea    0xfffffff4(%ebp),%eax
0x80486d7 <main+123>:	push   %eax
0x80486d8 <main+124>:	push   $0x1002
0x80486dd <main+129>:	push   $0xffff
0x80486e2 <main+134>:	mov    0xfffffff8(%ebp),%eax
0x80486e5 <main+137>:	push   %eax
0x80486e6 <main+138>:	call   0x80484b0 <setsockopt>

    int setsockopt(
        int          s,         /* socket descriptor */
        int          level,     /* 0xffff (SOL_SOCKET) */
        int          optname,   /* 0x1002 (SO_RCVBUF) */
        void        *optval,    /* pointer to a buffer containing optval */
        socklen_t   *optlen     /* pointer to buffer length */
    )


Pop arguments to first setsockopt call off stack.

0x80486eb <main+143>:	add    $0x20,%esp
0x80486ee <main+146>:	add    $0xfffffff4,%esp


Same thing, this time with optname 0x1001 (SO_SNDBUF).

0x80486f1 <main+149>:	push   $0x4
0x80486f3 <main+151>:	lea    0xfffffff4(%ebp),%eax
0x80486f6 <main+154>:	push   %eax
0x80486f7 <main+155>:	push   $0x1001
0x80486fc <main+160>:	push   $0xffff
0x8048701 <main+165>:	mov    0xfffffff8(%ebp),%eax
0x8048704 <main+168>:	push   %eax
0x8048705 <main+169>:	call   0x80484b0 <setsockopt>


0x804870a <main+174>:	add    $0x20,%esp
0x804870d <main+177>:	add    $0xfffffff4,%esp

Pop arguments to second setsockopt call off stack.


Probably the same call to setsockopt follows, except for the other socket
in the socketpair.

0x8048710 <main+180>:	push   $0x4
0x8048712 <main+182>:	lea    0xfffffff4(%ebp),%eax
0x8048715 <main+185>:	push   %eax
0x8048716 <main+186>:	push   $0x1002
0x804871b <main+191>:	push   $0xffff
0x8048720 <main+196>:	mov    0xfffffffc(%ebp),%eax
0x8048723 <main+199>:	push   %eax
0x8048724 <main+200>:	call   0x80484b0 <setsockopt>
0x8048729 <main+205>:	add    $0x20,%esp
0x804872c <main+208>:	add    $0xfffffff4,%esp
0x804872f <main+211>:	push   $0x4
0x8048731 <main+213>:	lea    0xfffffff4(%ebp),%eax
0x8048734 <main+216>:	push   %eax
0x8048735 <main+217>:	push   $0x1001
0x804873a <main+222>:	push   $0xffff
0x804873f <main+227>:	mov    0xfffffffc(%ebp),%eax
0x8048742 <main+230>:	push   %eax
0x8048743 <main+231>:	call   0x80484b0 <setsockopt>



0x8048748 <main+236>:	add    $0x20,%esp
0x804874b <main+239>:	add    $0xfffffffc,%esp
0x804874e <main+242>:	push   $0x4
0x8048750 <main+244>:	push   $0x4
0x8048752 <main+246>:	mov    0xfffffff8(%ebp),%eax
0x8048755 <main+249>:	push   %eax
0x8048756 <main+250>:	call   0x8048500 <fcntl>

     fcntl(
        int      fd,        /* socket descriptor */
        int      cmd,       /* 0x4 (O_NONBLOCK) */
        ...
    )

Puts the socket into non-blocking I/O mode.

0x804875b <main+255>:	add    $0x10,%esp
0x804875e <main+258>:	add    $0xfffffffc,%esp

Pop pop...


Same thing for other socket.

0x8048761 <main+261>:	push   $0x4
0x8048763 <main+263>:	push   $0x4
0x8048765 <main+265>:	mov    0xfffffffc(%ebp),%eax
0x8048768 <main+268>:	push   %eax
0x8048769 <main+269>:	call   0x8048500 <fcntl>

     fcntl(
        int      fd,        
        int      cmd,       
        ...
    )


0x804876e <main+274>:	add    $0x10,%esp
0x8048771 <main+277>:	add    $0xfffffffc,%esp



Push arguments to write onto stack.

0x8048774 <main+280>:	push   $0x32000
0x8048779 <main+285>:	lea    0xfffcdff4(%ebp),%eax
0x804877f <main+291>:	push   %eax
0x8048780 <main+292>:	mov    0xfffffff8(%ebp),%eax
0x8048783 <main+295>:	push   %eax
0x8048784 <main+296>:	call   0x80484a0 <write>

0x8048789 <main+301>:	add    $0x10,%esp
0x804878c <main+304>:	add    $0xfffffffc,%esp

    write(
        int         d,          /* socket descriptor */
        const void *buf,        /* buffer to write */
        size_t      nbytes      /* number of bytes to write (204800) */
    )


Call write again.

0x804878f <main+307>:	push   $0x32000
0x8048794 <main+312>:	lea    0xfffcdff4(%ebp),%eax
0x804879a <main+318>:	push   %eax
0x804879b <main+319>:	mov    0xfffffffc(%ebp),%eax
0x804879e <main+322>:	push   %eax
0x804879f <main+323>:	call   0x80484a0 <write>

0x80487a4 <main+328>:	add    $0x10,%esp



0x80487a7 <main+331>:	jmp    0x80486a0 <main+68>
0x80487ac <main+336>:	call   0x8048480 <pause>
0x80487b1 <main+341>:	xor    %eax,%eax
0x80487b3 <main+343>:	jmp    0x80487b8 <main+348>
0x80487b5 <main+345>:	lea    0x0(%esi),%esi
0x80487b8 <main+348>:	leave  
0x80487b9 <main+349>:	ret    
0x80487ba <main+350>:	nop    
0x80487bb <main+351>:	nop    
End of assembler dump.
(gdb) quit

--3uo+9/B/ebqu+fSQ--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-questions" in the body of the message




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