Skip to content

Commit 93b919d

Browse files
author
Al Viro
committed
debugfs: fix use-after-free on symlink traversal
symlink body shouldn't be freed without an RCU delay. Switch debugfs to ->destroy_inode() and use of call_rcu(); free both the inode and symlink body in the callback. Similar to solution for bpf, only here it's even more obvious that ->evict_inode() can be dropped. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
1 parent 0cdc17e commit 93b919d

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

fs/debugfs/inode.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,19 +163,24 @@ static int debugfs_show_options(struct seq_file *m, struct dentry *root)
163163
return 0;
164164
}
165165

166-
static void debugfs_evict_inode(struct inode *inode)
166+
static void debugfs_i_callback(struct rcu_head *head)
167167
{
168-
truncate_inode_pages_final(&inode->i_data);
169-
clear_inode(inode);
168+
struct inode *inode = container_of(head, struct inode, i_rcu);
170169
if (S_ISLNK(inode->i_mode))
171170
kfree(inode->i_link);
171+
free_inode_nonrcu(inode);
172+
}
173+
174+
static void debugfs_destroy_inode(struct inode *inode)
175+
{
176+
call_rcu(&inode->i_rcu, debugfs_i_callback);
172177
}
173178

174179
static const struct super_operations debugfs_super_operations = {
175180
.statfs = simple_statfs,
176181
.remount_fs = debugfs_remount,
177182
.show_options = debugfs_show_options,
178-
.evict_inode = debugfs_evict_inode,
183+
.destroy_inode = debugfs_destroy_inode,
179184
};
180185

181186
static void debugfs_release_dentry(struct dentry *dentry)

0 commit comments

Comments
 (0)