summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2019-03-26 01:39:50 +0000
committerAl Viro <viro@zeniv.linux.org.uk>2019-04-01 00:31:02 -0400
commit4fdcfab5b5537c21891e22e65996d4d0dd8ab4ca (patch)
treed0c9167b762a5837ac3030d2f1e869454a4c4ac6
parent9e98c678c2d6ae3a17cb2de55d17f69dddaa231b (diff)
downloadlinux-stable-4fdcfab5b5537c21891e22e65996d4d0dd8ab4ca.tar.gz
linux-stable-4fdcfab5b5537c21891e22e65996d4d0dd8ab4ca.tar.bz2
linux-stable-4fdcfab5b5537c21891e22e65996d4d0dd8ab4ca.zip
jffs2: fix use-after-free on symlink traversal
free the symlink body after the same RCU delay we have for freeing the struct inode itself, so that traversal during RCU pathwalk wouldn't step into freed memory. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/jffs2/readinode.c5
-rw-r--r--fs/jffs2/super.c5
2 files changed, 4 insertions, 6 deletions
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 389ea53ea487..bccfc40b3a74 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -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);
- if (f->target) {
- kfree(f->target);
- f->target = NULL;
- }
-
fds = f->dents;
while(fds) {
fd = fds;
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index bb6ae387469f..05d892c79339 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -47,7 +47,10 @@ static struct inode *jffs2_alloc_inode(struct super_block *sb)
static void jffs2_i_callback(struct rcu_head *head)
{
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)