Skip to content

Commit

Permalink
alpha: binfmt_aout fix
Browse files Browse the repository at this point in the history
This fixes the problem introduced by commit 3bfacef (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>
  • Loading branch information
Ivan Kokshaysky authored and Linus Torvalds committed May 2, 2009
1 parent 77b4cf5 commit 74641f5
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 6 deletions.
6 changes: 5 additions & 1 deletion arch/alpha/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ EXTRA_CFLAGS := -Werror -Wno-sign-compare

obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
irq_alpha.o signal.o setup.o ptrace.o time.o \
alpha_ksyms.o systbls.o err_common.o io.o binfmt_loader.o
alpha_ksyms.o systbls.o err_common.o io.o

obj-$(CONFIG_VGA_HOSE) += console.o
obj-$(CONFIG_SMP) += smp.o
Expand Down Expand Up @@ -43,6 +43,10 @@ else
# Misc support
obj-$(CONFIG_ALPHA_SRM) += srmcons.o

ifdef CONFIG_BINFMT_AOUT
obj-y += binfmt_loader.o
endif

# Core logic support
obj-$(CONFIG_ALPHA_APECS) += core_apecs.o
obj-$(CONFIG_ALPHA_CIA) += core_cia.o
Expand Down
2 changes: 1 addition & 1 deletion arch/alpha/kernel/binfmt_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,6 @@ static struct linux_binfmt loader_format = {

static int __init init_loader_binfmt(void)
{
return register_binfmt(&loader_format);
return insert_binfmt(&loader_format);
}
arch_initcall(init_loader_binfmt);
7 changes: 4 additions & 3 deletions fs/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,18 @@ int suid_dumpable = 0;
static LIST_HEAD(formats);
static DEFINE_RWLOCK(binfmt_lock);

int register_binfmt(struct linux_binfmt * fmt)
int __register_binfmt(struct linux_binfmt * fmt, int insert)
{
if (!fmt)
return -EINVAL;
write_lock(&binfmt_lock);
list_add(&fmt->lh, &formats);
insert ? list_add(&fmt->lh, &formats) :
list_add_tail(&fmt->lh, &formats);
write_unlock(&binfmt_lock);
return 0;
}

EXPORT_SYMBOL(register_binfmt);
EXPORT_SYMBOL(__register_binfmt);

void unregister_binfmt(struct linux_binfmt * fmt)
{
Expand Down
14 changes: 13 additions & 1 deletion include/linux/binfmts.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,19 @@ struct linux_binfmt {
int hasvdso;
};

extern int register_binfmt(struct linux_binfmt *);
extern int __register_binfmt(struct linux_binfmt *fmt, int insert);

/* Registration of default binfmt handlers */
static inline int register_binfmt(struct linux_binfmt *fmt)
{
return __register_binfmt(fmt, 0);
}
/* Same as above, but adds a new binfmt at the top of the list */
static inline int insert_binfmt(struct linux_binfmt *fmt)
{
return __register_binfmt(fmt, 1);
}

extern void unregister_binfmt(struct linux_binfmt *);

extern int prepare_binprm(struct linux_binprm *);
Expand Down

0 comments on commit 74641f5

Please sign in to comment.