示例#1
0
int
ELFNAME(os_pt_note)(struct proc *p, struct exec_package *epp, Elf_Ehdr *eh,
	char *os_name, size_t name_size, size_t desc_size)
{
	Elf_Phdr *hph, *ph;
	Elf_Note *np = NULL;
	size_t phsize;
	int error;

	phsize = eh->e_phnum * sizeof(Elf_Phdr);
	hph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
	if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff,
	    (caddr_t)hph, phsize)) != 0)
		goto out1;

	for (ph = hph;  ph < &hph[eh->e_phnum]; ph++) {
		if (ph->p_type != PT_NOTE ||
		    ph->p_filesz > 1024 ||
		    ph->p_filesz < sizeof(Elf_Note) + name_size)
			continue;

		np = (Elf_Note *)malloc(ph->p_filesz, M_TEMP, M_WAITOK);
		if ((error = ELFNAME(read_from)(p, epp->ep_vp, ph->p_offset,
		    (caddr_t)np, ph->p_filesz)) != 0)
			goto out2;

#if 0
		if (np->type != ELF_NOTE_TYPE_OSVERSION) {
			free(np, M_TEMP);
			np = NULL;
			continue;
		}
#endif

		/* Check the name and description sizes. */
		if (np->namesz != name_size ||
		    np->descsz != desc_size)
			goto out3;

		if (bcmp((np + 1), os_name, name_size))
			goto out3;

		/* XXX: We could check for the specific emulation here */
		/* All checks succeeded. */
		error = 0;
		goto out2;
	}

out3:
	error = ENOEXEC;
out2:
	if (np)
		free(np, M_TEMP);
out1:
	free(hph, M_TEMP);
	return error;
}
示例#2
0
int
ELFNAME(find_rd_root_image)(char *file, int fd, Elf_Phdr *ph, int segment,
                            long *prd_root_size_off, long *prd_root_image_off, off_t *pmmap_off,
                            size_t *pmmap_size)
{
    unsigned long kernel_start, kernel_size;
    uint64_t rd_root_size_off, rd_root_image_off;

    if (ELFNAME(nlist)(fd, ELFNAME(wantsyms))) {
        fprintf(stderr, "%s: no rd_root_image symbols?\n", file);
        exit(1);
    }
    kernel_start = ph->p_paddr;
    kernel_size = ph->p_filesz;

    rd_root_size_off = ELFNAME(wantsyms)[0].n_value - kernel_start;
    rd_root_size_off -= (ph->p_vaddr - ph->p_paddr);
    rd_root_image_off = ELFNAME(wantsyms)[1].n_value - kernel_start;
    rd_root_image_off -= (ph->p_vaddr - ph->p_paddr);

    if (debug) {
        fprintf(stderr, "segment %d rd_root_size_off = 0x%x\n", segment,
                rd_root_size_off);
        if ((ph->p_vaddr - ph->p_paddr) != 0)
            fprintf(stderr, "root_off v %x p %x, diff %x altered %x\n",
                    ph->p_vaddr, ph->p_paddr,
                    (ph->p_vaddr - ph->p_paddr),
                    rd_root_size_off - (ph->p_vaddr - ph->p_paddr));
        fprintf(stderr, "rd_root_image_off = 0x%x\n", rd_root_image_off);
    }

    /*
     * Sanity check locations of db_* symbols
     */
    if (rd_root_image_off < 0 || rd_root_image_off >= kernel_size)
        return (0);
    if (rd_root_size_off < 0 || rd_root_size_off >= kernel_size) {
        fprintf(stderr, "%s: rd_root_size not in data segment?\n",
                file);
        return (0);
    }
    *pmmap_off = ph->p_offset;
    *pmmap_size = kernel_size;
    *prd_root_size_off = rd_root_size_off;
    *prd_root_image_off = rd_root_image_off;
    return (1);
}
示例#3
0
/*
 * Check header for validity; return 0 for ok, ENOEXEC if error.
 * Remember OS tag for callers sake.
 */
