Package: linux-image-3.2.0-2-amd64
Version: 3.2.16-1

Hi,

CLONE_NEWNET is still buggy (i found random reports with the same error message 
from 2010).

uname: Linux * 3.2.0-2-amd64 #1 SMP Mon Apr 30 05:20:23 UTC 2012 x86_64 
GNU/Linux

See the attached example.
I don't think it matters much how the socket is used: just create the socket
before the unshare and use it somehow - listen() after unshare() triggered it 
too.

The kernel starts spamming the message after the program is terminated.

Also the port is not reachable from the outside - although i admit i couldn't
find docs mentioning this is supported, but it really should be.
(Given that struct net is part of struct sock(common) this shouldn't be hard)

I could reproduce it in virtualbox with rescue mode from
http://cdimage.debian.org/cdimage/wheezy_di_alpha1/amd64/iso-cd/debian-wheezy-DI-a1-amd64-netinst.iso
- when i started it a second time the process would even hang for some time 
(not killable).

logs look like this:
[  796.444219] unregister_netdevice: waiting for lo to become free. Usage count 
= 2
[  806.684213] unregister_netdevice: waiting for lo to become free. Usage count 
= 2
[  816.924212] unregister_netdevice: waiting for lo to become free. Usage count 
= 2
[  827.164217] unregister_netdevice: waiting for lo to become free. Usage count 
= 2
[  837.408237] unregister_netdevice: waiting for lo to become free. Usage count 
= 2
[  847.648216] unregister_netdevice: waiting for lo to become free. Usage count 
= 2
[  857.888219] unregister_netdevice: waiting for lo to become free. Usage count 
= 2
[  868.128224] unregister_netdevice: waiting for lo to become free. Usage count 
= 2
[  878.368221] unregister_netdevice: waiting for lo to become free. Usage count 
= 2
[  888.608215] unregister_netdevice: waiting for lo to become free. Usage count 
= 2
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>

int main() {
	int listenfd, acceptfd, connectfd;
	struct sockaddr_in addr;
	socklen_t addrlen = sizeof(addr);
	
	puts("newnet + listen/connect test");
	
	if (-1 == (listenfd = socket(AF_INET, SOCK_STREAM, 0))) { perror("socket failed"); abort(); }
	
	if (0 != listen(listenfd, 1)) { perror("listen failed"); abort(); }
	
	if (0 != unshare(CLONE_NEWNET)) { perror("unshare failed"); abort(); }
	
	if (0 != getsockname(listenfd, (struct sockaddr*) &addr, &addrlen)) { perror("getsockname failed"); }
	
	if (-1 == (connectfd = socket(AF_INET, SOCK_STREAM, 0))) { perror("socket failed"); abort(); }
	if (0 == connect(connectfd, (struct sockaddr*) &addr, addrlen)) {
		puts("successful connect - something is wrong here");
	} else {
		perror("connect failed as expected");
	}
	close(connectfd);
	
	printf("listening on 0.0.0.0:%i\n", (int) addr.sin_port);
	
	if (-1 == (acceptfd = accept(listenfd, NULL, NULL))) { perror("accept failed"); abort(); }
	{
		char buf[1024];
		int len = read(acceptfd, buf, sizeof(buf)-1);
		if (len < 0) { perror("read failed"); abort(); }
		buf[len] = 0;
		
		printf("received: '%s'\n", buf);
		write(acceptfd, buf, len);
		close(acceptfd);
	}
	
	puts("done.");
}

Reply via email to