Commit db5481e7 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull symlink fixes from Al Viro:
 "The ceph fix is already in mainline, Daniel's bpf fix is in bpf tree
  (1da6c4d9 "bpf: fix use after free in bpf_evict_inode"), the rest
  is in here"

* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  debugfs: fix use-after-free on symlink traversal
  ubifs: fix use-after-free on symlink traversal
  jffs2: fix use-after-free on symlink traversal
parents 79a3aaa7 93b919da
...@@ -163,19 +163,24 @@ static int debugfs_show_options(struct seq_file *m, struct dentry *root) ...@@ -163,19 +163,24 @@ static int debugfs_show_options(struct seq_file *m, struct dentry *root)
return 0; return 0;
} }
static void debugfs_evict_inode(struct inode *inode) static void debugfs_i_callback(struct rcu_head *head)
{ {
truncate_inode_pages_final(&inode->i_data); struct inode *inode = container_of(head, struct inode, i_rcu);
clear_inode(inode);
if (S_ISLNK(inode->i_mode)) if (S_ISLNK(inode->i_mode))
kfree(inode->i_link); kfree(inode->i_link);
free_inode_nonrcu(inode);
}
static void debugfs_destroy_inode(struct inode *inode)
{
call_rcu(&inode->i_rcu, debugfs_i_callback);
} }
static const struct super_operations debugfs_super_operations = { static const struct super_operations debugfs_super_operations = {
.statfs = simple_statfs, .statfs = simple_statfs,
.remount_fs = debugfs_remount, .remount_fs = debugfs_remount,
.show_options = debugfs_show_options, .show_options = debugfs_show_options,
.evict_inode = debugfs_evict_inode, .destroy_inode = debugfs_destroy_inode,
}; };
static void debugfs_release_dentry(struct dentry *dentry) static void debugfs_release_dentry(struct dentry *dentry)
......
...@@ -1414,11 +1414,6 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) ...@@ -1414,11 +1414,6 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL); jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL);
if (f->target) {
kfree(f->target);
f->target = NULL;
}
fds = f->dents; fds = f->dents;
while(fds) { while(fds) {
fd = fds; fd = fds;
......
...@@ -47,7 +47,10 @@ static struct inode *jffs2_alloc_inode(struct super_block *sb) ...@@ -47,7 +47,10 @@ static struct inode *jffs2_alloc_inode(struct super_block *sb)
static void jffs2_i_callback(struct rcu_head *head) static void jffs2_i_callback(struct rcu_head *head)
{ {
struct inode *inode = container_of(head, struct inode, i_rcu); struct inode *inode = container_of(head, struct inode, i_rcu);
kmem_cache_free(jffs2_inode_cachep, JFFS2_INODE_INFO(inode)); struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
kfree(f->target);
kmem_cache_free(jffs2_inode_cachep, f);
} }
static void jffs2_destroy_inode(struct inode *inode) static void jffs2_destroy_inode(struct inode *inode)
......
...@@ -276,14 +276,12 @@ static void ubifs_i_callback(struct rcu_head *head) ...@@ -276,14 +276,12 @@ static void ubifs_i_callback(struct rcu_head *head)
{ {
struct inode *inode = container_of(head, struct inode, i_rcu); struct inode *inode = container_of(head, struct inode, i_rcu);
struct ubifs_inode *ui = ubifs_inode(inode); struct ubifs_inode *ui = ubifs_inode(inode);
kfree(ui->data);
kmem_cache_free(ubifs_inode_slab, ui); kmem_cache_free(ubifs_inode_slab, ui);
} }
static void ubifs_destroy_inode(struct inode *inode) static void ubifs_destroy_inode(struct inode *inode)
{ {
struct ubifs_inode *ui = ubifs_inode(inode);
kfree(ui->data);
call_rcu(&inode->i_rcu, ubifs_i_callback); call_rcu(&inode->i_rcu, ubifs_i_callback);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment