Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3dc20cb2 authored by Al Viro's avatar Al Viro
Browse files

new helper: read_code()



switch binfmts that use ->read() to that (and to kernel_read()
in several cases in binfmt_flat - sure, it's nommu, but still,
doing ->read() into kmalloc'ed buffer...)

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 3af07613
Loading
Loading
Loading
Loading
+6 −24
Original line number Diff line number Diff line
@@ -323,11 +323,8 @@ static int load_aout_binary(struct linux_binprm *bprm)

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

		text_addr = N_TXTADDR(ex);

		pos = 32;
		map_size = ex.a_text+ex.a_data;

		error = vm_brk(text_addr & PAGE_MASK, map_size);
@@ -337,15 +334,12 @@ static int load_aout_binary(struct linux_binprm *bprm)
			return error;
		}

		error = bprm->file->f_op->read(bprm->file,
			 (char __user *)text_addr,
			  ex.a_text+ex.a_data, &pos);
		error = read_code(bprm->file, text_addr, 32,
				  ex.a_text + ex.a_data);
		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 {
#ifdef WARN_OLD
		static unsigned long error_time, error_time2;
@@ -367,14 +361,8 @@ static int load_aout_binary(struct linux_binprm *bprm)
#endif

		if (!bprm->file->f_op->mmap || (fd_offset & ~PAGE_MASK) != 0) {
			loff_t pos = fd_offset;

			vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
			bprm->file->f_op->read(bprm->file,
					(char __user *)N_TXTADDR(ex),
					ex.a_text+ex.a_data, &pos);
			flush_icache_range((unsigned long) N_TXTADDR(ex),
					   (unsigned long) N_TXTADDR(ex) +
			read_code(bprm->file, N_TXTADDR(ex), fd_offset,
					ex.a_text+ex.a_data);
			goto beyond_if;
		}
@@ -452,8 +440,6 @@ static int load_aout_library(struct file *file)
	start_addr =  ex.a_entry & 0xfffff000;

	if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
		loff_t pos = N_TXTOFF(ex);

#ifdef WARN_OLD
		static unsigned long error_time;
		if (time_after(jiffies, error_time + 5*HZ)) {
@@ -466,12 +452,8 @@ static int load_aout_library(struct file *file)
#endif
		vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);

		file->f_op->read(file, (char __user *)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);

		read_code(file, start_addr, N_TXTOFF(ex),
			  ex.a_text + ex.a_data);
		retval = 0;
		goto out;
	}
+6 −19
Original line number Diff line number Diff line
@@ -287,15 +287,12 @@ static int load_aout_binary(struct linux_binprm * bprm)
			return error;
		}

		error = bprm->file->f_op->read(bprm->file,
			  (char __user *)text_addr,
			  ex.a_text+ex.a_data, &pos);
		error = read_code(bprm->file, text_addr, pos,
				  ex.a_text+ex.a_data);
		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 {
		if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
		    (N_MAGIC(ex) != NMAGIC) && printk_ratelimit())
@@ -311,13 +308,8 @@ static int load_aout_binary(struct linux_binprm * bprm)
		}

		if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
			loff_t pos = fd_offset;
			vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
			bprm->file->f_op->read(bprm->file,
					(char __user *)N_TXTADDR(ex),
					ex.a_text+ex.a_data, &pos);
			flush_icache_range((unsigned long) N_TXTADDR(ex),
					   (unsigned long) N_TXTADDR(ex) +
			read_code(bprm->file, N_TXTADDR(ex), fd_offset,
				  ex.a_text + ex.a_data);
			goto beyond_if;
		}
@@ -397,8 +389,6 @@ static int load_aout_library(struct file *file)
	start_addr =  ex.a_entry & 0xfffff000;

	if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
		loff_t pos = N_TXTOFF(ex);

		if (printk_ratelimit())
		{
			printk(KERN_WARNING 
@@ -407,11 +397,8 @@ static int load_aout_library(struct file *file)
		}
		vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
		
		file->f_op->read(file, (char __user *)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);

		read_code(file, start_addr, N_TXTOFF(ex),
			  ex.a_text + ex.a_data);
		retval = 0;
		goto out;
	}
