Commit 1d2ddcfb authored by Jeff Dike's avatar Jeff Dike Committed by Linus Torvalds

[PATCH] uml: close TUN/TAP file descriptors

When UML opens a TUN/TAP device, the file descriptor could be copied into
later, long-lived threads, holding the device open even after the interface is
taken down, preventing it from being brought up again.  This patch makes these
descriptors close-on-exec so that they disappear from helper processes, and
adds CLONE_FILES to a UML helper thread so that the descriptors are closed in
the thread when they are closed elsewhere in UML.
Signed-off-by: default avatarJeff Dike <jdike@addtoit.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent fbd55779
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <termios.h> #include <termios.h>
#include <string.h> #include <string.h>
#include <signal.h> #include <signal.h>
#include <sched.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/socket.h> #include <sys/socket.h>
...@@ -73,7 +74,6 @@ static void winch_handler(int sig) ...@@ -73,7 +74,6 @@ static void winch_handler(int sig)
struct winch_data { struct winch_data {
int pty_fd; int pty_fd;
int pipe_fd; int pipe_fd;
int close_me;
}; };
static int winch_thread(void *arg) static int winch_thread(void *arg)
...@@ -84,7 +84,6 @@ static int winch_thread(void *arg) ...@@ -84,7 +84,6 @@ static int winch_thread(void *arg)
int count, err; int count, err;
char c = 1; char c = 1;
os_close_file(data->close_me);
pty_fd = data->pty_fd; pty_fd = data->pty_fd;
pipe_fd = data->pipe_fd; pipe_fd = data->pipe_fd;
count = os_write_file(pipe_fd, &c, sizeof(c)); count = os_write_file(pipe_fd, &c, sizeof(c));
...@@ -153,15 +152,16 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out) ...@@ -153,15 +152,16 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out)
} }
data = ((struct winch_data) { .pty_fd = fd, data = ((struct winch_data) { .pty_fd = fd,
.pipe_fd = fds[1], .pipe_fd = fds[1] } );
.close_me = fds[0] } ); /* CLONE_FILES so this thread doesn't hold open files which are open
err = run_helper_thread(winch_thread, &data, 0, &stack, 0); * now, but later closed. This is a problem with /dev/net/tun.
*/
err = run_helper_thread(winch_thread, &data, CLONE_FILES, &stack, 0);
if(err < 0){ if(err < 0){
printk("fork of winch_thread failed - errno = %d\n", errno); printk("fork of winch_thread failed - errno = %d\n", errno);
goto out_close; goto out_close;
} }
os_close_file(fds[1]);
*fd_out = fds[0]; *fd_out = fds[0];
n = os_read_file(fds[0], &c, sizeof(c)); n = os_read_file(fds[0], &c, sizeof(c));
if(n != sizeof(c)){ if(n != sizeof(c)){
...@@ -169,13 +169,12 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out) ...@@ -169,13 +169,12 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out)
printk("read failed, err = %d\n", -n); printk("read failed, err = %d\n", -n);
printk("fd %d will not support SIGWINCH\n", fd); printk("fd %d will not support SIGWINCH\n", fd);
err = -EINVAL; err = -EINVAL;
goto out_close1; goto out_close;
} }
return err ; return err ;
out_close: out_close:
os_close_file(fds[1]); os_close_file(fds[1]);
out_close1:
os_close_file(fds[0]); os_close_file(fds[0]);
out: out:
return err; return err;
......
...@@ -122,6 +122,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, ...@@ -122,6 +122,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
return(-EINVAL); return(-EINVAL);
} }
*fd_out = ((int *) CMSG_DATA(cmsg))[0]; *fd_out = ((int *) CMSG_DATA(cmsg))[0];
os_set_exec_close(*fd_out, 1);
return(0); return(0);
} }
...@@ -137,7 +138,8 @@ static int tuntap_open(void *data) ...@@ -137,7 +138,8 @@ static int tuntap_open(void *data)
return(err); return(err);
if(pri->fixed_config){ if(pri->fixed_config){
pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0); pri->fd = os_open_file("/dev/net/tun",
of_cloexec(of_rdwr(OPENFLAGS())), 0);
if(pri->fd < 0){ if(pri->fd < 0){
printk("Failed to open /dev/net/tun, err = %d\n", printk("Failed to open /dev/net/tun, err = %d\n",
-pri->fd); -pri->fd);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment