diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-07-02 11:10:22 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-07-02 11:10:22 -0700 |
commit | 28c7980fa14a3fbd8926686cfffb89b9542b0da1 (patch) | |
tree | 0f0e7dbc2e2c9e6f519d8fedf82e9b2034e2d22f /fs | |
parent | 5def00ca25fa5697cfe352e675dc7c03116b2403 (diff) | |
parent | dff745c1221a402b4921d54f292288373cff500c (diff) | |
download | lwn-28c7980fa14a3fbd8926686cfffb89b9542b0da1.tar.gz lwn-28c7980fa14a3fbd8926686cfffb89b9542b0da1.zip |
Merge tag 'v6.5/vfs.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull vfs fix from Christian Brauner:
"A fix for the backing file work from this cycle.
When init_file() failed it would call file_free_rcu() on the file
allocated by the caller of init_file(). It naively assumed that the
correct cleanup operation would be called depending on whether it is a
regular file or a backing file. However, that presupposes that the
FMODE_BACKING flag would already be set which it won't be as that is
done in the caller of init_file().
Fix that bug by moving the cleanup of the allocated file into the
caller where it belongs in the first place. There's no good reason for
init_file() to consume resources it didn't allocate. This is a
mainline only fix and was reported by syzbot. The fix was validated by
syzbot against the provided reproducer"
* tag 'v6.5/vfs.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
fs: move cleanup from init_file() into its callers
Diffstat (limited to 'fs')
-rw-r--r-- | fs/file_table.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/fs/file_table.c b/fs/file_table.c index e06c68e2d757..fc7d677ff5ad 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -160,7 +160,7 @@ static int init_file(struct file *f, int flags, const struct cred *cred) f->f_cred = get_cred(cred); error = security_file_alloc(f); if (unlikely(error)) { - file_free_rcu(&f->f_rcuhead); + put_cred(f->f_cred); return error; } @@ -208,8 +208,10 @@ struct file *alloc_empty_file(int flags, const struct cred *cred) return ERR_PTR(-ENOMEM); error = init_file(f, flags, cred); - if (unlikely(error)) + if (unlikely(error)) { + kmem_cache_free(filp_cachep, f); return ERR_PTR(error); + } percpu_counter_inc(&nr_files); @@ -240,8 +242,10 @@ struct file *alloc_empty_file_noaccount(int flags, const struct cred *cred) return ERR_PTR(-ENOMEM); error = init_file(f, flags, cred); - if (unlikely(error)) + if (unlikely(error)) { + kmem_cache_free(filp_cachep, f); return ERR_PTR(error); + } f->f_mode |= FMODE_NOACCOUNT; @@ -265,8 +269,10 @@ struct file *alloc_empty_backing_file(int flags, const struct cred *cred) return ERR_PTR(-ENOMEM); error = init_file(&ff->file, flags, cred); - if (unlikely(error)) + if (unlikely(error)) { + kfree(ff); return ERR_PTR(error); + } ff->file.f_mode |= FMODE_BACKING | FMODE_NOACCOUNT; return &ff->file; |