Example #1
0
static void *threaded_exec(void *arg)
{
	char *buff, *p2;
	struct text_object *obj = arg;
	struct execi_data *ed = obj->data.opaque;

	while (1) {
		buff = malloc(text_buffer_size);
		read_exec(ed->cmd, buff, text_buffer_size, 0);
		p2 = buff;
		while (*p2) {
			if (*p2 == '\001') {
				*p2 = ' ';
			}
			p2++;
		}
		timed_thread_lock(ed->p_timed_thread);
		if (ed->buffer)
			free(ed->buffer);
		ed->buffer = buff;
		timed_thread_unlock(ed->p_timed_thread);
		if (timed_thread_test(ed->p_timed_thread, 0)) {
			timed_thread_exit(ed->p_timed_thread);
		}
	}
	/* never reached */
}
Example #2
0
void scan_pre_exec_arg(struct text_object *obj, const char *arg)
{
	char buf[2048];

	obj->type = OBJ_text;
	read_exec(arg, buf, sizeof(buf), 1);
	obj->data.s = strndup(buf, text_buffer_size);
}
Example #3
0
void print_execbar(struct text_object *obj, char *p, int p_max_size)
{
	double barnum;
	read_exec(obj->data.s, p, p_max_size, 1);
	barnum = get_barnum(p);

	if (barnum >= 0.0) {
		barnum /= 100;
		new_bar(obj, p, p_max_size, round_to_int(barnum * 255.0));
	}
}
Example #4
0
void print_execgauge(struct text_object *obj, char *p, int p_max_size)
{
	double barnum;

	read_exec(obj->data.s, p, p_max_size, 1);
	barnum = get_barnum(p); /*using the same function*/

	if (barnum >= 0.0) {
		barnum /= 100;
		new_gauge(obj, p, p_max_size, round_to_int(barnum * 255.0));
	}
}
Example #5
0
static unsigned long load_aout_interp(struct exec * interp_ex,
                                      int interpreter_fd)
{
  unsigned long text_data, offset, elf_entry = ~0UL;
  char * addr;
  int retval;
  
  printf("WARNING: load_aout_interp() has not been tested at all!\n");

  current->end_code = interp_ex->a_text;
  text_data = interp_ex->a_text + interp_ex->a_data;
  current->end_data = text_data;
  current->brk = interp_ex->a_bss + text_data;

  switch (N_MAGIC(*interp_ex)) {
  case OMAGIC:
    offset = 32;
    addr = (char *) 0;
    break;
  case ZMAGIC:
  case QMAGIC:
    offset = N_TXTOFF(*interp_ex);
    addr = (char *) N_TXTADDR(*interp_ex);
    break;
  default:
    goto out;
  }

  if ((unsigned long)addr + text_data < text_data)
    goto out;

  do_mmap(-1, 0, text_data, PROT_READ|PROT_WRITE|PROT_EXEC, 
          MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0);
          
  retval = read_exec(interpreter_fd, offset, addr, text_data, 0);
  if (retval < 0)
    goto out;
    
#if 0    
  flush_icache_range((unsigned long)addr,
                     (unsigned long)addr + text_data);
#endif

  do_mmap(-1, ELF_PAGESTART(text_data + ELF_EXEC_PAGESIZE - 1),
          interp_ex->a_bss,  PROT_READ|PROT_WRITE|PROT_EXEC, 
          MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0);
  elf_entry = interp_ex->a_entry;

out:
  return elf_entry;
}
Example #6
0
static unsigned int load_aout_interp(struct exec * interp_ex,
			     struct inode * interpreter_inode)
{
  int retval;
  unsigned int elf_entry;
  
  current->mm->brk = interp_ex->a_bss +
    (current->mm->end_data = interp_ex->a_data +
     (current->mm->end_code = interp_ex->a_text));
  elf_entry = interp_ex->a_entry;
  
  
  if (N_MAGIC(*interp_ex) == OMAGIC) {
    do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data,
	    PROT_READ|PROT_WRITE|PROT_EXEC,
	    MAP_FIXED|MAP_PRIVATE, 0);
    retval = read_exec(interpreter_inode, 32, (char *) 0, 
		       interp_ex->a_text+interp_ex->a_data);
  } else if (N_MAGIC(*interp_ex) == ZMAGIC || N_MAGIC(*interp_ex) == QMAGIC) {
    do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data,
	    PROT_READ|PROT_WRITE|PROT_EXEC,
	    MAP_FIXED|MAP_PRIVATE, 0);
    retval = read_exec(interpreter_inode,
		       N_TXTOFF(*interp_ex) ,
		       (char *) N_TXTADDR(*interp_ex),
		       interp_ex->a_text+interp_ex->a_data);
  } else
    retval = -1;
  
  if(retval >= 0)
    do_mmap(NULL, (interp_ex->a_text + interp_ex->a_data + 0xfff) & 
	    0xfffff000, interp_ex->a_bss,
	    PROT_READ|PROT_WRITE|PROT_EXEC,
	    MAP_FIXED|MAP_PRIVATE, 0);
  if(retval < 0) return 0xffffffff;
  return elf_entry;
}
Example #7
0
int
load_coff_library (int fd)
{
    struct linux_binprm *bprm;  /* Parameters for the load operation   */
    int    status;              /* Status of the request               */
/*
 *  Read the first portion of the file.
 */
    bprm = (struct linux_binprm *) kmalloc (sizeof (struct linux_binprm),
					    GFP_KERNEL);
    if (0 == bprm) {
#ifdef COFF_DEBUG
	printk ("kmalloc failed\n");
#endif
        status = -ENOEXEC;
    }
    else {
        struct file         *file;  /* Pointer to the file table           */
        struct pt_regs       regs;  /* Register work area                  */
        int old_fs = get_fs ();     /* Previous FS register value          */

        memset (bprm, '\0', sizeof (struct linux_binprm));

	file           = current->files->fd[fd];
	bprm->inode    = file->f_inode;   /* The only item _really_ needed */
	bprm->filename = "";              /* Make it a legal string        */
/*
 *  Read the section list from the disk file.
 */
	set_fs (get_ds ());   /* Make it point to the proper location    */
	status = read_exec (bprm->inode,	 /* INODE for file       */
			    0L,                  /* Offset in the file   */
			    bprm->buf,           /* Buffer for read      */
			    sizeof (bprm->buf)); /* Size of the buffer   */
	set_fs (old_fs);	                 /* Restore the selector */
/*
 *  Try to load the library.
 */
	status = load_object (bprm, &regs, 0);
/*
 *  Release the work buffer and return the result.
 */
	kfree (bprm);                 /* Release the buffer area */
    }
/*
 *  Return the result of the load operation
 */
    return (status);
}
Example #8
0
void print_execgraph(struct text_object *obj, char *p, int p_max_size)
{
	double barnum;
	struct execi_data *ed = obj->data.opaque;

	if (!ed)
		return;

	read_exec(ed->cmd, p, p_max_size, 1);
	barnum = get_barnum(p);

	if (barnum >= 0) {
		new_graph(obj, p, p_max_size, round_to_int(barnum));
	}
}
Example #9
0
void print_execi(struct text_object *obj, char *p, int p_max_size)
{
	struct execi_data *ed = obj->data.opaque;

	if (!ed)
		return;

	if (time_to_update(ed)) {
		if (!ed->buffer)
			ed->buffer = malloc(text_buffer_size);
		read_exec(ed->cmd, ed->buffer, text_buffer_size, 1);
		ed->last_update = current_update_time;
	}
	snprintf(p, p_max_size, "%s", ed->buffer);
}
Example #10
0
void print_execibar(struct text_object *obj, char *p, int p_max_size)
{
	struct execi_data *ed = obj->data.opaque;
	double barnum;

	if (!ed)
		return;

	if (time_to_update(ed)) {
		read_exec(ed->cmd, p, p_max_size, 1);
		barnum = get_barnum(p);

		if (barnum >= 0.0) {
			ed->barnum = barnum;
		}
		ed->last_update = current_update_time;
	}
	new_bar(obj, p, p_max_size, round_to_int(ed->barnum * 2.55));
}
Example #11
0
void print_execp(struct text_object *obj, char *p, int p_max_size)
{
	struct information *tmp_info;
	struct text_object subroot;
	char *buf;

	buf = malloc(text_buffer_size);
	memset(buf, 0, text_buffer_size);

	read_exec(obj->data.s, buf, text_buffer_size, 1);

	tmp_info = malloc(sizeof(struct information));
	memcpy(tmp_info, &info, sizeof(struct information));
	parse_conky_vars(&subroot, buf, p, p_max_size, tmp_info);

	free_text_objects(&subroot, 1);
	free(tmp_info);
	free(buf);
}
Example #12
0
static unsigned long load_aout_interp(struct exec * interp_ex,
			     struct dentry * interpreter_dentry)
{
	unsigned long text_data, offset, elf_entry = ~0UL;
	char * addr;
	int retval;

	current->mm->end_code = interp_ex->a_text;
	text_data = interp_ex->a_text + interp_ex->a_data;
	current->mm->end_data = text_data;
	current->mm->brk = interp_ex->a_bss + text_data;

	switch (N_MAGIC(*interp_ex)) {
	case OMAGIC:
		offset = 32;
		addr = (char *) 0;
		break;
	case ZMAGIC:
	case QMAGIC:
		offset = N_TXTOFF(*interp_ex);
		addr = (char *) N_TXTADDR(*interp_ex);
		break;
	default:
		goto out;
	}

	do_mmap(NULL, 0, text_data,
		PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0);
	retval = read_exec(interpreter_dentry, offset, addr, text_data, 0);
	if (retval < 0)
		goto out;
	flush_icache_range((unsigned long)addr,
	                   (unsigned long)addr + text_data);

	do_mmap(NULL, ELF_PAGESTART(text_data + ELF_EXEC_PAGESIZE - 1),
		interp_ex->a_bss,
		PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0);
	elf_entry = interp_ex->a_entry;

out:
	return elf_entry;
}
Example #13
0
void print_execigraph(struct text_object *obj, char *p, int p_max_size)
{
	struct execi_data *ed = obj->data.opaque;

	if (!ed)
		return;

	if (time_to_update(ed)) {
		double barnum;

		read_exec(ed->cmd, p, p_max_size, 1);
		barnum = get_barnum(p);

		if (barnum >= 0.0) {
			ed->barnum = barnum;
		}
		ed->last_update = current_update_time;
	}
	new_graph(obj, p, p_max_size, (int) (ed->barnum));
}
Example #14
0
static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex,
			     struct inode * interpreter_inode)
{
        struct file * file;
	struct elf_phdr *elf_phdata  =  NULL;
	struct elf_phdr *eppnt;
	unsigned int len;
	unsigned int load_addr;
	int elf_exec_fileno;
	int elf_bss;
	int old_fs, retval;
	unsigned int last_bss;
	int error;
	int i, k;
	
	elf_bss = 0;
	last_bss = 0;
	error = load_addr = 0;
	
	/* First of all, some simple consistency checks */
	if((interp_elf_ex->e_type != ET_EXEC && 
	    interp_elf_ex->e_type != ET_DYN) || 
	   (interp_elf_ex->e_machine != EM_386 && interp_elf_ex->e_machine != EM_486) ||
	   (!interpreter_inode->i_op || 
	    !interpreter_inode->i_op->default_file_ops->mmap)){
		return 0xffffffff;
	};
	
	/* Now read in all of the header information */
	
	if(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) 
	    return 0xffffffff;
	
