Skip to content

Commit 4c6d80e

Browse files
nmantheykees
authored andcommitted
pstore: Fix double-free in pstore_mkfile() failure path
The pstore_mkfile() function is passed a pointer to a struct pstore_record. On success it consumes this 'record' pointer and references it from the created inode. On failure, however, it may or may not free the record. There are even two different code paths which return -ENOMEM -- one of which does and the other doesn't free the record. Make the behaviour deterministic by never consuming and freeing the record when returning failure, allowing the caller to do the cleanup consistently. Signed-off-by: Norbert Manthey <nmanthey@amazon.de> Link: https://lore.kernel.org/r/1562331960-26198-1-git-send-email-nmanthey@amazon.de Fixes: 83f70f0 ("pstore: Do not duplicate record metadata") Fixes: 1dfff7d ("pstore: Pass record contents instead of copying") Cc: stable@vger.kernel.org [kees: also move "private" allocation location, rename inode cleanup label] Signed-off-by: Kees Cook <keescook@chromium.org>
1 parent fa1af75 commit 4c6d80e

1 file changed

Lines changed: 6 additions & 7 deletions

File tree

fs/pstore/inode.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -318,22 +318,21 @@ int pstore_mkfile(struct dentry *root, struct pstore_record *record)
318318
goto fail;
319319
inode->i_mode = S_IFREG | 0444;
320320
inode->i_fop = &pstore_file_operations;
321-
private = kzalloc(sizeof(*private), GFP_KERNEL);
322-
if (!private)
323-
goto fail_alloc;
324-
private->record = record;
325-
326321
scnprintf(name, sizeof(name), "%s-%s-%llu%s",
327322
pstore_type_to_name(record->type),
328323
record->psi->name, record->id,
329324
record->compressed ? ".enc.z" : "");
330325

326+
private = kzalloc(sizeof(*private), GFP_KERNEL);
327+
if (!private)
328+
goto fail_inode;
329+
331330
dentry = d_alloc_name(root, name);
332331
if (!dentry)
333332
goto fail_private;
334333

334+
private->record = record;
335335
inode->i_size = private->total_size = size;
336-
337336
inode->i_private = private;
338337

339338
if (record->time.tv_sec)
@@ -349,7 +348,7 @@ int pstore_mkfile(struct dentry *root, struct pstore_record *record)
349348

350349
fail_private:
351350
free_pstore_private(private);
352-
fail_alloc:
351+
fail_inode:
353352
iput(inode);
354353

355354
fail:

0 commit comments

Comments
 (0)