diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-08-15 21:03:26 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-09-26 21:08:55 -0400 |
commit | 56007cae94f349387c088e738c7dcb6bc513063b (patch) | |
tree | b501eb1cc30619cb1cc9828a18256808546389de /fs/file.c | |
parent | 1983e781da2f7f77906f4ccc2c3dc279cd61d1ff (diff) |
move put_unused_fd() and fd_install() to fs/file.c
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/file.c')
-rw-r--r-- | fs/file.c | 44 |
1 files changed, 44 insertions, 0 deletions
@@ -569,3 +569,47 @@ int get_unused_fd_flags(unsigned flags) | |||
569 | return __alloc_fd(current->files, 0, rlimit(RLIMIT_NOFILE), flags); | 569 | return __alloc_fd(current->files, 0, rlimit(RLIMIT_NOFILE), flags); |
570 | } | 570 | } |
571 | EXPORT_SYMBOL(get_unused_fd_flags); | 571 | EXPORT_SYMBOL(get_unused_fd_flags); |
572 | |||
573 | static void __put_unused_fd(struct files_struct *files, unsigned int fd) | ||
574 | { | ||
575 | struct fdtable *fdt = files_fdtable(files); | ||
576 | __clear_open_fd(fd, fdt); | ||
577 | if (fd < files->next_fd) | ||
578 | files->next_fd = fd; | ||
579 | } | ||
580 | |||
581 | void put_unused_fd(unsigned int fd) | ||
582 | { | ||
583 | struct files_struct *files = current->files; | ||
584 | spin_lock(&files->file_lock); | ||
585 | __put_unused_fd(files, fd); | ||
586 | spin_unlock(&files->file_lock); | ||
587 | } | ||
588 | |||
589 | EXPORT_SYMBOL(put_unused_fd); | ||
590 | |||
591 | /* | ||
592 | * Install a file pointer in the fd array. | ||
593 | * | ||
594 | * The VFS is full of places where we drop the files lock between | ||
595 | * setting the open_fds bitmap and installing the file in the file | ||
596 | * array. At any such point, we are vulnerable to a dup2() race | ||
597 | * installing a file in the array before us. We need to detect this and | ||
598 | * fput() the struct file we are about to overwrite in this case. | ||
599 | * | ||
600 | * It should never happen - if we allow dup2() do it, _really_ bad things | ||
601 | * will follow. | ||
602 | */ | ||
603 | |||
604 | void fd_install(unsigned int fd, struct file *file) | ||
605 | { | ||
606 | struct files_struct *files = current->files; | ||
607 | struct fdtable *fdt; | ||
608 | spin_lock(&files->file_lock); | ||
609 | fdt = files_fdtable(files); | ||
610 | BUG_ON(fdt->fd[fd] != NULL); | ||
611 | rcu_assign_pointer(fdt->fd[fd], file); | ||
612 | spin_unlock(&files->file_lock); | ||
613 | } | ||
614 | |||
615 | EXPORT_SYMBOL(fd_install); | ||