[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>
This commit is contained in:
parent
3b1253880b
commit
f8f95702f0
40
fs/fcntl.c
40
fs/fcntl.c
@ -55,14 +55,16 @@ static int get_close_on_exec(unsigned int fd)
|
||||
* file_lock held for write.
|
||||
*/
|
||||
|
||||
static int locate_fd(struct files_struct *files,
|
||||
struct file *file, unsigned int orig_start)
|
||||
static int locate_fd(unsigned int orig_start, int cloexec)
|
||||
{
|
||||
struct files_struct *files = current->files;
|
||||
unsigned int newfd;
|
||||
unsigned int start;
|
||||
int error;
|
||||
struct fdtable *fdt;
|
||||
|
||||
spin_lock(&files->file_lock);
|
||||
|
||||
error = -EINVAL;
|
||||
if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
|
||||
goto out;
|
||||
@ -97,42 +99,28 @@ repeat:
|
||||
if (error)
|
||||
goto repeat;
|
||||
|
||||
/*
|
||||
* We reacquired files_lock, so we are safe as long as
|
||||
* we reacquire the fdtable pointer and use it while holding
|
||||
* the lock, no one can free it during that time.
|
||||
*/
|
||||
if (start <= files->next_fd)
|
||||
files->next_fd = newfd + 1;
|
||||
|
||||
FD_SET(newfd, fdt->open_fds);
|
||||
if (cloexec)
|
||||
FD_SET(newfd, fdt->close_on_exec);
|
||||
else
|
||||
FD_CLR(newfd, fdt->close_on_exec);
|
||||
error = newfd;
|
||||
|
||||
|
||||
out:
|
||||
spin_unlock(&files->file_lock);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int dupfd(struct file *file, unsigned int start, int cloexec)
|
||||
{
|
||||
struct files_struct * files = current->files;
|
||||
struct fdtable *fdt;
|
||||
int fd;
|
||||
|
||||
spin_lock(&files->file_lock);
|
||||
fd = locate_fd(files, file, start);
|
||||
if (fd >= 0) {
|
||||
/* locate_fd() may have expanded fdtable, load the ptr */
|
||||
fdt = files_fdtable(files);
|
||||
FD_SET(fd, fdt->open_fds);
|
||||
if (cloexec)
|
||||
FD_SET(fd, fdt->close_on_exec);
|
||||
else
|
||||
FD_CLR(fd, fdt->close_on_exec);
|
||||
spin_unlock(&files->file_lock);
|
||||
int fd = locate_fd(start, cloexec);
|
||||
if (fd >= 0)
|
||||
fd_install(fd, file);
|
||||
} else {
|
||||
spin_unlock(&files->file_lock);
|
||||
else
|
||||
fput(file);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user