	elf_phdata =  (struct elf_phdr *) 
		kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, GFP_KERNEL);
	if(!elf_phdata) return 0xffffffff;
	
	old_fs = get_fs();
	set_fs(get_ds());
	retval = read_exec(interpreter_inode, interp_elf_ex->e_phoff, (char *) elf_phdata,
			   sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
	set_fs(old_fs);
	
	elf_exec_fileno = open_inode(interpreter_inode, O_RDONLY);
	if (elf_exec_fileno < 0) return 0xffffffff;
	file = current->files->fd[elf_exec_fileno];

	eppnt = elf_phdata;
	for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
	  if(eppnt->p_type == PT_LOAD) {
	    error = do_mmap(file, 
			    eppnt->p_vaddr & 0xfffff000,
			    eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),
			    PROT_READ | PROT_WRITE | PROT_EXEC,
			    MAP_PRIVATE | (interp_elf_ex->e_type == ET_EXEC ? MAP_FIXED : 0),
			    eppnt->p_offset & 0xfffff000);
	    
	    if(!load_addr && interp_elf_ex->e_type == ET_DYN)
	      load_addr = error;
	    k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
	    if(k > elf_bss) elf_bss = k;
	    if(error < 0 && error > -1024) break;  /* Real error */
	    k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
	    if(k > last_bss) last_bss = k;
	  }
	
	/* Now use mmap to map the library into memory. */

	
	sys_close(elf_exec_fileno);
	if(error < 0 && error > -1024) {
	        kfree(elf_phdata);
		return 0xffffffff;
	}

	padzero(elf_bss);
	len = (elf_bss + 0xfff) & 0xfffff000; /* What we have mapped so far */

	/* Map the last of the bss segment */
	if (last_bss > len)
	  do_mmap(NULL, len, last_bss-len,
		  PROT_READ|PROT_WRITE|PROT_EXEC,
		  MAP_FIXED|MAP_PRIVATE, 0);
	kfree(elf_phdata);

	return ((unsigned int) interp_elf_ex->e_entry) + load_addr;
}
Example #15
0
static int
load_object (struct linux_binprm * bprm, struct pt_regs *regs, int lib_ok)
{
    COFF_FILHDR  *coff_hdr = (COFF_FILHDR *) bprm->buf;	/* COFF Header */
    COFF_SCNHDR  *sect_bufr;	/* Pointer to section table            */
    COFF_SCNHDR  *text_sect;	/* Pointer to the text section         */
    COFF_SCNHDR  *data_sect;	/* Pointer to the data section         */
    COFF_SCNHDR  *bss_sect;	/* Pointer to the bss section          */
    int text_count;		/* Number of text sections             */
    int data_count;		/* Number of data sections             */
    int bss_count;		/* Number of bss sections              */
    int lib_count;		/* Number of lib sections              */
    unsigned int start_addr = 0;/* Starting location for program       */
    int status = 0;		/* Result status register              */
    int fd = -1;		/* Open file descriptor                */
    struct file *fp     = NULL;	/* Pointer to the file at "fd"         */
    short int sections  = 0;	/* Number of sections in the file      */
    short int aout_size = 0;	/* Size of the a.out header area       */
    short int flags;		/* Flag bits from the COFF header      */

#ifdef COFF_DEBUG
    printk ("binfmt_coff entry: %s\n", bprm->filename);
#endif

/*
 *  Validate the magic value for the object file.
 */
    do {
	if (COFF_I386BADMAG (*coff_hdr)) {
#ifdef COFF_DEBUG
	    printk ("bad filehdr magic\n");
#endif
	    status = -ENOEXEC;
	    break;
	}
/*
 *  The object file should have 32 BIT little endian format. Do not allow
 *  it to have the 16 bit object file flag set as Linux is not able to run
 *  on the 80286/80186/8086.
 */
	flags = COFF_SHORT (coff_hdr->f_flags);
	if ((flags & (COFF_F_AR32WR | COFF_F_AR16WR)) != COFF_F_AR32WR) {
#ifdef COFF_DEBUG
	    printk ("invalid f_flags bits\n");
#endif
	    status = -ENOEXEC;
	    break;
	}
/*
 *  Extract the header information which we need.
 */
	sections  = COFF_SHORT (coff_hdr->f_nscns);   /* Number of sections */
	aout_size = COFF_SHORT (coff_hdr->f_opthdr);  /* Size of opt. headr */
/*
 *  If the file is not executable then reject the execution. This means
 *  that there must not be external references.
 */
	if ((flags & COFF_F_EXEC) == 0) {
#ifdef COFF_DEBUG
	    printk ("not executable bit\n");
#endif
	    status = -ENOEXEC;
	    break;
	}
/*
 *  There must be at least one section.
 */
	if (sections == 0) {
#ifdef COFF_DEBUG
	    printk ("no sections\n");
#endif
	    status = -ENOEXEC;
	    break;
	}
/*
 *  Do some additional consistency checks.
 *  The system requires mapping for this loader. If you try
 *  to use a file system with no mapping, the format is not valid.
 */
	if (!bprm->inode->i_op ||
	    !bprm->inode->i_op->default_file_ops->mmap) {
#ifdef COFF_DEBUG
	    printk ("no mmap in fs\n");
#endif
	    status = -ENOEXEC;
	}
    }
    while (0);
/*
 *  Allocate a buffer to hold the entire coff section list.
 */
    if (status >= 0) {
	int nbytes = sections * COFF_SCNHSZ;

	sect_bufr = (COFF_SCNHDR *) kmalloc (nbytes, GFP_KERNEL);
	if (0 == sect_bufr) {
#ifdef COFF_DEBUG
	    printk ("kmalloc failed\n");
#endif
	    status = -ENOEXEC;
	}
/*
 *  Read the section list from the disk file.
 */
	else {
	     int old_fs = get_fs ();
	     set_fs (get_ds ());  /* Make it point to the proper location    */
	     status = read_exec (bprm->inode,	     /* INODE for file       */
			    aout_size + COFF_FILHSZ, /* Offset in the file   */
			    (char *) sect_bufr,      /* Buffer for read      */
			    nbytes);                 /* Byte count reqd.     */
	     set_fs (old_fs);	                     /* Restore the selector */
#ifdef COFF_DEBUG
	     if (status < 0)
	        printk ("read aout hdr, status = %d\n", status);
#endif
	 }
    }
    else
	sect_bufr = NULL;	/* Errors do not have a section buffer */
/*
 *  Count the number of sections for the required types and store the location
 *  of the last section for the three primary types.
 */
    text_count = 0;
    data_count = 0;
    bss_count  = 0;
    lib_count  = 0;

    text_sect = NULL;
    data_sect = NULL;
    bss_sect  = NULL;
/*
 *  Loop through the sections and find the various types
 */
    if (status >= 0) {
	int nIndex;
	COFF_SCNHDR *sect_ptr = sect_bufr;

	for (nIndex = 0; nIndex < sections; ++nIndex) {
	    long int sect_flags = COFF_LONG (sect_ptr->s_flags);

	    switch (sect_flags) {
	    case COFF_STYP_TEXT:
		text_sect = sect_ptr;
		++text_count;
		status = is_properly_aligned (sect_ptr);
		break;

	    case COFF_STYP_DATA:
		data_sect = sect_ptr;
		++data_count;
		status = is_properly_aligned (sect_ptr);
		break;

	    case COFF_STYP_BSS:
		bss_sect = sect_ptr;
		++bss_count;
		break;

	    case COFF_STYP_LIB:
#ifdef COFF_DEBUG
		printk (".lib section found\n");
#endif
		++lib_count;
		break;

	    default:
		break;
	    }
	    sect_ptr = (COFF_SCNHDR *) & ((char *) sect_ptr)[COFF_SCNHSZ];
	}
/*
 *  Ensure that there are the required sections. There must be one text
 *  sections and one each of the data and bss sections for an executable.
 *  A library may or may not have a data / bss section.
 */
	if (text_count != 1) {
	    status = -ENOEXEC;
#ifdef COFF_DEBUG
	    printk ("no text sections\n");
#endif
	}
	else {
	    if (lib_ok) {
		if (data_count != 1 || bss_count != 1) {
		    status = -ENOEXEC;
#ifdef COFF_DEBUG
		    printk ("no .data nor .bss sections\n");
#endif
		}
	    }
	}
    }
/*
 *  If there is no additional header then assume the file starts at
 *  the first byte of the text section. This may not be the proper place,
 *  so the best solution is to include the optional header. A shared library
 *  __MUST__ have an optional header to indicate that it is a shared library.
 */
    if (status >= 0) {
	if (aout_size == 0) {
	    if (!lib_ok) {
		status = -ENOEXEC;
#ifdef COFF_DEBUG
		printk ("no header in library\n");
#endif
	    }
	    start_addr = COFF_LONG (text_sect->s_vaddr);
	}
/*
 *  There is some header. Ensure that it is sufficient.
 */
	else {
	    if (aout_size < COFF_AOUTSZ) {
		status = -ENOEXEC;
#ifdef COFF_DEBUG
		printk ("header too small\n");
#endif
	    }
	    else {
		COFF_AOUTHDR *aout_hdr =	/* Pointer to a.out header */
		(COFF_AOUTHDR *) & ((char *) coff_hdr)[COFF_FILHSZ];
		short int aout_magic = COFF_SHORT (aout_hdr->magic); /* id */
/*
 *  Validate the magic number in the a.out header. If it is valid then
 *  update the starting symbol location. Do not accept these file formats
 *  when loading a shared library.
 */
		switch (aout_magic) {
		case COFF_OMAGIC:
		case COFF_ZMAGIC:
		case COFF_STMAGIC:
		    if (!lib_ok) {
			status = -ENOEXEC;
#ifdef COFF_DEBUG
			printk ("wrong a.out header magic\n");
#endif
		    }
		    start_addr = (unsigned int) COFF_LONG (aout_hdr->entry);
		    break;
/*
 *  Magic value for a shared library. This is valid only when loading a
 *  shared library. (There is no need for a start_addr. It won't be used.)
 */
		case COFF_SHMAGIC:
		    if (lib_ok) {
#ifdef COFF_DEBUG
			printk ("wrong a.out header magic\n");
#endif
			status = -ENOEXEC;
		    }
		    break;

		default:
#ifdef COFF_DEBUG
		    printk ("wrong a.out header magic\n");
#endif
		    status = -ENOEXEC;
		    break;
		}
	    }
	}
    }
/*
 *  Fetch a file pointer to the executable.
 */
    if (status >= 0) {
	fd = open_inode (bprm->inode, O_RDONLY);
	if (fd < 0) {
#ifdef COFF_DEBUG
	    printk ("can not open inode, result = %d\n", fd);
#endif
	    status = fd;
	}
	else
	    fp = current->files->fd[fd];
    }
    else
	fd = -1;		/* Invalidate the open file descriptor */
/*
 *  Generate the proper values for the text fields
 *
 *  THIS IS THE POINT OF NO RETURN. THE NEW PROCESS WILL TRAP OUT SHOULD
 *  SOMETHING FAIL IN THE LOAD SEQUENCE FROM THIS POINT ONWARD.
 */
    if (status >= 0) {
	long text_scnptr = COFF_LONG (text_sect->s_scnptr);
	long text_size   = COFF_LONG (text_sect->s_size);
	long text_vaddr  = COFF_LONG (text_sect->s_vaddr);

	long data_scnptr;
	long data_size;
	long data_vaddr;

	long bss_size;
	long bss_vaddr;
/*
 *  Generate the proper values for the data fields
 */
	if (data_sect != NULL) {
	    data_scnptr = COFF_LONG (data_sect->s_scnptr);
	    data_size   = COFF_LONG (data_sect->s_size);
	    data_vaddr  = COFF_LONG (data_sect->s_vaddr);
	}
	else {
	    data_scnptr = 0;
	    data_size   = 0;
	    data_vaddr  = 0;
	}
/*
 *  Generate the proper values for the bss fields
 */
	if (bss_sect != NULL) {
	    bss_size  = COFF_LONG (bss_sect->s_size);
	    bss_vaddr = COFF_LONG (bss_sect->s_vaddr);
	}
	else {
	    bss_size  = 0;
	    bss_vaddr = 0;
	}
/*
 *  Flush the executable from memory. At this point the executable is
 *  committed to being defined or a segmentation violation will occur.
 */
	if (lib_ok) {
#ifdef COFF_DEBUG
	    printk ("flushing executable\n");
#endif
	    flush_old_exec (bprm);
/*
 *  Define the initial locations for the various items in the new process
 */
	    current->mm->mmap        = NULL;
	    current->mm->rss         = 0;
/*
 *  Construct the parameter and environment string table entries.
 */
	    bprm->p += change_ldt (0, bprm->page);
	    bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
	    bprm->p  = (unsigned long) create_tables ((char *) bprm->p,
						      bprm->argc,
						      bprm->envc,
						      1);
/*
 *  Do the end processing once the stack has been constructed
 */
	    current->mm->start_code  = text_vaddr & PAGE_MASK;
	    current->mm->end_code    = text_vaddr + text_size;
	    current->mm->end_data    = data_vaddr + data_size;
	    current->mm->start_brk   =
	    current->mm->brk         = bss_vaddr + bss_size;
	    current->suid            =
	    current->euid            = bprm->e_uid;
	    current->sgid            =
	    current->egid            = bprm->e_gid;
	    current->executable      = bprm->inode; /* Store inode for file  */
	    ++bprm->inode->i_count;             /* Count the open inode  */
	    regs->eip                = start_addr;  /* Current EIP register  */
	    regs->esp                =
	    current->mm->start_stack = bprm->p;
	}
/*
 *   Map the text pages
 */

#ifdef COFF_DEBUG
	printk (".text: vaddr = %d, size = %d, scnptr = %d\n",
		 text_vaddr,
		 text_size,
		 text_scnptr);
#endif
	status = do_mmap (fp,
			  text_vaddr & PAGE_MASK,
			  text_size + (text_vaddr & ~PAGE_MASK),
			  PROT_READ | PROT_EXEC,
			  MAP_FIXED | MAP_SHARED,
			  text_scnptr & PAGE_MASK);

	status = (status == (text_vaddr & PAGE_MASK)) ? 0 : -ENOEXEC;
/*
 *   Map the data pages
 */
	if (status >= 0 && data_size != 0) {
#ifdef COFF_DEBUG
	    printk (".data: vaddr = %d, size = %d, scnptr = %d\n",
		     data_vaddr,
		     data_size,
		     data_scnptr);
#endif
	    status = do_mmap (fp,
			      data_vaddr & PAGE_MASK,
			      data_size + (data_vaddr & ~PAGE_MASK),
			      PROT_READ | PROT_WRITE | PROT_EXEC,
			      MAP_FIXED | MAP_PRIVATE,
			      data_scnptr & PAGE_MASK);

	    status = (status == (data_vaddr & PAGE_MASK)) ? 0 : -ENOEXEC;
	}
/*
 *   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 (status >= 0 && bss_size != 0) {
#ifdef COFF_DEBUG
	    printk (".bss: vaddr = %d, size = %d\n",
		     bss_vaddr,
		     bss_size);
#endif
	    zeromap_page_range (PAGE_ALIGN (bss_vaddr),
				PAGE_ALIGN (bss_size),
				PAGE_COPY);

	    status = clear_memory (bss_vaddr, bss_size);
	}
/*
 *  Load any shared library for the executable.
 */
	if (status >= 0 && lib_ok && lib_count != 0) {
	    int nIndex;
	    COFF_SCNHDR *sect_ptr = sect_bufr;
/*
 *  Find the library sections. (There should be at least one. It was counted
 *  earlier.) This will eventually recurse to our code and load the shared
 *  library with our own procedures.
 */
	    for (nIndex = 0; nIndex < sections; ++nIndex) {
		long int sect_flags = COFF_LONG (sect_ptr->s_flags);
		if (sect_flags == COFF_STYP_LIB) {
		    status = preload_library (bprm, sect_ptr, fp);
		    if (status != 0)
			break;
		}
	    sect_ptr = (COFF_SCNHDR *) &((char *) sect_ptr) [COFF_SCNHSZ];
	    }
	}
/*
 *   Generate any needed trap for this process. If an error occurred 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 (lib_ok) {
	    if (status < 0)
		send_sig (SIGSEGV, current, 0);	/* Generate the error trap  */
	    else {
		if (current->flags & PF_PTRACED)
		    send_sig (SIGTRAP, current, 0);
	    }
	    status = 0;		/* We are committed. It can't fail */
	}
    }
