diff options
author | Jeff Dike <jdike@addtoit.com> | 2006-02-07 15:58:41 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-07 19:12:32 -0500 |
commit | 1d2ddcfb1935c9c0e98c4295458b01f24e3274f9 (patch) | |
tree | 94bc4ad32840430b22e22057dbf8deb70e72492a | |
parent | fbd5577901388ff9306a05eb63648c30e4722134 (diff) |
[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: Jeff Dike <jdike@addtoit.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/um/drivers/chan_user.c | 15 | ||||
-rw-r--r-- | arch/um/os-Linux/drivers/tuntap_user.c | 4 |
2 files changed, 10 insertions, 9 deletions
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 5d50d4a44abf..2f880cb167a5 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <termios.h> | 9 | #include <termios.h> |
10 | #include <string.h> | 10 | #include <string.h> |
11 | #include <signal.h> | 11 | #include <signal.h> |
12 | #include <sched.h> | ||
12 | #include <sys/stat.h> | 13 | #include <sys/stat.h> |
13 | #include <sys/ioctl.h> | 14 | #include <sys/ioctl.h> |
14 | #include <sys/socket.h> | 15 | #include <sys/socket.h> |
@@ -73,7 +74,6 @@ static void winch_handler(int sig) | |||
73 | struct winch_data { | 74 | struct winch_data { |
74 | int pty_fd; | 75 | int pty_fd; |
75 | int pipe_fd; | 76 | int pipe_fd; |
76 | int close_me; | ||
77 | }; | 77 | }; |
78 | 78 | ||
79 | static int winch_thread(void *arg) | 79 | static int winch_thread(void *arg) |
@@ -84,7 +84,6 @@ static int winch_thread(void *arg) | |||
84 | int count, err; | 84 | int count, err; |
85 | char c = 1; | 85 | char c = 1; |
86 | 86 | ||
87 | os_close_file(data->close_me); | ||
88 | pty_fd = data->pty_fd; | 87 | pty_fd = data->pty_fd; |
89 | pipe_fd = data->pipe_fd; | 88 | pipe_fd = data->pipe_fd; |
90 | count = os_write_file(pipe_fd, &c, sizeof(c)); | 89 | 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 | } | 152 | } |
154 | 153 | ||
155 | data = ((struct winch_data) { .pty_fd = fd, | 154 | data = ((struct winch_data) { .pty_fd = fd, |
156 | .pipe_fd = fds[1], | 155 | .pipe_fd = fds[1] } ); |
157 | .close_me = fds[0] } ); | 156 | /* CLONE_FILES so this thread doesn't hold open files which are open |
158 | err = run_helper_thread(winch_thread, &data, 0, &stack, 0); | 157 | * now, but later closed. This is a problem with /dev/net/tun. |
158 | */ | ||
159 | err = run_helper_thread(winch_thread, &data, CLONE_FILES, &stack, 0); | ||
159 | if(err < 0){ | 160 | if(err < 0){ |
160 | printk("fork of winch_thread failed - errno = %d\n", errno); | 161 | printk("fork of winch_thread failed - errno = %d\n", errno); |
161 | goto out_close; | 162 | goto out_close; |
162 | } | 163 | } |
163 | 164 | ||
164 | os_close_file(fds[1]); | ||
165 | *fd_out = fds[0]; | 165 | *fd_out = fds[0]; |
166 | n = os_read_file(fds[0], &c, sizeof(c)); | 166 | n = os_read_file(fds[0], &c, sizeof(c)); |
167 | if(n != sizeof(c)){ | 167 | if(n != sizeof(c)){ |
@@ -169,13 +169,12 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out) | |||
169 | printk("read failed, err = %d\n", -n); | 169 | printk("read failed, err = %d\n", -n); |
170 | printk("fd %d will not support SIGWINCH\n", fd); | 170 | printk("fd %d will not support SIGWINCH\n", fd); |
171 | err = -EINVAL; | 171 | err = -EINVAL; |
172 | goto out_close1; | 172 | goto out_close; |
173 | } | 173 | } |
174 | return err ; | 174 | return err ; |
175 | 175 | ||
176 | out_close: | 176 | out_close: |
177 | os_close_file(fds[1]); | 177 | os_close_file(fds[1]); |
178 | out_close1: | ||
179 | os_close_file(fds[0]); | 178 | os_close_file(fds[0]); |
180 | out: | 179 | out: |
181 | return err; | 180 | return err; |
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index 52945338b64d..87c3aa0252db 100644 --- a/arch/um/os-Linux/drivers/tuntap_user.c +++ b/arch/um/os-Linux/drivers/tuntap_user.c | |||
@@ -122,6 +122,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, | |||
122 | return(-EINVAL); | 122 | return(-EINVAL); |
123 | } | 123 | } |
124 | *fd_out = ((int *) CMSG_DATA(cmsg))[0]; | 124 | *fd_out = ((int *) CMSG_DATA(cmsg))[0]; |
125 | os_set_exec_close(*fd_out, 1); | ||
125 | return(0); | 126 | return(0); |
126 | } | 127 | } |
127 | 128 | ||
@@ -137,7 +138,8 @@ static int tuntap_open(void *data) | |||
137 | return(err); | 138 | return(err); |
138 | 139 | ||
139 | if(pri->fixed_config){ | 140 | if(pri->fixed_config){ |
140 | pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0); | 141 | pri->fd = os_open_file("/dev/net/tun", |
142 | of_cloexec(of_rdwr(OPENFLAGS())), 0); | ||
141 | if(pri->fd < 0){ | 143 | if(pri->fd < 0){ |
142 | printk("Failed to open /dev/net/tun, err = %d\n", | 144 | printk("Failed to open /dev/net/tun, err = %d\n", |
143 | -pri->fd); | 145 | -pri->fd); |