The file /usr/lib/ibcs/coff/binfmt-coff.c:
* committed to being defined or a segmentation violation will occur.
*/
if (binary) {
COFF_SCNHDR *sect_ptr2 = sect_bufr;
u_long personality = PER_SVR3;
int i;
if ((status = flush_old_exec(bprm)))
goto out_free_file;
/*
* Look for clues as to the system this binary was compiled
* on in the comments section(s).
*
* Only look at the main binary, not the shared libraries
* (or would it be better to prefer shared libraries over
* binaries? Or could they be different???)
*/
for (i = 0; i < sections; i++) {
long sect_flags = COFF_LONG(sect_ptr2->s_flags);
if (sect_flags == COFF_STYP_INFO &&
(status = coff_parse_comments(bprm->file,
sect_ptr2, &personality)) > 0)
goto found;
sect_ptr2 = (COFF_SCNHDR *) &((char *)sect_ptr2)[COFF_SC
NHSZ];
}
/*
* If no .comments section was found there is no way to
* figure out the personality. Odds on it is SCO though...
*/
personality = PER_SCOSVR3;
found:
if (lPers) personality = lPers;
if ( (personality & 0xFF) == (current->personality & 0xFF) ) set
_personality(0);
set_personality(personality);
#if defined(CONFIG_ABI_TRACE)
abi_trace(ABI_TRACE_UNIMPL,"Personality %08lX assigned
",personality);
#endif
#ifdef CONFIG_64BIT
set_thread_flag(TIF_IA32);
clear_thread_flag(TIF_ABI_PENDING);
#endif
current->mm->start_data = 0;
current->mm->end_data = 0;
current->mm->end_code = 0;
current->mm->mmap = NULL;
current->flags &= ~PF_FORKNOEXEC;
#ifdef set_mm_counter
#if _KSL > 14
set_mm_counter(current->mm, file_rss, 0);
#else
set_mm_counter(current->mm, rss, 0);
#endif
#else
current->mm->rss = 0;
#endif
/*
* Construct the parameter and environment
* string table entries.
*/
#if _KSL > 10
if ((status = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT))
< 0)
#else
if ((status = setup_arg_pages(bprm, EXSTACK_DEFAULT)) < 0)
#endif
goto sigsegv;
p = (u_long)coff_mktables((char *)bprm->p,
bprm->argc, bprm->envc);
current->mm->end_code = text.size +
(current->mm->start_code = text.vaddr);
current->mm->end_data = data.size +
(current->mm->start_data = data.vaddr);
current->mm->brk = bss.size +
(current->mm->start_brk = bss.vaddr);
current->mm->start_stack = p;
compute_creds(bprm);
#if _KSL < 15
#ifdef CONFIG_64BIT
__asm__ volatile (
"movl %0,%%fs; movl %0,%%es; movl %0,%%ds"
: :"r" (0));
__asm__ volatile (
"pushf; cli; swapgs; movl %0,%%gs; mfence; swapgs; popf"
: :"r" (0));
write_pda(oldrsp,p);
_FLG(regs) = 0x200;
#else
__asm__ volatile (
"movl %0,%%fs ; movl %0,%%gs"
: :"r" (0));
_DS(regs) = _ES(regs) = __USER_DS;
#endif
_SS(regs) = __USER_DS;
_SP(regs) = p;
_CS(regs) = __USER_CS;
_IP(regs) = start_addr;
set_fs(USER_DS);
#else
start_thread(regs, start_addr, p);
#endif
#ifdef CONFIG_64BIT
__asm__ volatile("movl %0,%%es; movl %0,%%ds": :"r" (__USER32_DS));
_SS(regs) = __USER32_DS;
_CS(regs) = __USER32_CS;
#endif
}
old_fs = get_fs();
set_fs(get_ds());
if (!pageable) {
/*
* Read the file from disk...
*
* XXX: untested.
*/
loff_t pos = data.scnptr;
status = do_brk(text.vaddr, text.size);
bprm->file->f_op->read(bprm->file,
(char *)data.vaddr, data.scnptr, &pos);
status = do_brk(data.vaddr, data.size);
bprm->file->f_op->read(bprm->file,
(char *)text.vaddr, text.scnptr, &pos);
status = 0;
} else {
/* map the text pages...*/
cap_raise(current->cap_effective,CAP_SYS_RAWIO);
m_addr = map_coff(bprm->file, &text, PROT_READ | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE
,
text.scnptr & PAGE_MASK);
if(!ce) cap_lower(current->cap_effective,CAP_SYS_RAWIO);
if (m_addr != (text.vaddr & PAGE_MASK)) {
status = -ENOEXEC;
set_fs(old_fs);
goto out_free_file;
}
/* map the data pages */
if (data.size != 0) {
cap_raise(current->cap_effective,CAP_SYS_RAWIO);
m_addr = map_coff(bprm->file, &data,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUT
ABLE,
data.scnptr & PAGE_MASK);
if(!ce) cap_lower(current->cap_effective,CAP_SYS_RAWIO);
if (m_addr != (data.vaddr & PAGE_MASK)) {
status = -ENOEXEC;
set_fs(old_fs);
goto out_free_file;
}
}
status = 0;
}
/*
* Construct the bss data for the process. The bss ranges from the
* end of the data (which may not be on a page boundary) to the end
* of the bss section. Allocate any necessary pages for the data.
*/
if (bss.size != 0) {
cap_raise(current->cap_effective,CAP_SYS_RAWIO);
down_write(¤t->mm->mmap_sem);
do_mmap(NULL, PAGE_ALIGN(bss.vaddr),
bss.size + bss.vaddr -
PAGE_ALIGN(bss.vaddr),
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_32BIT, 0);
up_write(¤t->mm->mmap_sem);
if(!ce) cap_lower(current->cap_effective,CAP_SYS_RAWIO);
if ((status = coff_clear_memory(bss.vaddr, bss.size)) < 0) {
set_fs(old_fs);
goto out_free_file;
}
}
set_fs(old_fs);
if (!binary)
goto out_free_file;
/*
* Load any shared library for the executable.
*/
if (lib_count)
status = coff_preload_shlibs(bprm, sect_bufr, sections);
set_binfmt(&coff_format);
/*
* Generate any needed trap for this process. If an error occured then
* generate a segmentation violation. If the process is being debugged
* then generate the load trap. (Note: If this is a library load then
* do not generate the trap here. Pass the error to the caller who
* will do it for the process in the outer lay of this procedure call.)
*/
if (status < 0) {
sigsegv:
printk(KERN_WARNING "coff: trapping process with SEGV
");
send_sig(SIGSEGV, current, 0); /* Generate the error trap */
}
#ifdef CONFIG_PTRACE
/* --- Red Hat specific handling --- */
#else
else if (current->ptrace & PT_PTRACED)
send_sig(SIGTRAP, current, 0);
#endif
/* We are committed. It can't fail */
status = 0;
out_free_file:
SYS(close,coff_exec_fileno);
out_free_buf:
kfree(sect_bufr);
return (status);
}
/*
* This procedure is called to load a library section. The various
* libraries are loaded from the list given in the section data.
*/
static int
coff_preload_shlib(struct linux_binprm *exe_bprm, COFF_SCNHDR *sect)
{
COFF_SLIBHD *phdr;
char *buffer;
long nbytes;
int err = 0;
/*
* Fetch the size of the section. There must be
* enough room for at least one entry.
*/
nbytes = (long)COFF_LONG(sect->s_size);
if (nbytes < (long)COFF_SLIBSZ)
return -ENOEXEC;
if (!(buffer = kmalloc(nbytes, GFP_KERNEL))) {
printk(KERN_WARNING "coff: unable to allocate shlib buffer
");
return -ENOMEM;
}
err = kernel_read(exe_bprm->file,
COFF_LONG(sect->s_scnptr), buffer, nbytes);
if (err < 0)
goto out;
if (err != nbytes)
goto enoexec;
/*
* Go through the list of libraries in the data area.
*/
phdr = (COFF_SLIBHD *)buffer;
while (nbytes > (long)COFF_SLIBSZ) {
int entry_size, header_size;
mm_segment_t old_fs = get_fs();
entry_size = COFF_LONG(phdr->sl_entsz) * 4;
header_size = COFF_LONG(phdr->sl_pathndx) * 4;
/*
* Validate the sizes of the various items.
* I don't trust the linker!!
*/
if ((u_int)header_size >= (u_int)nbytes)
goto enoexec;
if ((u_int)entry_size <= (u_int)header_size)
goto enoexec;
if (entry_size <= 0)
goto enoexec;
set_fs(get_ds());
err = SYS(uselib,&((char *)phdr)[header_size]);
set_fs(old_fs);
if (err < 0)
goto out;
/*
* Point to the next library in the section data.
*/
nbytes -= entry_size;
phdr = (COFF_SLIBHD *) & ((char *) phdr)[entry_size];
}
out:
kfree(buffer);
return (err);
enoexec:
err = -ENOEXEC;
goto out;
}
/*
* Find all library sections and preload the shared libraries.
*
* This will eventually recurse to our code and load the shared
* library with our own procedures.
*/
static int
coff_preload_shlibs(struct linux_binprm *bpp, COFF_SCNHDR *sp, int sections)
{
long flags;
int err = 0, i;
for (i = 0; i < sections; i++) {
flags = COFF_LONG(sp->s_flags);
if (flags == COFF_STYP_LIB) {
if ((err = coff_preload_shlib(bpp, sp)))
break;
}
sp = (COFF_SCNHDR *)&((char *)sp)[COFF_SCNHSZ];
}
return (err);
}
/*
* Load the image for an (coff) binary.
*
* => this procedure is called by the main load sequence,
* it will load the executable and prepare it for execution
*/
static int
coff_load_binary(struct linux_binprm *bpp, struct pt_regs *rp)
{
int ret;
ret = coff_load_object(bpp, rp, 1);
if (ret >= 0) SYS(vserver,rp);
return ret;
}
/*
* Load the image for a (coff) shared library.
*
* => this is called when we need to load a library based upon a file name.
* => also called through coff_preload_shlib
*/
static int
coff_load_shlib(struct file *fp)
{
struct linux_binprm *bpp;
struct pt_regs regs;
int err = -ENOMEM;
if (!(bpp = kmalloc(sizeof(struct linux_binprm), GFP_KERNEL))) {
printk(KERN_WARNING "coff: kmalloc failed
");
goto out;
}
memset(bpp, 0, sizeof(struct linux_binprm));
bpp->file = fp;
if ((err = kernel_read(fp, 0L, bpp->buf, sizeof(bpp->buf))) < 0)
printk(KERN_WARNING "coff: unable to read library header
");
else
err = coff_load_object(bpp, ®s, 0);
kfree(bpp);
out:
return (err);
}
static int __init
coff_module_init(void)
{
return (register_binfmt(&coff_format));
}
static void __exit
coff_module_exit(void)
{
unregister_binfmt(&coff_format);
}
module_init(coff_module_init);
module_exit(coff_module_exit);
(Is there a way to include a file like the above without having to quote it? I take it it makes for difficult reading, including a large file tike this.)