/*
 *  Do any cleanup processing
 */
    if (fd >= 0)
	sys_close (fd);		/* Close unused code file      */

    if (sect_bufr != NULL)
	kfree (sect_bufr);	/* Release section list buffer */
/*
 *  Return the completion status.
 */
#ifdef COFF_DEBUG
    printk ("binfmt_coff: result = %d\n", status);
#endif
    return (status);
}
Example #16
0
static int load_elf_library(int fd)
{
  /* uselib syscall isn't implemented so we don't need this function 
     just yet... */
  return -EINVAL;
  
#if 0
  struct file * file;
  struct dentry * dentry;
  struct inode * inode;
  struct elf_phdr *elf_phdata;
  unsigned long elf_bss = 0, bss, len, k;
  int retval, error, i, j;
  struct elfhdr elf_ex;
  loff_t offset = 0;

  error = -EACCES;
  file = fget(fd);
  if (!file || !file->f_op)
    goto out;
  dentry = file->f_dentry;
  inode = dentry->d_inode;

  /* seek to the beginning of the file */
  error = -ENOEXEC;

  /* N.B. save current DS?? */
  set_fs(KERNEL_DS);
  retval = file->f_op->read(file, (char *) &elf_ex, sizeof(elf_ex), &offset);
  set_fs(USER_DS);
  if (retval != sizeof(elf_ex))
    goto out_putf;

  if (elf_ex.e_ident[0] != 0x7f ||
      strncmp(&elf_ex.e_ident[1], "ELF", 3) != 0)
    goto out_putf;

  /* First of all, some simple consistency checks */
  if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
     !elf_check_arch(elf_ex.e_machine) ||
     (!inode->i_op || !inode->i_op->default_file_ops->mmap))
    goto out_putf;

  /* Now read in all of the header information */

  j = sizeof(struct elf_phdr) * elf_ex.e_phnum;
  if (j > ELF_EXEC_PAGESIZE)
    goto out_putf;

  error = -ENOMEM;
  elf_phdata = (struct elf_phdr *) kmalloc(j, GFP_KERNEL);
  if (!elf_phdata)
    goto out_putf;

  /* N.B. check for error return?? */
  retval = read_exec(dentry, elf_ex.e_phoff, (char *) elf_phdata,
         sizeof(struct elf_phdr) * elf_ex.e_phnum, 1);

  error = -ENOEXEC;
  for (j = 0, i = 0; i<elf_ex.e_phnum; i++)
    if ((elf_phdata + i)->p_type == PT_LOAD) j++;
  if (j != 1)
    goto out_free_ph;

  while (elf_phdata->p_type != PT_LOAD) elf_phdata++;

  /* Now use mmap to map the library into memory. */
  error = do_mmap(file,
      ELF_PAGESTART(elf_phdata->p_vaddr),
      (elf_phdata->p_filesz +
       ELF_PAGEOFFSET(elf_phdata->p_vaddr)),
      PROT_READ | PROT_WRITE | PROT_EXEC,
      MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
      (elf_phdata->p_offset -
       ELF_PAGEOFFSET(elf_phdata->p_vaddr)));
  if (error != ELF_PAGESTART(elf_phdata->p_vaddr))
    goto out_free_ph;

  k = elf_phdata->p_vaddr + elf_phdata->p_filesz;
  if (k > elf_bss)
    elf_bss = k;
  padzero(elf_bss);

  len = ELF_PAGESTART(elf_phdata->p_filesz + elf_phdata->p_vaddr + 
        ELF_EXEC_PAGESIZE - 1);
  bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
  if (bss > len)
    do_mmap(NULL, len, bss - len,
      PROT_READ|PROT_WRITE|PROT_EXEC,
      MAP_FIXED|MAP_PRIVATE, 0);
  error = 0;

out_free_ph:
  kfree(elf_phdata);
out_putf:
  fput(file);
out:
  return error;
#endif  
}
Example #17
0
int
do_ranlib(void)
{
	CF cf;
	off_t size;
	FILE	*afp, *tfp;
	long	symcnt;			/* symbol count */
	long	tsymlen;		/* total string length */
	int	i, current_mid;

	current_mid = -1;
	afp = open_archive(O_RDWR);
	tfp = tmp();

	SETCF(afp, archive, tfp, tname, 0);

	/* Read through the archive, creating list of symbols. */
	symcnt = tsymlen = 0;
	ntsize = 0;
	r_fuzz = SARMAG;
	pnext = &rhead;
	while(get_arobj(afp)) {
		int new_mid;

		if (!strncmp(chdr.name, AR_NAMTAB, sizeof(AR_NAMTAB) - 1)) {
			size = ftello(afp);
			get_namtab(afp);
			ntsize = chdr.size + sizeof(struct ar_hdr);
			(void)fseeko(afp, size, SEEK_SET);
			r_fuzz += skip_arobj(afp);
			continue;
		}

		if (!strncmp(chdr.name, RANLIBMAG, sizeof(RANLIBMAG) - 1) ||
		    !strncmp(chdr.name, RANLIBMAG2, sizeof(RANLIBMAG2) - 1)) {
			r_fuzz += skip_arobj(afp);
			continue;
		}
		new_mid = read_exec(afp, tfp, &symcnt, &tsymlen);
		if (new_mid != -1) {
			if (current_mid == -1)
				current_mid = new_mid;
			else if (new_mid != current_mid)
				errx(1, "mixed object format archive: %x / %x",
					new_mid, current_mid);
		}
		put_arobj(&cf, NULL);
	}
	*pnext = NULL;

	SETCF(tfp, tname, afp, archive, NOPAD);

	/* Create the symbol table.  Endianess the same as last mid seen */
	symobj(afp, current_mid, symcnt, tsymlen);
	put_nametab(&cf);

	/* Copy the saved objects into the archive. */
	size = ftello(tfp);
	rewind(tfp);
	copy_ar(&cf, size);
	fflush(afp);
	(void)ftruncate(fileno(afp), ftello(afp));
	(void)fclose(tfp);

	/* Set the time. */
	settime(afp);
	close_archive(afp);
	return(0);
}
Example #18
0
AST_stmt* readASTStmt(BufferedReader* reader) {
    uint8_t type = reader->readByte();
    if (VERBOSITY("parsing") >= 3)
        printf("type = %d\n", type);
    if (type == 0)
        return NULL;

    uint8_t checkbyte = reader->readByte();
    assert(checkbyte == 0xae);

    switch (type) {
        case AST_TYPE::Assert:
            return read_assert(reader);
        case AST_TYPE::Assign:
            return read_assign(reader);
        case AST_TYPE::AugAssign:
            return read_augassign(reader);
        case AST_TYPE::Break:
            return read_break(reader);
        case AST_TYPE::ClassDef:
            return read_classdef(reader);
        case AST_TYPE::Continue:
            return read_continue(reader);
        case AST_TYPE::Delete:
            return read_delete(reader);
        case AST_TYPE::Exec:
            return read_exec(reader);
        case AST_TYPE::Expr:
            return read_expr(reader);
        case AST_TYPE::For:
            return read_for(reader);
        case AST_TYPE::FunctionDef:
            return read_functiondef(reader);
        case AST_TYPE::Global:
            return read_global(reader);
        case AST_TYPE::If:
            return read_if(reader);
        case AST_TYPE::Import:
            return read_import(reader);
        case AST_TYPE::ImportFrom:
            return read_importfrom(reader);
        case AST_TYPE::Pass:
            return read_pass(reader);
        case AST_TYPE::Print:
            return read_print(reader);
        case AST_TYPE::Raise:
            return read_raise(reader);
        case AST_TYPE::Return:
            return read_return(reader);
        case AST_TYPE::TryExcept:
            return read_tryexcept(reader);
        case AST_TYPE::TryFinally:
            return read_tryfinally(reader);
        case AST_TYPE::While:
            return read_while(reader);
        case AST_TYPE::With:
            return read_with(reader);
        default:
            fprintf(stderr, "Unknown stmt node type (parser.cpp:" STRINGIFY(__LINE__) "): %d\n", type);
            exit(1);
            break;
    }
}
Example #19
0
static int load_elf_binary(struct linux_binprm *bprm)
{
  struct pt_regs regs; 
  int interpreter_fd = -1;
   unsigned long load_addr = 0, load_bias;
  int load_addr_set = 0;
  char * elf_interpreter = NULL;
  unsigned int interpreter_type = INTERPRETER_NONE;
  unsigned long error;
  struct elf_phdr * elf_ppnt, *elf_phdata;
  unsigned long elf_bss, k, elf_brk;
  int elf_exec_fileno;
  int retval, size, i;
  unsigned long elf_entry, interp_load_addr = 0;
  unsigned long start_code, end_code, end_data;
  struct elfhdr elf_ex;
  struct elfhdr interp_elf_ex;
    struct exec interp_ex;
  char passed_fileno[6];
  
  /* Get the exec-header */
  elf_ex = *((struct elfhdr *) bprm->buf);
  my_print("[debug]here to run elf\n");
  retval = -ENOEXEC;
  /* First of all, some simple consistency checks */
  if (elf_ex.e_ident[0] != 0x7f ||
      strncmp(&elf_ex.e_ident[1], "ELF", 3) != 0)
    goto out;
  //my_print("[ender]1\n");
  if (elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN)
    goto out;
  if (!elf_check_arch(elf_ex.e_machine))
    goto out;
  //my_print("[ender]2\n");

  /* Now read in all of the header information */

  if (elf_ex.e_phentsize != sizeof(struct elf_phdr) ||
      elf_ex.e_phnum < 1 ||
      elf_ex.e_phnum > 65536 / sizeof(struct elf_phdr))
    goto out;
 // my_print("[ender]3\n");
  retval = -ENOMEM;
  size = elf_ex.e_phentsize * elf_ex.e_phnum;
  elf_phdata = (struct elf_phdr *) malloc(size);
  if (!elf_phdata)
    goto out;

  retval = read_exec(bprm->fd, elf_ex.e_phoff, (char *) elf_phdata, size, 1);
  if (retval < 0)
    goto out_free_ph;
  //my_print("[ender]4\n");

  elf_exec_fileno = dup(bprm->fd);
  lseek(elf_exec_fileno, 0, SEEK_SET);

  elf_ppnt = elf_phdata;
  elf_bss = 0;
  elf_brk = 0;

  start_code = ~0UL;
  end_code = 0;
  end_data = 0;

  /* look for interpreter */
  for (i = 0; i < elf_ex.e_phnum; i++) {
    if (elf_ppnt->p_type == PT_INTERP) {
      retval = -ENOEXEC;
        if (elf_interpreter ||
          elf_ppnt->p_filesz < 2 ||
          elf_ppnt->p_filesz > PAGE_SIZE)
        goto out_free_dentry;

      /* This is the program interpreter used for
       * shared libraries - for now assume that this
       * is an a.out format binary
       */

      retval = -ENOMEM;
      elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
      if (!elf_interpreter)
        goto out_free_file;

      retval = read_exec(bprm->fd, elf_ppnt->p_offset,
             elf_interpreter, elf_ppnt->p_filesz, 1);
      if (retval < 0)
        goto out_free_interp;
      elf_interpreter[elf_ppnt->p_filesz - 1] = 0;
      
#if 0
      /* If the program interpreter is one of these two,
       * then assume an iBCS2 image. Otherwise assume
       * a native linux image.
       */
      if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
          strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0)
        ibcs2_interpreter = 1;
#endif

      log_debug(LOG_LINEXEC_EXEC, "Using ELF interpreter: %s", elf_interpreter);
	  if( elf_interpreter[0] == '/'){
		  char tmp [MAX_PATH];
          change_path_to_relative(tmp, elf_interpreter);
		  free(elf_interpreter);
		  //elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
          elf_interpreter = (char *)malloc(strlen(tmp)+1);
		  if (!elf_interpreter)
			  goto out_free_file;
		  strcpy(elf_interpreter, tmp);
	  }
      interpreter_fd = open(elf_interpreter, O_RDONLY);
	  my_print("[debug]open elf_interpreter %s\n", elf_interpreter);
      if (interpreter_fd < 0) {
        retval = -errno;
        goto out_free_interp;
      }

#if 0        
      retval = permission(interpreter_dentry->d_inode, MAY_EXEC);
      if (retval < 0)
        goto out_free_dentry;
#endif
        
      retval = read_exec(interpreter_fd, 0, bprm->buf, 128, 1);
      if (retval < 0)
        goto out_free_dentry;

      /* Get the exec headers */
      interp_ex = *((struct exec *) bprm->buf);
      interp_elf_ex = *((struct elfhdr *) bprm->buf);
    }
    elf_ppnt++;
	//my_print("[ender]6\n");
  }

  /* Some simple consistency checks for the interpreter */
  if (elf_interpreter) {
    interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;

    /* Now figure out which format our binary is */
    if ((N_MAGIC(interp_ex) != OMAGIC) &&
        (N_MAGIC(interp_ex) != ZMAGIC) &&
        (N_MAGIC(interp_ex) != QMAGIC))
      interpreter_type = INTERPRETER_ELF;

    if (interp_elf_ex.e_ident[0] != 0x7f ||
        strncmp(&interp_elf_ex.e_ident[1], "ELF", 3) != 0)
      interpreter_type &= ~INTERPRETER_ELF;

    retval = -ELIBBAD;
    if (!interpreter_type)
      goto out_free_dentry;

    /* Make sure only one type was selected */
    if ((interpreter_type & INTERPRETER_ELF) &&
         interpreter_type != INTERPRETER_ELF) {
      printf("ELF: Ambiguous type, using ELF\n");
      interpreter_type = INTERPRETER_ELF;
    }
  }
  //my_print("[ender]7\n");
  /* OK, we are done with that, now set up the arg stuff,
     and then start this sucker up */
  if (!bprm->sh_bang) {
    char * passed_p;

    if (interpreter_type == INTERPRETER_AOUT) {
      sprintf(passed_fileno, "%d", elf_exec_fileno);
      passed_p = passed_fileno;

      if (elf_interpreter) {
        bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p);
        bprm->argc++;
      }
    }
    retval = -E2BIG;
    if (!bprm->p)
      goto out_free_dentry;
  }


