On Wed, Apr 06, 2011 at 02:53:46PM -0700, Kees Cook wrote:
> On Wed, Apr 06, 2011 at 05:35:07PM -0400, Scott Kitterman wrote:
> > He offers this as a test case:
> 
> I can confirm the behavior difference between maverick and natty by doing
> this:
> 
> while ./testcase.pl ; do echo -n . ; done
> 
> On maverick, this runs forever. Natty immediately fails:
> 
> Parent 792
> 
> Child 793
> .bind: Address already in use at ./testcase.pl line 9.
> 
> 
> I hope this is a Net::Server delta and not a kernel delta.

This looks like a kernel bug to me. I can reproduce it with C as well.

$ ./testcase
parent: 3781
before:
tcp        0      0 0.0.0.0:12345           0.0.0.0:*               LISTEN     
after:
child: 3786

$ ./testcase
bind: Address already in use

$ kill 3786

$ ./testcase
parent: 3810
before:
tcp        0      0 0.0.0.0:12345           0.0.0.0:*               LISTEN     
after:
child: 3817

:(

-- 
Kees Cook
Ubuntu Security Team
/* Author: Kees Cook <[email protected]>
 * Copyright 2011 Canonical, Ltd
 * License: GPLv2
 */
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <stdint.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
#include <netinet/in.h>

#define PORT 12345

int main(int argc, char * argv[])
{
    struct sigaction reaper;
    struct protoent *proto;
    struct sockaddr_in saddr;
    int server, on=1;
    char cmd[80];

    if (!(proto=getprotobyname("tcp"))) {
        perror("getprotobyname");
        return 1;
    }
    if ((server = socket(PF_INET, SOCK_STREAM, proto->p_proto))<0) {
        perror("socket");
        return 1;
    }
    if (setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
        perror("setsockopt");
        return 1;
    }

    memset(&saddr, 0, sizeof(saddr));
    saddr.sin_family      = AF_INET;
    saddr.sin_addr.s_addr = htonl(INADDR_ANY);
    saddr.sin_port        = htons(PORT);

    if (bind(server, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
        perror("bind");
        return 1;
    }
    if (listen(server,5)<0) {
        perror("listen");
        return 1;
    }


    printf("parent: %d\n", getpid());

    printf("before:\n");
    sprintf(cmd, "netstat -an | grep :%d", PORT);
    system(cmd);

    int pid = fork();
    if (pid == 0) {
        printf("child: %d\n", getpid());
        sleep(100);
        exit(0);
    }
    shutdown(server, SHUT_RDWR);

    printf("after:\n");
    system(cmd);

    return 0;
}
-- 
ubuntu-devel mailing list
[email protected]
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/ubuntu-devel

Reply via email to