int
ELFNAME(olf_check_header)(Elf_Ehdr *ehdr, int type, u_int8_t *os)
{
	int i;

	/*
	 * We need to check magic, class size, endianess, version, and OS
	 * before we look at the rest of the Elf_Ehdr structure. These few
	 * elements are represented in a machine independant fashion.
	 */
	if (!IS_OLF(*ehdr) ||
	    ehdr->e_ident[OI_CLASS] != ELF_TARG_CLASS ||
	    ehdr->e_ident[OI_DATA] != ELF_TARG_DATA ||
	    ehdr->e_ident[OI_VERSION] != ELF_TARG_VER)
		return (ENOEXEC);

	for (i = 0;
	    i < sizeof(ELFNAME(probes)) / sizeof(ELFNAME(probes)[0]);
	    i++) {
		if ((1 << ehdr->e_ident[OI_OS]) & ELFNAME(probes)[i].os_mask)
			goto os_ok;
	}
	return (ENOEXEC);

os_ok:
	/* Now check the machine dependant header */
	if (ehdr->e_machine != ELF_TARG_MACH ||
	    ehdr->e_version != ELF_TARG_VER)
		return (ENOEXEC);

	/* Check the type */
	if (ehdr->e_type != type)
		return (ENOEXEC);

	/* Don't allow an insane amount of sections. */
	if (ehdr->e_phnum > ELF_MAX_VALID_PHDR)
		return (ENOEXEC);

	*os = ehdr->e_ident[OI_OS];
	return (0);
}
示例#4
0
int
linux_elf_probe(struct proc *p, struct exec_package *epp, char *itp,
    u_long *pos, u_int8_t *os)
{
	Elf32_Ehdr *eh = epp->ep_hdr;
	char *bp, *brand;
	int error;
	size_t len;

	if (!(emul_linux_elf.e_flags & EMUL_ENABLED))
		return (ENOEXEC);

	/*
	 * Modern Linux binaries carry an identification note.
	 */
	if (ELFNAME(os_pt_note)(p, epp, epp->ep_hdr, "GNU", 4, 0x10) == 0) {
		goto recognized;
	}

	brand = elf32_check_brand(eh);
	if (brand != NULL && strcmp(brand, "Linux") != 0)
		return (EINVAL);

	/*
	 * If this is a static binary, do not allow it to run, as it
	 * has not been identified. We'll give non-static binaries a
	 * chance to run, as the Linux ld.so name is usually unique
	 * enough to clear any amibiguity.
	 */
	if (itp == NULL)
		return (EINVAL);

recognized:
	if (itp) {
		if ((error = emul_find(p, NULL, linux_emul_path, itp, &bp, 0)))
			return (error);
		if ((error = copystr(bp, itp, MAXPATHLEN, &len)))
			return (error);
		free(bp, M_TEMP);
	}
	epp->ep_emul = &emul_linux_elf;
	*pos = ELF32_NO_ADDR;
	if (*os == OOS_NULL)
		*os = OOS_LINUX;

	mtx_init(&futex_lock, IPL_NONE);
	futex_pool_init();

	return (0);
}
示例#5
0
void *
ELFNAME(locate_image)(int fd, struct elfhdr *ghead,  char *file,
                      long *prd_root_size_off, long *prd_root_image_off, off_t *pmmap_off,
                      size_t *pmmap_size)
{
    int n;
    int found = 0;
    size_t phsize;
    Elf_Ehdr head;

    Elf_Phdr *ph;

    /* elfhdr may not have the full header? */
    lseek(fd, 0, SEEK_SET);

    if (read(fd, &head, sizeof(head)) != sizeof(head)) {
        fprintf(stderr, "%s: can't read phdr area\n", file);
        exit(1);
    }

    phsize = head.e_phnum * sizeof(Elf_Phdr);
    ph = malloc(phsize);


    lseek(fd, head.e_phoff, SEEK_SET);

    if (read(fd, ph, phsize) != phsize) {
        fprintf(stderr, "%s: can't read phdr area\n", file);
        exit(1);
    }

    for (n = 0; n < head.e_phnum && !found; n++) {
        if (ph[n].p_type == PT_LOAD)
            found = ELFNAME(find_rd_root_image)(file, fd, &ph[n],
                                                n, prd_root_size_off, prd_root_image_off,
                                                pmmap_off, pmmap_size);
    }
    if (!found) {
        fprintf(stderr, "%s: can't locate space for rd_root_image!\n",
                file);
        exit(1);
    }
    free(ph);
}
示例#6
0