#if 0
  /* Flush all traces of the currently running executable */
  retval = flush_old_exec(bprm);
  if (retval)
    goto out_free_dentry;
#endif  

  /* OK, This is the point of no return */
  current->end_data = 0;
  current->end_code = 0;
#if 0
  current->mm->mmap = NULL;
  current->flags &= ~PF_FORKNOEXEC;

#endif  
  elf_entry = (unsigned long) elf_ex.e_entry;
  //printf("[ender]8\n");

#if 0
  /* Do this immediately, since STACK_TOP as used in setup_arg_pages
     may depend on the personality.  */
  SET_PERSONALITY(elf_ex, ibcs2_interpreter);
#endif  

  /* Do this so that we can load the interpreter, if need be.  We will
     change some of these later */
//  current->mm->rss = 0;
  bprm->p = setup_arg_pages(bprm->p, bprm);
  
  current->start_stack = bprm->p;

  /* Try and get dynamic programs out of the way of the default mmap
     base, as well as whatever program they might try to exec.  This
     is because the brk will follow the loader, and is not movable.  */

  load_bias = ELF_PAGESTART(elf_ex.e_type==ET_DYN ? ELF_ET_DYN_BASE : 0);
#ifdef __VERBOSE__
  printf("load_bias: %08lX\n", load_bias);
#endif

  /* Now we do a little grungy work by mmaping the ELF image into
     the correct location in memory.  At this point, we assume that
     the image should be loaded at fixed address, not at a variable
     address. */

  for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
    int elf_prot = 0, elf_flags;
    unsigned long vaddr;

    if (elf_ppnt->p_type != PT_LOAD)
      continue;

    if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
    if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
    if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;

    elf_flags = MAP_PRIVATE; // |MAP_DENYWRITE|MAP_EXECUTABLE;

    vaddr = elf_ppnt->p_vaddr;
    if (elf_ex.e_type == ET_EXEC || load_addr_set) {
      elf_flags |= MAP_FIXED;
    }
	//my_print("[ender]9\n");
#ifdef __VERBOSE__
    printf("mapping: %08lX\n", ELF_PAGESTART(load_bias + vaddr));
#endif
    error = do_mmap(bprm->fd, ELF_PAGESTART(load_bias + vaddr),
                    (elf_ppnt->p_filesz + ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
                    elf_prot, elf_flags, 
                    (elf_ppnt->p_offset - ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));

#ifdef __VERBOSE__
    printf("error: %08lX\n", error);
#endif

    if (!load_addr_set) {
      load_addr_set = 1;
      load_addr = (elf_ppnt->p_vaddr - elf_ppnt->p_offset);
#ifdef __VERBOSE__
      printf("load_addr: %08lX, vaddr: %08lX\n", load_addr, vaddr);
#endif      
      if (elf_ex.e_type == ET_DYN) {
        load_bias += error - ELF_PAGESTART(load_bias + vaddr);
        load_addr += error;
      
#ifdef __VERBOSE__
        printf("new\nload_bias: %08lX, load_addr: %08lX\n", load_bias, load_addr);
#endif        
      }
    }
    k = elf_ppnt->p_vaddr;
    if (k < start_code) start_code = k;
    k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
    if (k > elf_bss)
      elf_bss = k;
    if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
      end_code = k;
    if (end_data < k)
      end_data = k;
    k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
    if (k > elf_brk)
      elf_brk = k;
  }
  
  close(bprm->fd);
  
  elf_entry += load_bias;
  elf_bss += load_bias;
  elf_brk += load_bias;
  start_code += load_bias;
  end_code += load_bias;
  end_data += load_bias;

  if (elf_interpreter) {
    if (interpreter_type == INTERPRETER_AOUT) {
      elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
    } else {
      elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd, 
                                  &interp_load_addr);
    }                                  
    close(interpreter_fd);
    if (elf_entry == ~0UL) {
      printf("Unable to load interpreter %.128s\n", elf_interpreter);
      free(elf_interpreter);
      free(elf_phdata);
      
      //send_sig(SIGSEGV, current, 0);
      exit(1);
      return 0;
    }

    free(elf_interpreter);
  }
  
  free(elf_phdata);

  if (interpreter_type != INTERPRETER_AOUT)
    close(elf_exec_fileno);
  
#if 0
#ifndef VM_STACK_FLAGS
  current->executable = dget(bprm->dentry);
#endif
#endif
  bprm->p = (unsigned long)create_elf_tables((char *)bprm->p,
                        bprm->argc, bprm->envc,
                        (interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL),
                        load_addr, load_bias, interp_load_addr,
                        (interpreter_type == INTERPRETER_AOUT ? 0 : 1));

#if 0                        
  /* N.B. passed_fileno might not be initialized? */
  if (interpreter_type == INTERPRETER_AOUT)
    current->arg_start += strlen(passed_fileno) + 1;
#endif  
    
  current->start_brk = current->brk = elf_brk;
  current->end_code = end_code;
  current->start_code = start_code;
  current->end_data = end_data;
  current->start_stack = bprm->p;

  /* Calling set_brk effectively mmaps the pages that we need
   * for the bss and break sections
   */
  set_brk(elf_bss, elf_brk);
  padzero(elf_bss);
  log_debug(LOG_LINEXEC_EXEC,"start_brk: %lx" , current->start_brk);
  log_debug(LOG_LINEXEC_EXEC,"end_code: %lx" , current->end_code);
  log_debug(LOG_LINEXEC_EXEC,"start_code: %lx" , current->start_code);
  log_debug(LOG_LINEXEC_EXEC,"end_data: %lx" , current->end_data);
  log_debug(LOG_LINEXEC_EXEC,"start_stack: %lx" , current->start_stack);
  log_debug(LOG_LINEXEC_EXEC,"brk: %lx" , current->brk);

  /*
   * The ABI may specify that certain registers be set up in special
   * ways (on i386 %edx is the address of a DT_FINI function, for
   * example.  This macro performs whatever initialization to
   * the regs structure is required.
   */
  ELF_PLAT_INIT((&regs));

  regs.eip = elf_entry;
  regs.esp = bprm->p;

#if 0
  if (current->flags & PF_PTRACED)
    send_sig(SIGTRAP, current, 0);
#endif

#ifndef __DEBUG__


//  dumpMemoryMap();
  log_verbose(LOG_LINEXEC_EXEC, "[transfering control to Linux executable]");
  //getchar();
  //printf("[ender]11\n");
  ASM_EXEC_JUMP(regs);
  
  printf("You should never see this message!\n");
 
#else

  printf("execve() finished, but in debug mode. exiting...\n");
 
#endif
    
  retval = 0;
out:
  return retval;

  /* error cleanup */
out_free_dentry:
  close(interpreter_fd);
  
out_free_interp:
  if (elf_interpreter) {
    free(elf_interpreter);
  }

out_free_file:
  close(elf_exec_fileno);
  
out_free_ph:
  free(elf_phdata);
  goto out;
}
Example #20
0
static inline int
do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
	struct file * file;
	struct dentry *interpreter_dentry = NULL; /* to shut gcc up */
 	unsigned long load_addr = 0, load_bias;
	int load_addr_set = 0;
	char * elf_interpreter = NULL;
	unsigned int interpreter_type = INTERPRETER_NONE;
	unsigned char ibcs2_interpreter = 0;
	mm_segment_t old_fs;
	unsigned long error;
	struct elf_phdr * elf_ppnt, *elf_phdata;
	unsigned long elf_bss, k, elf_brk;
	int elf_exec_fileno;
	int retval, size, i;
	unsigned long elf_entry, interp_load_addr = 0;
	unsigned long start_code, end_code, end_data;
	struct elfhdr elf_ex;
	struct elfhdr interp_elf_ex;
  	struct exec interp_ex;
	char passed_fileno[6];

	/* Get the exec-header */
	elf_ex = *((struct elfhdr *) bprm->buf);

	retval = -ENOEXEC;
	/* First of all, some simple consistency checks */
	if (elf_ex.e_ident[0] != 0x7f ||
	    strncmp(&elf_ex.e_ident[1], "ELF", 3) != 0)
		goto out;

	if (elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN)
		goto out;
	if (!elf_check_arch(elf_ex.e_machine))
		goto out;
#ifdef __mips__

/* allow only mips1 if exec is MIPSEB elf, 
	because IRIX binaries handled elsewhere. */

/* borrowed from binutils/include/elf/common.h*/
#define EI_DATA         5               /* Data encoding */
#define ELFDATA2MSB     2               /* 2's complement, big endian */

	if ((elf_ex.e_ident[EI_DATA] == ELFDATA2MSB ) &&
		(elf_ex.e_flags & EF_MIPS_ARCH) ) {
			retval = -ENOEXEC;
			goto out;
	}
