Commit f8f95702f0c4529b0f59488f4509608f0c160e77

Authored by Al Viro
1 parent 3b1253880b

[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

... ... @@ -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 }