extern char linux_sigcode[], linux_esigcode[];
extern struct sysent linux_sysent[];
extern char *linux_syscallnames[];

struct emul ELFNAMEEND(emul_linux) = {
	"linux",
	native_to_linux_errno,
	linux_sendsig,
	LINUX_SYS_syscall,
	LINUX_SYS_MAXSYSCALL,
	linux_sysent,
	linux_syscallnames,
	LINUX_ELF_AUX_ARGSIZ,
	ELFNAME(copyargs),
	linux_setregs,
	linux_sigcode,
	linux_esigcode,
};


#ifdef LINUX_GCC_SIGNATURE
/*
 * Take advantage of the fact that all the linux binaries are compiled
 * with gcc, and gcc sticks in the comment field a signature. Note that
 * on SVR4 binaries, the gcc signature will follow the OS name signature,
 * that will not be a problem. We don't bother to read in the string table,
 * but we check all the progbits headers.
 *
 * XXX This only works in the i386.  On the alpha (at least)
示例#7
0
/*
 * Phase II of load. It is now safe to load the interpreter. Info collected
 * when loading the program is available for setup of the interpreter.
 */
int
ELFNAME2(exec,fixup)(struct proc *p, struct exec_package *epp)
{
	char	*interp;
	int	error;
	struct	elf_args *ap;
	AuxInfo ai[ELF_AUX_ENTRIES], *a;
	Elf_Addr	pos = epp->ep_interp_pos;

	if (epp->ep_interp == NULL) {
		return (0);
	}

	interp = (char *)epp->ep_interp;
	ap = (struct elf_args *)epp->ep_emul_arg;

	if ((error = ELFNAME(load_file)(p, interp, epp, ap, &pos)) != 0) {
		free((char *)ap, M_TEMP);
		free((char *)interp, M_TEMP);
		kill_vmcmds(&epp->ep_vmcmds);
		return (error);
	}
	/*
	 * We have to do this ourselves...
	 */
	error = exec_process_vmcmds(p, epp);

	/*
	 * Push extra arguments on the stack needed by dynamically
	 * linked binaries
	 */
	if (error == 0) {
		a = ai;

		a->au_id = AUX_phdr;
		a->au_v = ap->arg_phaddr;
		a++;

		a->au_id = AUX_phent;
		a->au_v = ap->arg_phentsize;
		a++;

		a->au_id = AUX_phnum;
		a->au_v = ap->arg_phnum;
		a++;

		a->au_id = AUX_pagesz;
		a->au_v = PAGE_SIZE;
		a++;

		a->au_id = AUX_base;
		a->au_v = ap->arg_interp;
		a++;

		a->au_id = AUX_flags;
		a->au_v = 0;
		a++;

		a->au_id = AUX_entry;
		a->au_v = ap->arg_entry;
		a++;

		a->au_id = AUX_null;
		a->au_v = 0;
		a++;

		error = copyout(ai, epp->ep_emul_argp, sizeof ai);
	}
	free((char *)ap, M_TEMP);
	free((char *)interp, M_TEMP);
	return (error);
}
示例#8
0
/*
 * Prepare an Elf binary's exec package
 *
 * First, set of the various offsets/lengths in the exec package.
 *
 * Then, mark the text image busy (so it can be demand paged) or error out if
 * this is not possible.  Finally, set up vmcmds for the text, data, bss, and
 * stack segments.
 */