#endif
	if (!bprm->dentry->d_inode->i_op		   ||
	    !bprm->dentry->d_inode->i_op->default_file_ops ||
	    !bprm->dentry->d_inode->i_op->default_file_ops->mmap)
		goto out;

	/* Now read in all of the header information */

	retval = -ENOMEM;
	size = elf_ex.e_phentsize * elf_ex.e_phnum;
	elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
	if (!elf_phdata)
		goto out;

	retval = read_exec(bprm->dentry, elf_ex.e_phoff,
				(char *) elf_phdata, size, 1);
	if (retval < 0)
		goto out_free_ph;

	retval = open_dentry(bprm->dentry, O_RDONLY);
	if (retval < 0)
		goto out_free_ph;
	elf_exec_fileno = retval;
	file = fget(elf_exec_fileno);

	elf_ppnt = elf_phdata;
	elf_bss = 0;
	elf_brk = 0;

	start_code = ~0UL;
	end_code = 0;
	end_data = 0;

	for (i = 0; i < elf_ex.e_phnum; i++) {
		if (elf_ppnt->p_type == PT_INTERP) {
			retval = -EINVAL;
		  	if (elf_interpreter)
				goto out_free_interp;

			/* This is the program interpreter used for
			 * shared libraries - for now assume that this
			 * is an a.out format binary
			 */

			retval = -ENOMEM;
			elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz,
							   GFP_KERNEL);
			if (!elf_interpreter)
				goto out_free_file;

			retval = read_exec(bprm->dentry, elf_ppnt->p_offset,
					   elf_interpreter,
					   elf_ppnt->p_filesz, 1);
			if (retval < 0)
				goto out_free_interp;
			/* If the program interpreter is one of these two,
			 * then assume an iBCS2 image. Otherwise assume
			 * a native linux image.
			 */
			if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
			    strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0)
				ibcs2_interpreter = 1;
#if 0
			printk("Using ELF interpreter %s\n", elf_interpreter);
#endif
			old_fs = get_fs(); /* This could probably be optimized */
			set_fs(get_ds());
#ifdef __sparc__
			if (ibcs2_interpreter) {
				unsigned long old_pers = current->personality;
					
				current->personality = PER_SVR4;
				interpreter_dentry = open_namei(elf_interpreter,
								0, 0);
				current->personality = old_pers;
			} else
#endif					
				interpreter_dentry = open_namei(elf_interpreter,
								0, 0);
			set_fs(old_fs);
			retval = PTR_ERR(interpreter_dentry);
			if (IS_ERR(interpreter_dentry))
				goto out_free_interp;
			retval = permission(interpreter_dentry->d_inode, MAY_EXEC);
			if (retval < 0)
				goto out_free_dentry;
			retval = read_exec(interpreter_dentry, 0, bprm->buf, 128, 1);
			if (retval < 0)
				goto out_free_dentry;

			/* Get the exec headers */
			interp_ex = *((struct exec *) bprm->buf);
			interp_elf_ex = *((struct elfhdr *) bprm->buf);
		}
		elf_ppnt++;
	}

	/* Some simple consistency checks for the interpreter */
	if (elf_interpreter) {
		interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;

		/* Now figure out which format our binary is */
		if ((N_MAGIC(interp_ex) != OMAGIC) &&
		    (N_MAGIC(interp_ex) != ZMAGIC) &&
		    (N_MAGIC(interp_ex) != QMAGIC))
			interpreter_type = INTERPRETER_ELF;

		if (interp_elf_ex.e_ident[0] != 0x7f ||
		    strncmp(&interp_elf_ex.e_ident[1], "ELF", 3) != 0)
			interpreter_type &= ~INTERPRETER_ELF;

		retval = -ELIBBAD;
		if (!interpreter_type)
			goto out_free_dentry;

		/* Make sure only one type was selected */
		if ((interpreter_type & INTERPRETER_ELF) &&
		     interpreter_type != INTERPRETER_ELF) {
			printk(KERN_WARNING "ELF: Ambiguous type, using ELF\n");
			interpreter_type = INTERPRETER_ELF;
		}
	}

	/* OK, we are done with that, now set up the arg stuff,
	   and then start this sucker up */

	if (!bprm->sh_bang) {
		char * passed_p;

		if (interpreter_type == INTERPRETER_AOUT) {
		  sprintf(passed_fileno, "%d", elf_exec_fileno);
		  passed_p = passed_fileno;

		  if (elf_interpreter) {
		    bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2);
		    bprm->argc++;
		  }
		}
		retval = -E2BIG;
		if (!bprm->p)
			goto out_free_dentry;
	}

	/* Flush all traces of the currently running executable */
	retval = flush_old_exec(bprm);
	if (retval)
		goto out_free_dentry;

	/* OK, This is the point of no return */
	current->mm->end_data = 0;
	current->mm->end_code = 0;
	current->mm->mmap = NULL;
	current->flags &= ~PF_FORKNOEXEC;
	elf_entry = (unsigned long) elf_ex.e_entry;

	/* Do this immediately, since STACK_TOP as used in setup_arg_pages
	   may depend on the personality.  */
	SET_PERSONALITY(elf_ex, ibcs2_interpreter);

	/* Do this so that we can load the interpreter, if need be.  We will
	   change some of these later */
	current->mm->rss = 0;
	bprm->p = setup_arg_pages(bprm->p, bprm);
	current->mm->start_stack = bprm->p;

	/* Try and get dynamic programs out of the way of the default mmap
	   base, as well as whatever program they might try to exec.  This
	   is because the brk will follow the loader, and is not movable.  */

	load_bias = ELF_PAGESTART(elf_ex.e_type==ET_DYN ? ELF_ET_DYN_BASE : 0);

	/* Now we do a little grungy work by mmaping the ELF image into
	   the correct location in memory.  At this point, we assume that
	   the image should be loaded at fixed address, not at a variable
	   address. */

	old_fs = get_fs();
	set_fs(get_ds());
	for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
		int elf_prot = 0, elf_flags;
		unsigned long vaddr;

		if (elf_ppnt->p_type != PT_LOAD)
			continue;

		if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
		if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
		if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;

		elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE;

		vaddr = elf_ppnt->p_vaddr;
		if (elf_ex.e_type == ET_EXEC || load_addr_set) {
			elf_flags |= MAP_FIXED;
		}

		error = do_mmap(file, ELF_PAGESTART(load_bias + vaddr),
		                (elf_ppnt->p_filesz +
		                ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
		                elf_prot, elf_flags, (elf_ppnt->p_offset -
		                ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));

		if (!load_addr_set) {
			load_addr_set = 1;
			load_addr = (elf_ppnt->p_vaddr - elf_ppnt->p_offset);
			if (elf_ex.e_type == ET_DYN) {
				load_bias += error -
				             ELF_PAGESTART(load_bias + vaddr);
				load_addr += error;
			}
		}
		k = elf_ppnt->p_vaddr;
		if (k < start_code) start_code = k;
		k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
		if (k > elf_bss)
			elf_bss = k;
		if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
			end_code = k;
		if (end_data < k)
			end_data = k;
		k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
		if (k > elf_brk)
			elf_brk = k;
	}
	set_fs(old_fs);
	fput(file); /* all done with the file */

	elf_entry += load_bias;
	elf_bss += load_bias;
	elf_brk += load_bias;
	start_code += load_bias;
	end_code += load_bias;
	end_data += load_bias;

	if (elf_interpreter) {
		if (interpreter_type == INTERPRETER_AOUT)
			elf_entry = load_aout_interp(&interp_ex,
						     interpreter_dentry);
		else
			elf_entry = load_elf_interp(&interp_elf_ex,
						    interpreter_dentry,
						    &interp_load_addr);

		dput(interpreter_dentry);
		kfree(elf_interpreter);

		if (elf_entry == ~0UL) {
			printk(KERN_ERR "Unable to load interpreter\n");
			kfree(elf_phdata);
			send_sig(SIGSEGV, current, 0);
			return 0;
		}
	}

	kfree(elf_phdata);

	if (interpreter_type != INTERPRETER_AOUT)
		sys_close(elf_exec_fileno);

	if (current->exec_domain && current->exec_domain->module)
		__MOD_DEC_USE_COUNT(current->exec_domain->module);
	if (current->binfmt && current->binfmt->module)
		__MOD_DEC_USE_COUNT(current->binfmt->module);
	current->exec_domain = lookup_exec_domain(current->personality);
	current->binfmt = &elf_format;
	if (current->exec_domain && current->exec_domain->module)
		__MOD_INC_USE_COUNT(current->exec_domain->module);
	if (current->binfmt && current->binfmt->module)
		__MOD_INC_USE_COUNT(current->binfmt->module);

#ifndef VM_STACK_FLAGS
	current->executable = dget(bprm->dentry);
#endif
	compute_creds(bprm);
	current->flags &= ~PF_FORKNOEXEC;
	bprm->p = (unsigned long)
	  create_elf_tables((char *)bprm->p,
			bprm->argc,
			bprm->envc,
			(interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL),
			load_addr, load_bias,
			interp_load_addr,
			(interpreter_type == INTERPRETER_AOUT ? 0 : 1));
	/* N.B. passed_fileno might not be initialized? */
	if (interpreter_type == INTERPRETER_AOUT)
		current->mm->arg_start += strlen(passed_fileno) + 1;
	current->mm->start_brk = current->mm->brk = elf_brk;
	current->mm->end_code = end_code;
	current->mm->start_code = start_code;
	current->mm->end_data = end_data;
	current->mm->start_stack = bprm->p;

	/* Calling set_brk effectively mmaps the pages that we need
	 * for the bss and break sections
	 */
	set_brk(elf_bss, elf_brk);

	padzero(elf_bss);

#if 0
	printk("(start_brk) %x\n" , current->mm->start_brk);
	printk("(end_code) %x\n" , current->mm->end_code);
	printk("(start_code) %x\n" , current->mm->start_code);
	printk("(end_data) %x\n" , current->mm->end_data);
	printk("(start_stack) %x\n" , current->mm->start_stack);
	printk("(brk) %x\n" , current->mm->brk);
#endif

	if ( current->personality == PER_SVR4 )
	{
		/* Why this, you ask???  Well SVr4 maps page 0 as read-only,
		   and some applications "depend" upon this behavior.
		   Since we do not have the power to recompile these, we
		   emulate the SVr4 behavior.  Sigh.  */
		/* N.B. Shouldn't the size here be PAGE_SIZE?? */
		error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,
				MAP_FIXED | MAP_PRIVATE, 0);
	}

#ifdef ELF_PLAT_INIT
	/*
	 * The ABI may specify that certain registers be set up in special
	 * ways (on i386 %edx is the address of a DT_FINI function, for
	 * example.  This macro performs whatever initialization to
	 * the regs structure is required.
	 */
	ELF_PLAT_INIT(regs);
#endif

	start_thread(regs, elf_entry, bprm->p);
	if (current->flags & PF_PTRACED)
		send_sig(SIGTRAP, current, 0);
	retval = 0;
out:
	return retval;

	/* error cleanup */
out_free_dentry:
	dput(interpreter_dentry);
out_free_interp:
	if (elf_interpreter)
		kfree(elf_interpreter);
out_free_file:
	fput(file);
	sys_close(elf_exec_fileno);
out_free_ph:
	kfree(elf_phdata);
	goto out;
}
Example #21
0
static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
                                     int interpreter_fd,
                                     unsigned long *interp_load_addr)
{
  struct elf_phdr *elf_phdata;
  struct elf_phdr *eppnt;
  unsigned long load_addr = 0;
  int load_addr_set = 0;
  unsigned long last_bss = 0, elf_bss = 0;
  unsigned long error = ~0UL;
  int elf_exec_fileno;
  int retval, i, size;

  /* First of all, some simple consistency checks */
  if (interp_elf_ex->e_type != ET_EXEC &&
      interp_elf_ex->e_type != ET_DYN)
    goto out;
  if (!elf_check_arch(interp_elf_ex->e_machine))
    goto out;

  /*
   * If the size of this structure has changed, then punt, since
   * we will be doing the wrong thing.
   */
  if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr))
    goto out;

  /* Now read in all of the header information */

  if (interp_elf_ex->e_phnum < 1 || interp_elf_ex->e_phnum >
      ELF_EXEC_PAGESIZE / sizeof(struct elf_phdr))
    goto out;
  size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum;
  elf_phdata = (struct elf_phdr *) malloc(size);
  if (!elf_phdata)
    goto out;

  retval = read_exec(interpreter_fd, interp_elf_ex->e_phoff,
                     (char *) elf_phdata, size, 1);
  error = retval;
  if (retval < 0)
    goto out_free;

  error = ~0UL;
  elf_exec_fileno = dup(interpreter_fd);
  if (elf_exec_fileno < 0)
    goto out_free;
  
  eppnt = elf_phdata;
  
  for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
    if (eppnt->p_type == PT_LOAD) {
      int elf_type = MAP_PRIVATE; // | MAP_DENYWRITE;
      int elf_prot = 0;
      unsigned long vaddr = 0;
      unsigned long k, map_addr;

      if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
      if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
      if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
      vaddr = eppnt->p_vaddr;
      
      if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
        elf_type |= MAP_FIXED;
      }

