From: Kirill Korotaev Date: Sun, 30 Oct 2005 23:02:26 +0000 (-0800) Subject: [PATCH] proc: fix of error path in proc_get_inode() X-Git-Tag: v2.6.15-rc1~59^2~15^2~90 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e9543659715602e3180f00a227bb6db34141ac41;p=linux-2.6 [PATCH] proc: fix of error path in proc_get_inode() This patch fixes incorrect error path in proc_get_inode(), when module can't be get due to being unloaded. When try_module_get() fails, this function puts de(!) and still returns inode with non-getted de. There are still unresolved known bugs in proc yet to be fixed: - proc_dir_entry tree is managed without any serialization - create_proc_entry() doesn't setup de->owner anyhow, so setting it later manually is inatomic. - looks like almost all modules do not care whether it's de->owner is set... Signed-Off-By: Denis Lunev Signed-Off-By: Kirill Korotaev Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- diff --git a/fs/proc/inode.c b/fs/proc/inode.c index effa6c0c46..e6a818a93f 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -156,10 +156,13 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino, WARN_ON(de && de->deleted); + if (de != NULL && !try_module_get(de->owner)) + goto out_mod; + inode = iget(sb, ino); if (!inode) - goto out_fail; - + goto out_ino; + PROC_I(inode)->pde = de; if (de) { if (de->mode) { @@ -171,20 +174,20 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino, inode->i_size = de->size; if (de->nlink) inode->i_nlink = de->nlink; - if (!try_module_get(de->owner)) - goto out_fail; if (de->proc_iops) inode->i_op = de->proc_iops; if (de->proc_fops) inode->i_fop = de->proc_fops; } -out: return inode; -out_fail: +out_ino: + if (de != NULL) + module_put(de->owner); +out_mod: de_put(de); - goto out; + return NULL; } int proc_fill_super(struct super_block *s, void *data, int silent)