int
ELFNAME2(exec,makecmds)(struct proc *p, struct exec_package *epp)
{
	Elf_Ehdr *eh = epp->ep_hdr;
	Elf_Phdr *ph, *pp;
	Elf_Addr phdr = 0;
	int error, i;
	char interp[MAXPATHLEN];
	u_long pos = 0, phsize;
	u_int8_t os = OOS_NULL;

	if (epp->ep_hdrvalid < sizeof(Elf_Ehdr))
		return (ENOEXEC);

	if (ELFNAME(check_header)(eh, ET_EXEC) &&
	    ELFNAME(olf_check_header)(eh, ET_EXEC, &os))
		return (ENOEXEC);

	/*
	 * check if vnode is in open for writing, because we want to demand-
	 * page out of it.  if it is, don't do it, for various reasons.
	 */
	if (epp->ep_vp->v_writecount != 0) {
#ifdef DIAGNOSTIC
		if (epp->ep_vp->v_flag & VTEXT)
			panic("exec: a VTEXT vnode has writecount != 0");
#endif
		return (ETXTBSY);
	}
	/*
	 * Allocate space to hold all the program headers, and read them
	 * from the file
	 */
	phsize = eh->e_phnum * sizeof(Elf_Phdr);
	ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);

	if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff, (caddr_t)ph,
	    phsize)) != 0)
		goto bad;

	epp->ep_tsize = ELFDEFNNAME(NO_ADDR);
	epp->ep_dsize = ELFDEFNNAME(NO_ADDR);

	interp[0] = '\0';

	for (i = 0; i < eh->e_phnum; i++) {
		pp = &ph[i];
		if (pp->p_type == PT_INTERP) {
			if (pp->p_filesz >= sizeof(interp))
				goto bad;
			if ((error = ELFNAME(read_from)(p, epp->ep_vp,
			    pp->p_offset, (caddr_t)interp, pp->p_filesz)) != 0)
				goto bad;
			break;
		}
	}

	/*
	 * OK, we want a slightly different twist of the
	 * standard emulation package for "real" elf.
	 */
	epp->ep_emul = &ELFNAMEEND(emul);
	pos = ELFDEFNNAME(NO_ADDR);

	/*
	 * On the same architecture, we may be emulating different systems.
	 * See which one will accept this executable.
	 *
	 * Probe functions would normally see if the interpreter (if any)
	 * exists. Emulation packages may possibly replace the interpreter in
	 * interp[] with a changed path (/emul/xxx/<path>), and also
	 * set the ep_emul field in the exec package structure.
	 */
	error = ENOEXEC;
	p->p_os = OOS_OPENBSD;
#ifdef NATIVE_EXEC_ELF
	if (ELFNAME(os_pt_note)(p, epp, epp->ep_hdr, "OpenBSD", 8, 4) == 0) {
		goto native;
	}
#endif
	for (i = 0;
	    i < sizeof(ELFNAME(probes)) / sizeof(ELFNAME(probes)[0]) && error;
	    i++) {
		if (os == OOS_NULL || ((1 << os) & ELFNAME(probes)[i].os_mask))
			error = ELFNAME(probes)[i].func ?
			    (*ELFNAME(probes)[i].func)(p, epp, interp, &pos, &os) :
			    0;
	}
	if (!error)
		p->p_os = os;
#ifndef NATIVE_EXEC_ELF
	else
		goto bad;