#ifdef __VERBOSE__ 
      printf("mapping: %08lX  (load_addr: %08lX, vaddr:%08lX)\n",  
            load_addr + ELF_PAGESTART(vaddr), load_addr, vaddr);
#endif
  

      map_addr = do_mmap(elf_exec_fileno, load_addr + ELF_PAGESTART(vaddr),
                         eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr),
                         elf_prot, elf_type,
                         eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr));

#ifdef __VERBOSE__ 
      printf("map_addr: %08lX\n", map_addr);
#endif      
 
      if (map_addr > -1024UL) /* Real error */
        goto out_close;

      if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
        load_addr = map_addr - ELF_PAGESTART(vaddr);
        load_addr_set = 1;
      }

      /*
       * Find the end of the file mapping for this phdr, and keep
       * track of the largest address we see for this.
       */
      k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
      if (k > elf_bss)
        elf_bss = k;

      /*
       * Do the same thing for the memory mapping - between
       * elf_bss and last_bss is the bss section.
       */
      k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
      if (k > last_bss)
        last_bss = k;
    }
  }

  /* Now use mmap to map the library into memory. */

  /*
   * Now fill out the bss section.  First pad the last page up
   * to the page boundary, and then perform a mmap to make sure
   * that there are zero-mapped pages up to and including the 
   * last bss page.
   */
  padzero(elf_bss);
  elf_bss = ELF_PAGESTART(elf_bss + ELF_EXEC_PAGESIZE - 1); /* What we have mapped so far */

  /* Map the last of the bss segment */
  if (last_bss > elf_bss)
    do_mmap(-1, elf_bss, last_bss - elf_bss, PROT_READ|PROT_WRITE|PROT_EXEC,
            MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0);

  *interp_load_addr = load_addr;
  /*
   * AUDIT: is everything deallocated properly if this happens
   * to be ~0UL? We'd better switch to out-of-band error reporting.
   * Also for a.out.
   */
  error = ((unsigned long) interp_elf_ex->e_entry) + load_addr;

out_close:
  close(elf_exec_fileno);
  
out_free:
  free(elf_phdata);
  
out:
  return error;
}
Example #22
0
static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
				     struct dentry * interpreter_dentry,
				     unsigned long *interp_load_addr)
{
	struct file * file;
	struct elf_phdr *elf_phdata;
	struct elf_phdr *eppnt;
	unsigned long load_addr = 0;
	int load_addr_set = 0;
	unsigned long last_bss = 0, elf_bss = 0;
	unsigned long error = ~0UL;
	int elf_exec_fileno;
	int retval, i, size;

	/* First of all, some simple consistency checks */
	if (interp_elf_ex->e_type != ET_EXEC &&
	    interp_elf_ex->e_type != ET_DYN)
		goto out;
	if (!elf_check_arch(interp_elf_ex->e_machine))
		goto out;
	if (!interpreter_dentry->d_inode->i_op ||
	    !interpreter_dentry->d_inode->i_op->default_file_ops->mmap)
		goto out;

	/*
	 * If the size of this structure has changed, then punt, since
	 * we will be doing the wrong thing.
	 */
	if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr))
		goto out;

	/* Now read in all of the header information */

	size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum;
	if (size > ELF_EXEC_PAGESIZE)
		goto out;
	elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
	if (!elf_phdata)
		goto out;

	retval = read_exec(interpreter_dentry, interp_elf_ex->e_phoff,
			   (char *) elf_phdata, size, 1);
	error = retval;
	if (retval < 0)
		goto out_free;

	error = ~0UL;
	elf_exec_fileno = open_dentry(interpreter_dentry, O_RDONLY);
	if (elf_exec_fileno < 0)
		goto out_free;
	file = fget(elf_exec_fileno);

	eppnt = elf_phdata;
	for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
	  if (eppnt->p_type == PT_LOAD) {
	    int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
	    int elf_prot = 0;
	    unsigned long vaddr = 0;
	    unsigned long k, map_addr;

	    if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
	    if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
	    if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
	    vaddr = eppnt->p_vaddr;
	    if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
	    	elf_type |= MAP_FIXED;
#ifdef __sparc__
	    } else {
		load_addr = get_unmapped_area(0, eppnt->p_filesz +
					ELF_PAGEOFFSET(vaddr));
#endif
	    }

	    map_addr = do_mmap(file,
			    load_addr + ELF_PAGESTART(vaddr),
			    eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr),
			    elf_prot,
			    elf_type,
			    eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr));
	    if (map_addr > -1024UL) /* Real error */
		goto out_close;

	    if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
		load_addr = map_addr - ELF_PAGESTART(vaddr);
		load_addr_set = 1;
	    }

	    /*
	     * Find the end of the file mapping for this phdr, and keep
	     * track of the largest address we see for this.
	     */
	    k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
	    if (k > elf_bss)
		elf_bss = k;

	    /*
	     * Do the same thing for the memory mapping - between
	     * elf_bss and last_bss is the bss section.
	     */
	    k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
	    if (k > last_bss)
		last_bss = k;
	  }
	}

	/* Now use mmap to map the library into memory. */

	/*
	 * Now fill out the bss section.  First pad the last page up
	 * to the page boundary, and then perform a mmap to make sure
	 * that there are zero-mapped pages up to and including the 
	 * last bss page.
	 */
	padzero(elf_bss);
	elf_bss = ELF_PAGESTART(elf_bss + ELF_EXEC_PAGESIZE - 1); /* What we have mapped so far */

	/* Map the last of the bss segment */
	if (last_bss > elf_bss)
		do_mmap(NULL, elf_bss, last_bss - elf_bss,
			PROT_READ|PROT_WRITE|PROT_EXEC,
			MAP_FIXED|MAP_PRIVATE, 0);

	*interp_load_addr = load_addr;
	error = ((unsigned long) interp_elf_ex->e_entry) + load_addr;

out_close:
	fput(file);
	sys_close(elf_exec_fileno);
out_free:
	kfree(elf_phdata);
out:
	return error;
}
Example #23
0
static int
preload_library (struct linux_binprm *exe_bprm,
		 COFF_SCNHDR * sect, struct file *fp)
{
    int status = 0;		/* Completion status                  */
    long nbytes;		/* Count of bytes in the header area  */
/*
 *  Fetch the size of the section. There must be enough room for at least
 *  one entry.
 */
    nbytes = COFF_LONG (sect->s_size);
    if (nbytes < COFF_SLIBSZ) {
	status = -ENOEXEC;
#ifdef COFF_DEBUG
	printk ("library section too small\n");
#endif
    }
/*
 *  Allocate a buffer to hold the section data
 */
    else {
	COFF_SLIBHD *phdr;
	char *buffer = (char *) kmalloc (nbytes, GFP_KERNEL);

        if (0 == buffer) {
	    status = -ENOEXEC;
#ifdef COFF_DEBUG
	    printk ("kmalloc failed\n");
#endif
	}
	else {
	    int old_fs   = get_fs ();
/*
 *  Read the section data from the disk file.
 */
	    set_fs (get_ds ());   /* Make it point to the proper location    */
	    status = read_exec (exe_bprm->inode,     /* INODE for file       */
			    COFF_LONG (sect->s_scnptr), /* Disk location     */
			    buffer,                     /* Buffer for read   */
			    nbytes);                    /* Byte count reqd.  */
	    set_fs (old_fs);                         /* Restore the selector */
/*
 *  Check the result. The value returned is the byte count actually read.
 */
	    if (status >= 0 && status != nbytes) {
#ifdef COFF_DEBUG
		printk ("read of lib section was short\n");
#endif
		status = -ENOEXEC;
	    }
	}
/*
 *  At this point, go through the list of libraries in the data area.
 */
	phdr = (COFF_SLIBHD *) buffer;
	while (status >= 0 && nbytes > COFF_SLIBSZ) {
	    int entry_size  = COFF_LONG (phdr->sl_entsz)   * sizeof (long);
	    int header_size = COFF_LONG (phdr->sl_pathndx) * sizeof (long);
/*
 *  Validate the sizes of the various items. I don't trust the linker!!
 */
	    if ((unsigned) header_size >= (unsigned) nbytes ||
		entry_size <= 0 ||
		(unsigned) entry_size <= (unsigned) header_size) {
		status = -ENOEXEC;
#ifdef COFF_DEBUG
		printk ("header count is invalid\n");
#endif
	    }
/*
 *  Load the library. Stop the load process on the first error.
 */
	    else {
		status = preload_this_library (exe_bprm,
					       &((char *) phdr)[header_size]);
#ifdef COFF_DEBUG
		printk ("preload_this_library result = %d\n", status);
#endif
	    }
/*
 *  Point to the next library in the section data.
 */
	    nbytes -= entry_size;
	    phdr = (COFF_SLIBHD *) &((char *) phdr)[entry_size];
	}
/*
 *  Release the space for the library list.
 */
	if (buffer != NULL)
	    kfree (buffer);
    }
/*
 *  Return the resulting status to the caller.
 */
    return (status);
}
Example #24
0
void print_exec(struct text_object *obj, char *p, int p_max_size)
{
	read_exec(obj->data.s, p, p_max_size, 1);
	remove_deleted_chars(p);
}
Example #25
0
static inline int
do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
	struct exec ex;
	struct file * file;
	int fd;
	unsigned long error;
	unsigned long p = bprm->p;
	unsigned long fd_offset;
	unsigned long rlim;

	ex = *((struct exec *) bprm->buf);		/* exec-header */
	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && 
	     N_MAGIC(ex) != QMAGIC) ||
	    N_TRSIZE(ex) || N_DRSIZE(ex) ||
	    bprm->inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
		return -ENOEXEC;
	}

	current->personality = PER_LINUX;
	fd_offset = N_TXTOFF(ex);

#if defined (__i386__) || defined (CONFIG_ARM)
	if (N_MAGIC(ex) == ZMAGIC && fd_offset != BLOCK_SIZE) {
		printk(KERN_NOTICE "N_TXTOFF != BLOCK_SIZE. See a.out.h.\n");
		return -ENOEXEC;
	}

	if (N_MAGIC(ex) == ZMAGIC && ex.a_text &&
	    (fd_offset < bprm->inode->i_sb->s_blocksize)) {
		printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n");
		return -ENOEXEC;
	}
#endif
#if defined(CONFIG_ARM)
	if (N_MACHTYPE(ex) != M_ARM) {
		printk(KERN_NOTICE "Binary != ARM.  Please recompile binary.\n");
		return -ENOEXEC;
	}
#endif

	/* Check initial limits. This avoids letting people circumvent
	 * size limits imposed on them by creating programs with large
	 * arrays in the data or bss.
	 */
	rlim = current->rlim[RLIMIT_DATA].rlim_cur;
	if (rlim >= RLIM_INFINITY)
		rlim = ~0;
	if (ex.a_data + ex.a_bss > rlim)
		return -ENOMEM;

	if (flush_old_exec(bprm))
		return -ENOMEM;

	/* OK, This is the point of no return */

	current->mm->end_code = ex.a_text +
		(current->mm->start_code = N_TXTADDR(ex));
	current->mm->end_data = ex.a_data +
		(current->mm->start_data = N_DATADDR(ex));
	current->mm->brk = ex.a_bss +
		(current->mm->start_brk = N_BSSADDR(ex));

	current->mm->rss = 0;
	current->mm->mmap = NULL;
	current->suid = current->euid = current->fsuid = bprm->e_uid;
	current->sgid = current->egid = current->fsgid = bprm->e_gid;
 	current->flags &= ~PF_FORKNOEXEC;
	if (N_MAGIC(ex) == OMAGIC) {
#if defined(__alpha__) || defined(CONFIG_ARM)
#ifndef CONFIG_ARM
		do_mmap(NULL, N_TXTADDR(ex) & PAGE_MASK,
			ex.a_text+ex.a_data + PAGE_SIZE - 1,
			PROT_READ|PROT_WRITE|PROT_EXEC,
			MAP_FIXED|MAP_PRIVATE, 0);
#else
		do_mmap(NULL, N_TXTADDR(ex),
			ex.a_text+ex.a_data,
			PROT_READ|PROT_WRITE|PROT_EXEC,
			MAP_FIXED|MAP_PRIVATE, 0);
#endif
		read_exec(bprm->inode, fd_offset, (char *) N_TXTADDR(ex),
			  ex.a_text+ex.a_data, 0);
#else
		do_mmap(NULL, 0, ex.a_text+ex.a_data,
			PROT_READ|PROT_WRITE|PROT_EXEC,
			MAP_FIXED|MAP_PRIVATE, 0);
		read_exec(bprm->inode, 32, (char *) 0, ex.a_text+ex.a_data, 0);
#endif
	} else {
		if (ex.a_text & 0xfff || ex.a_data & 0xfff)
			printk(KERN_NOTICE "executable not page aligned\n");
		
		fd = open_inode(bprm->inode, O_RDONLY);
		
		if (fd < 0) {
			send_sig(SIGKILL, current, 0);
			return fd;
		}
		file = current->files->fd[fd];
		if (!file->f_op || !file->f_op->mmap) {
			sys_close(fd);
			do_mmap(NULL, 0, ex.a_text+ex.a_data,
				PROT_READ|PROT_WRITE|PROT_EXEC,
				MAP_FIXED|MAP_PRIVATE, 0);
			read_exec(bprm->inode, fd_offset,
				  (char *) N_TXTADDR(ex), ex.a_text+ex.a_data, 0);
			goto beyond_if;
		}

		error = do_mmap(file, N_TXTADDR(ex), ex.a_text,
			PROT_READ | PROT_EXEC,
			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
			fd_offset);

		if (error != N_TXTADDR(ex)) {
			sys_close(fd);
			send_sig(SIGKILL, current, 0);
			return error;
		}
		
 		error = do_mmap(file, N_DATADDR(ex), ex.a_data,
				PROT_READ | PROT_WRITE | PROT_EXEC,
				MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
				fd_offset + ex.a_text);
		sys_close(fd);
		if (error != N_DATADDR(ex)) {
			send_sig(SIGKILL, current, 0);
			return error;
		}
	}
