Add switch_files_struct() to install another table on a task. It consumes the reference to the new table and puts the old one. Convert every place that switches a descriptor table except unshare_files(). No functional changes. Signed-off-by: Christian Brauner (Amutable) --- fs/file.c | 23 +++++++++++------------ include/linux/fdtable.h | 1 + kernel/fork.c | 6 ++---- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/fs/file.c b/fs/file.c index 59673547de90..345011dad472 100644 --- a/fs/file.c +++ b/fs/file.c @@ -515,16 +515,18 @@ void put_files_struct(struct files_struct *files) } } -void exit_files(struct task_struct *tsk) +/* Install @files on @tsk, consuming the reference, and put the old table. */ +void switch_files_struct(struct task_struct *tsk, struct files_struct *files) { - struct files_struct * files = tsk->files; + scoped_guard(task_lock, tsk) + swap(tsk->files, files); + put_files_struct(files); +} - if (files) { - task_lock(tsk); - tsk->files = NULL; - task_unlock(tsk); - put_files_struct(files); - } +void exit_files(struct task_struct *tsk) +{ + if (tsk->files) + switch_files_struct(tsk, NULL); } struct files_struct init_files = { @@ -855,10 +857,7 @@ SYSCALL_DEFINE3(close_range, unsigned int, fd, unsigned int, max_fd, * We're done closing the files we were supposed to. Time to install * the new file descriptor table and drop the old one. */ - task_lock(me); - me->files = cur_fds; - task_unlock(me); - put_files_struct(fds); + switch_files_struct(me, cur_fds); } return 0; diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h index c45306a9f007..9614c6ecd477 100644 --- a/include/linux/fdtable.h +++ b/include/linux/fdtable.h @@ -100,6 +100,7 @@ static inline bool close_on_exec(unsigned int fd, const struct files_struct *fil struct task_struct; void put_files_struct(struct files_struct *fs); +void switch_files_struct(struct task_struct *tsk, struct files_struct *files); int unshare_files(void); struct fd_range { unsigned int from, to; diff --git a/kernel/fork.c b/kernel/fork.c index 416758c8a3d4..7c6fe82dbb9f 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -3320,10 +3320,8 @@ int ksys_unshare(unsigned long unshare_flags) if (new_fs) new_fs = switch_fs_struct(new_fs); - if (new_fd) { - guard(task_lock)(current); - swap(current->files, new_fd); - } + if (new_fd) + switch_files_struct(current, no_free_ptr(new_fd)); if (new_cred) { /* Install the new user namespace */ -- 2.53.0