+2 −5
Original line number Diff line number Diff line
@@ -926,7 +926,6 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(
	struct elf32_fdpic_loadseg *seg;
	struct elf32_phdr *phdr;
	unsigned long load_addr, base = ULONG_MAX, top = 0, maddr = 0, mflags;
	loff_t fpos;
	int loop, ret;

	load_addr = params->load_addr;
@@ -964,14 +963,12 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(
		if (params->phdrs[loop].p_type != PT_LOAD)
			continue;

		fpos = phdr->p_offset;

		seg->addr = maddr + (phdr->p_vaddr - base);
		seg->p_vaddr = phdr->p_vaddr;
		seg->p_memsz = phdr->p_memsz;

		ret = file->f_op->read(file, (void *) seg->addr,
				       phdr->p_filesz, &fpos);
		ret = read_code(file, seg->addr, phdr->p_offset,
				       phdr->p_filesz);
		if (ret < 0)
			return ret;

+18 −19
Original line number Diff line number Diff line
@@ -207,11 +207,12 @@ static int decompress_exec(

	/* Read in first chunk of data and parse gzip header. */
	fpos = offset;
	ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos);
	ret = kernel_read(bprm->file, offset, buf, LBUFSIZE);

	strm.next_in = buf;
	strm.avail_in = ret;
	strm.total_in = 0;
	fpos += ret;

	retval = -ENOEXEC;

@@ -277,7 +278,7 @@ static int decompress_exec(
	}

	while ((ret = zlib_inflate(&strm, Z_NO_FLUSH)) == Z_OK) {
		ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos);
		ret = kernel_read(bprm->file, fpos, buf, LBUFSIZE);
		if (ret <= 0)
			break;
		len -= ret;
@@ -285,6 +286,7 @@ static int decompress_exec(
		strm.next_in = buf;
		strm.avail_in = ret;
		strm.total_in = 0;
		fpos += ret;
	}

	if (ret < 0) {
@@ -428,6 +430,7 @@ static int load_flat_file(struct linux_binprm * bprm,
	unsigned long textpos = 0, datapos = 0, result;
	unsigned long realdatastart = 0;
	unsigned long text_len, data_len, bss_len, stack_len, flags;
	unsigned long full_data;
	unsigned long len, memp = 0;
	unsigned long memp_size, extra, rlim;
	unsigned long *reloc = 0, *rp;
@@ -451,6 +454,7 @@ static int load_flat_file(struct linux_binprm * bprm,
	relocs    = ntohl(hdr->reloc_count);
	flags     = ntohl(hdr->flags);
	rev       = ntohl(hdr->rev);
	full_data = data_len + relocs * sizeof(unsigned long);

	if (strncmp(hdr->magic, "bFLT", 4)) {
		/*
@@ -577,12 +581,12 @@ static int load_flat_file(struct linux_binprm * bprm,
#ifdef CONFIG_BINFMT_ZFLAT
		if (flags & FLAT_FLAG_GZDATA) {
			result = decompress_exec(bprm, fpos, (char *) datapos, 
						 data_len + (relocs * sizeof(unsigned long)), 0);
						 full_data, 0);
		} else
#endif
		{
			result = bprm->file->f_op->read(bprm->file, (char *) datapos,
					data_len + (relocs * sizeof(unsigned long)), &fpos);
			result = read_code(bprm->file, datapos, fpos,
					full_data);
		}
		if (IS_ERR_VALUE(result)) {
			printk("Unable to read data+bss, errno %d\n", (int)-result);
@@ -627,30 +631,25 @@ static int load_flat_file(struct linux_binprm * bprm,
		if (flags & FLAT_FLAG_GZIP) {
			result = decompress_exec(bprm, sizeof (struct flat_hdr),
					 (((char *) textpos) + sizeof (struct flat_hdr)),
					 (text_len + data_len + (relocs * sizeof(unsigned long))
					 (text_len + full_data
						  - sizeof (struct flat_hdr)),
					 0);
			memmove((void *) datapos, (void *) realdatastart,
					data_len + (relocs * sizeof(unsigned long)));
					full_data);
		} else if (flags & FLAT_FLAG_GZDATA) {
			fpos = 0;
			result = bprm->file->f_op->read(bprm->file,
					(char *) textpos, text_len, &fpos);
			result = read_code(bprm->file, textpos, 0, text_len);
			if (!IS_ERR_VALUE(result))
				result = decompress_exec(bprm, text_len, (char *) datapos,
						 data_len + (relocs * sizeof(unsigned long)), 0);
						 full_data, 0);
		}
		else
#endif
		{
			fpos = 0;
			result = bprm->file->f_op->read(bprm->file,
					(char *) textpos, text_len, &fpos);
			if (!IS_ERR_VALUE(result)) {
				fpos = ntohl(hdr->data_start);
				result = bprm->file->f_op->read(bprm->file, (char *) datapos,
					data_len + (relocs * sizeof(unsigned long)), &fpos);
			}
			result = read_code(bprm->file, textpos, 0, text_len);
			if (!IS_ERR_VALUE(result))
				result = read_code(bprm->file, datapos,
						   ntohl(hdr->data_start),
						   full_data);
		}
		if (IS_ERR_VALUE(result)) {
			printk("Unable to read code+data+bss, errno %d\n",(int)-result);
+9 −0
Original line number Diff line number Diff line
@@ -802,6 +802,15 @@ int kernel_read(struct file *file, loff_t offset,

EXPORT_SYMBOL(kernel_read);

ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len)
{
	ssize_t res = file->f_op->read(file, (void __user *)addr, len, &pos);
	if (res > 0)
		flush_icache_range(addr, addr + len);
	return res;
}
EXPORT_SYMBOL(read_code);

static int exec_mmap(struct mm_struct *mm)
{
	struct task_struct *tsk;
Loading