beyond_if:
	if (current->exec_domain && current->exec_domain->use_count)
		(*current->exec_domain->use_count)--;
	if (current->binfmt && current->binfmt->use_count)
		(*current->binfmt->use_count)--;
	current->exec_domain = lookup_exec_domain(current->personality);
	current->binfmt = &aout_format;
	if (current->exec_domain && current->exec_domain->use_count)
		(*current->exec_domain->use_count)++;
	if (current->binfmt && current->binfmt->use_count)
		(*current->binfmt->use_count)++;

	set_brk(current->mm->start_brk, current->mm->brk);

	p = setup_arg_pages(p, bprm);
	
	p = (unsigned long) create_aout_tables((char *)p, bprm);
	current->mm->start_stack = p;
#ifdef __alpha__
	regs->gp = ex.a_gpvalue;
#endif
	start_thread(regs, ex.a_entry, p);
	if (current->flags & PF_PTRACED)
		send_sig(SIGTRAP, current, 0);
#ifndef CONFIG_ARM
	return 0;
#else
	return regs->ARM_r0;
#endif
}
Example #26
0
static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
	struct elfhdr elf_ex;
	struct elfhdr interp_elf_ex;
	struct file * file;
  	struct exec interp_ex;
	struct inode *interpreter_inode;
	unsigned int load_addr;
	unsigned int interpreter_type = INTERPRETER_NONE;
	int i;
	int old_fs;
	int error;
	struct elf_phdr * elf_ppnt, *elf_phdata;
	int elf_exec_fileno;
	unsigned int elf_bss, k, elf_brk;
	int retval;
	char * elf_interpreter;
	unsigned int elf_entry;
	int status;
	unsigned int start_code, end_code, end_data;
	unsigned int elf_stack;
	char passed_fileno[6];
	
	status = 0;
	load_addr = 0;
	elf_ex = *((struct elfhdr *) bprm->buf);	  /* exec-header */
	
	if (elf_ex.e_ident[0] != 0x7f ||
	    strncmp(&elf_ex.e_ident[1], "ELF",3) != 0)
		return  -ENOEXEC;
	
	
	/* First of all, some simple consistency checks */
	if(elf_ex.e_type != ET_EXEC || 
	   (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
	   (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops ||
	    !bprm->inode->i_op->default_file_ops->mmap)){
		return -ENOEXEC;
	};
	
	/* Now read in all of the header information */
	
	elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize * 
						 elf_ex.e_phnum, GFP_KERNEL);
	
	old_fs = get_fs();
	set_fs(get_ds());
	retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata,
			   elf_ex.e_phentsize * elf_ex.e_phnum);
	set_fs(old_fs);
	if (retval < 0) {
	        kfree (elf_phdata);
		return retval;
	}
	
	elf_ppnt = elf_phdata;
	
	elf_bss = 0;
	elf_brk = 0;
	
	elf_exec_fileno = open_inode(bprm->inode, O_RDONLY);

	if (elf_exec_fileno < 0) {
	        kfree (elf_phdata);
		return elf_exec_fileno;
	}
	
	file = current->files->fd[elf_exec_fileno];
	
	elf_stack = 0xffffffff;
	elf_interpreter = NULL;
	start_code = 0;
	end_code = 0;
	end_data = 0;
	
	old_fs = get_fs();
	set_fs(get_ds());
	
	for(i=0;i < elf_ex.e_phnum; i++){
		if(elf_ppnt->p_type == PT_INTERP) {
			/* This is the program interpreter used for shared libraries - 
			   for now assume that this is an a.out format binary */
			
			elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz, 
							   GFP_KERNEL);
			
			retval = read_exec(bprm->inode,elf_ppnt->p_offset,elf_interpreter,
					   elf_ppnt->p_filesz);
#if 0
			printk("Using ELF interpreter %s\n", elf_interpreter);
#endif
			if(retval >= 0)
				retval = namei(elf_interpreter, &interpreter_inode);
			if(retval >= 0)
				retval = read_exec(interpreter_inode,0,bprm->buf,128);
			
			if(retval >= 0){
				interp_ex = *((struct exec *) bprm->buf);		/* exec-header */
				interp_elf_ex = *((struct elfhdr *) bprm->buf);	  /* exec-header */
				
			};
			if(retval < 0) {
			  kfree (elf_phdata);
			  kfree(elf_interpreter);
			  return retval;
			};
		};
		elf_ppnt++;
	};
	
	set_fs(old_fs);
	
	/* Some simple consistency checks for the interpreter */
	if(elf_interpreter){
	        interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
		if(retval < 0) {
			kfree(elf_interpreter);
			kfree(elf_phdata);
			return -ELIBACC;
		};
		/* Now figure out which format our binary is */
		if((N_MAGIC(interp_ex) != OMAGIC) && 
		   (N_MAGIC(interp_ex) != ZMAGIC) &&
		   (N_MAGIC(interp_ex) != QMAGIC)) 
		  interpreter_type = INTERPRETER_ELF;

		if (interp_elf_ex.e_ident[0] != 0x7f ||
		    strncmp(&interp_elf_ex.e_ident[1], "ELF",3) != 0)
		  interpreter_type &= ~INTERPRETER_ELF;

		if(!interpreter_type)
		  {
		    kfree(elf_interpreter);
		    kfree(elf_phdata);
		    return -ELIBBAD;
		  };
	}
	
	/* OK, we are done with that, now set up the arg stuff,
	   and then start this sucker up */
	
	if (!bprm->sh_bang) {
		char * passed_p;
		
		if(interpreter_type == INTERPRETER_AOUT) {
		  sprintf(passed_fileno, "%d", elf_exec_fileno);
		  passed_p = passed_fileno;
		
		  if(elf_interpreter) {
		    bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2);
		    bprm->argc++;
		  };
		};
		if (!bprm->p) {
		        if(elf_interpreter) {
			      kfree(elf_interpreter);
			}
		        kfree (elf_phdata);
			return -E2BIG;
		}
	}
	
	/* OK, This is the point of no return */
	flush_old_exec(bprm);

	current->mm->end_data = 0;
	current->mm->end_code = 0;
	current->mm->start_mmap = ELF_START_MMAP;
	current->mm->mmap = NULL;
	elf_entry = (unsigned int) elf_ex.e_entry;
	
	/* Do this so that we can load the interpreter, if need be.  We will
	   change some of these later */
	current->mm->rss = 0;
	bprm->p += change_ldt(0, bprm->page);
	current->mm->start_stack = bprm->p;
	
	/* Now we do a little grungy work by mmaping the ELF image into
	   the correct location in memory.  At this point, we assume that
	   the image should be loaded at fixed address, not at a variable
	   address. */
	
	old_fs = get_fs();
	set_fs(get_ds());
	
	elf_ppnt = elf_phdata;
	for(i=0;i < elf_ex.e_phnum; i++){
		
		if(elf_ppnt->p_type == PT_INTERP) {
			/* Set these up so that we are able to load the interpreter */
		  /* Now load the interpreter into user address space */
		  set_fs(old_fs);

		  if(interpreter_type & 1) elf_entry = 
		    load_aout_interp(&interp_ex, interpreter_inode);

		  if(interpreter_type & 2) elf_entry = 
		    load_elf_interp(&interp_elf_ex, interpreter_inode);

		  old_fs = get_fs();
		  set_fs(get_ds());

		  iput(interpreter_inode);
		  kfree(elf_interpreter);
			
		  if(elf_entry == 0xffffffff) { 
		    printk("Unable to load interpreter\n");
		    kfree(elf_phdata);
		    send_sig(SIGSEGV, current, 0);
		    return 0;
		  };
		};
		
		
		if(elf_ppnt->p_type == PT_LOAD) {
			error = do_mmap(file,
					elf_ppnt->p_vaddr & 0xfffff000,
					elf_ppnt->p_filesz + (elf_ppnt->p_vaddr & 0xfff),
					PROT_READ | PROT_WRITE | PROT_EXEC,
					MAP_FIXED | MAP_PRIVATE,
					elf_ppnt->p_offset & 0xfffff000);
			
#ifdef LOW_ELF_STACK
			if(elf_ppnt->p_vaddr & 0xfffff000 < elf_stack) 
				elf_stack = elf_ppnt->p_vaddr & 0xfffff000;
#endif
			
			if(!load_addr) 
			  load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
			k = elf_ppnt->p_vaddr;
			if(k > start_code) start_code = k;
			k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
			if(k > elf_bss) elf_bss = k;
			if((elf_ppnt->p_flags | PROT_WRITE) && end_code <  k)
				end_code = k; 
			if(end_data < k) end_data = k; 
			k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
			if(k > elf_brk) elf_brk = k;		     
		      };
		elf_ppnt++;
	};
	set_fs(old_fs);
	
	kfree(elf_phdata);
	
	if(interpreter_type != INTERPRETER_AOUT) sys_close(elf_exec_fileno);

       	/* The following 3 lines need a little bit of work if we are loading
	   an iBCS2 binary.  We should initially load it this way, and if
	   we get a lcall7, then we should look to see if the iBCS2 execution
	   profile is present.  If it is, then switch to that, otherwise
	   bomb. */
	current->personality = PER_LINUX;
	current->lcall7 = no_lcall7;
	current->signal_map = current->signal_invmap = ident_map;

	current->executable = bprm->inode;
	bprm->inode->i_count++;
#ifdef LOW_ELF_STACK
	current->start_stack = p = elf_stack - 4;