#else
native:
#endif /* NATIVE_EXEC_ELF */
	/*
	 * Load all the necessary sections
	 */
	for (i = 0; i < eh->e_phnum; i++) {
		Elf_Addr addr = ELFDEFNNAME(NO_ADDR), size = 0;
		int prot = 0;

		pp = &ph[i];

		switch (ph[i].p_type) {
		case PT_LOAD:
			/*
			 * Calcuates size of text and data segments
			 * by starting at first and going to end of last.
			 * 'rwx' sections are treated as data.
			 * this is correct for BSS_PLT, but may not be
			 * for DATA_PLT, is fine for TEXT_PLT.
			 */
			ELFNAME(load_psection)(&epp->ep_vmcmds, epp->ep_vp,
			    &ph[i], &addr, &size, &prot, 0);
			/*
			 * Decide whether it's text or data by looking
			 * at the protection of the section
			 */
			if (prot & VM_PROT_WRITE) {
				/* data section */
				if (epp->ep_dsize == ELFDEFNNAME(NO_ADDR)) {
					epp->ep_daddr = addr;
					epp->ep_dsize = size;
				} else {
					if (addr < epp->ep_daddr) {
						epp->ep_dsize =
						    epp->ep_dsize +
						    epp->ep_daddr -
						    addr;
						epp->ep_daddr = addr;
					} else
						epp->ep_dsize = addr+size -
						    epp->ep_daddr;
				}
			} else if (prot & VM_PROT_EXECUTE) {
				/* text section */
				if (epp->ep_tsize == ELFDEFNNAME(NO_ADDR)) {
					epp->ep_taddr = addr;
					epp->ep_tsize = size;
				} else {
					if (addr < epp->ep_taddr) {
						epp->ep_tsize =
						    epp->ep_tsize +
						    epp->ep_taddr -
						    addr;
						epp->ep_taddr = addr;
					} else
						epp->ep_tsize = addr+size -
						    epp->ep_taddr;
				}
			}
			break;

		case PT_SHLIB:
			error = ENOEXEC;
			goto bad;

		case PT_INTERP:
			/* Already did this one */
		case PT_DYNAMIC:
		case PT_NOTE:
			break;

		case PT_PHDR:
			/* Note address of program headers (in text segment) */
			phdr = pp->p_vaddr;
			break;

		default:
			/*
			 * Not fatal, we don't need to understand everything
			 * :-)
			 */
			break;
		}
	}

	/*
	 * Check if we found a dynamically linked binary and arrange to load
	 * it's interpreter when the exec file is released.
	 */
	if (interp[0]) {
		char *ip;
		struct elf_args *ap;

		ip = (char *)malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
		ap = (struct elf_args *)
		    malloc(sizeof(struct elf_args), M_TEMP, M_WAITOK);

		bcopy(interp, ip, MAXPATHLEN);
		epp->ep_interp = ip;
		epp->ep_interp_pos = pos;

		ap->arg_phaddr = phdr;
		ap->arg_phentsize = eh->e_phentsize;
		ap->arg_phnum = eh->e_phnum;
		ap->arg_entry = eh->e_entry;
		ap->arg_os = os;

		epp->ep_emul_arg = ap;
		epp->ep_entry = eh->e_entry; /* keep check_exec() happy */
	} else {
		epp->ep_interp = NULL;
		epp->ep_entry = eh->e_entry;
	}

#if defined(COMPAT_SVR4) && defined(i386)
#ifndef ELF_MAP_PAGE_ZERO
	/* Dell SVR4 maps page zero, yeuch! */
	if (p->p_os == OOS_DELL)
#endif
		NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, PAGE_SIZE, 0,
		    epp->ep_vp, 0, VM_PROT_READ);
#endif

	free((char *)ph, M_TEMP);
	vn_marktext(epp->ep_vp);
	return (exec_setup_stack(p, epp));

bad:
	free((char *)ph, M_TEMP);
	kill_vmcmds(&epp->ep_vmcmds);
	return (ENOEXEC);
}
示例#9
0
/*
 * Load a file (interpreter/library) pointed to by path [stolen from
 * coff_load_shlib()]. Made slightly generic so it might be used externally.
 */
int
ELFNAME(load_file)(struct proc *p, char *path, struct exec_package *epp,
	struct elf_args *ap, Elf_Addr *last)
{
	int error, i;
	struct nameidata nd;
	Elf_Ehdr eh;
	Elf_Phdr *ph = NULL;
	u_long phsize;
	char *bp = NULL;
	Elf_Addr addr;
	struct vnode *vp;
	u_int8_t os;			/* Just a dummy in this routine */
	Elf_Phdr *base_ph = NULL;
	struct interp_ld_sec {
		Elf_Addr vaddr;
		u_long memsz;
	} loadmap[ELF_MAX_VALID_PHDR];
	int nload, idx = 0;
	Elf_Addr pos = *last;
	int file_align;

