summaryrefslogtreecommitdiff
path: root/fs/file_table.c
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2023-07-01 20:11:34 +0300
committerChristian Brauner <brauner@kernel.org>2023-07-02 13:15:49 +0200
commitdff745c1221a402b4921d54f292288373cff500c (patch)
treee2245a005ed20bc43bce3d6c621fa710cb902758 /fs/file_table.c
parent995b406c7e972fab181a4bb57f3b95e59b8e5bf3 (diff)
fs: move cleanup from init_file() into its callers
The use of file_free_rcu() in init_file() to free the struct that was allocated by the caller was hacky and we got what we deserved. Let init_file() and its callers take care of cleaning up each after their own allocated resources on error. Fixes: 62d53c4a1dfe ("fs: use backing_file container for internal files with "fake" f_path") # mainline only Reported-and-tested-by: syzbot+ada42aab05cf51b00e98@syzkaller.appspotmail.com Signed-off-by: Amir Goldstein <amir73il@gmail.com> Message-Id: <20230701171134.239409-1-amir73il@gmail.com> Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'fs/file_table.c')
-rw-r--r--fs/file_table.c14
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;