diff options
-rw-r--r-- | arch/alpha/kernel/osf_sys.c | 4 | ||||
-rw-r--r-- | arch/ia64/kernel/perfmon.c | 7 | ||||
-rw-r--r-- | arch/sparc64/solaris/ioctl.c | 8 | ||||
-rw-r--r-- | drivers/char/tty_io.c | 4 | ||||
-rw-r--r-- | fs/exec.c | 8 | ||||
-rw-r--r-- | fs/fcntl.c | 47 | ||||
-rw-r--r-- | fs/file.c | 42 | ||||
-rw-r--r-- | fs/locks.c | 8 | ||||
-rw-r--r-- | fs/open.c | 41 | ||||
-rw-r--r-- | fs/proc/array.c | 5 | ||||
-rw-r--r-- | fs/proc/base.c | 4 | ||||
-rw-r--r-- | fs/select.c | 12 | ||||
-rw-r--r-- | include/linux/file.h | 23 | ||||
-rw-r--r-- | include/linux/init_task.h | 13 | ||||
-rw-r--r-- | kernel/exit.c | 21 | ||||
-rw-r--r-- | kernel/fork.c | 82 | ||||
-rw-r--r-- | security/selinux/hooks.c | 6 |
17 files changed, 211 insertions, 124 deletions
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 167fd89f8707..2b034182a0ca 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c | |||
@@ -974,6 +974,7 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, | |||
974 | size_t size; | 974 | size_t size; |
975 | long timeout; | 975 | long timeout; |
976 | int ret = -EINVAL; | 976 | int ret = -EINVAL; |
977 | struct fdtable *fdt; | ||
977 | 978 | ||
978 | timeout = MAX_SCHEDULE_TIMEOUT; | 979 | timeout = MAX_SCHEDULE_TIMEOUT; |
979 | if (tvp) { | 980 | if (tvp) { |
@@ -995,7 +996,8 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, | |||
995 | } | 996 | } |
996 | } | 997 | } |
997 | 998 | ||
998 | if (n < 0 || n > current->files->max_fdset) | 999 | fdt = files_fdtable(current->files); |
1000 | if (n < 0 || n > fdt->max_fdset) | ||
999 | goto out_nofds; | 1001 | goto out_nofds; |
1000 | 1002 | ||
1001 | /* | 1003 | /* |
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index f1201ac8a116..4ad97b3b39dc 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/pagemap.h> | 38 | #include <linux/pagemap.h> |
39 | #include <linux/mount.h> | 39 | #include <linux/mount.h> |
40 | #include <linux/bitops.h> | 40 | #include <linux/bitops.h> |
41 | #include <linux/rcupdate.h> | ||
41 | 42 | ||
42 | #include <asm/errno.h> | 43 | #include <asm/errno.h> |
43 | #include <asm/intrinsics.h> | 44 | #include <asm/intrinsics.h> |
@@ -2217,15 +2218,17 @@ static void | |||
2217 | pfm_free_fd(int fd, struct file *file) | 2218 | pfm_free_fd(int fd, struct file *file) |
2218 | { | 2219 | { |
2219 | struct files_struct *files = current->files; | 2220 | struct files_struct *files = current->files; |
2221 | struct fdtable *fdt = files_fdtable(files); | ||
2220 | 2222 | ||
2221 | /* | 2223 | /* |
2222 | * there ie no fd_uninstall(), so we do it here | 2224 | * there ie no fd_uninstall(), so we do it here |
2223 | */ | 2225 | */ |
2224 | spin_lock(&files->file_lock); | 2226 | spin_lock(&files->file_lock); |
2225 | files->fd[fd] = NULL; | 2227 | rcu_assign_pointer(fdt->fd[fd], NULL); |
2226 | spin_unlock(&files->file_lock); | 2228 | spin_unlock(&files->file_lock); |
2227 | 2229 | ||
2228 | if (file) put_filp(file); | 2230 | if (file) |
2231 | put_filp(file); | ||
2229 | put_unused_fd(fd); | 2232 | put_unused_fd(fd); |
2230 | } | 2233 | } |
2231 | 2234 | ||
diff --git a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c index cac0a1cf0050..374766455f5e 100644 --- a/arch/sparc64/solaris/ioctl.c +++ b/arch/sparc64/solaris/ioctl.c | |||
@@ -293,11 +293,13 @@ static struct module_info { | |||
293 | static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg) | 293 | static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg) |
294 | { | 294 | { |
295 | struct inode *ino; | 295 | struct inode *ino; |
296 | struct fdtable *fdt; | ||
296 | /* I wonder which of these tests are superfluous... --patrik */ | 297 | /* I wonder which of these tests are superfluous... --patrik */ |
297 | spin_lock(¤t->files->file_lock); | 298 | spin_lock(¤t->files->file_lock); |
298 | if (! current->files->fd[fd] || | 299 | fdt = files_fdtable(current->files); |
299 | ! current->files->fd[fd]->f_dentry || | 300 | if (! fdt->fd[fd] || |
300 | ! (ino = current->files->fd[fd]->f_dentry->d_inode) || | 301 | ! fdt->fd[fd]->f_dentry || |
302 | ! (ino = fdt->fd[fd]->f_dentry->d_inode) || | ||
301 | ! S_ISSOCK(ino->i_mode)) { | 303 | ! S_ISSOCK(ino->i_mode)) { |
302 | spin_unlock(¤t->files->file_lock); | 304 | spin_unlock(¤t->files->file_lock); |
303 | return TBADF; | 305 | return TBADF; |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 6a56ae4f7725..0bfc7af68917 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -2454,6 +2454,7 @@ static void __do_SAK(void *arg) | |||
2454 | int i; | 2454 | int i; |
2455 | struct file *filp; | 2455 | struct file *filp; |
2456 | struct tty_ldisc *disc; | 2456 | struct tty_ldisc *disc; |
2457 | struct fdtable *fdt; | ||
2457 | 2458 | ||
2458 | if (!tty) | 2459 | if (!tty) |
2459 | return; | 2460 | return; |
@@ -2480,7 +2481,8 @@ static void __do_SAK(void *arg) | |||
2480 | task_lock(p); | 2481 | task_lock(p); |
2481 | if (p->files) { | 2482 | if (p->files) { |
2482 | spin_lock(&p->files->file_lock); | 2483 | spin_lock(&p->files->file_lock); |
2483 | for (i=0; i < p->files->max_fds; i++) { | 2484 | fdt = files_fdtable(p->files); |
2485 | for (i=0; i < fdt->max_fds; i++) { | ||
2484 | filp = fcheck_files(p->files, i); | 2486 | filp = fcheck_files(p->files, i); |
2485 | if (!filp) | 2487 | if (!filp) |
2486 | continue; | 2488 | continue; |
@@ -798,6 +798,7 @@ no_thread_group: | |||
798 | static inline void flush_old_files(struct files_struct * files) | 798 | static inline void flush_old_files(struct files_struct * files) |
799 | { | 799 | { |
800 | long j = -1; | 800 | long j = -1; |
801 | struct fdtable *fdt; | ||
801 | 802 | ||
802 | spin_lock(&files->file_lock); | 803 | spin_lock(&files->file_lock); |
803 | for (;;) { | 804 | for (;;) { |
@@ -805,12 +806,13 @@ static inline void flush_old_files(struct files_struct * files) | |||
805 | 806 | ||
806 | j++; | 807 | j++; |
807 | i = j * __NFDBITS; | 808 | i = j * __NFDBITS; |
808 | if (i >= files->max_fds || i >= files->max_fdset) | 809 | fdt = files_fdtable(files); |
810 | if (i >= fdt->max_fds || i >= fdt->max_fdset) | ||
809 | break; | 811 | break; |
810 | set = files->close_on_exec->fds_bits[j]; | 812 | set = fdt->close_on_exec->fds_bits[j]; |
811 | if (!set) | 813 | if (!set) |
812 | continue; | 814 | continue; |
813 | files->close_on_exec->fds_bits[j] = 0; | 815 | fdt->close_on_exec->fds_bits[j] = 0; |
814 | spin_unlock(&files->file_lock); | 816 | spin_unlock(&files->file_lock); |
815 | for ( ; set ; i++,set >>= 1) { | 817 | for ( ; set ; i++,set >>= 1) { |
816 | if (set & 1) { | 818 | if (set & 1) { |
diff --git a/fs/fcntl.c b/fs/fcntl.c index 6fbc9d8fcc36..bfecc6238083 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -24,20 +24,24 @@ | |||
24 | void fastcall set_close_on_exec(unsigned int fd, int flag) | 24 | void fastcall set_close_on_exec(unsigned int fd, int flag) |
25 | { | 25 | { |
26 | struct files_struct *files = current->files; | 26 | struct files_struct *files = current->files; |
27 | struct fdtable *fdt; | ||
27 | spin_lock(&files->file_lock); | 28 | spin_lock(&files->file_lock); |
29 | fdt = files_fdtable(files); | ||
28 | if (flag) | 30 | if (flag) |
29 | FD_SET(fd, files->close_on_exec); | 31 | FD_SET(fd, fdt->close_on_exec); |
30 | else | 32 | else |
31 | FD_CLR(fd, files->close_on_exec); | 33 | FD_CLR(fd, fdt->close_on_exec); |
32 | spin_unlock(&files->file_lock); | 34 | spin_unlock(&files->file_lock); |
33 | } | 35 | } |
34 | 36 | ||
35 | static inline int get_close_on_exec(unsigned int fd) | 37 | static inline int get_close_on_exec(unsigned int fd) |
36 | { | 38 | { |
37 | struct files_struct *files = current->files; | 39 | struct files_struct *files = current->files; |
40 | struct fdtable *fdt; | ||
38 | int res; | 41 | int res; |
39 | spin_lock(&files->file_lock); | 42 | spin_lock(&files->file_lock); |
40 | res = FD_ISSET(fd, files->close_on_exec); | 43 | fdt = files_fdtable(files); |
44 | res = FD_ISSET(fd, fdt->close_on_exec); | ||
41 | spin_unlock(&files->file_lock); | 45 | spin_unlock(&files->file_lock); |
42 | return res; | 46 | return res; |
43 | } | 47 | } |
@@ -54,24 +58,26 @@ static int locate_fd(struct files_struct *files, | |||
54 | unsigned int newfd; | 58 | unsigned int newfd; |
55 | unsigned int start; | 59 | unsigned int start; |
56 | int error; | 60 | int error; |
61 | struct fdtable *fdt; | ||
57 | 62 | ||
58 | error = -EINVAL; | 63 | error = -EINVAL; |
59 | if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) | 64 | if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) |
60 | goto out; | 65 | goto out; |
61 | 66 | ||
67 | fdt = files_fdtable(files); | ||
62 | repeat: | 68 | repeat: |
63 | /* | 69 | /* |
64 | * Someone might have closed fd's in the range | 70 | * Someone might have closed fd's in the range |
65 | * orig_start..files->next_fd | 71 | * orig_start..fdt->next_fd |
66 | */ | 72 | */ |
67 | start = orig_start; | 73 | start = orig_start; |
68 | if (start < files->next_fd) | 74 | if (start < fdt->next_fd) |
69 | start = files->next_fd; | 75 | start = fdt->next_fd; |
70 | 76 | ||
71 | newfd = start; | 77 | newfd = start; |
72 | if (start < files->max_fdset) { | 78 | if (start < fdt->max_fdset) { |
73 | newfd = find_next_zero_bit(files->open_fds->fds_bits, | 79 | newfd = find_next_zero_bit(fdt->open_fds->fds_bits, |
74 | files->max_fdset, start); | 80 | fdt->max_fdset, start); |
75 | } | 81 | } |
76 | 82 | ||
77 | error = -EMFILE; | 83 | error = -EMFILE; |
@@ -89,8 +95,8 @@ repeat: | |||
89 | if (error) | 95 | if (error) |
90 | goto repeat; | 96 | goto repeat; |
91 | 97 | ||
92 | if (start <= files->next_fd) | 98 | if (start <= fdt->next_fd) |
93 | files->next_fd = newfd + 1; | 99 | fdt->next_fd = newfd + 1; |
94 | 100 | ||
95 | error = newfd; | 101 | error = newfd; |
96 | 102 | ||
@@ -101,13 +107,16 @@ out: | |||
101 | static int dupfd(struct file *file, unsigned int start) | 107 | static int dupfd(struct file *file, unsigned int start) |
102 | { | 108 | { |
103 | struct files_struct * files = current->files; | 109 | struct files_struct * files = current->files; |
110 | struct fdtable *fdt; | ||
104 | int fd; | 111 | int fd; |
105 | 112 | ||
106 | spin_lock(&files->file_lock); | 113 | spin_lock(&files->file_lock); |
107 | fd = locate_fd(files, file, start); | 114 | fd = locate_fd(files, file, start); |
108 | if (fd >= 0) { | 115 | if (fd >= 0) { |
109 | FD_SET(fd, files->open_fds); | 116 | /* locate_fd() may have expanded fdtable, load the ptr */ |
110 | FD_CLR(fd, files->close_on_exec); | 117 | fdt = files_fdtable(files); |
118 | FD_SET(fd, fdt->open_fds); | ||
119 | FD_CLR(fd, fdt->close_on_exec); | ||
111 | spin_unlock(&files->file_lock); | 120 | spin_unlock(&files->file_lock); |
112 | fd_install(fd, file); | 121 | fd_install(fd, file); |
113 | } else { | 122 | } else { |
@@ -123,6 +132,7 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd) | |||
123 | int err = -EBADF; | 132 | int err = -EBADF; |
124 | struct file * file, *tofree; | 133 | struct file * file, *tofree; |
125 | struct files_struct * files = current->files; | 134 | struct files_struct * files = current->files; |
135 | struct fdtable *fdt; | ||
126 | 136 | ||
127 | spin_lock(&files->file_lock); | 137 | spin_lock(&files->file_lock); |
128 | if (!(file = fcheck(oldfd))) | 138 | if (!(file = fcheck(oldfd))) |
@@ -148,13 +158,14 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd) | |||
148 | 158 | ||
149 | /* Yes. It's a race. In user space. Nothing sane to do */ | 159 | /* Yes. It's a race. In user space. Nothing sane to do */ |
150 | err = -EBUSY; | 160 | err = -EBUSY; |
151 | tofree = files->fd[newfd]; | 161 | fdt = files_fdtable(files); |
152 | if (!tofree && FD_ISSET(newfd, files->open_fds)) | 162 | tofree = fdt->fd[newfd]; |
163 | if (!tofree && FD_ISSET(newfd, fdt->open_fds)) | ||
153 | goto out_fput; | 164 | goto out_fput; |
154 | 165 | ||
155 | files->fd[newfd] = file; | 166 | fdt->fd[newfd] = file; |
156 | FD_SET(newfd, files->open_fds); | 167 | FD_SET(newfd, fdt->open_fds); |
157 | FD_CLR(newfd, files->close_on_exec); | 168 | FD_CLR(newfd, fdt->close_on_exec); |
158 | spin_unlock(&files->file_lock); | 169 | spin_unlock(&files->file_lock); |
159 | 170 | ||
160 | if (tofree) | 171 | if (tofree) |
@@ -59,13 +59,15 @@ static int expand_fd_array(struct files_struct *files, int nr) | |||
59 | { | 59 | { |
60 | struct file **new_fds; | 60 | struct file **new_fds; |
61 | int error, nfds; | 61 | int error, nfds; |
62 | struct fdtable *fdt; | ||
62 | 63 | ||
63 | 64 | ||
64 | error = -EMFILE; | 65 | error = -EMFILE; |
65 | if (files->max_fds >= NR_OPEN || nr >= NR_OPEN) | 66 | fdt = files_fdtable(files); |
67 | if (fdt->max_fds >= NR_OPEN || nr >= NR_OPEN) | ||
66 | goto out; | 68 | goto out; |
67 | 69 | ||
68 | nfds = files->max_fds; | 70 | nfds = fdt->max_fds; |
69 | spin_unlock(&files->file_lock); | 71 | spin_unlock(&files->file_lock); |
70 | 72 | ||
71 | /* | 73 | /* |
@@ -95,13 +97,14 @@ static int expand_fd_array(struct files_struct *files, int nr) | |||
95 | goto out; | 97 | goto out; |
96 | 98 | ||
97 | /* Copy the existing array and install the new pointer */ | 99 | /* Copy the existing array and install the new pointer */ |
100 | fdt = files_fdtable(files); | ||
98 | 101 | ||
99 | if (nfds > files->max_fds) { | 102 | if (nfds > fdt->max_fds) { |
100 | struct file **old_fds; | 103 | struct file **old_fds; |
101 | int i; | 104 | int i; |
102 | 105 | ||
103 | old_fds = xchg(&files->fd, new_fds); | 106 | old_fds = xchg(&fdt->fd, new_fds); |
104 | i = xchg(&files->max_fds, nfds); | 107 | i = xchg(&fdt->max_fds, nfds); |
105 | 108 | ||
106 | /* Don't copy/clear the array if we are creating a new | 109 | /* Don't copy/clear the array if we are creating a new |
107 | fd array for fork() */ | 110 | fd array for fork() */ |
@@ -164,12 +167,14 @@ static int expand_fdset(struct files_struct *files, int nr) | |||
164 | { | 167 | { |
165 | fd_set *new_openset = NULL, *new_execset = NULL; | 168 | fd_set *new_openset = NULL, *new_execset = NULL; |
166 | int error, nfds = 0; | 169 | int error, nfds = 0; |
170 | struct fdtable *fdt; | ||
167 | 171 | ||
168 | error = -EMFILE; | 172 | error = -EMFILE; |
169 | if (files->max_fdset >= NR_OPEN || nr >= NR_OPEN) | 173 | fdt = files_fdtable(files); |
174 | if (fdt->max_fdset >= NR_OPEN || nr >= NR_OPEN) | ||
170 | goto out; | 175 | goto out; |
171 | 176 | ||
172 | nfds = files->max_fdset; | 177 | nfds = fdt->max_fdset; |
173 | spin_unlock(&files->file_lock); | 178 | spin_unlock(&files->file_lock); |
174 | 179 | ||
175 | /* Expand to the max in easy steps */ | 180 | /* Expand to the max in easy steps */ |
@@ -193,24 +198,25 @@ static int expand_fdset(struct files_struct *files, int nr) | |||
193 | error = 0; | 198 | error = 0; |
194 | 199 | ||
195 | /* Copy the existing tables and install the new pointers */ | 200 | /* Copy the existing tables and install the new pointers */ |
196 | if (nfds > files->max_fdset) { | 201 | fdt = files_fdtable(files); |
197 | int i = files->max_fdset / (sizeof(unsigned long) * 8); | 202 | if (nfds > fdt->max_fdset) { |
198 | int count = (nfds - files->max_fdset) / 8; | 203 | int i = fdt->max_fdset / (sizeof(unsigned long) * 8); |
204 | int count = (nfds - fdt->max_fdset) / 8; | ||
199 | 205 | ||
200 | /* | 206 | /* |
201 | * Don't copy the entire array if the current fdset is | 207 | * Don't copy the entire array if the current fdset is |
202 | * not yet initialised. | 208 | * not yet initialised. |
203 | */ | 209 | */ |
204 | if (i) { | 210 | if (i) { |
205 | memcpy (new_openset, files->open_fds, files->max_fdset/8); | 211 | memcpy (new_openset, fdt->open_fds, fdt->max_fdset/8); |
206 | memcpy (new_execset, files->close_on_exec, files->max_fdset/8); | 212 | memcpy (new_execset, fdt->close_on_exec, fdt->max_fdset/8); |
207 | memset (&new_openset->fds_bits[i], 0, count); | 213 | memset (&new_openset->fds_bits[i], 0, count); |
208 | memset (&new_execset->fds_bits[i], 0, count); | 214 | memset (&new_execset->fds_bits[i], 0, count); |
209 | } | 215 | } |
210 | 216 | ||
211 | nfds = xchg(&files->max_fdset, nfds); | 217 | nfds = xchg(&fdt->max_fdset, nfds); |
212 | new_openset = xchg(&files->open_fds, new_openset); | 218 | new_openset = xchg(&fdt->open_fds, new_openset); |
213 | new_execset = xchg(&files->close_on_exec, new_execset); | 219 | new_execset = xchg(&fdt->close_on_exec, new_execset); |
214 | spin_unlock(&files->file_lock); | 220 | spin_unlock(&files->file_lock); |
215 | free_fdset (new_openset, nfds); | 221 | free_fdset (new_openset, nfds); |
216 | free_fdset (new_execset, nfds); | 222 | free_fdset (new_execset, nfds); |
@@ -237,13 +243,15 @@ out: | |||
237 | int expand_files(struct files_struct *files, int nr) | 243 | int expand_files(struct files_struct *files, int nr) |
238 | { | 244 | { |
239 | int err, expand = 0; | 245 | int err, expand = 0; |
246 | struct fdtable *fdt; | ||
240 | 247 | ||
241 | if (nr >= files->max_fdset) { | 248 | fdt = files_fdtable(files); |
249 | if (nr >= fdt->max_fdset) { | ||
242 | expand = 1; | 250 | expand = 1; |
243 | if ((err = expand_fdset(files, nr))) | 251 | if ((err = expand_fdset(files, nr))) |
244 | goto out; | 252 | goto out; |
245 | } | 253 | } |
246 | if (nr >= files->max_fds) { | 254 | if (nr >= fdt->max_fds) { |
247 | expand = 1; | 255 | expand = 1; |
248 | if ((err = expand_fd_array(files, nr))) | 256 | if ((err = expand_fd_array(files, nr))) |
249 | goto out; | 257 | goto out; |
diff --git a/fs/locks.c b/fs/locks.c index 11956b6179ff..c2c09b4798d6 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -2198,21 +2198,23 @@ void steal_locks(fl_owner_t from) | |||
2198 | { | 2198 | { |
2199 | struct files_struct *files = current->files; | 2199 | struct files_struct *files = current->files; |
2200 | int i, j; | 2200 | int i, j; |
2201 | struct fdtable *fdt; | ||
2201 | 2202 | ||
2202 | if (from == files) | 2203 | if (from == files) |
2203 | return; | 2204 | return; |
2204 | 2205 | ||
2205 | lock_kernel(); | 2206 | lock_kernel(); |
2206 | j = 0; | 2207 | j = 0; |
2208 | fdt = files_fdtable(files); | ||
2207 | for (;;) { | 2209 | for (;;) { |
2208 | unsigned long set; | 2210 | unsigned long set; |
2209 | i = j * __NFDBITS; | 2211 | i = j * __NFDBITS; |
2210 | if (i >= files->max_fdset || i >= files->max_fds) | 2212 | if (i >= fdt->max_fdset || i >= fdt->max_fds) |
2211 | break; | 2213 | break; |
2212 | set = files->open_fds->fds_bits[j++]; | 2214 | set = fdt->open_fds->fds_bits[j++]; |
2213 | while (set) { | 2215 | while (set) { |
2214 | if (set & 1) { | 2216 | if (set & 1) { |
2215 | struct file *file = files->fd[i]; | 2217 | struct file *file = fdt->fd[i]; |
2216 | if (file) | 2218 | if (file) |
2217 | __steal_locks(file, from); | 2219 | __steal_locks(file, from); |
2218 | } | 2220 | } |
@@ -842,14 +842,16 @@ int get_unused_fd(void) | |||
842 | { | 842 | { |
843 | struct files_struct * files = current->files; | 843 | struct files_struct * files = current->files; |
844 | int fd, error; | 844 | int fd, error; |
845 | struct fdtable *fdt; | ||
845 | 846 | ||
846 | error = -EMFILE; | 847 | error = -EMFILE; |
847 | spin_lock(&files->file_lock); | 848 | spin_lock(&files->file_lock); |
848 | 849 | ||
849 | repeat: | 850 | repeat: |
850 | fd = find_next_zero_bit(files->open_fds->fds_bits, | 851 | fdt = files_fdtable(files); |
851 | files->max_fdset, | 852 | fd = find_next_zero_bit(fdt->open_fds->fds_bits, |
852 | files->next_fd); | 853 | fdt->max_fdset, |
854 | fdt->next_fd); | ||
853 | 855 | ||
854 | /* | 856 | /* |
855 | * N.B. For clone tasks sharing a files structure, this test | 857 | * N.B. For clone tasks sharing a files structure, this test |
@@ -872,14 +874,14 @@ repeat: | |||
872 | goto repeat; | 874 | goto repeat; |
873 | } | 875 | } |
874 | 876 | ||
875 | FD_SET(fd, files->open_fds); | 877 | FD_SET(fd, fdt->open_fds); |
876 | FD_CLR(fd, files->close_on_exec); | 878 | FD_CLR(fd, fdt->close_on_exec); |
877 | files->next_fd = fd + 1; | 879 | fdt->next_fd = fd + 1; |
878 | #if 1 | 880 | #if 1 |
879 | /* Sanity check */ | 881 | /* Sanity check */ |
880 | if (files->fd[fd] != NULL) { | 882 | if (fdt->fd[fd] != NULL) { |
881 | printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd); | 883 | printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd); |
882 | files->fd[fd] = NULL; | 884 | fdt->fd[fd] = NULL; |
883 | } | 885 | } |
884 | #endif | 886 | #endif |
885 | error = fd; | 887 | error = fd; |
@@ -893,9 +895,10 @@ EXPORT_SYMBOL(get_unused_fd); | |||
893 | 895 | ||
894 | static inline void __put_unused_fd(struct files_struct *files, unsigned int fd) | 896 | static inline void __put_unused_fd(struct files_struct *files, unsigned int fd) |
895 | { | 897 | { |
896 | __FD_CLR(fd, files->open_fds); | 898 | struct fdtable *fdt = files_fdtable(files); |
897 | if (fd < files->next_fd) | 899 | __FD_CLR(fd, fdt->open_fds); |
898 | files->next_fd = fd; | 900 | if (fd < fdt->next_fd) |
901 | fdt->next_fd = fd; | ||
899 | } | 902 | } |
900 | 903 | ||
901 | void fastcall put_unused_fd(unsigned int fd) | 904 | void fastcall put_unused_fd(unsigned int fd) |
@@ -924,10 +927,12 @@ EXPORT_SYMBOL(put_unused_fd); | |||
924 | void fastcall fd_install(unsigned int fd, struct file * file) | 927 | void fastcall fd_install(unsigned int fd, struct file * file) |
925 | { | 928 | { |
926 | struct files_struct *files = current->files; | 929 | struct files_struct *files = current->files; |
930 | struct fdtable *fdt; | ||
927 | spin_lock(&files->file_lock); | 931 | spin_lock(&files->file_lock); |
928 | if (unlikely(files->fd[fd] != NULL)) | 932 | fdt = files_fdtable(files); |
933 | if (unlikely(fdt->fd[fd] != NULL)) | ||
929 | BUG(); | 934 | BUG(); |
930 | files->fd[fd] = file; | 935 | fdt->fd[fd] = file; |
931 | spin_unlock(&files->file_lock); | 936 | spin_unlock(&files->file_lock); |
932 | } | 937 | } |
933 | 938 | ||
@@ -1010,15 +1015,17 @@ asmlinkage long sys_close(unsigned int fd) | |||
1010 | { | 1015 | { |
1011 | struct file * filp; | 1016 | struct file * filp; |
1012 | struct files_struct *files = current->files; | 1017 | struct files_struct *files = current->files; |
1018 | struct fdtable *fdt; | ||
1013 | 1019 | ||
1014 | spin_lock(&files->file_lock); | 1020 | spin_lock(&files->file_lock); |
1015 | if (fd >= files->max_fds) | 1021 | fdt = files_fdtable(files); |
1022 | if (fd >= fdt->max_fds) | ||
1016 | goto out_unlock; | 1023 | goto out_unlock; |
1017 | filp = files->fd[fd]; | 1024 | filp = fdt->fd[fd]; |
1018 | if (!filp) | 1025 | if (!filp) |
1019 | goto out_unlock; | 1026 | goto out_unlock; |
1020 | files->fd[fd] = NULL; | 1027 | fdt->fd[fd] = NULL; |
1021 | FD_CLR(fd, files->close_on_exec); | 1028 | FD_CLR(fd, fdt->close_on_exec); |
1022 | __put_unused_fd(files, fd); | 1029 | __put_unused_fd(files, fd); |
1023 | spin_unlock(&files->file_lock); | 1030 | spin_unlock(&files->file_lock); |
1024 | return filp_close(filp, files); | 1031 | return filp_close(filp, files); |
diff --git a/fs/proc/array.c b/fs/proc/array.c index 37668fe998ad..d88d518d30f6 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -159,6 +159,7 @@ static inline char * task_state(struct task_struct *p, char *buffer) | |||
159 | { | 159 | { |
160 | struct group_info *group_info; | 160 | struct group_info *group_info; |
161 | int g; | 161 | int g; |
162 | struct fdtable *fdt = NULL; | ||
162 | 163 | ||
163 | read_lock(&tasklist_lock); | 164 | read_lock(&tasklist_lock); |
164 | buffer += sprintf(buffer, | 165 | buffer += sprintf(buffer, |
@@ -179,10 +180,12 @@ static inline char * task_state(struct task_struct *p, char *buffer) | |||
179 | p->gid, p->egid, p->sgid, p->fsgid); | 180 | p->gid, p->egid, p->sgid, p->fsgid); |
180 | read_unlock(&tasklist_lock); | 181 | read_unlock(&tasklist_lock); |
181 | task_lock(p); | 182 | task_lock(p); |
183 | if (p->files) | ||
184 | fdt = files_fdtable(p->files); | ||
182 | buffer += sprintf(buffer, | 185 | buffer += sprintf(buffer, |
183 | "FDSize:\t%d\n" | 186 | "FDSize:\t%d\n" |
184 | "Groups:\t", | 187 | "Groups:\t", |
185 | p->files ? p->files->max_fds : 0); | 188 | fdt ? fdt->max_fds : 0); |
186 | 189 | ||
187 | group_info = p->group_info; | 190 | group_info = p->group_info; |
188 | get_group_info(group_info); | 191 | get_group_info(group_info); |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 84751f3f52d5..d0087a0b024b 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1039,6 +1039,7 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) | |||
1039 | int retval; | 1039 | int retval; |
1040 | char buf[NUMBUF]; | 1040 | char buf[NUMBUF]; |
1041 | struct files_struct * files; | 1041 | struct files_struct * files; |
1042 | struct fdtable *fdt; | ||
1042 | 1043 | ||
1043 | retval = -ENOENT; | 1044 | retval = -ENOENT; |
1044 | if (!pid_alive(p)) | 1045 | if (!pid_alive(p)) |
@@ -1062,8 +1063,9 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) | |||
1062 | if (!files) | 1063 | if (!files) |
1063 | goto out; | 1064 | goto out; |
1064 | spin_lock(&files->file_lock); | 1065 | spin_lock(&files->file_lock); |
1066 | fdt = files_fdtable(files); | ||
1065 | for (fd = filp->f_pos-2; | 1067 | for (fd = filp->f_pos-2; |
1066 | fd < files->max_fds; | 1068 | fd < fdt->max_fds; |
1067 | fd++, filp->f_pos++) { | 1069 | fd++, filp->f_pos++) { |
1068 | unsigned int i,j; | 1070 | unsigned int i,j; |
1069 | 1071 | ||
diff --git a/fs/select.c b/fs/select.c index b80e7eb0ac0d..2e56325c73c4 100644 --- a/fs/select.c +++ b/fs/select.c | |||
@@ -132,11 +132,13 @@ static int max_select_fd(unsigned long n, fd_set_bits *fds) | |||
132 | unsigned long *open_fds; | 132 | unsigned long *open_fds; |
133 | unsigned long set; | 133 | unsigned long set; |
134 | int max; | 134 | int max; |
135 | struct fdtable *fdt; | ||
135 | 136 | ||
136 | /* handle last in-complete long-word first */ | 137 | /* handle last in-complete long-word first */ |
137 | set = ~(~0UL << (n & (__NFDBITS-1))); | 138 | set = ~(~0UL << (n & (__NFDBITS-1))); |
138 | n /= __NFDBITS; | 139 | n /= __NFDBITS; |
139 | open_fds = current->files->open_fds->fds_bits+n; | 140 | fdt = files_fdtable(current->files); |
141 | open_fds = fdt->open_fds->fds_bits+n; | ||
140 | max = 0; | 142 | max = 0; |
141 | if (set) { | 143 | if (set) { |
142 | set &= BITS(fds, n); | 144 | set &= BITS(fds, n); |
@@ -299,6 +301,7 @@ sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s | |||
299 | char *bits; | 301 | char *bits; |
300 | long timeout; | 302 | long timeout; |
301 | int ret, size, max_fdset; | 303 | int ret, size, max_fdset; |
304 | struct fdtable *fdt; | ||
302 | 305 | ||
303 | timeout = MAX_SCHEDULE_TIMEOUT; | 306 | timeout = MAX_SCHEDULE_TIMEOUT; |
304 | if (tvp) { | 307 | if (tvp) { |
@@ -326,7 +329,8 @@ sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s | |||
326 | goto out_nofds; | 329 | goto out_nofds; |
327 | 330 | ||
328 | /* max_fdset can increase, so grab it once to avoid race */ | 331 | /* max_fdset can increase, so grab it once to avoid race */ |
329 | max_fdset = current->files->max_fdset; | 332 | fdt = files_fdtable(current->files); |
333 | max_fdset = fdt->max_fdset; | ||
330 | if (n > max_fdset) | 334 | if (n > max_fdset) |
331 | n = max_fdset; | 335 | n = max_fdset; |
332 | 336 | ||
@@ -464,9 +468,11 @@ asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long ti | |||
464 | unsigned int i; | 468 | unsigned int i; |
465 | struct poll_list *head; | 469 | struct poll_list *head; |
466 | struct poll_list *walk; | 470 | struct poll_list *walk; |
471 | struct fdtable *fdt; | ||
467 | 472 | ||
468 | /* Do a sanity check on nfds ... */ | 473 | /* Do a sanity check on nfds ... */ |
469 | if (nfds > current->files->max_fdset && nfds > OPEN_MAX) | 474 | fdt = files_fdtable(current->files); |
475 | if (nfds > fdt->max_fdset && nfds > OPEN_MAX) | ||
470 | return -EINVAL; | 476 | return -EINVAL; |
471 | 477 | ||
472 | if (timeout) { | 478 | if (timeout) { |
diff --git a/include/linux/file.h b/include/linux/file.h index 5206beb9a80e..db372230848e 100644 --- a/include/linux/file.h +++ b/include/linux/file.h | |||
@@ -16,23 +16,29 @@ | |||
16 | */ | 16 | */ |
17 | #define NR_OPEN_DEFAULT BITS_PER_LONG | 17 | #define NR_OPEN_DEFAULT BITS_PER_LONG |
18 | 18 | ||
19 | struct fdtable { | ||
20 | unsigned int max_fds; | ||
21 | int max_fdset; | ||
22 | int next_fd; | ||
23 | struct file ** fd; /* current fd array */ | ||
24 | fd_set *close_on_exec; | ||
25 | fd_set *open_fds; | ||
26 | }; | ||
27 | |||
19 | /* | 28 | /* |
20 | * Open file table structure | 29 | * Open file table structure |
21 | */ | 30 | */ |
22 | struct files_struct { | 31 | struct files_struct { |
23 | atomic_t count; | 32 | atomic_t count; |
24 | spinlock_t file_lock; /* Protects all the below members. Nests inside tsk->alloc_lock */ | 33 | spinlock_t file_lock; /* Protects all the below members. Nests inside tsk->alloc_lock */ |
25 | int max_fds; | 34 | struct fdtable fdtab; |
26 | int max_fdset; | ||
27 | int next_fd; | ||
28 | struct file ** fd; /* current fd array */ | ||
29 | fd_set *close_on_exec; | ||
30 | fd_set *open_fds; | ||
31 | fd_set close_on_exec_init; | 35 | fd_set close_on_exec_init; |
32 | fd_set open_fds_init; | 36 | fd_set open_fds_init; |
33 | struct file * fd_array[NR_OPEN_DEFAULT]; | 37 | struct file * fd_array[NR_OPEN_DEFAULT]; |
34 | }; | 38 | }; |
35 | 39 | ||
40 | #define files_fdtable(files) (&(files)->fdtab) | ||
41 | |||
36 | extern void FASTCALL(__fput(struct file *)); | 42 | extern void FASTCALL(__fput(struct file *)); |
37 | extern void FASTCALL(fput(struct file *)); | 43 | extern void FASTCALL(fput(struct file *)); |
38 | 44 | ||
@@ -63,9 +69,10 @@ extern int expand_files(struct files_struct *, int nr); | |||
63 | static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd) | 69 | static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd) |
64 | { | 70 | { |
65 | struct file * file = NULL; | 71 | struct file * file = NULL; |
72 | struct fdtable *fdt = files_fdtable(files); | ||
66 | 73 | ||
67 | if (fd < files->max_fds) | 74 | if (fd < fdt->max_fds) |
68 | file = files->fd[fd]; | 75 | file = fdt->fd[fd]; |
69 | return file; | 76 | return file; |
70 | } | 77 | } |
71 | 78 | ||
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index c727c195a91a..94aefa54a1b5 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
@@ -3,16 +3,21 @@ | |||
3 | 3 | ||
4 | #include <linux/file.h> | 4 | #include <linux/file.h> |
5 | 5 | ||
6 | #define INIT_FILES \ | 6 | #define INIT_FDTABLE \ |
7 | { \ | 7 | { \ |
8 | .count = ATOMIC_INIT(1), \ | ||
9 | .file_lock = SPIN_LOCK_UNLOCKED, \ | ||
10 | .max_fds = NR_OPEN_DEFAULT, \ | 8 | .max_fds = NR_OPEN_DEFAULT, \ |
11 | .max_fdset = __FD_SETSIZE, \ | 9 | .max_fdset = __FD_SETSIZE, \ |
12 | .next_fd = 0, \ | 10 | .next_fd = 0, \ |
13 | .fd = &init_files.fd_array[0], \ | 11 | .fd = &init_files.fd_array[0], \ |
14 | .close_on_exec = &init_files.close_on_exec_init, \ | 12 | .close_on_exec = &init_files.close_on_exec_init, \ |
15 | .open_fds = &init_files.open_fds_init, \ | 13 | .open_fds = &init_files.open_fds_init, \ |
14 | } | ||
15 | |||
16 | #define INIT_FILES \ | ||
17 | { \ | ||
18 | .count = ATOMIC_INIT(1), \ | ||
19 | .file_lock = SPIN_LOCK_UNLOCKED, \ | ||
20 | .fdtab = INIT_FDTABLE, \ | ||
16 | .close_on_exec_init = { { 0, } }, \ | 21 | .close_on_exec_init = { { 0, } }, \ |
17 | .open_fds_init = { { 0, } }, \ | 22 | .open_fds_init = { { 0, } }, \ |
18 | .fd_array = { NULL, } \ | 23 | .fd_array = { NULL, } \ |
diff --git a/kernel/exit.c b/kernel/exit.c index 5b0fb9f09f21..83beb1e93b18 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -368,17 +368,19 @@ EXPORT_SYMBOL(daemonize); | |||
368 | static inline void close_files(struct files_struct * files) | 368 | static inline void close_files(struct files_struct * files) |
369 | { | 369 | { |
370 | int i, j; | 370 | int i, j; |
371 | struct fdtable *fdt; | ||
371 | 372 | ||
372 | j = 0; | 373 | j = 0; |
374 | fdt = files_fdtable(files); | ||
373 | for (;;) { | 375 | for (;;) { |
374 | unsigned long set; | 376 | unsigned long set; |
375 | i = j * __NFDBITS; | 377 | i = j * __NFDBITS; |
376 | if (i >= files->max_fdset || i >= files->max_fds) | 378 | if (i >= fdt->max_fdset || i >= fdt->max_fds) |
377 | break; | 379 | break; |
378 | set = files->open_fds->fds_bits[j++]; | 380 | set = fdt->open_fds->fds_bits[j++]; |
379 | while (set) { | 381 | while (set) { |
380 | if (set & 1) { | 382 | if (set & 1) { |
381 | struct file * file = xchg(&files->fd[i], NULL); | 383 | struct file * file = xchg(&fdt->fd[i], NULL); |
382 | if (file) | 384 | if (file) |
383 | filp_close(file, files); | 385 | filp_close(file, files); |
384 | } | 386 | } |
@@ -403,16 +405,19 @@ struct files_struct *get_files_struct(struct task_struct *task) | |||
403 | 405 | ||
404 | void fastcall put_files_struct(struct files_struct *files) | 406 | void fastcall put_files_struct(struct files_struct *files) |
405 | { | 407 | { |
408 | struct fdtable *fdt; | ||
409 | |||
406 | if (atomic_dec_and_test(&files->count)) { | 410 | if (atomic_dec_and_test(&files->count)) { |
407 | close_files(files); | 411 | close_files(files); |
408 | /* | 412 | /* |
409 | * Free the fd and fdset arrays if we expanded them. | 413 | * Free the fd and fdset arrays if we expanded them. |
410 | */ | 414 | */ |
411 | if (files->fd != &files->fd_array[0]) | 415 | fdt = files_fdtable(files); |
412 | free_fd_array(files->fd, files->max_fds); | 416 | if (fdt->fd != &files->fd_array[0]) |
413 | if (files->max_fdset > __FD_SETSIZE) { | 417 | free_fd_array(fdt->fd, fdt->max_fds); |
414 | free_fdset(files->open_fds, files->max_fdset); | 418 | if (fdt->max_fdset > __FD_SETSIZE) { |
415 | free_fdset(files->close_on_exec, files->max_fdset); | 419 | free_fdset(fdt->open_fds, fdt->max_fdset); |
420 | free_fdset(fdt->close_on_exec, fdt->max_fdset); | ||
416 | } | 421 | } |
417 | kmem_cache_free(files_cachep, files); | 422 | kmem_cache_free(files_cachep, files); |
418 | } | 423 | } |
diff --git a/kernel/fork.c b/kernel/fork.c index b25802065031..ecc694debb50 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -568,21 +568,47 @@ static inline int copy_fs(unsigned long clone_flags, struct task_struct * tsk) | |||
568 | static int count_open_files(struct files_struct *files, int size) | 568 | static int count_open_files(struct files_struct *files, int size) |
569 | { | 569 | { |
570 | int i; | 570 | int i; |
571 | struct fdtable *fdt; | ||
571 | 572 | ||
572 | /* Find the last open fd */ | 573 | /* Find the last open fd */ |
574 | fdt = files_fdtable(files); | ||
573 | for (i = size/(8*sizeof(long)); i > 0; ) { | 575 | for (i = size/(8*sizeof(long)); i > 0; ) { |
574 | if (files->open_fds->fds_bits[--i]) | 576 | if (fdt->open_fds->fds_bits[--i]) |
575 | break; | 577 | break; |
576 | } | 578 | } |
577 | i = (i+1) * 8 * sizeof(long); | 579 | i = (i+1) * 8 * sizeof(long); |
578 | return i; | 580 | return i; |
579 | } | 581 | } |
580 | 582 | ||
583 | static struct files_struct *alloc_files(void) | ||
584 | { | ||
585 | struct files_struct *newf; | ||
586 | struct fdtable *fdt; | ||
587 | |||
588 | newf = kmem_cache_alloc(files_cachep, SLAB_KERNEL); | ||
589 | if (!newf) | ||
590 | goto out; | ||
591 | |||
592 | atomic_set(&newf->count, 1); | ||
593 | |||
594 | spin_lock_init(&newf->file_lock); | ||
595 | fdt = files_fdtable(newf); | ||
596 | fdt->next_fd = 0; | ||
597 | fdt->max_fds = NR_OPEN_DEFAULT; | ||
598 | fdt->max_fdset = __FD_SETSIZE; | ||
599 | fdt->close_on_exec = &newf->close_on_exec_init; | ||
600 | fdt->open_fds = &newf->open_fds_init; | ||
601 | fdt->fd = &newf->fd_array[0]; | ||
602 | out: | ||
603 | return newf; | ||
604 | } | ||
605 | |||
581 | static int copy_files(unsigned long clone_flags, struct task_struct * tsk) | 606 | static int copy_files(unsigned long clone_flags, struct task_struct * tsk) |
582 | { | 607 | { |
583 | struct files_struct *oldf, *newf; | 608 | struct files_struct *oldf, *newf; |
584 | struct file **old_fds, **new_fds; | 609 | struct file **old_fds, **new_fds; |
585 | int open_files, size, i, error = 0, expand; | 610 | int open_files, size, i, error = 0, expand; |
611 | struct fdtable *old_fdt, *new_fdt; | ||
586 | 612 | ||
587 | /* | 613 | /* |
588 | * A background process may not have any files ... | 614 | * A background process may not have any files ... |
@@ -603,35 +629,27 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk) | |||
603 | */ | 629 | */ |
604 | tsk->files = NULL; | 630 | tsk->files = NULL; |
605 | error = -ENOMEM; | 631 | error = -ENOMEM; |
606 | newf = kmem_cache_alloc(files_cachep, SLAB_KERNEL); | 632 | newf = alloc_files(); |
607 | if (!newf) | 633 | if (!newf) |
608 | goto out; | 634 | goto out; |
609 | 635 | ||
610 | atomic_set(&newf->count, 1); | ||
611 | |||
612 | spin_lock_init(&newf->file_lock); | ||
613 | newf->next_fd = 0; | ||
614 | newf->max_fds = NR_OPEN_DEFAULT; | ||
615 | newf->max_fdset = __FD_SETSIZE; | ||
616 | newf->close_on_exec = &newf->close_on_exec_init; | ||
617 | newf->open_fds = &newf->open_fds_init; | ||
618 | newf->fd = &newf->fd_array[0]; | ||
619 | |||
620 | spin_lock(&oldf->file_lock); | 636 | spin_lock(&oldf->file_lock); |
621 | 637 | old_fdt = files_fdtable(oldf); | |
622 | open_files = count_open_files(oldf, oldf->max_fdset); | 638 | new_fdt = files_fdtable(newf); |
639 | size = old_fdt->max_fdset; | ||
640 | open_files = count_open_files(oldf, old_fdt->max_fdset); | ||
623 | expand = 0; | 641 | expand = 0; |
624 | 642 | ||
625 | /* | 643 | /* |
626 | * Check whether we need to allocate a larger fd array or fd set. | 644 | * Check whether we need to allocate a larger fd array or fd set. |
627 | * Note: we're not a clone task, so the open count won't change. | 645 | * Note: we're not a clone task, so the open count won't change. |
628 | */ | 646 | */ |
629 | if (open_files > newf->max_fdset) { | 647 | if (open_files > new_fdt->max_fdset) { |
630 | newf->max_fdset = 0; | 648 | new_fdt->max_fdset = 0; |
631 | expand = 1; | 649 | expand = 1; |
632 | } | 650 | } |
633 | if (open_files > newf->max_fds) { | 651 | if (open_files > new_fdt->max_fds) { |
634 | newf->max_fds = 0; | 652 | new_fdt->max_fds = 0; |
635 | expand = 1; | 653 | expand = 1; |
636 | } | 654 | } |
637 | 655 | ||
@@ -646,11 +664,11 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk) | |||
646 | spin_lock(&oldf->file_lock); | 664 | spin_lock(&oldf->file_lock); |
647 | } | 665 | } |
648 | 666 | ||
649 | old_fds = oldf->fd; | 667 | old_fds = old_fdt->fd; |
650 | new_fds = newf->fd; | 668 | new_fds = new_fdt->fd; |
651 | 669 | ||
652 | memcpy(newf->open_fds->fds_bits, oldf->open_fds->fds_bits, open_files/8); | 670 | memcpy(new_fdt->open_fds->fds_bits, old_fdt->open_fds->fds_bits, open_files/8); |
653 | memcpy(newf->close_on_exec->fds_bits, oldf->close_on_exec->fds_bits, open_files/8); | 671 | memcpy(new_fdt->close_on_exec->fds_bits, old_fdt->close_on_exec->fds_bits, open_files/8); |
654 | 672 | ||
655 | for (i = open_files; i != 0; i--) { | 673 | for (i = open_files; i != 0; i--) { |
656 | struct file *f = *old_fds++; | 674 | struct file *f = *old_fds++; |
@@ -663,24 +681,24 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk) | |||
663 | * is partway through open(). So make sure that this | 681 | * is partway through open(). So make sure that this |
664 | * fd is available to the new process. | 682 | * fd is available to the new process. |
665 | */ | 683 | */ |
666 | FD_CLR(open_files - i, newf->open_fds); | 684 | FD_CLR(open_files - i, new_fdt->open_fds); |
667 | } | 685 | } |
668 | *new_fds++ = f; | 686 | *new_fds++ = f; |
669 | } | 687 | } |
670 | spin_unlock(&oldf->file_lock); | 688 | spin_unlock(&oldf->file_lock); |
671 | 689 | ||
672 | /* compute the remainder to be cleared */ | 690 | /* compute the remainder to be cleared */ |
673 | size = (newf->max_fds - open_files) * sizeof(struct file *); | 691 | size = (new_fdt->max_fds - open_files) * sizeof(struct file *); |
674 | 692 | ||
675 | /* This is long word aligned thus could use a optimized version */ | 693 | /* This is long word aligned thus could use a optimized version */ |
676 | memset(new_fds, 0, size); | 694 | memset(new_fds, 0, size); |
677 | 695 | ||
678 | if (newf->max_fdset > open_files) { | 696 | if (new_fdt->max_fdset > open_files) { |
679 | int left = (newf->max_fdset-open_files)/8; | 697 | int left = (new_fdt->max_fdset-open_files)/8; |
680 | int start = open_files / (8 * sizeof(unsigned long)); | 698 | int start = open_files / (8 * sizeof(unsigned long)); |
681 | 699 | ||
682 | memset(&newf->open_fds->fds_bits[start], 0, left); | 700 | memset(&new_fdt->open_fds->fds_bits[start], 0, left); |
683 | memset(&newf->close_on_exec->fds_bits[start], 0, left); | 701 | memset(&new_fdt->close_on_exec->fds_bits[start], 0, left); |
684 | } | 702 | } |
685 | 703 | ||
686 | tsk->files = newf; | 704 | tsk->files = newf; |
@@ -689,9 +707,9 @@ out: | |||
689 | return error; | 707 | return error; |
690 | 708 | ||
691 | out_release: | 709 | out_release: |
692 | free_fdset (newf->close_on_exec, newf->max_fdset); | 710 | free_fdset (new_fdt->close_on_exec, new_fdt->max_fdset); |
693 | free_fdset (newf->open_fds, newf->max_fdset); | 711 | free_fdset (new_fdt->open_fds, new_fdt->max_fdset); |
694 | free_fd_array(newf->fd, newf->max_fds); | 712 | free_fd_array(new_fdt->fd, new_fdt->max_fds); |
695 | kmem_cache_free(files_cachep, newf); | 713 | kmem_cache_free(files_cachep, newf); |
696 | goto out; | 714 | goto out; |
697 | } | 715 | } |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3f0b533be92c..acb5a495a902 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -1594,6 +1594,7 @@ static inline void flush_unauthorized_files(struct files_struct * files) | |||
1594 | struct avc_audit_data ad; | 1594 | struct avc_audit_data ad; |
1595 | struct file *file, *devnull = NULL; | 1595 | struct file *file, *devnull = NULL; |
1596 | struct tty_struct *tty = current->signal->tty; | 1596 | struct tty_struct *tty = current->signal->tty; |
1597 | struct fdtable *fdt; | ||
1597 | long j = -1; | 1598 | long j = -1; |
1598 | 1599 | ||
1599 | if (tty) { | 1600 | if (tty) { |
@@ -1627,9 +1628,10 @@ static inline void flush_unauthorized_files(struct files_struct * files) | |||
1627 | 1628 | ||
1628 | j++; | 1629 | j++; |
1629 | i = j * __NFDBITS; | 1630 | i = j * __NFDBITS; |
1630 | if (i >= files->max_fds || i >= files->max_fdset) | 1631 | fdt = files_fdtable(files); |
1632 | if (i >= fdt->max_fds || i >= fdt->max_fdset) | ||
1631 | break; | 1633 | break; |
1632 | set = files->open_fds->fds_bits[j]; | 1634 | set = fdt->open_fds->fds_bits[j]; |
1633 | if (!set) | 1635 | if (!set) |
1634 | continue; | 1636 | continue; |
1635 | spin_unlock(&files->file_lock); | 1637 | spin_unlock(&files->file_lock); |