Skip to content

Commit 609e28b

Browse files
committed
pstore: Remove filesystem records when backend is unregistered
If a backend was unloaded without having first removed all its associated records in pstorefs, subsequent removals would crash while attempting to call into the now missing backend. Add automatic removal from the tree in pstore_unregister(), so that no references to the backend remain. Reported-by: Luis Henriques <[email protected]> Link: https://lore.kernel.org/lkml/[email protected] Link: https://lore.kernel.org/lkml/[email protected]/ Signed-off-by: Kees Cook <[email protected]>
1 parent 78c83c8 commit 609e28b

File tree

3 files changed

+36
-0
lines changed

3 files changed

+36
-0
lines changed

fs/pstore/inode.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ static struct super_block *pstore_sb;
3636

3737
struct pstore_private {
3838
struct list_head list;
39+
struct dentry *dentry;
3940
struct pstore_record *record;
4041
size_t total_size;
4142
};
@@ -191,6 +192,7 @@ static int pstore_unlink(struct inode *dir, struct dentry *dentry)
191192
list_del_init(&p->list);
192193
else
193194
rc = -ENOENT;
195+
p->dentry = NULL;
194196
mutex_unlock(&records_list_lock);
195197
if (rc)
196198
return rc;
@@ -306,6 +308,35 @@ static struct dentry *psinfo_lock_root(void)
306308
return root;
307309
}
308310

311+
int pstore_put_backend_records(struct pstore_info *psi)
312+
{
313+
struct pstore_private *pos, *tmp;
314+
struct dentry *root;
315+
int rc = 0;
316+
317+
root = psinfo_lock_root();
318+
if (!root)
319+
return 0;
320+
321+
mutex_lock(&records_list_lock);
322+
list_for_each_entry_safe(pos, tmp, &records_list, list) {
323+
if (pos->record->psi == psi) {
324+
list_del_init(&pos->list);
325+
rc = simple_unlink(d_inode(root), pos->dentry);
326+
if (WARN_ON(rc))
327+
break;
328+
d_drop(pos->dentry);
329+
dput(pos->dentry);
330+
pos->dentry = NULL;
331+
}
332+
}
333+
mutex_unlock(&records_list_lock);
334+
335+
inode_unlock(d_inode(root));
336+
337+
return rc;
338+
}
339+
309340
/*
310341
* Make a regular file in the root directory of our file system.
311342
* Load it up with "size" bytes of data from "buf".
@@ -352,6 +383,7 @@ int pstore_mkfile(struct dentry *root, struct pstore_record *record)
352383
if (!dentry)
353384
goto fail_private;
354385

386+
private->dentry = dentry;
355387
private->record = record;
356388
inode->i_size = private->total_size = size;
357389
inode->i_private = private;

fs/pstore/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ extern void pstore_set_kmsg_bytes(int);
3131
extern void pstore_get_records(int);
3232
extern void pstore_get_backend_records(struct pstore_info *psi,
3333
struct dentry *root, int quiet);
34+
extern int pstore_put_backend_records(struct pstore_info *psi);
3435
extern int pstore_mkfile(struct dentry *root,
3536
struct pstore_record *record);
3637
extern void pstore_record_init(struct pstore_record *record,

fs/pstore/platform.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,9 @@ void pstore_unregister(struct pstore_info *psi)
657657
del_timer_sync(&pstore_timer);
658658
flush_work(&pstore_work);
659659

660+
/* Remove all backend records from filesystem tree. */
661+
pstore_put_backend_records(psi);
662+
660663
free_buf_for_compression();
661664

662665
psinfo = NULL;

0 commit comments

Comments
 (0)