Skip to content

Commit e954365

Browse files
Kirill KorotaevLinus Torvalds
authored andcommitted
[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 <den@sw.ru> Signed-Off-By: Kirill Korotaev <dev@sw.ru> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
1 parent f12ec44 commit e954365

File tree

1 file changed

+10
-7
lines changed

1 file changed

+10
-7
lines changed

fs/proc/inode.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,13 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
156156

157157
WARN_ON(de && de->deleted);
158158

159+
if (de != NULL && !try_module_get(de->owner))
160+
goto out_mod;
161+
159162
inode = iget(sb, ino);
160163
if (!inode)
161-
goto out_fail;
162-
164+
goto out_ino;
165+
163166
PROC_I(inode)->pde = de;
164167
if (de) {
165168
if (de->mode) {
@@ -171,20 +174,20 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
171174
inode->i_size = de->size;
172175
if (de->nlink)
173176
inode->i_nlink = de->nlink;
174-
if (!try_module_get(de->owner))
175-
goto out_fail;
176177
if (de->proc_iops)
177178
inode->i_op = de->proc_iops;
178179
if (de->proc_fops)
179180
inode->i_fop = de->proc_fops;
180181
}
181182

182-
out:
183183
return inode;
184184

185-
out_fail:
185+
out_ino:
186+
if (de != NULL)
187+
module_put(de->owner);
188+
out_mod:
186189
de_put(de);
187-
goto out;
190+
return NULL;
188191
}
189192

190193
int proc_fill_super(struct super_block *s, void *data, int silent)

0 commit comments

Comments
 (0)