	bp = path;
	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p);
	if ((error = namei(&nd)) != 0) {
		return (error);
	}
	vp = nd.ni_vp;
	if (vp->v_type != VREG) {
		error = EACCES;
		goto bad;
	}
	if ((error = VOP_GETATTR(vp, epp->ep_vap, p->p_ucred, p)) != 0)
		goto bad;
	if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
		error = EACCES;
		goto bad;
	}
	if ((error = VOP_ACCESS(vp, VREAD, p->p_ucred, p)) != 0)
		goto bad1;
	if ((error = ELFNAME(read_from)(p, nd.ni_vp, 0,
				    (caddr_t)&eh, sizeof(eh))) != 0)
		goto bad1;

	if (ELFNAME(check_header)(&eh, ET_DYN) &&
	    ELFNAME(olf_check_header)(&eh, ET_DYN, &os)) {
		error = ENOEXEC;
		goto bad1;
	}

	phsize = eh.e_phnum * sizeof(Elf_Phdr);
	ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);

	if ((error = ELFNAME(read_from)(p, nd.ni_vp, eh.e_phoff, (caddr_t)ph,
	    phsize)) != 0)
		goto bad1;

	for (i = 0; i < eh.e_phnum; i++) {
		if (ph[i].p_type == PT_LOAD) {
			loadmap[idx].vaddr = trunc_page(ph[i].p_vaddr);
			loadmap[idx].memsz = round_page (ph[i].p_vaddr +
			    ph[i].p_memsz - loadmap[idx].vaddr);
			file_align = ph[i].p_align;
			idx++;
		}
	}
	nload = idx;

	/*
	 * If no position to load the interpreter was set by a probe
	 * function, pick the same address that a non-fixed mmap(0, ..)
	 * would (i.e. something safely out of the way).
	 */
	if (pos == ELFDEFNNAME(NO_ADDR)) {
		pos = uvm_map_hint(p, VM_PROT_EXECUTE);
	}

	pos = ELF_ROUND(pos, file_align);
	*last = epp->ep_interp_pos = pos;
	for (i = 0; i < nload;/**/) {
		vaddr_t	addr;
		struct	uvm_object *uobj;
		off_t	uoff;
		size_t	size;

#ifdef this_needs_fixing
		if (i == 0) {
			uobj = &vp->v_uvm.u_obj;
			/* need to fix uoff */
		} else {
#endif
			uobj = NULL;
			uoff = 0;
#ifdef this_needs_fixing
		}
#endif

		addr = trunc_page(pos + loadmap[i].vaddr);
		size =  round_page(addr + loadmap[i].memsz) - addr;

		/* CRAP - map_findspace does not avoid daddr+MAXDSIZ */
		if ((addr + size > (vaddr_t)p->p_vmspace->vm_daddr) &&
		    (addr < (vaddr_t)p->p_vmspace->vm_daddr + MAXDSIZ))
			addr = round_page((vaddr_t)p->p_vmspace->vm_daddr +
			    MAXDSIZ);

		if (uvm_map_findspace(&p->p_vmspace->vm_map, addr, size,
		    &addr, uobj, uoff, 0, UVM_FLAG_FIXED) == NULL) {
			if (uvm_map_findspace(&p->p_vmspace->vm_map, addr, size,
			    &addr, uobj, uoff, 0, 0) == NULL) {
				error = ENOMEM; /* XXX */
				goto bad1;
			}
		} 
		if (addr != pos + loadmap[i].vaddr) {
			/* base changed. */
			pos = addr - trunc_page(loadmap[i].vaddr);
			pos = ELF_ROUND(pos,file_align);
			epp->ep_interp_pos = *last = pos;
			i = 0;
			continue;
		}

		i++;
	}

	/*
	 * Load all the necessary sections
	 */
	for (i = 0; i < eh.e_phnum; i++) {
		Elf_Addr size = 0;
		int prot = 0;
		int flags;

		switch (ph[i].p_type) {
		case PT_LOAD:
			if (base_ph == NULL) {
				flags = VMCMD_BASE;
				addr = *last;
				base_ph = &ph[i];
			} else {
				flags = VMCMD_RELATIVE;
				addr = ph[i].p_vaddr - base_ph->p_vaddr;
			}
			ELFNAME(load_psection)(&epp->ep_vmcmds, nd.ni_vp,
			    &ph[i], &addr, &size, &prot, flags);
			/* If entry is within this section it must be text */
			if (eh.e_entry >= ph[i].p_vaddr &&
			    eh.e_entry < (ph[i].p_vaddr + size)) {
 				epp->ep_entry = addr + eh.e_entry -
				    ELF_TRUNC(ph[i].p_vaddr,ph[i].p_align);
				ap->arg_interp = addr;
			}
			addr += size;
			break;

		case PT_DYNAMIC:
		case PT_PHDR:
		case PT_NOTE:
			break;

		default:
			break;
		}
	}

	vn_marktext(nd.ni_vp);

