aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fcntl.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2008-04-23 20:38:10 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2008-04-25 09:24:05 -0400
commitf8f95702f0c4529b0f59488f4509608f0c160e77 (patch)
tree618c1ed56eb48da11189f1db9216dd92750c9812 /fs/fcntl.c
parent3b1253880b7a9e6db54b943b2d40bcf2202f58ab (diff)
[PATCH] sanitize locate_fd()
* 'file' argument is unused; lose it. * move setting flags from the caller (dupfd()) to locate_fd(); pass cloexec flag as new argument. Note that files_fdtable() that used to be in dupfd() isn't needed in the place in locate_fd() where the moved code ends up - we know that ->file_lock hadn't been dropped since the last time we calculated fdt because we can get there only if expand_files() returns 0 and it doesn't drop/reacquire in that case. * move getting/dropping ->file_lock into locate_fd(). Now the caller doesn't need to do anything with files_struct *files anymore and we can move that inside locate_fd() as well, killing the struct files_struct * argument. At that point locate_fd() is extremely similar to get_unused_fd_flags() and the next patches will merge those two. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r--fs/fcntl.c40
1 files changed, 14 insertions, 26 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c
index e632da761fc1..3f3ac630ccde 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -55,14 +55,16 @@ static int get_close_on_exec(unsigned int fd)
55 * file_lock held for write. 55 * file_lock held for write.
56 */ 56 */
57 57
58static int locate_fd(struct files_struct *files, 58static int locate_fd(unsigned int orig_start, int cloexec)
59 struct file *file, unsigned int orig_start)
60{ 59{
60 struct files_struct *files = current->files;
61 unsigned int newfd; 61 unsigned int newfd;
62 unsigned int start; 62 unsigned int start;
63 int error; 63 int error;
64 struct fdtable *fdt; 64 struct fdtable *fdt;
65 65
66 spin_lock(&files->file_lock);
67
66 error = -EINVAL; 68 error = -EINVAL;
67 if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) 69 if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
68 goto out; 70 goto out;
@@ -97,42 +99,28 @@ repeat:
97 if (error) 99 if (error)
98 goto repeat; 100 goto repeat;
99 101
100 /*
101 * We reacquired files_lock, so we are safe as long as
102 * we reacquire the fdtable pointer and use it while holding
103 * the lock, no one can free it during that time.
104 */
105 if (start <= files->next_fd) 102 if (start <= files->next_fd)
106 files->next_fd = newfd + 1; 103 files->next_fd = newfd + 1;
107 104
105 FD_SET(newfd, fdt->open_fds);
106 if (cloexec)
107 FD_SET(newfd, fdt->close_on_exec);
108 else
109 FD_CLR(newfd, fdt->close_on_exec);
108 error = newfd; 110 error = newfd;
109 111
110out: 112out:
113 spin_unlock(&files->file_lock);
111 return error; 114 return error;
112} 115}
113 116
114static int dupfd(struct file *file, unsigned int start, int cloexec) 117static int dupfd(struct file *file, unsigned int start, int cloexec)
115{ 118{
116 struct files_struct * files = current->files; 119 int fd = locate_fd(start, cloexec);
117 struct fdtable *fdt; 120 if (fd >= 0)
118 int fd;
119
120 spin_lock(&files->file_lock);
121 fd = locate_fd(files, file, start);
122 if (fd >= 0) {
123 /* locate_fd() may have expanded fdtable, load the ptr */
124 fdt = files_fdtable(files);
125 FD_SET(fd, fdt->open_fds);
126 if (cloexec)
127 FD_SET(fd, fdt->close_on_exec);
128 else
129 FD_CLR(fd, fdt->close_on_exec);
130 spin_unlock(&files->file_lock);
131 fd_install(fd, file); 121 fd_install(fd, file);
132 } else { 122 else
133 spin_unlock(&files->file_lock);
134 fput(file); 123 fput(file);
135 }
136 124
137 return fd; 125 return fd;
138} 126}