diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2008-04-23 20:38:10 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2008-04-25 09:24:05 -0400 |
commit | f8f95702f0c4529b0f59488f4509608f0c160e77 (patch) | |
tree | 618c1ed56eb48da11189f1db9216dd92750c9812 /fs/fcntl.c | |
parent | 3b1253880b7a9e6db54b943b2d40bcf2202f58ab (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.c | 40 |
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 | ||
58 | static int locate_fd(struct files_struct *files, | 58 | static 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 | ||
110 | out: | 112 | out: |
113 | spin_unlock(&files->file_lock); | ||
111 | return error; | 114 | return error; |
112 | } | 115 | } |
113 | 116 | ||
114 | static int dupfd(struct file *file, unsigned int start, int cloexec) | 117 | static 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 | } |