diff options
author | Ivan Kokshaysky <ink@jurassic.park.msu.ru> | 2009-04-30 18:08:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-05-02 18:36:10 -0400 |
commit | 74641f584da8eccf30becfbb5507ab457187db22 (patch) | |
tree | da212b7ae1b5a2a50a4314b3a75df5763623295e /fs/exec.c | |
parent | 77b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ec (diff) |
alpha: binfmt_aout fix
This fixes the problem introduced by commit 3bfacef412 (get rid of
special-casing the /sbin/loader on alpha): osf/1 ecoff binary segfaults
when binfmt_aout built as module. That happens because aout binary
handler gets on the top of the binfmt list due to late registration, and
kernel attempts to execute the binary without preparatory work that must
be done by binfmt_loader.
Fixed by changing the registration order of the default binfmt handlers
using list_add_tail() and introducing insert_binfmt() function which
places new handler on the top of the binfmt list. This might be generally
useful for installing arch-specific frontends for default handlers or just
for overriding them.
Signed-off-by: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Richard Henderson <rth@twiddle.net
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 7 |
1 files changed, 4 insertions, 3 deletions
@@ -69,17 +69,18 @@ int suid_dumpable = 0; | |||
69 | static LIST_HEAD(formats); | 69 | static LIST_HEAD(formats); |
70 | static DEFINE_RWLOCK(binfmt_lock); | 70 | static DEFINE_RWLOCK(binfmt_lock); |
71 | 71 | ||
72 | int register_binfmt(struct linux_binfmt * fmt) | 72 | int __register_binfmt(struct linux_binfmt * fmt, int insert) |
73 | { | 73 | { |
74 | if (!fmt) | 74 | if (!fmt) |
75 | return -EINVAL; | 75 | return -EINVAL; |
76 | write_lock(&binfmt_lock); | 76 | write_lock(&binfmt_lock); |
77 | list_add(&fmt->lh, &formats); | 77 | insert ? list_add(&fmt->lh, &formats) : |
78 | list_add_tail(&fmt->lh, &formats); | ||
78 | write_unlock(&binfmt_lock); | 79 | write_unlock(&binfmt_lock); |
79 | return 0; | 80 | return 0; |
80 | } | 81 | } |
81 | 82 | ||
82 | EXPORT_SYMBOL(register_binfmt); | 83 | EXPORT_SYMBOL(__register_binfmt); |
83 | 84 | ||
84 | void unregister_binfmt(struct linux_binfmt * fmt) | 85 | void unregister_binfmt(struct linux_binfmt * fmt) |
85 | { | 86 | { |