bad1:
	VOP_CLOSE(nd.ni_vp, FREAD, p->p_ucred, p);
bad:
	if (ph != NULL)
		free((char *)ph, M_TEMP);

	*last = addr;
	vput(nd.ni_vp);
	return (error);
}
示例#10
0
int
ELFNAME(nlist)(int fd, struct nlist *list)
{
    struct nlist *p;
    caddr_t strtab;
    Elf_Off symoff = 0, symstroff = 0;
    Elf_Word symsize = 0;
    long symstrsize = 0;
    Elf_Sword nent, cc, i;
    Elf_Sym sbuf[1024];
    Elf_Sym *s;
    Elf_Ehdr ehdr;
    Elf_Shdr *shdr = NULL;
    size_t shdr_size;
    struct stat st;
    int usemalloc = 0;
    size_t left, len;

    /* Make sure obj is OK */
    if (pread(fd, &ehdr, sizeof(Elf_Ehdr), (off_t)0) != sizeof(Elf_Ehdr) ||
            !ELFNAME(__elf_is_okay__)(&ehdr) || fstat(fd, &st) < 0)
        return (-1);

    /* calculate section header table size */
    shdr_size = ehdr.e_shentsize * ehdr.e_shnum;

    /* Make sure it's not too big to mmap */
    if (SIZE_MAX - ehdr.e_shoff < shdr_size ||
            S_ISREG(st.st_mode) && ehdr.e_shoff + shdr_size > st.st_size) {
        errno = EFBIG;
        return (-1);
    }

    /* mmap section header table */
    shdr = (Elf_Shdr *)mmap(NULL, (size_t)shdr_size, PROT_READ,
                            MAP_SHARED|MAP_FILE, fd, (off_t) ehdr.e_shoff);
    if (shdr == MAP_FAILED) {
        usemalloc = 1;
        if ((shdr = malloc(shdr_size)) == NULL)
            return (-1);

        if (pread(fd, shdr, shdr_size, (off_t)ehdr.e_shoff) !=
                shdr_size) {
            free(shdr);
            return (-1);
        }
    }

    /*
     * Find the symbol table entry and its corresponding
     * string table entry.	Version 1.1 of the ABI states
     * that there is only one symbol table but that this
     * could change in the future.
     */
    for (i = 0; i < ehdr.e_shnum; i++) {
        if (shdr[i].sh_type == SHT_SYMTAB) {
            if (shdr[i].sh_link >= ehdr.e_shnum)
                continue;
            symoff = shdr[i].sh_offset;
            symsize = shdr[i].sh_size;
            symstroff = shdr[shdr[i].sh_link].sh_offset;
            symstrsize = shdr[shdr[i].sh_link].sh_size;
            break;
        }
    }

    /* Flush the section header table */
    if (usemalloc)
        free(shdr);
    else
        munmap((caddr_t)shdr, shdr_size);

    /*
     * clean out any left-over information for all valid entries.
     * Type and value defined to be 0 if not found; historical
     * versions cleared other and desc as well.  Also figure out
     * the largest string length so don't read any more of the
     * string table than we have to.
     *
     * XXX clearing anything other than n_type and n_value violates
     * the semantics given in the man page.
     */
    nent = 0;
    for (p = list; !ISLAST(p); ++p) {
        p->n_type = 0;
        p->n_other = 0;
        p->n_desc = 0;
        p->n_value = 0;
        ++nent;
    }

    /* Don't process any further if object is stripped. */
    /* ELFism - dunno if stripped by looking at header */
    if (symoff == 0)
        return nent;

    /* Check for files too large to mmap. */
    if (SIZE_MAX - symstrsize < symstroff ||
            S_ISREG(st.st_mode) && symstrsize + symstroff > st.st_size) {
        errno = EFBIG;
        return (-1);
    }

    /*
     * Map string table into our address space.  This gives us
     * an easy way to randomly access all the strings, without
     * making the memory allocation permanent as with malloc/free
     * (i.e., munmap will return it to the system).
     */
    if (usemalloc) {
        if ((strtab = malloc(symstrsize)) == NULL)
            return (-1);
        if (pread(fd, strtab, symstrsize, (off_t)symstroff) !=
                symstrsize) {
            free(strtab);
            return (-1);
        }
    } else {
        strtab = mmap(NULL, (size_t)symstrsize, PROT_READ,
                      MAP_SHARED|MAP_FILE, fd, (off_t) symstroff);
        if (strtab == MAP_FAILED)
            return (-1);
    }

    while (symsize >= sizeof(Elf_Sym)) {
        cc = MIN(symsize, sizeof(sbuf));
        if (pread(fd, sbuf, cc, (off_t)symoff) != cc)
            break;
        symsize -= cc;
        symoff += cc;
        for (s = sbuf; cc > 0; ++s, cc -= sizeof(*s)) {
            Elf_Word soff = s->st_name;

            if (soff == 0 || soff >= symstrsize)
                continue;
            left = symstrsize - soff;

            for (p = list; !ISLAST(p); p++) {
                char *sym;

                /*
                 * First we check for the symbol as it was
                 * provided by the user. If that fails
                 * and the first char is an '_', skip over
                 * the '_' and try again.
                 * XXX - What do we do when the user really
                 *       wants '_foo' and there are symbols
                 *       for both 'foo' and '_foo' in the
                 *	 table and 'foo' is first?
                 */
                sym = p->n_name;
                len = strlen(sym);

                if ((len >= left ||
                        strcmp(&strtab[soff], sym) != 0) &&
                        (sym[0] != '_' || len - 1 >= left ||
                         strcmp(&strtab[soff], sym + 1) != 0))
                    continue;

                p->n_value = s->st_value;

                /* XXX - type conversion */
                /*	 is pretty rude. */
                switch(ELF_ST_TYPE(s->st_info)) {
                case STT_NOTYPE:
                    switch (s->st_shndx) {
                    case SHN_UNDEF:
                        p->n_type = N_UNDF;
                        break;
                    case SHN_ABS:
                        p->n_type = N_ABS;
                        break;
                    case SHN_COMMON:
                        p->n_type = N_COMM;
                        break;
                    default:
                        p->n_type = N_COMM | N_EXT;
                        break;
                    }
                    break;
                case STT_OBJECT:
                    p->n_type = N_DATA;
                    break;
                case STT_FUNC:
                    p->n_type = N_TEXT;
                    break;
                case STT_FILE:
                    p->n_type = N_FN;
                    break;
                }
                if (ELF_ST_BIND(s->st_info) == STB_LOCAL)
                    p->n_type = N_EXT;
                p->n_desc = 0;
                p->n_other = 0;
                if (--nent <= 0)
                    break;
            }
        }
    }
elf_done:
    if (usemalloc)
        free(strtab);
    else
        munmap(strtab, symstrsize);
    return (nent);
}
示例#11
0
#include <limits.h>

#include <sys/exec_elf.h>

#include "elfrdsetroot.h"

void *
ELFNAME(locate_image)(int, struct elfhdr *,  char *, long *, long *, off_t *,
                      size_t *);
int
ELFNAME(find_rd_root_image)(char *, int, Elf_Phdr *, int, long *, long *,
                            off_t *, size_t *);

struct elf_fn ELFDEFNNAME(fn) =
{
    ELFNAME(locate_image),
    ELFNAME(find_rd_root_image)
};

void *
ELFNAME(locate_image)(int fd, struct elfhdr *ghead,  char *file,
                      long *prd_root_size_off, long *prd_root_image_off, off_t *pmmap_off,
                      size_t *pmmap_size)
{
    int n;
    int found = 0;
    size_t phsize;
    Elf_Ehdr head;

    Elf_Phdr *ph;