Use list_head in binfmt handling
Switch single-linked binfmt formats list to usual list_head's. This leads to one-liners in register_binfmt() and unregister_binfmt(). The downside is one pointer more in struct linux_binfmt. This is not a problem, since the set of registered binfmts on typical box is very small -- (ELF + something distro enabled for you). Test-booted, played with executable .txt files, modprobe/rmmod binfmt_misc. Signed-off-by: Alexey Dobriyan <adobriyan@sw.ru> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
deba0f49b9
commit
e4dc1b14d8
4 changed files with 17 additions and 33 deletions
|
@ -47,8 +47,11 @@ static int irix_core_dump(long signr, struct pt_regs * regs,
|
||||||
struct file *file);
|
struct file *file);
|
||||||
|
|
||||||
static struct linux_binfmt irix_format = {
|
static struct linux_binfmt irix_format = {
|
||||||
NULL, THIS_MODULE, load_irix_binary, load_irix_library,
|
.module = THIS_MODULE,
|
||||||
irix_core_dump, PAGE_SIZE
|
.load_binary = load_irix_binary,
|
||||||
|
.load_shlib = load_irix_library,
|
||||||
|
.core_dump = irix_core_dump,
|
||||||
|
.min_coredump = PAGE_SIZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Debugging routines. */
|
/* Debugging routines. */
|
||||||
|
|
|
@ -38,8 +38,11 @@ static int load_aout32_library(struct file*);
|
||||||
static int aout32_core_dump(long signr, struct pt_regs * regs, struct file *file);
|
static int aout32_core_dump(long signr, struct pt_regs * regs, struct file *file);
|
||||||
|
|
||||||
static struct linux_binfmt aout32_format = {
|
static struct linux_binfmt aout32_format = {
|
||||||
NULL, THIS_MODULE, load_aout32_binary, load_aout32_library, aout32_core_dump,
|
.module = THIS_MODULE,
|
||||||
PAGE_SIZE
|
.load_binary = load_aout32_binary,
|
||||||
|
.load_shlib = load_aout32_library,
|
||||||
|
.core_dump = aout32_core_dump,
|
||||||
|
.min_coredump = PAGE_SIZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void set_brk(unsigned long start, unsigned long end)
|
static void set_brk(unsigned long start, unsigned long end)
|
||||||
|
|
34
fs/exec.c
34
fs/exec.c
|
@ -66,27 +66,15 @@ int suid_dumpable = 0;
|
||||||
EXPORT_SYMBOL(suid_dumpable);
|
EXPORT_SYMBOL(suid_dumpable);
|
||||||
/* The maximal length of core_pattern is also specified in sysctl.c */
|
/* The maximal length of core_pattern is also specified in sysctl.c */
|
||||||
|
|
||||||
static struct linux_binfmt *formats;
|
static LIST_HEAD(formats);
|
||||||
static DEFINE_RWLOCK(binfmt_lock);
|
static DEFINE_RWLOCK(binfmt_lock);
|
||||||
|
|
||||||
int register_binfmt(struct linux_binfmt * fmt)
|
int register_binfmt(struct linux_binfmt * fmt)
|
||||||
{
|
{
|
||||||
struct linux_binfmt ** tmp = &formats;
|
|
||||||
|
|
||||||
if (!fmt)
|
if (!fmt)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (fmt->next)
|
|
||||||
return -EBUSY;
|
|
||||||
write_lock(&binfmt_lock);
|
write_lock(&binfmt_lock);
|
||||||
while (*tmp) {
|
list_add(&fmt->lh, &formats);
|
||||||
if (fmt == *tmp) {
|
|
||||||
write_unlock(&binfmt_lock);
|
|
||||||
return -EBUSY;
|
|
||||||
}
|
|
||||||
tmp = &(*tmp)->next;
|
|
||||||
}
|
|
||||||
fmt->next = formats;
|
|
||||||
formats = fmt;
|
|
||||||
write_unlock(&binfmt_lock);
|
write_unlock(&binfmt_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -95,20 +83,10 @@ EXPORT_SYMBOL(register_binfmt);
|
||||||
|
|
||||||
int unregister_binfmt(struct linux_binfmt * fmt)
|
int unregister_binfmt(struct linux_binfmt * fmt)
|
||||||
{
|
{
|
||||||
struct linux_binfmt ** tmp = &formats;
|
|
||||||
|
|
||||||
write_lock(&binfmt_lock);
|
write_lock(&binfmt_lock);
|
||||||
while (*tmp) {
|
list_del(&fmt->lh);
|
||||||
if (fmt == *tmp) {
|
|
||||||
*tmp = fmt->next;
|
|
||||||
fmt->next = NULL;
|
|
||||||
write_unlock(&binfmt_lock);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
tmp = &(*tmp)->next;
|
|
||||||
}
|
|
||||||
write_unlock(&binfmt_lock);
|
write_unlock(&binfmt_lock);
|
||||||
return -EINVAL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(unregister_binfmt);
|
EXPORT_SYMBOL(unregister_binfmt);
|
||||||
|
@ -155,7 +133,7 @@ asmlinkage long sys_uselib(const char __user * library)
|
||||||
struct linux_binfmt * fmt;
|
struct linux_binfmt * fmt;
|
||||||
|
|
||||||
read_lock(&binfmt_lock);
|
read_lock(&binfmt_lock);
|
||||||
for (fmt = formats ; fmt ; fmt = fmt->next) {
|
list_for_each_entry(fmt, &formats, lh) {
|
||||||
if (!fmt->load_shlib)
|
if (!fmt->load_shlib)
|
||||||
continue;
|
continue;
|
||||||
if (!try_module_get(fmt->module))
|
if (!try_module_get(fmt->module))
|
||||||
|
@ -1284,7 +1262,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
|
||||||
retval = -ENOENT;
|
retval = -ENOENT;
|
||||||
for (try=0; try<2; try++) {
|
for (try=0; try<2; try++) {
|
||||||
read_lock(&binfmt_lock);
|
read_lock(&binfmt_lock);
|
||||||
for (fmt = formats ; fmt ; fmt = fmt->next) {
|
list_for_each_entry(fmt, &formats, lh) {
|
||||||
int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
|
int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
|
||||||
if (!fn)
|
if (!fn)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -63,7 +63,7 @@ struct linux_binprm{
|
||||||
* linux accepts.
|
* linux accepts.
|
||||||
*/
|
*/
|
||||||
struct linux_binfmt {
|
struct linux_binfmt {
|
||||||
struct linux_binfmt * next;
|
struct list_head lh;
|
||||||
struct module *module;
|
struct module *module;
|
||||||
int (*load_binary)(struct linux_binprm *, struct pt_regs * regs);
|
int (*load_binary)(struct linux_binprm *, struct pt_regs * regs);
|
||||||
int (*load_shlib)(struct file *);
|
int (*load_shlib)(struct file *);
|
||||||
|
|
Loading…
Reference in a new issue