/*
|
/*
|
* linux/fs/binfmt_flat.c
|
* linux/fs/binfmt_flat.c
|
*
|
*
|
* Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
|
* Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
|
* The Silver Hammer Group, Ltd.
|
* The Silver Hammer Group, Ltd.
|
*
|
*
|
* This is a relatively simple binary format, intended solely to contain
|
* This is a relatively simple binary format, intended solely to contain
|
* the bare minimum needed to load and execute simple binaries, with
|
* the bare minimum needed to load and execute simple binaries, with
|
* special attention to executing from ROM, when possible.
|
* special attention to executing from ROM, when possible.
|
*
|
*
|
* Originally based on:
|
* Originally based on:
|
*
|
*
|
* linux/fs/binfmt_aout.c
|
* linux/fs/binfmt_aout.c
|
*
|
*
|
* Copyright (C) 1991, 1992, 1996 Linus Torvalds
|
* Copyright (C) 1991, 1992, 1996 Linus Torvalds
|
*/
|
*/
|
|
|
|
|
#include <linux/module.h>
|
#include <linux/module.h>
|
|
|
#include <linux/fs.h>
|
#include <linux/fs.h>
|
#include <linux/sched.h>
|
#include <linux/sched.h>
|
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
#include <linux/mm.h>
|
#include <linux/mm.h>
|
#include <linux/mman.h>
|
#include <linux/mman.h>
|
#include <linux/a.out.h>
|
#include <linux/a.out.h>
|
#include <linux/errno.h>
|
#include <linux/errno.h>
|
#include <linux/signal.h>
|
#include <linux/signal.h>
|
#include <linux/string.h>
|
#include <linux/string.h>
|
#include <linux/stat.h>
|
#include <linux/stat.h>
|
#include <linux/fcntl.h>
|
#include <linux/fcntl.h>
|
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
#include <linux/user.h>
|
#include <linux/user.h>
|
#include <linux/malloc.h>
|
#include <linux/malloc.h>
|
#include <linux/binfmts.h>
|
#include <linux/binfmts.h>
|
#include <linux/personality.h>
|
#include <linux/personality.h>
|
|
|
#include <asm/system.h>
|
#include <asm/system.h>
|
#include <asm/segment.h>
|
#include <asm/segment.h>
|
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
#include <asm/flat.h>
|
#include <asm/flat.h>
|
|
|
#undef DEBUG
|
#undef DEBUG
|
|
|
static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);
|
static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);
|
|
|
extern void dump_thread(struct pt_regs *, struct user *);
|
extern void dump_thread(struct pt_regs *, struct user *);
|
|
|
static struct linux_binfmt flat_format = {
|
static struct linux_binfmt flat_format = {
|
#ifndef MODULE
|
#ifndef MODULE
|
NULL, NULL, load_flat_binary, NULL, NULL
|
NULL, NULL, load_flat_binary, NULL, NULL
|
#else
|
#else
|
NULL, &mod_use_count_, load_flat_binary, NULL, NULL
|
NULL, &mod_use_count_, load_flat_binary, NULL, NULL
|
#endif
|
#endif
|
};
|
};
|
|
|
static unsigned long putstring(unsigned long p, char * string)
|
static unsigned long putstring(unsigned long p, char * string)
|
{
|
{
|
unsigned long l = strlen(string)+1;
|
unsigned long l = strlen(string)+1;
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk("put_string '%s'\n", string);
|
printk("put_string '%s'\n", string);
|
#endif
|
#endif
|
p -= l;
|
p -= l;
|
memcpy((void*)p, string, l);
|
memcpy((void*)p, string, l);
|
return p;
|
return p;
|
}
|
}
|
|
|
static unsigned long putstringarray(unsigned long p, int count, char ** array)
|
static unsigned long putstringarray(unsigned long p, int count, char ** array)
|
{
|
{
|
/*p=putstring(p, "");*/
|
/*p=putstring(p, "");*/
|
/*printk("p1=%x, array=%x\n", p, array);
|
/*printk("p1=%x, array=%x\n", p, array);
|
printk("array[0]=%x\n", array[0]);*/
|
printk("array[0]=%x\n", array[0]);*/
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk("putstringarray(%d)\n", count);
|
printk("putstringarray(%d)\n", count);
|
#endif
|
#endif
|
while(count) {
|
while(count) {
|
p=putstring(p, array[--count]);
|
p=putstring(p, array[--count]);
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk("p2=%x\n", p);
|
printk("p2=%x\n", p);
|
#endif
|
#endif
|
}
|
}
|
return p;
|
return p;
|
}
|
}
|
|
|
static unsigned long stringarraylen(int count, char ** array)
|
static unsigned long stringarraylen(int count, char ** array)
|
{
|
{
|
int l = 4;
|
int l = 4;
|
while(count) {
|
while(count) {
|
l += strlen(array[--count]);
|
l += strlen(array[--count]);
|
l++;
|
l++;
|
l+=4;
|
l+=4;
|
}
|
}
|
return l;
|
return l;
|
}
|
}
|
|
|
/*
|
/*
|
* create_flat_tables() parses the env- and arg-strings in new user
|
* create_flat_tables() parses the env- and arg-strings in new user
|
* memory and creates the pointer tables from them, and puts their
|
* memory and creates the pointer tables from them, and puts their
|
* addresses on the "stack", returning the new stack pointer value.
|
* addresses on the "stack", returning the new stack pointer value.
|
*/
|
*/
|
static unsigned long create_flat_tables(unsigned long pp, struct linux_binprm * bprm)
|
static unsigned long create_flat_tables(unsigned long pp, struct linux_binprm * bprm)
|
{
|
{
|
unsigned long *argv,*envp;
|
unsigned long *argv,*envp;
|
unsigned long * sp;
|
unsigned long * sp;
|
char * p = (char*)pp;
|
char * p = (char*)pp;
|
int argc = bprm->argc;
|
int argc = bprm->argc;
|
int envc = bprm->envc;
|
int envc = bprm->envc;
|
|
|
sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);
|
sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);
|
#ifdef __alpha__
|
#ifdef __alpha__
|
/* whee.. test-programs are so much fun. */
|
/* whee.. test-programs are so much fun. */
|
put_user(0, --sp);
|
put_user(0, --sp);
|
put_user(0, --sp);
|
put_user(0, --sp);
|
if (bprm->loader) {
|
if (bprm->loader) {
|
put_user(0, --sp);
|
put_user(0, --sp);
|
put_user(0x3eb, --sp);
|
put_user(0x3eb, --sp);
|
put_user(bprm->loader, --sp);
|
put_user(bprm->loader, --sp);
|
put_user(0x3ea, --sp);
|
put_user(0x3ea, --sp);
|
}
|
}
|
put_user(bprm->exec, --sp);
|
put_user(bprm->exec, --sp);
|
put_user(0x3e9, --sp);
|
put_user(0x3e9, --sp);
|
#endif
|
#endif
|
sp -= envc+1;
|
sp -= envc+1;
|
envp = sp;
|
envp = sp;
|
sp -= argc+1;
|
sp -= argc+1;
|
argv = sp;
|
argv = sp;
|
#if defined(__i386__) || defined(__mc68000__)
|
#if defined(__i386__) || defined(__mc68000__)
|
put_user(envp,--sp);
|
put_user(envp,--sp);
|
put_user(argv,--sp);
|
put_user(argv,--sp);
|
#endif
|
#endif
|
put_user(argc,--sp);
|
put_user(argc,--sp);
|
current->mm->arg_start = (unsigned long) p;
|
current->mm->arg_start = (unsigned long) p;
|
while (argc-->0) {
|
while (argc-->0) {
|
put_user(p,argv++);
|
put_user(p,argv++);
|
while (get_user(p++)) /* nothing */ ;
|
while (get_user(p++)) /* nothing */ ;
|
}
|
}
|
put_user(NULL,argv);
|
put_user(NULL,argv);
|
current->mm->arg_end = current->mm->env_start = (unsigned long) p;
|
current->mm->arg_end = current->mm->env_start = (unsigned long) p;
|
while (envc-->0) {
|
while (envc-->0) {
|
put_user(p,envp++);
|
put_user(p,envp++);
|
while (get_user(p++)) /* nothing */ ;
|
while (get_user(p++)) /* nothing */ ;
|
}
|
}
|
put_user(NULL,envp);
|
put_user(NULL,envp);
|
current->mm->env_end = (unsigned long) p;
|
current->mm->env_end = (unsigned long) p;
|
return (unsigned long)sp;
|
return (unsigned long)sp;
|
}
|
}
|
|
|
void do_reloc(struct flat_reloc * r)
|
void do_reloc(struct flat_reloc * r)
|
{
|
{
|
unsigned long * ptr = (unsigned long*)
|
unsigned long * ptr = (unsigned long*)
|
(current->mm->start_data + r->offset);
|
(current->mm->start_data + r->offset);
|
|
|
|
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk("Relocation of variable at DATASEG+%x (address %p, currently %x) into segment %x+%x\n",
|
printk("Relocation of variable at DATASEG+%x (address %p, currently %x) into segment %x+%x\n",
|
r->offset, ptr, *ptr, r->type, *ptr);
|
r->offset, ptr, *ptr, r->type, *ptr);
|
|
|
printk("TEXTSEG=%x, DATASEG=%x, BSSSEG=%x\n",
|
printk("TEXTSEG=%x, DATASEG=%x, BSSSEG=%x\n",
|
current->mm->start_code,
|
current->mm->start_code,
|
current->mm->start_data,
|
current->mm->start_data,
|
current->mm->end_data);
|
current->mm->end_data);
|
|
|
printk("Relocation type = %d, offset = %d\n", r->type, r->offset);
|
printk("Relocation type = %d, offset = %d\n", r->type, r->offset);
|
#endif
|
#endif
|
|
|
switch (r->type) {
|
switch (r->type) {
|
case FLAT_RELOC_TYPE_TEXT:
|
case FLAT_RELOC_TYPE_TEXT:
|
*ptr += current->mm->start_code;
|
*ptr += current->mm->start_code;
|
break;
|
break;
|
case FLAT_RELOC_TYPE_DATA:
|
case FLAT_RELOC_TYPE_DATA:
|
*ptr += current->mm->start_data;
|
*ptr += current->mm->start_data;
|
break;
|
break;
|
case FLAT_RELOC_TYPE_BSS:
|
case FLAT_RELOC_TYPE_BSS:
|
*ptr += current->mm->end_data;
|
*ptr += current->mm->end_data;
|
break;
|
break;
|
default:
|
default:
|
printk("Unknown relocation\n");
|
printk("Unknown relocation\n");
|
}
|
}
|
|
|
|
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk("Relocation became %x\n", *ptr);
|
printk("Relocation became %x\n", *ptr);
|
#endif
|
#endif
|
}
|
}
|
|
|
|
|
/*
|
/*
|
* These are the functions used to load a.out style executables and shared
|
* These are the functions used to load a.out style executables and shared
|
* libraries. There is no binary dependent code anywhere else.
|
* libraries. There is no binary dependent code anywhere else.
|
*/
|
*/
|
|
|
inline int
|
inline int
|
do_load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
|
do_load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
|
{
|
{
|
struct flat_hdr * hdr;
|
struct flat_hdr * hdr;
|
struct file * file;
|
struct file * file;
|
unsigned long error;
|
unsigned long error;
|
unsigned long pos;
|
unsigned long pos;
|
unsigned long p = bprm->p;
|
unsigned long p = bprm->p;
|
unsigned long data_len, bss_len, stack_len, code_len;
|
unsigned long data_len, bss_len, stack_len, code_len;
|
|
|
|
|
current->personality = PER_LINUX;
|
current->personality = PER_LINUX;
|
|
|
file = current->files->fd[open_inode(bprm->inode, O_RDONLY)];
|
file = current->files->fd[open_inode(bprm->inode, O_RDONLY)];
|
|
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk("BINFMT_FLAT: Loading file: %x\n", file);
|
printk("BINFMT_FLAT: Loading file: %x\n", file);
|
show_free_areas();
|
show_free_areas();
|
#endif
|
#endif
|
|
|
hdr = (struct flat_hdr*)bprm->buf;
|
hdr = (struct flat_hdr*)bprm->buf;
|
|
|
if (strncmp(hdr->magic, "bFLT", 4) || (hdr->rev != 2)) {
|
if (strncmp(hdr->magic, "bFLT", 4) || (hdr->rev != 2)) {
|
printk("bad magic/rev (%ld, need %d)\n", hdr->rev, 2);
|
printk("bad magic/rev (%ld, need %d)\n", hdr->rev, 2);
|
return -ENOEXEC;
|
return -ENOEXEC;
|
}
|
}
|
|
|
if (flush_old_exec(bprm)) {
|
if (flush_old_exec(bprm)) {
|
printk("unable to flush\n");
|
printk("unable to flush\n");
|
return -ENOMEM;
|
return -ENOMEM;
|
}
|
}
|
|
|
/*printk("hdr->entry = %d, hdr->data_start = %d, hdr->data_end = %d, hdr->bss_end = %d, hdr->stack_size = %d\n",
|
/*printk("hdr->entry = %d, hdr->data_start = %d, hdr->data_end = %d, hdr->bss_end = %d, hdr->stack_size = %d\n",
|
hdr->entry, hdr->data_start, hdr->data_end,
|
hdr->entry, hdr->data_start, hdr->data_end,
|
hdr->bss_end, hdr->stack_size);*/
|
hdr->bss_end, hdr->stack_size);*/
|
|
|
/* OK, This is the point of no return */
|
/* OK, This is the point of no return */
|
|
|
code_len = hdr->data_start;
|
code_len = hdr->data_start;
|
data_len = hdr->data_end - hdr->data_start;
|
data_len = hdr->data_end - hdr->data_start;
|
bss_len = hdr->bss_end - hdr->data_end;
|
bss_len = hdr->bss_end - hdr->data_end;
|
stack_len = hdr->stack_size;
|
stack_len = hdr->stack_size;
|
|
|
/* Make room on stack for arguments & environment */
|
/* Make room on stack for arguments & environment */
|
stack_len += strlen(bprm->filename) + 1;
|
stack_len += strlen(bprm->filename) + 1;
|
stack_len += stringarraylen(bprm->envc, bprm->envp);
|
stack_len += stringarraylen(bprm->envc, bprm->envp);
|
stack_len += stringarraylen(bprm->argc, bprm->argv);
|
stack_len += stringarraylen(bprm->argc, bprm->argv);
|
|
|
/*stack_len += 4-((pos+data_len+bss_len+stack_len) & 3);*/ /* Align stack */
|
/*stack_len += 4-((pos+data_len+bss_len+stack_len) & 3);*/ /* Align stack */
|
|
|
/*printk("Stack = %d, (%d)\n", stack_len, stack_len & 3);*/
|
/*printk("Stack = %d, (%d)\n", stack_len, stack_len & 3);*/
|
|
|
error = do_mmap(file,
|
error = do_mmap(file,
|
0,
|
0,
|
code_len + data_len + bss_len + stack_len,
|
code_len + data_len + bss_len + stack_len,
|
PROT_READ|PROT_EXEC | ((hdr->flags & FLAT_FLAG_RAM) ? PROT_WRITE : 0),
|
PROT_READ|PROT_EXEC | ((hdr->flags & FLAT_FLAG_RAM) ? PROT_WRITE : 0),
|
0 /* MAP_* */,
|
0 /* MAP_* */,
|
0);
|
0);
|
|
|
if (error >= -4096) {
|
if (error >= -4096) {
|
printk("Unable to map flat executable, errno %d\n", (int)-error);
|
printk("Unable to map flat executable, errno %d\n", (int)-error);
|
return error; /* Beyond point of no return? Oh well... */
|
return error; /* Beyond point of no return? Oh well... */
|
}
|
}
|
|
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk("BINFMT_FLAT: mmap returned: %x\n", error);
|
printk("BINFMT_FLAT: mmap returned: %x\n", error);
|
show_free_areas();
|
show_free_areas();
|
#endif
|
#endif
|
|
|
current->mm->executable = 0;
|
current->mm->executable = 0;
|
|
|
if (is_in_rom(error)) {
|
if (is_in_rom(error)) {
|
unsigned long result;
|
unsigned long result;
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk("BINFMT_FLAT: ROM mapping of file\n");
|
printk("BINFMT_FLAT: ROM mapping of file\n");
|
#endif
|
#endif
|
/* do_mmap returned a ROM mapping, so allocate RAM for data + bss + stack */
|
/* do_mmap returned a ROM mapping, so allocate RAM for data + bss + stack */
|
/*pos = kmalloc(data_len+bss_len+stack_len, GFP_KERNEL);*/
|
/*pos = kmalloc(data_len+bss_len+stack_len, GFP_KERNEL);*/
|
pos = do_mmap(0, 0, data_len+bss_len+stack_len, PROT_READ|PROT_WRITE|PROT_EXEC, 0, 0);
|
pos = do_mmap(0, 0, data_len+bss_len+stack_len, PROT_READ|PROT_WRITE|PROT_EXEC, 0, 0);
|
if (pos >= (unsigned long)-4096) {
|
if (pos >= (unsigned long)-4096) {
|
printk("Unable to allocate RAM for process, errno %d\n", (int)-pos);
|
printk("Unable to allocate RAM for process, errno %d\n", (int)-pos);
|
return pos;
|
return pos;
|
}
|
}
|
|
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n", data_len+bss_len+stack_len, pos);
|
printk("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n", data_len+bss_len+stack_len, pos);
|
show_free_areas();
|
show_free_areas();
|
#endif
|
#endif
|
|
|
/* And then fill it in */
|
/* And then fill it in */
|
|
|
/*printk("Reading data from %d-%d to %x\n", hdr->data_start, hdr->data_end - hdr->data_start, pos);*/
|
/*printk("Reading data from %d-%d to %x\n", hdr->data_start, hdr->data_end - hdr->data_start, pos);*/
|
|
|
result = read_exec(bprm->inode, hdr->data_start, (char *)pos,
|
result = read_exec(bprm->inode, hdr->data_start, (char *)pos,
|
data_len, 0);
|
data_len, 0);
|
if (result >= (unsigned long)-4096) {
|
if (result >= (unsigned long)-4096) {
|
do_munmap(pos, 0);
|
do_munmap(pos, 0);
|
printk("Unable to read data+bss, errno %d\n", (int)-result);
|
printk("Unable to read data+bss, errno %d\n", (int)-result);
|
}
|
}
|
|
|
/*printk("Clearing %x to %x\n", pos+data_len, pos+data_len+bss_len+stack_len);*/
|
/*printk("Clearing %x to %x\n", pos+data_len, pos+data_len+bss_len+stack_len);*/
|
|
|
memset((void*)(pos + data_len), 0, bss_len + stack_len);
|
memset((void*)(pos + data_len), 0, bss_len + stack_len);
|
|
|
if (bprm->inode->i_sb->s_flags & MS_SYNCHRONOUS) {
|
if (bprm->inode->i_sb->s_flags & MS_SYNCHRONOUS) {
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk("Retaining inode\n");
|
printk("Retaining inode\n");
|
#endif
|
#endif
|
current->mm->executable = bprm->inode;
|
current->mm->executable = bprm->inode;
|
bprm->inode->i_count++;
|
bprm->inode->i_count++;
|
}
|
}
|
|
|
} else {
|
} else {
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk("BINFMT_FLAT: RAM mapping of file\n");
|
printk("BINFMT_FLAT: RAM mapping of file\n");
|
#endif
|
#endif
|
|
|
/* Since we got a RAM mapping, mmap has already allocated a block for us, and
|
/* Since we got a RAM mapping, mmap has already allocated a block for us, and
|
read in the data. . */
|
read in the data. . */
|
|
|
pos = error + code_len;
|
pos = error + code_len;
|
|
|
}
|
}
|
|
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk("ROM mapping is %x, Entry point is %x, data_start is %x\n", error, hdr->entry, hdr->data_start);
|
printk("ROM mapping is %x, Entry point is %x, data_start is %x\n", error, hdr->entry, hdr->data_start);
|
#endif
|
#endif
|
|
|
current->mm->start_code = error + hdr->entry;
|
current->mm->start_code = error + hdr->entry;
|
current->mm->end_code = error + hdr->data_start;
|
current->mm->end_code = error + hdr->data_start;
|
current->mm->start_data = pos;
|
current->mm->start_data = pos;
|
|
|
current->mm->end_data = pos + data_len;
|
current->mm->end_data = pos + data_len;
|
current->mm->brk = pos + data_len + bss_len;
|
current->mm->brk = pos + data_len + bss_len;
|
|
|
/*printk("start_code: %x, end_code: %x\n", current->mm->start_code,current->mm->end_code);
|
/*printk("start_code: %x, end_code: %x\n", current->mm->start_code,current->mm->end_code);
|
printk("start_data: %x, end_data: %x\n", current->mm->start_data,current->mm->end_data);*/
|
printk("start_data: %x, end_data: %x\n", current->mm->start_data,current->mm->end_data);*/
|
|
|
/*printk("Loaded flat file, BSS=%x, DATA=%x, TEXT=%x\n",
|
/*printk("Loaded flat file, BSS=%x, DATA=%x, TEXT=%x\n",
|
current->mm->end_data,
|
current->mm->end_data,
|
current->mm->start_data,
|
current->mm->start_data,
|
current->mm->start_code);*/
|
current->mm->start_code);*/
|
|
|
if (is_in_rom(error)) {
|
if (is_in_rom(error)) {
|
int r;
|
int r;
|
for(r=0;r<hdr->reloc_count;r++) {
|
for(r=0;r<hdr->reloc_count;r++) {
|
struct flat_reloc * reloc = (struct flat_reloc*)
|
struct flat_reloc * reloc = (struct flat_reloc*)
|
(error + hdr->reloc_start + (sizeof(struct flat_reloc)*r));
|
(error + hdr->reloc_start + (sizeof(struct flat_reloc)*r));
|
do_reloc(reloc);
|
do_reloc(reloc);
|
}
|
}
|
} else {
|
} else {
|
int r;
|
int r;
|
for(r=0;r<hdr->reloc_count;r++) {
|
for(r=0;r<hdr->reloc_count;r++) {
|
struct flat_reloc reloc;
|
struct flat_reloc reloc;
|
unsigned long result = read_exec(bprm->inode,
|
unsigned long result = read_exec(bprm->inode,
|
hdr->reloc_start + (sizeof(struct flat_reloc)*r),
|
hdr->reloc_start + (sizeof(struct flat_reloc)*r),
|
(char *)&reloc,
|
(char *)&reloc,
|
sizeof(struct flat_reloc),
|
sizeof(struct flat_reloc),
|
0);
|
0);
|
if (result >= (unsigned long)-4096) {
|
if (result >= (unsigned long)-4096) {
|
printk("Failure reloading relocation\n");
|
printk("Failure reloading relocation\n");
|
} else
|
} else
|
do_reloc(&reloc);
|
do_reloc(&reloc);
|
}
|
}
|
}
|
}
|
|
|
current->mm->rss = 0;
|
current->mm->rss = 0;
|
current->suid = current->euid = current->fsuid = bprm->e_uid;
|
current->suid = current->euid = current->fsuid = bprm->e_uid;
|
current->sgid = current->egid = current->fsgid = bprm->e_gid;
|
current->sgid = current->egid = current->fsgid = bprm->e_gid;
|
current->flags &= ~PF_FORKNOEXEC;
|
current->flags &= ~PF_FORKNOEXEC;
|
|
|
|
|
|
|
/*for(i=0;i<16;i++) {
|
/*for(i=0;i<16;i++) {
|
printk("%.2x ", ((char*)pos)[i] & 0xff);
|
printk("%.2x ", ((char*)pos)[i] & 0xff);
|
}
|
}
|
printk("\n");*/
|
printk("\n");*/
|
|
|
|
|
|
|
if (current->exec_domain && current->exec_domain->use_count)
|
if (current->exec_domain && current->exec_domain->use_count)
|
(*current->exec_domain->use_count)--;
|
(*current->exec_domain->use_count)--;
|
if (current->binfmt && current->binfmt->use_count)
|
if (current->binfmt && current->binfmt->use_count)
|
(*current->binfmt->use_count)--;
|
(*current->binfmt->use_count)--;
|
current->exec_domain = lookup_exec_domain(current->personality);
|
current->exec_domain = lookup_exec_domain(current->personality);
|
current->binfmt = &flat_format;
|
current->binfmt = &flat_format;
|
if (current->exec_domain && current->exec_domain->use_count)
|
if (current->exec_domain && current->exec_domain->use_count)
|
(*current->exec_domain->use_count)++;
|
(*current->exec_domain->use_count)++;
|
if (current->binfmt && current->binfmt->use_count)
|
if (current->binfmt && current->binfmt->use_count)
|
(*current->binfmt->use_count)++;
|
(*current->binfmt->use_count)++;
|
|
|
/*set_brk(current->mm->start_brk, current->mm->brk);*/
|
/*set_brk(current->mm->start_brk, current->mm->brk);*/
|
|
|
p = pos + data_len + bss_len + stack_len - 4;
|
p = pos + data_len + bss_len + stack_len - 4;
|
|
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk("p=%x\n", p);
|
printk("p=%x\n", p);
|
#endif
|
#endif
|
|
|
p = putstringarray(p, 1, &bprm->filename);
|
p = putstringarray(p, 1, &bprm->filename);
|
|
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk("p(filename)=%x\n", p);
|
printk("p(filename)=%x\n", p);
|
#endif
|
#endif
|
|
|
p = putstringarray(p, bprm->envc, bprm->envp);
|
p = putstringarray(p, bprm->envc, bprm->envp);
|
|
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk("p(envp)=%x\n", p);
|
printk("p(envp)=%x\n", p);
|
#endif
|
#endif
|
|
|
p = putstringarray(p, bprm->argc, bprm->argv);
|
p = putstringarray(p, bprm->argc, bprm->argv);
|
|
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk("p(argv)=%x\n", p);
|
printk("p(argv)=%x\n", p);
|
#endif
|
#endif
|
|
|
p = create_flat_tables(p, bprm);
|
p = create_flat_tables(p, bprm);
|
|
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printk("p(create_flat_tables)=%x\n", p);
|
printk("p(create_flat_tables)=%x\n", p);
|
|
|
printk("arg_start = %x\n", current->mm->arg_start);
|
printk("arg_start = %x\n", current->mm->arg_start);
|
printk("arg_end = %x\n", current->mm->arg_end);
|
printk("arg_end = %x\n", current->mm->arg_end);
|
printk("env_start = %x\n", current->mm->env_start);
|
printk("env_start = %x\n", current->mm->env_start);
|
printk("env_end = %x\n", current->mm->env_end);
|
printk("env_end = %x\n", current->mm->env_end);
|
#endif
|
#endif
|
|
|
current->mm->start_stack = p;
|
current->mm->start_stack = p;
|
|
|
/*printk("start_stack: %x\n", current->mm->start_stack);*/
|
/*printk("start_stack: %x\n", current->mm->start_stack);*/
|
|
|
/*(*(volatile unsigned char *)0xdeadbee0) = 1;*/
|
/*(*(volatile unsigned char *)0xdeadbee0) = 1;*/
|
|
|
#ifdef DEBUG
|
#ifdef DEBUG
|
show_free_areas();
|
show_free_areas();
|
#endif
|
#endif
|
|
|
start_thread(regs, current->mm->start_code /*, current->mm->start_data*/ /*- hdr->data_start*/, p);
|
start_thread(regs, current->mm->start_code /*, current->mm->start_data*/ /*- hdr->data_start*/, p);
|
|
|
if (current->flags & PF_PTRACED)
|
if (current->flags & PF_PTRACED)
|
send_sig(SIGTRAP, current, 0);
|
send_sig(SIGTRAP, current, 0);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
static int
|
static int
|
load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
|
load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
|
{
|
{
|
int retval;
|
int retval;
|
|
|
MOD_INC_USE_COUNT;
|
MOD_INC_USE_COUNT;
|
retval = do_load_flat_binary(bprm, regs);
|
retval = do_load_flat_binary(bprm, regs);
|
MOD_DEC_USE_COUNT;
|
MOD_DEC_USE_COUNT;
|
return retval;
|
return retval;
|
}
|
}
|
|
|
int init_flat_binfmt(void) {
|
int init_flat_binfmt(void) {
|
return register_binfmt(&flat_format);
|
return register_binfmt(&flat_format);
|
}
|
}
|
|
|
#ifdef MODULE
|
#ifdef MODULE
|
int init_module(void) {
|
int init_module(void) {
|
return init_flat_binfmt();
|
return init_flat_binfmt();
|
}
|
}
|
|
|
void cleanup_module( void) {
|
void cleanup_module( void) {
|
unregister_binfmt(&flat_format);
|
unregister_binfmt(&flat_format);
|
}
|
}
|
#endif
|
#endif
|
|
|
|
|