#endif
	bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
	bprm->p = (unsigned long) 
	  create_elf_tables((char *)bprm->p,
			bprm->argc,
			bprm->envc,
			(interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL),
			load_addr,    
			(interpreter_type == INTERPRETER_AOUT ? 0 : 1));
	if(interpreter_type == INTERPRETER_AOUT)
	  current->mm->arg_start += strlen(passed_fileno) + 1;
	current->mm->start_brk = current->mm->brk = elf_brk;
	current->mm->end_code = end_code;
	current->mm->start_code = start_code;
	current->mm->end_data = end_data;
	current->mm->start_stack = bprm->p;
	current->suid = current->euid = bprm->e_uid;
	current->sgid = current->egid = bprm->e_gid;

	/* Calling sys_brk effectively mmaps the pages that we need for the bss and break
	   sections */
	current->mm->brk = (elf_bss + 0xfff) & 0xfffff000;
	sys_brk((elf_brk + 0xfff) & 0xfffff000);

	padzero(elf_bss);

	/* Why this, you ask???  Well SVr4 maps page 0 as read-only,
	   and some applications "depend" upon this behavior.
	   Since we do not have the power to recompile these, we
	   emulate the SVr4 behavior.  Sigh.  */
	error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,
			MAP_FIXED | MAP_PRIVATE, 0);

	regs->eip = elf_entry;		/* eip, magic happens :-) */
	regs->esp = bprm->p;			/* stack pointer */
	if (current->flags & PF_PTRACED)
		send_sig(SIGTRAP, current, 0);
	return 0;
}
Example #27
0
static int load_elf_library(int fd){
        struct file * file;
	struct elfhdr elf_ex;
	struct elf_phdr *elf_phdata  =  NULL;
	struct  inode * inode;
	unsigned int len;
	int elf_bss;
	int old_fs, retval;
	unsigned int bss;
	int error;
	int i,j, k;
	
	len = 0;
	file = current->files->fd[fd];
	inode = file->f_inode;
	elf_bss = 0;
	
	set_fs(KERNEL_DS);
	if (file->f_op->read(inode, file, (char *) &elf_ex, sizeof(elf_ex)) != sizeof(elf_ex)) {
		sys_close(fd);
		return -EACCES;
	}
	set_fs(USER_DS);
	
	if (elf_ex.e_ident[0] != 0x7f ||
	    strncmp(&elf_ex.e_ident[1], "ELF",3) != 0)
		return -ENOEXEC;
	
	/* First of all, some simple consistency checks */
	if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
	   (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
	   (!inode->i_op ||
	    !inode->i_op->default_file_ops->mmap)){
		return -ENOEXEC;
	};
	
	/* Now read in all of the header information */
	
	if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) 
		return -ENOEXEC;
	
	elf_phdata =  (struct elf_phdr *) 
		kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL);
	
	old_fs = get_fs();
	set_fs(get_ds());
	retval = read_exec(inode, elf_ex.e_phoff, (char *) elf_phdata,
			   sizeof(struct elf_phdr) * elf_ex.e_phnum);
	set_fs(old_fs);
	
	j = 0;
	for(i=0; i<elf_ex.e_phnum; i++)
		if((elf_phdata + i)->p_type == PT_LOAD) j++;
	
	if(j != 1)  {
		kfree(elf_phdata);
		return -ENOEXEC;
	};
	
	while(elf_phdata->p_type != PT_LOAD) elf_phdata++;
	
	/* Now use mmap to map the library into memory. */
	error = do_mmap(file,
			elf_phdata->p_vaddr & 0xfffff000,
			elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff),
			PROT_READ | PROT_WRITE | PROT_EXEC,
			MAP_FIXED | MAP_PRIVATE,
			elf_phdata->p_offset & 0xfffff000);

	k = elf_phdata->p_vaddr + elf_phdata->p_filesz;
	if(k > elf_bss) elf_bss = k;
	
	sys_close(fd);
	if (error != elf_phdata->p_vaddr & 0xfffff000) {
	        kfree(elf_phdata);
		return error;
	}

	padzero(elf_bss);

	len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
	bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
	if (bss > len)
	  do_mmap(NULL, len, bss-len,
		  PROT_READ|PROT_WRITE|PROT_EXEC,
		  MAP_FIXED|MAP_PRIVATE, 0);
	kfree(elf_phdata);
	return 0;
}
Example #28
0
static int load_svr3_binary (struct linux_binprm *bprm,
						struct pt_regs *regs) {
	struct file *file;
	int error, retval, i, j, shlibs;
	int fd[1+SHLIB_MAX];
	long entry;
	unsigned long rlim;
	unsigned long p = bprm->p;

	struct filehdr *fh;
	struct aouthdr *ah;
	struct scnhdr *sh;
	char *buf, *libs_buf;

	/*  Main binary + SHLIB_MAX   */
	struct bin_info bin_info[SHLIB_MAX + 1];

/*  Cheking accessable headers by bprm->buf (128 bytes).   */

	fh = (struct filehdr *) bprm->buf;
	if (fh->f_magic != MC68MAGIC ||
	    fh->f_opthdr < AOUTSZ ||
	    fh->f_nscns < 3 ||
	    !(fh->f_flags & F_AR32W) ||
	    !(fh->f_flags & F_EXEC)
	)  return -ENOEXEC;

	ah = (struct aouthdr *) ((char *) bprm->buf + FILHSZ);
	if (ah->magic == SHMAGIC)  return -ELIBEXEC;
	if ((ah->magic != DMAGIC && ah->magic != ZMAGIC) ||
	    !ah->tsize ||
	    ah->tsize + ah->dsize + FILHSZ + fh->f_opthdr +
		 SCNHSZ * fh->f_nscns > bprm->inode->i_size ||
	    ah->text_start + ah->tsize > ah->data_start
	)  return -ENOEXEC;

	if (fh->f_nscns > 24) {
	    printk ("Too many sections in svr3 binary file\n");
	    return -ENOEXEC;
	}


/*      Touch main binary file (which has # 0).  */

	fd[0] = open_inode (bprm->inode, O_RDONLY);
	if (fd[0] < 0)  return fd[0];

	buf = (char *) kmalloc (2*1024, GFP_KERNEL);
	if (!buf)  { sys_close (fd[0]);  return -ENOMEM; }
	libs_buf = buf + 1024;

	retval = touch_svr3_binary (fd[0], buf, &bin_info[0], 0);
	if (retval < 0)  { sys_close(fd[0]); kfree (buf); return retval; }

/*      Looking for STYP_LIB section for shared libraries.  */

	sh = (struct scnhdr *) (buf + FILHSZ + fh->f_opthdr);

	for (i = 0; i < fh->f_nscns; i++)
	    if (sh[i].s_flags == STYP_LIB)  break;

	if (i == fh->f_nscns)  shlibs = 0;
	else  shlibs = sh[i].s_nlib;

/*      Touch target shared library binary files (## 1--SHLIB_MAX).  */

	if (shlibs) {
	    void *p;
	    int slib_size = sh[i].s_size;

	    if (shlibs > SHLIB_MAX)  { retval = -ELIBMAX; goto error_close; }

	    file = bin_info[0].file;

	    retval = sys_lseek (fd[0], sh[i].s_scnptr, 0);
	    if (retval < 0)  goto error_close;
	    if (retval != sh[i].s_scnptr) {
		retval = -EACCES;
		goto error_close;
	    }

	    set_fs (KERNEL_DS);
	    retval = file->f_op->read (file->f_inode, file, libs_buf, 1024);
	    set_fs (USER_DS);
	    if (retval < 0)  goto error_close;
	    if (retval < slib_size) {
		retval = -ELIBSCN;
		goto error_close;
	    }

	    for (p = libs_buf, j = 1; j <= shlibs; j++) {
		int len;
		char *name;
		struct slib *slibh = (struct slib *) p;

		p += slibh->sl_pathndx * 4;
		len = (slibh->sl_entsz - slibh->sl_pathndx) * 4;
		if (len <= 0 || p + len > (void *) libs_buf + slib_size) {
		    retval = -ELIBSCN;
		    goto error_close;
		}

		/* Target shared library path name. Must be
		  followed by one or more zeroes.          */
		name = (char *) p;

		/* Try to access this library.  */

		set_fs (KERNEL_DS);
		fd[j] = sys_open (name, 0, 0);
		set_fs (USER_DS);
		if (fd[j] < 0)  { retval = fd[j]; goto error_close; }

		retval = touch_svr3_binary (fd[j],buf,&bin_info[j],SHMAGIC);
		if (retval < 0)  {
		    /*  Renumbering for shared library context.  */
		    if (retval == -ENOEXEC)  retval = -ELIBBAD;
		    else if (retval == -EACCES)  retval = -ELIBACC;

		    goto error_close;
		}

		p += len;
	    }

	} /*  if (shlibs) ....   */

	/* Check initial limits. This avoids letting people circumvent
	 * size limits imposed on them by creating programs with large
	 * arrays in the data or bss.
	 */
	rlim = current->rlim[RLIMIT_DATA].rlim_cur;
	if (rlim >= RLIM_INFINITY)  rlim = ~0;
	if (ah->dsize + ah->bsize > rlim) {     /*  XXX: but in shlibs too  */
		retval = -ENOMEM;
		goto error_close;
	}

	kfree (buf);

	/*  OK, this is the point of noreturn.  */

	entry = ah->entry & ~0x1;   /* Avoids possibly hult after `rte' ??? */

	flush_old_exec (bprm);

	current->personality = PER_SVR3;

	current->mm->end_code = bin_info[0].text_len +
		(current->mm->start_code = bin_info[0].text_addr);
	current->mm->end_data = bin_info[0].data_len +
		(current->mm->start_data = bin_info[0].data_addr);
	current->mm->brk = bin_info[0].bss_len +
		(current->mm->start_brk = current->mm->end_data);

	current->mm->rss = 0;
	current->mm->mmap = NULL;
	current->suid = current->euid = current->fsuid = bprm->e_uid;
	current->sgid = current->egid = current->fsgid = bprm->e_gid;
	current->flags &= ~PF_FORKNOEXEC;

	/*  mmap all binaries    */

	for (i = 0; i < 1 + shlibs; i++) {
	    struct bin_info *binf = &bin_info[i];
	    unsigned int blocksize = binf->file->f_inode->i_sb->s_blocksize;
	    unsigned int start_bss, end_bss;

	    if (binf->text_addr & (PAGE_SIZE - 1) ||
		binf->data_addr & (PAGE_SIZE - 1) ||
		binf->text_offs & (blocksize - 1) ||
		binf->data_offs & (blocksize - 1) ||
		!binf->file->f_op->mmap
	    ) {
		/*  cannot mmap immediatly   */
		do_mmap (NULL, PAGE_ROUND(binf->text_addr),
			 binf->text_len + (binf->text_addr -
					   PAGE_ROUND(binf->text_addr)),
			 PROT_READ | PROT_WRITE | PROT_EXEC,
			 MAP_FIXED | MAP_PRIVATE, 0);
		read_exec (binf->file->f_inode, binf->text_offs,
			    (char *) binf->text_addr, binf->text_len, 0);

		do_mmap (NULL, PAGE_ROUND(binf->data_addr),
			 binf->data_len + (binf->data_addr -
					   PAGE_ROUND(binf->data_addr)),
			 PROT_READ | PROT_WRITE | PROT_EXEC,
			 MAP_FIXED | MAP_PRIVATE, 0);
		read_exec (binf->file->f_inode, binf->data_offs,
			    (char *) binf->data_addr, binf->data_len, 0);

		/* there's no nice way of flushing a number of
		   user pages to ram 8*( */
		flush_cache_all();

	    } else {

		error = do_mmap (binf->file, binf->text_addr, binf->text_len,
				 PROT_READ | PROT_EXEC,
				 MAP_FIXED | MAP_PRIVATE |
					MAP_DENYWRITE | MAP_EXECUTABLE,
				 binf->text_offs);
		if (error != binf->text_addr)  goto error_kill_close;

		error = do_mmap (binf->file, binf->data_addr, binf->data_len,
				 PROT_READ | PROT_WRITE | PROT_EXEC,
				 MAP_FIXED | MAP_PRIVATE |
					MAP_DENYWRITE | MAP_EXECUTABLE,
				 binf->data_offs);
		if (error != binf->data_addr)  goto error_kill_close;

#ifdef DMAGIC_NODEMAND
		/*  DMAGIC  is for pure executable (not demand loading).
		  But let the shared libraries be demand load ???   */
		if (i == 0 && ah->magic == DMAGIC) {
		    volatile char c;
		    unsigned long addr;

		    /*  Touch all pages in .text and .data segments.  */
		    for (addr = binf->text_addr;
			    addr < binf->text_addr + binf->text_len;
				addr += PAGE_SIZE
		    )  c = get_fs_byte ((char *) addr);
		    for (addr = binf->data_addr;
			    addr < binf->data_addr + binf->data_len;
				addr += PAGE_SIZE
		    )  c = get_fs_byte ((char *) addr);
		}
#endif
	    }

	    sys_close (fd[i]);

	    start_bss = PAGE_ALIGN(binf->data_addr + binf->data_len);
	    end_bss = PAGE_ALIGN(binf->data_addr + binf->data_len +
							binf->bss_len);

	    /*  svr3 binaries very hope that .bss section
	       had been initialized by zeroes. Oh...    */

	    if (binf->bss_len != 0) {
		/*  Because there may be skipped heap by alignment. */
		int addr = binf->data_addr + binf->data_len;
		int i = start_bss - addr;

		/*  start_bss is aligned, addr may be no   */
		while (i & 0x3) {
		    put_fs_byte (0, (char *) addr);
		    addr++; i--;
		}
		i >>= 2;
		while (i--) {
		    put_fs_long (0, (long *) addr);
		    addr += sizeof (long);
		}
	    }

	    if (end_bss >= start_bss)
		    do_mmap (NULL, start_bss, end_bss - start_bss,
			     PROT_READ | PROT_WRITE | PROT_EXEC,
			     MAP_FIXED | MAP_PRIVATE, 0);

#ifdef DMAGIC_NODEMAND
	    /*  The same reason as above.  */
	    if (i == 0 && ah->magic == DMAGIC) {
		volatile char c;
		unsigned long addr;

		for (addr = start_bss; addr < end_bss; addr += PAGE_SIZE)
			c = get_fs_byte ((char *) addr);
	    }
#endif

	    /*  OK, now all is mmapped for binary # i   */
	}  /*  for (i = ... )   */