backing file: free directly
authorChristian Brauner <brauner@kernel.org>
Thu, 5 Oct 2023 17:08:35 +0000 (19:08 +0200)
committerChristian Brauner <brauner@kernel.org>
Thu, 19 Oct 2023 09:02:49 +0000 (11:02 +0200)
Backing files as used by overlayfs are never installed into file
descriptor tables and are explicitly documented as such. They aren't
subject to rcu access conditions like regular files are.

Their lifetime is bound to the lifetime of the overlayfs file, i.e.,
they're stashed in ovl_file->private_data and go away otherwise. If
they're set as vma->vm_file - which is their main purpose - then they're
subject to regular refcount rules and vma->vm_file can't be installed
into an fdtable after having been set. All in all I don't see any need
for rcu delay here. So free it directly.

This all hinges on such hybrid beasts to never actually be installed
into fdtables which - as mentioned before - is not allowed. So add an
explicit WARN_ON_ONCE() so we catch any case where someone is suddenly
trying to install one of those things into a file descriptor table so we
can have a nice long chat with them.

Link: https://lore.kernel.org/r/20231005-sakralbau-wappnen-f5c31755ed70@brauner
Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/file.c
fs/file_table.c

index 4eb0266316732a78c80e8dca1cc636b622f3cc5a..1a475d7d636e03b1c4a252399132fa67db0bba18 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -604,6 +604,9 @@ void fd_install(unsigned int fd, struct file *file)
        struct files_struct *files = current->files;
        struct fdtable *fdt;
 
+       if (WARN_ON_ONCE(unlikely(file->f_mode & FMODE_BACKING)))
+               return;
+
        rcu_read_lock_sched();
 
        if (unlikely(files->resize_in_progress)) {
index a79a8003134377b49aec6e45a05b0cb8df29b608..08fd1dd6d863693ae85044e91f101596f2ad6b70 100644 (file)
@@ -61,13 +61,6 @@ struct path *backing_file_real_path(struct file *f)
 }
 EXPORT_SYMBOL_GPL(backing_file_real_path);
 
-static void file_free_rcu(struct rcu_head *head)
-{
-       struct file *f = container_of(head, struct file, f_rcuhead);
-
-       kfree(backing_file(f));
-}
-
 static inline void file_free(struct file *f)
 {
        security_file_free(f);
@@ -76,7 +69,7 @@ static inline void file_free(struct file *f)
        put_cred(f->f_cred);
        if (unlikely(f->f_mode & FMODE_BACKING)) {
                path_put(backing_file_real_path(f));
-               call_rcu(&f->f_rcuhead, file_free_rcu);
+               kfree(backing_file(f));
        } else {
                kmem_cache_free(filp_cachep, f);
        }