Commit f8f95702f0c4529b0f59488f4509608f0c160e77
1 parent
3b1253880b
Exists in
master
and in
4 other branches
[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>
Showing 1 changed file with 14 additions and 26 deletions Side-by-side Diff
fs/fcntl.c
... | ... | @@ -55,14 +55,16 @@ |
55 | 55 | * file_lock held for write. |
56 | 56 | */ |
57 | 57 | |
58 | -static int locate_fd(struct files_struct *files, | |
59 | - struct file *file, unsigned int orig_start) | |
58 | +static int locate_fd(unsigned int orig_start, int cloexec) | |
60 | 59 | { |
60 | + struct files_struct *files = current->files; | |
61 | 61 | unsigned int newfd; |
62 | 62 | unsigned int start; |
63 | 63 | int error; |
64 | 64 | struct fdtable *fdt; |
65 | 65 | |
66 | + spin_lock(&files->file_lock); | |
67 | + | |
66 | 68 | error = -EINVAL; |
67 | 69 | if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) |
68 | 70 | goto out; |
69 | 71 | |
70 | 72 | |
71 | 73 | |
72 | 74 | |
73 | 75 | |
74 | 76 | |
... | ... | @@ -97,42 +99,28 @@ |
97 | 99 | if (error) |
98 | 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 | 102 | if (start <= files->next_fd) |
106 | 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 | 110 | error = newfd; |
109 | - | |
111 | + | |
110 | 112 | out: |
113 | + spin_unlock(&files->file_lock); | |
111 | 114 | return error; |
112 | 115 | } |
113 | 116 | |
114 | 117 | static int dupfd(struct file *file, unsigned int start, int cloexec) |
115 | 118 | { |
116 | - struct files_struct * files = current->files; | |
117 | - struct fdtable *fdt; | |
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); | |
119 | + int fd = locate_fd(start, cloexec); | |
120 | + if (fd >= 0) | |
131 | 121 | fd_install(fd, file); |
132 | - } else { | |
133 | - spin_unlock(&files->file_lock); | |
122 | + else | |
134 | 123 | fput(file); |
135 | - } | |
136 | 124 | |
137 | 125 | return fd; |
138 | 126 | } |