diff options
author | Denis V. Lunev <den@openvz.org> | 2008-04-29 04:02:00 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-29 11:06:20 -0400 |
commit | 59b7435149eab2dd06dd678742faff6049cb655f (patch) | |
tree | ceadbf157a001b83a3ab2c89156426e88a782208 | |
parent | b640a89ddd742782bd2d83873da30d4776d1b9c6 (diff) |
proc: introduce proc_create_data to setup de->data
This set of patches fixes an proc ->open'less usage due to ->proc_fops flip in
the most part of the kernel code. The original OOPS is described in the
commit 2d3a4e3666325a9709cc8ea2e88151394e8f20fc:
Typical PDE creation code looks like:
pde = create_proc_entry("foo", 0, NULL);
if (pde)
pde->proc_fops = &foo_proc_fops;
Notice that PDE is first created, only then ->proc_fops is set up to
final value. This is a problem because right after creation
a) PDE is fully visible in /proc , and
b) ->proc_fops are proc_file_operations which do not have ->open callback. So, it's
possible to ->read without ->open (see one class of oopses below).
The fix is new API called proc_create() which makes sure ->proc_fops are
set up before gluing PDE to main tree. Typical new code looks like:
pde = proc_create("foo", 0, NULL, &foo_proc_fops);
if (!pde)
return -ENOMEM;
Fix most networking users for a start.
In the long run, create_proc_entry() for regular files will go.
In addition to this, proc_create_data is introduced to fix reading from
proc without PDE->data. The race is basically the same as above.
create_proc_entries is replaced in the entire kernel code as new method
is also simply better.
This patch:
The problem is the same as for de->proc_fops. Right now PDE becomes visible
without data set. So, the entry could be looked up without data. This, in
most cases, will simply OOPS.
proc_create_data call is created to address this issue. proc_create now
becomes a wrapper around it.
Signed-off-by: Denis V. Lunev <den@openvz.org>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: "J. Bruce Fields" <bfields@fieldses.org>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Bjorn Helgaas <bjorn.helgaas@hp.com>
Cc: Chris Mason <chris.mason@oracle.com>
Acked-by: David Howells <dhowells@redhat.com>
Cc: Dmitry Torokhov <dtor@mail.ru>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Grant Grundler <grundler@parisc-linux.org>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: Haavard Skinnemoen <hskinnemoen@atmel.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
Cc: Jaroslav Kysela <perex@suse.cz>
Cc: Jeff Garzik <jgarzik@pobox.com>
Cc: Jeff Mahoney <jeffm@suse.com>
Cc: Jesper Nilsson <jesper.nilsson@axis.com>
Cc: Karsten Keil <kkeil@suse.de>
Cc: Kyle McMartin <kyle@parisc-linux.org>
Cc: Len Brown <lenb@kernel.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Cc: Matthew Wilcox <matthew@wil.cx>
Cc: Mauro Carvalho Chehab <mchehab@infradead.org>
Cc: Mikael Starvik <starvik@axis.com>
Cc: Nadia Derbey <Nadia.Derbey@bull.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Osterlund <petero2@telia.com>
Cc: Pierre Peiffer <peifferp@gmail.com>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: Takashi Iwai <tiwai@suse.de>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Trond Myklebust <trond.myklebust@fys.uio.no>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/proc/generic.c | 8 | ||||
-rw-r--r-- | fs/proc/root.c | 2 | ||||
-rw-r--r-- | include/linux/proc_fs.h | 17 |
3 files changed, 21 insertions, 6 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 0f3d97d41b0f..9d53b39a9cf8 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -675,9 +675,10 @@ struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, | |||
675 | return ent; | 675 | return ent; |
676 | } | 676 | } |
677 | 677 | ||
678 | struct proc_dir_entry *proc_create(const char *name, mode_t mode, | 678 | struct proc_dir_entry *proc_create_data(const char *name, mode_t mode, |
679 | struct proc_dir_entry *parent, | 679 | struct proc_dir_entry *parent, |
680 | const struct file_operations *proc_fops) | 680 | const struct file_operations *proc_fops, |
681 | void *data) | ||
681 | { | 682 | { |
682 | struct proc_dir_entry *pde; | 683 | struct proc_dir_entry *pde; |
683 | nlink_t nlink; | 684 | nlink_t nlink; |
@@ -698,6 +699,7 @@ struct proc_dir_entry *proc_create(const char *name, mode_t mode, | |||
698 | if (!pde) | 699 | if (!pde) |
699 | goto out; | 700 | goto out; |
700 | pde->proc_fops = proc_fops; | 701 | pde->proc_fops = proc_fops; |
702 | pde->data = data; | ||
701 | if (proc_register(parent, pde) < 0) | 703 | if (proc_register(parent, pde) < 0) |
702 | goto out_free; | 704 | goto out_free; |
703 | return pde; | 705 | return pde; |
diff --git a/fs/proc/root.c b/fs/proc/root.c index c741b45a5503..95117538a4f6 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -230,5 +230,5 @@ void pid_ns_release_proc(struct pid_namespace *ns) | |||
230 | EXPORT_SYMBOL(proc_symlink); | 230 | EXPORT_SYMBOL(proc_symlink); |
231 | EXPORT_SYMBOL(proc_mkdir); | 231 | EXPORT_SYMBOL(proc_mkdir); |
232 | EXPORT_SYMBOL(create_proc_entry); | 232 | EXPORT_SYMBOL(create_proc_entry); |
233 | EXPORT_SYMBOL(proc_create); | 233 | EXPORT_SYMBOL(proc_create_data); |
234 | EXPORT_SYMBOL(remove_proc_entry); | 234 | EXPORT_SYMBOL(remove_proc_entry); |
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 29abcb805754..9883bc942262 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h | |||
@@ -116,9 +116,10 @@ void de_put(struct proc_dir_entry *de); | |||
116 | 116 | ||
117 | extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, | 117 | extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, |
118 | struct proc_dir_entry *parent); | 118 | struct proc_dir_entry *parent); |
119 | struct proc_dir_entry *proc_create(const char *name, mode_t mode, | 119 | struct proc_dir_entry *proc_create_data(const char *name, mode_t mode, |
120 | struct proc_dir_entry *parent, | 120 | struct proc_dir_entry *parent, |
121 | const struct file_operations *proc_fops); | 121 | const struct file_operations *proc_fops, |
122 | void *data); | ||
122 | extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent); | 123 | extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent); |
123 | 124 | ||
124 | extern struct vfsmount *proc_mnt; | 125 | extern struct vfsmount *proc_mnt; |
@@ -173,6 +174,12 @@ extern struct proc_dir_entry *proc_mkdir(const char *,struct proc_dir_entry *); | |||
173 | extern struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode, | 174 | extern struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode, |
174 | struct proc_dir_entry *parent); | 175 | struct proc_dir_entry *parent); |
175 | 176 | ||
177 | static inline struct proc_dir_entry *proc_create(const char *name, mode_t mode, | ||
178 | struct proc_dir_entry *parent, const struct file_operations *proc_fops) | ||
179 | { | ||
180 | return proc_create_data(name, mode, parent, proc_fops, NULL); | ||
181 | } | ||
182 | |||
176 | static inline struct proc_dir_entry *create_proc_read_entry(const char *name, | 183 | static inline struct proc_dir_entry *create_proc_read_entry(const char *name, |
177 | mode_t mode, struct proc_dir_entry *base, | 184 | mode_t mode, struct proc_dir_entry *base, |
178 | read_proc_t *read_proc, void * data) | 185 | read_proc_t *read_proc, void * data) |
@@ -214,6 +221,12 @@ static inline struct proc_dir_entry *proc_create(const char *name, | |||
214 | { | 221 | { |
215 | return NULL; | 222 | return NULL; |
216 | } | 223 | } |
224 | static inline struct proc_dir_entry *proc_create_data(const char *name, | ||
225 | mode_t mode, struct proc_dir_entry *parent, | ||
226 | const struct file_operations *proc_fops, void *data) | ||
227 | { | ||
228 | return NULL; | ||
229 | } | ||
217 | #define remove_proc_entry(name, parent) do {} while (0) | 230 | #define remove_proc_entry(name, parent) do {} while (0) |
218 | 231 | ||
219 | static inline struct proc_dir_entry *proc_symlink(const char *name, | 232 | static inline struct proc_dir_entry *proc_symlink(const char *name, |