Skip to content

Commit 42560f9

Browse files
konisakpm00
authored andcommitted
nilfs2: fix sysfs interface lifetime
The current nilfs2 sysfs support has issues with the timing of creation and deletion of sysfs entries, potentially leading to null pointer dereferences, use-after-free, and lockdep warnings. Some of the sysfs attributes for nilfs2 per-filesystem instance refer to metadata file "cpfile", "sufile", or "dat", but nilfs_sysfs_create_device_group that creates those attributes is executed before the inodes for these metadata files are loaded, and nilfs_sysfs_delete_device_group which deletes these sysfs entries is called after releasing their metadata file inodes. Therefore, access to some of these sysfs attributes may occur outside of the lifetime of these metadata files, resulting in inode NULL pointer dereferences or use-after-free. In addition, the call to nilfs_sysfs_create_device_group() is made during the locking period of the semaphore "ns_sem" of nilfs object, so the shrinker call caused by the memory allocation for the sysfs entries, may derive lock dependencies "ns_sem" -> (shrinker) -> "locks acquired in nilfs_evict_inode()". Since nilfs2 may acquire "ns_sem" deep in the call stack holding other locks via its error handler __nilfs_error(), this causes lockdep to report circular locking. This is a false positive and no circular locking actually occurs as no inodes exist yet when nilfs_sysfs_create_device_group() is called. Fortunately, the lockdep warnings can be resolved by simply moving the call to nilfs_sysfs_create_device_group() out of "ns_sem". This fixes these sysfs issues by revising where the device's sysfs interface is created/deleted and keeping its lifetime within the lifetime of the metadata files above. Link: https://lkml.kernel.org/r/[email protected] Fixes: dd70edb ("nilfs2: integrate sysfs support into driver") Signed-off-by: Ryusuke Konishi <[email protected]> Reported-by: [email protected] Link: https://lkml.kernel.org/r/[email protected] Reported-by: [email protected] Link: https://lkml.kernel.org/r/[email protected] Cc: Viacheslav Dubeyko <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 7c7b962 commit 42560f9

File tree

2 files changed

+9
-5
lines changed

2 files changed

+9
-5
lines changed

fs/nilfs2/super.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ static void nilfs_put_super(struct super_block *sb)
482482
up_write(&nilfs->ns_sem);
483483
}
484484

485+
nilfs_sysfs_delete_device_group(nilfs);
485486
iput(nilfs->ns_sufile);
486487
iput(nilfs->ns_cpfile);
487488
iput(nilfs->ns_dat);
@@ -1105,6 +1106,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
11051106
nilfs_put_root(fsroot);
11061107

11071108
failed_unload:
1109+
nilfs_sysfs_delete_device_group(nilfs);
11081110
iput(nilfs->ns_sufile);
11091111
iput(nilfs->ns_cpfile);
11101112
iput(nilfs->ns_dat);

fs/nilfs2/the_nilfs.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ void destroy_nilfs(struct the_nilfs *nilfs)
8787
{
8888
might_sleep();
8989
if (nilfs_init(nilfs)) {
90-
nilfs_sysfs_delete_device_group(nilfs);
9190
brelse(nilfs->ns_sbh[0]);
9291
brelse(nilfs->ns_sbh[1]);
9392
}
@@ -305,6 +304,10 @@ int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb)
305304
goto failed;
306305
}
307306

307+
err = nilfs_sysfs_create_device_group(sb);
308+
if (unlikely(err))
309+
goto sysfs_error;
310+
308311
if (valid_fs)
309312
goto skip_recovery;
310313

@@ -366,6 +369,9 @@ int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb)
366369
goto failed;
367370

368371
failed_unload:
372+
nilfs_sysfs_delete_device_group(nilfs);
373+
374+
sysfs_error:
369375
iput(nilfs->ns_cpfile);
370376
iput(nilfs->ns_sufile);
371377
iput(nilfs->ns_dat);
@@ -697,10 +703,6 @@ int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data)
697703
if (err)
698704
goto failed_sbh;
699705

700-
err = nilfs_sysfs_create_device_group(sb);
701-
if (err)
702-
goto failed_sbh;
703-
704706
set_nilfs_init(nilfs);
705707
err = 0;
706708
out:

0 commit comments

Comments
 (0)