예제 #1
0
/*
 * Set that machine state for performing an upcall that starts
 * the entry function with the given argument.
 */
void
cpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg,
    stack_t *stack)
{

	/* 
	 * Do any extra cleaning that needs to be done.
	 * The thread may have optional components
	 * that are not present in a fresh thread.
	 * This may be a recycled thread so make it look
	 * as though it's newly allocated.
	 */
	cpu_thread_clean(td);

#ifdef COMPAT_FREEBSD32
	if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
		/*
		 * Set the trap frame to point at the beginning of the entry
		 * function.
		 */
		td->td_frame->tf_rbp = 0;
		td->td_frame->tf_rsp =
		   (((uintptr_t)stack->ss_sp + stack->ss_size - 4) & ~0x0f) - 4;
		td->td_frame->tf_rip = (uintptr_t)entry;

		/* Return address sentinel value to stop stack unwinding. */
		suword32((void *)td->td_frame->tf_rsp, 0);

		/* Pass the argument to the entry point. */
		suword32((void *)(td->td_frame->tf_rsp + sizeof(int32_t)),
		    (uint32_t)(uintptr_t)arg);

		return;
	}
#endif

	/*
	 * Set the trap frame to point at the beginning of the uts
	 * function.
	 */
	td->td_frame->tf_rbp = 0;
	td->td_frame->tf_rsp =
	    ((register_t)stack->ss_sp + stack->ss_size) & ~0x0f;
	td->td_frame->tf_rsp -= 8;
	td->td_frame->tf_rip = (register_t)entry;
	td->td_frame->tf_ds = _udatasel;
	td->td_frame->tf_es = _udatasel;
	td->td_frame->tf_fs = _ufssel;
	td->td_frame->tf_gs = _ugssel;
	td->td_frame->tf_flags = TF_HASSEGS;

	/* Return address sentinel value to stop stack unwinding. */
	suword((void *)td->td_frame->tf_rsp, 0);

	/* Pass the argument to the entry point. */
	td->td_frame->tf_rdi = (register_t)arg;
}
예제 #2
0
/* ARGSUSED */
int
ufs_fioisbusy(struct vnode *vp, int *isbusy, struct cred *cr)
{
	int is_it_busy;

	/*
	 * The caller holds one reference, there may be one in the dnlc
	 * so we need to flush it.
	 */
	if (vp->v_count > 1)
		dnlc_purge_vp(vp);
	/*
	 * Since we've just flushed the dnlc and we hold a reference
	 * to this vnode, then anything but 1 means busy (this had
	 * BETTER not be zero!). Also, it's possible for someone to
	 * have this file mmap'ed with no additional reference count.
	 */
	ASSERT(vp->v_count > 0);
	if ((vp->v_count == 1) && (VTOI(vp)->i_mapcnt == 0))
		is_it_busy = 0;
	else
		is_it_busy = 1;

	if (suword32(isbusy, is_it_busy))
		return (EFAULT);
	return (0);
}
예제 #3
0
enum ftt_type
_fp_write_word(
	uint32_t *address,		/* FPU data address. */
	uint32_t value,			/* Word value to write. */
	fp_simd_type *pfpsd)		/* Pointer to fpu simulator data. */
{
	if (((uintptr_t)address & 0x3) != 0)
		return (ftt_alignment);	/* Must be word-aligned. */

	if (get_udatamodel() == DATAMODEL_ILP32) {
		/*
		 * If this is a 32-bit program, chop the address accordingly.
		 * The intermediate uintptr_t casts prevent warnings under a
		 * certain compiler, and the temporary 32 bit storage is
		 * intended to force proper code generation and break up what
		 * would otherwise be a quadruple cast.
		 */
		caddr32_t address32 = (caddr32_t)(uintptr_t)address;
		address = (uint32_t *)(uintptr_t)address32;
	}

	if (suword32(address, value) == -1) {
		pfpsd->fp_trapaddr = (caddr_t)address;
		pfpsd->fp_traprw = S_WRITE;
		return (ftt_fault);
	}
	return (ftt_none);
}
예제 #4
0
static int
elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
{
	Elf32_Auxargs *args;
	Elf32_Addr *base;
	Elf32_Addr *pos;
	struct linux32_ps_strings *arginfo;

	arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS;

	KASSERT(curthread->td_proc == imgp->proc,
	    ("unsafe elf_linux_fixup(), should be curproc"));
	base = (Elf32_Addr *)*stack_base;
	args = (Elf32_Auxargs *)imgp->auxargs;
	pos = base + (imgp->args->argc + imgp->args->envc + 2);

	AUXARGS_ENTRY_32(pos, LINUX_AT_SYSINFO_EHDR,
	    imgp->proc->p_sysent->sv_shared_page_base);
	AUXARGS_ENTRY_32(pos, LINUX_AT_SYSINFO, linux32_vsyscall);
	AUXARGS_ENTRY_32(pos, LINUX_AT_HWCAP, cpu_feature);

	/*
	 * Do not export AT_CLKTCK when emulating Linux kernel prior to 2.4.0,
	 * as it has appeared in the 2.4.0-rc7 first time.
	 * Being exported, AT_CLKTCK is returned by sysconf(_SC_CLK_TCK),
	 * glibc falls back to the hard-coded CLK_TCK value when aux entry
	 * is not present.
	 * Also see linux_times() implementation.
	 */
	if (linux_kernver(curthread) >= LINUX_KERNVER_2004000)
		AUXARGS_ENTRY_32(pos, LINUX_AT_CLKTCK, stclohz);
	AUXARGS_ENTRY_32(pos, AT_PHDR, args->phdr);
	AUXARGS_ENTRY_32(pos, AT_PHENT, args->phent);
	AUXARGS_ENTRY_32(pos, AT_PHNUM, args->phnum);
	AUXARGS_ENTRY_32(pos, AT_PAGESZ, args->pagesz);
	AUXARGS_ENTRY_32(pos, AT_FLAGS, args->flags);
	AUXARGS_ENTRY_32(pos, AT_ENTRY, args->entry);
	AUXARGS_ENTRY_32(pos, AT_BASE, args->base);
	AUXARGS_ENTRY_32(pos, LINUX_AT_SECURE, 0);
	AUXARGS_ENTRY_32(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
	AUXARGS_ENTRY_32(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
	AUXARGS_ENTRY_32(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
	AUXARGS_ENTRY_32(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
	AUXARGS_ENTRY_32(pos, LINUX_AT_PLATFORM, PTROUT(linux_platform));
	AUXARGS_ENTRY(pos, LINUX_AT_RANDOM, PTROUT(imgp->canary));
	if (imgp->execpathp != 0)
		AUXARGS_ENTRY(pos, LINUX_AT_EXECFN, PTROUT(imgp->execpathp));
	if (args->execfd != -1)
		AUXARGS_ENTRY_32(pos, AT_EXECFD, args->execfd);
	AUXARGS_ENTRY_32(pos, AT_NULL, 0);

	free(imgp->auxargs, M_TEMP);
	imgp->auxargs = NULL;

	base--;
	suword32(base, (uint32_t)imgp->args->argc);
	*stack_base = (register_t *)base;
	return (0);
}
예제 #5
0
static inline int
suword_lwpid(void *addr, lwpid_t lwpid)
{
	int error;

	if (SV_CURPROC_FLAG(SV_LP64))
		error = suword(addr, lwpid);
	else
		error = suword32(addr, lwpid);
	return (error);
}
예제 #6
0
int
suword32_nowatch(void *addr, uint32_t value)
{
	int watched, ret;

	watched = watch_disable_addr(addr, sizeof (value), S_WRITE);
	ret = suword32(addr, value);
	if (watched)
		watch_enable_addr(addr, sizeof (value), S_WRITE);

	return (ret);
}
예제 #7
0
int
freebsd32_cap_ioctls_get(struct thread *td,
    struct freebsd32_cap_ioctls_get_args *uap)
{
	struct filedesc *fdp;
	struct filedescent *fdep;
	uint32_t *cmds32;
	u_long *cmds;
	size_t maxcmds;
	int error, fd;
	u_int i;

	fd = uap->fd;
	cmds32 = uap->cmds;
	maxcmds = uap->maxcmds;

	AUDIT_ARG_FD(fd);

	fdp = td->td_proc->p_fd;
	FILEDESC_SLOCK(fdp);

	if (fget_locked(fdp, fd) == NULL) {
		error = EBADF;
		goto out;
	}

	/*
	 * If all ioctls are allowed (fde_nioctls == -1 && fde_ioctls == NULL)
	 * the only sane thing we can do is to not populate the given array and
	 * return CAP_IOCTLS_ALL (actually, INT_MAX).
	 */

	fdep = &fdp->fd_ofiles[fd];
	cmds = fdep->fde_ioctls;
	if (cmds32 != NULL && cmds != NULL) {
		for (i = 0; i < MIN(fdep->fde_nioctls, maxcmds); i++) {
			error = suword32(&cmds32[i], cmds[i]);
			if (error != 0)
				goto out;
		}
	}
	if (fdep->fde_nioctls == -1)
		td->td_retval[0] = INT_MAX;
	else
		td->td_retval[0] = fdep->fde_nioctls;

	error = 0;
out:
	FILEDESC_SUNLOCK(fdp);
	return (error);
}
예제 #8
0
/* ARGSUSED */
int
ufs_fiogdio(
	struct vnode	*vp,		/* file's vnode */
	uint_t		*diop,		/* dio state returned here */
	int		flag,		/* flag from ufs_ioctl */
	struct cred	*cr)		/* credentials from ufs_ioctl */
{
	struct ufsvfs	*ufsvfsp	= VTOI(vp)->i_ufsvfs;

	/*
	 * forcibly unmounted
	 */
	if (ufsvfsp == NULL)
		return (EIO);

	if (suword32(diop, ufsvfsp->vfs_dio))
		return (EFAULT);
	return (0);
}
예제 #9
0
파일: linux_fork.c 프로젝트: 2asoft/freebsd
void
linux_thread_detach(struct thread *td)
{
	struct linux_sys_futex_args cup;
	struct linux_emuldata *em;
	int *child_clear_tid;
	int error;

	em = em_find(td);
	KASSERT(em != NULL, ("thread_detach: emuldata not found.\n"));

	LINUX_CTR1(thread_detach, "thread(%d)", em->em_tid);

	release_futexes(td, em);

	child_clear_tid = em->child_clear_tid;

	if (child_clear_tid != NULL) {

		LINUX_CTR2(thread_detach, "thread(%d) %p",
		    em->em_tid, child_clear_tid);
	
		error = suword32(child_clear_tid, 0);
		if (error != 0)
			return;

		cup.uaddr = child_clear_tid;
		cup.op = LINUX_FUTEX_WAKE;
		cup.val = 1;		/* wake one */
		cup.timeout = NULL;
		cup.uaddr2 = NULL;
		cup.val3 = 0;
		error = linux_sys_futex(td, &cup);
		/*
		 * this cannot happen at the moment and if this happens it
		 * probably means there is a user space bug
		 */
		if (error != 0)
			linux_msg(td, "futex stuff in thread_detach failed.");
	}
}
예제 #10
0
파일: cpc.c 프로젝트: apprisi/illumos-gate
/*
 * System call to access CPU performance counters.
 */
static int
cpc(int cmd, id_t lwpid, void *udata1, void *udata2, void *udata3)
{
	kthread_t	*t;
	int		error;
	int		size;
	const char	*str;
	int		code;

	/*
	 * This CPC syscall should only be loaded if it found a PCBE to use.
	 */
	ASSERT(pcbe_ops != NULL);

	if (curproc->p_agenttp == curthread) {
		/*
		 * Only if /proc is invoking this system call from
		 * the agent thread do we allow the caller to examine
		 * the contexts of other lwps in the process.  And
		 * because we know we're the agent, we know we don't
		 * have to grab p_lock because no-one else can change
		 * the state of the process.
		 */
		if ((t = idtot(curproc, lwpid)) == NULL || t == curthread)
			return (set_errno(ESRCH));
		ASSERT(t->t_tid == lwpid && ttolwp(t) != NULL);
	} else
		t = curthread;

	if (t->t_cpc_set == NULL && (cmd == CPC_SAMPLE || cmd == CPC_RELE))
		return (set_errno(EINVAL));

	switch (cmd) {
	case CPC_BIND:
		/*
		 * udata1 = pointer to packed nvlist buffer
		 * udata2 = size of packed nvlist buffer
		 * udata3 = User addr to return error subcode in.
		 */

		rw_enter(&kcpc_cpuctx_lock, RW_READER);
		if (kcpc_cpuctx || dtrace_cpc_in_use) {
			rw_exit(&kcpc_cpuctx_lock);
			return (set_errno(EAGAIN));
		}

		if (kcpc_hw_lwp_hook() != 0) {
			rw_exit(&kcpc_cpuctx_lock);
			return (set_errno(EACCES));
		}

		/*
		 * An LWP may only have one set bound to it at a time; if there
		 * is a set bound to this LWP already, we unbind it here.
		 */
		if (t->t_cpc_set != NULL)
			(void) kcpc_unbind(t->t_cpc_set);
		ASSERT(t->t_cpc_set == NULL);

		if ((error = kcpc_copyin_set(&t->t_cpc_set, udata1,
		    (size_t)udata2)) != 0) {
			rw_exit(&kcpc_cpuctx_lock);
			return (set_errno(error));
		}

		if ((error = kcpc_verify_set(t->t_cpc_set)) != 0) {
			rw_exit(&kcpc_cpuctx_lock);
			kcpc_free_set(t->t_cpc_set);
			t->t_cpc_set = NULL;
			if (copyout(&error, udata3, sizeof (error)) == -1)
				return (set_errno(EFAULT));
			return (set_errno(EINVAL));
		}

		if ((error = kcpc_bind_thread(t->t_cpc_set, t, &code)) != 0) {
			rw_exit(&kcpc_cpuctx_lock);
			kcpc_free_set(t->t_cpc_set);
			t->t_cpc_set = NULL;
			/*
			 * EINVAL and EACCES are the only errors with more
			 * specific subcodes.
			 */
			if ((error == EINVAL || error == EACCES) &&
			    copyout(&code, udata3, sizeof (code)) == -1)
				return (set_errno(EFAULT));
			return (set_errno(error));
		}

		rw_exit(&kcpc_cpuctx_lock);
		return (0);
	case CPC_SAMPLE:
		/*
		 * udata1 = pointer to user's buffer
		 * udata2 = pointer to user's hrtime
		 * udata3 = pointer to user's tick
		 */
		/*
		 * We only allow thread-bound sets to be sampled via the
		 * syscall, so if this set has a CPU-bound context, return an
		 * error.
		 */
		if (t->t_cpc_set->ks_ctx->kc_cpuid != -1)
			return (set_errno(EINVAL));
		if ((error = kcpc_sample(t->t_cpc_set, udata1, udata2,
		    udata3)) != 0)
			return (set_errno(error));

		return (0);
	case CPC_PRESET:
	case CPC_RESTART:
		/*
		 * These are valid only if this lwp has a bound set.
		 */
		if (t->t_cpc_set == NULL)
			return (set_errno(EINVAL));
		if (cmd == CPC_PRESET) {
			/*
			 * The preset is shipped up to us from userland in two
			 * parts. This lets us handle 64-bit values from 32-bit
			 * and 64-bit applications in the same manner.
			 *
			 * udata1 = index of request to preset
			 * udata2 = new 64-bit preset (most sig. 32 bits)
			 * udata3 = new 64-bit preset (least sig. 32 bits)
			 */
			if ((error = kcpc_preset(t->t_cpc_set, (intptr_t)udata1,
			    ((uint64_t)(uintptr_t)udata2 << 32ULL) |
			    (uint64_t)(uintptr_t)udata3)) != 0)
				return (set_errno(error));
		} else {
			/*
			 * udata[1-3] = unused
			 */
			if ((error = kcpc_restart(t->t_cpc_set)) != 0)
				return (set_errno(error));
		}
		return (0);
	case CPC_ENABLE:
	case CPC_DISABLE:
		udata1 = 0;
		/*FALLTHROUGH*/
	case CPC_USR_EVENTS:
	case CPC_SYS_EVENTS:
		if (t != curthread || t->t_cpc_set == NULL)
			return (set_errno(EINVAL));
		/*
		 * Provided for backwards compatibility with CPCv1.
		 *
		 * Stop the counters and record the current counts. Use the
		 * counts as the preset to rebind a new set with the requests
		 * reconfigured as requested.
		 *
		 * udata1: 1 == enable; 0 == disable
		 * udata{2,3}: unused
		 */
		rw_enter(&kcpc_cpuctx_lock, RW_READER);
		if ((error = kcpc_enable(t,
		    cmd, (int)(uintptr_t)udata1)) != 0) {
			rw_exit(&kcpc_cpuctx_lock);
			return (set_errno(error));
		}
		rw_exit(&kcpc_cpuctx_lock);
		return (0);
	case CPC_NPIC:
		return (cpc_ncounters);
	case CPC_CAPS:
		return (pcbe_ops->pcbe_caps);
	case CPC_EVLIST_SIZE:
	case CPC_LIST_EVENTS:
		/*
		 * udata1 = pointer to user's int or buffer
		 * udata2 = picnum
		 * udata3 = unused
		 */
		if ((uintptr_t)udata2 >= cpc_ncounters)
			return (set_errno(EINVAL));

		size = strlen(
		    pcbe_ops->pcbe_list_events((uintptr_t)udata2)) + 1;

		if (cmd == CPC_EVLIST_SIZE) {
			if (suword32(udata1, size) == -1)
				return (set_errno(EFAULT));
		} else {
			if (copyout(
			    pcbe_ops->pcbe_list_events((uintptr_t)udata2),
			    udata1, size) == -1)
				return (set_errno(EFAULT));
		}
		return (0);
	case CPC_ATTRLIST_SIZE:
	case CPC_LIST_ATTRS:
		/*
		 * udata1 = pointer to user's int or buffer
		 * udata2 = unused
		 * udata3 = unused
		 *
		 * attrlist size is length of PCBE-supported attributes, plus
		 * room for "picnum\0" plus an optional ',' separator char.
		 */
		str = pcbe_ops->pcbe_list_attrs();
		size = strlen(str) + sizeof (SEPARATOR ATTRLIST) + 1;
		if (str[0] != '\0')
			/*
			 * A ',' separator character is necessary.
			 */
			size += 1;

		if (cmd == CPC_ATTRLIST_SIZE) {
			if (suword32(udata1, size) == -1)
				return (set_errno(EFAULT));
		} else {
			/*
			 * Copyout the PCBE attributes, and then append the
			 * generic attribute list (with separator if necessary).
			 */
			if (copyout(str, udata1, strlen(str)) == -1)
				return (set_errno(EFAULT));
			if (str[0] != '\0') {
				if (copyout(SEPARATOR ATTRLIST,
				    ((char *)udata1) + strlen(str),
				    strlen(SEPARATOR ATTRLIST) + 1)
				    == -1)
					return (set_errno(EFAULT));
			} else
				if (copyout(ATTRLIST,
				    (char *)udata1 + strlen(str),
				    strlen(ATTRLIST) + 1) == -1)
					return (set_errno(EFAULT));
		}
		return (0);
	case CPC_IMPL_NAME:
	case CPC_CPUREF:
		/*
		 * udata1 = pointer to user's buffer
		 * udata2 = unused
		 * udata3 = unused
		 */
		if (cmd == CPC_IMPL_NAME) {
			str = pcbe_ops->pcbe_impl_name();
			ASSERT(strlen(str) < CPC_MAX_IMPL_NAME);
		} else {
			str = pcbe_ops->pcbe_cpuref();
			ASSERT(strlen(str) < CPC_MAX_CPUREF);
		}

		if (copyout(str, udata1, strlen(str) + 1) != 0)
			return (set_errno(EFAULT));
		return (0);
	case CPC_INVALIDATE:
		kcpc_invalidate(t);
		return (0);
	case CPC_RELE:
		if ((error = kcpc_unbind(t->t_cpc_set)) != 0)
			return (set_errno(error));
		return (0);
	default:
		return (set_errno(EINVAL));
	}
}
예제 #11
0
/*
 * XXX copied from ia32_sysvec.c.
 */
static register_t *
linux_copyout_strings(struct image_params *imgp)
{
	int argc, envc;
	u_int32_t *vectp;
	char *stringp, *destp;
	u_int32_t *stack_base;
	struct linux32_ps_strings *arginfo;

	/*
	 * Calculate string base and vector table pointers.
	 * Also deal with signal trampoline code for this exec type.
	 */
	arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS;
	destp =	(caddr_t)arginfo - SPARE_USRSPACE - linux_szplatform -
	    roundup((ARG_MAX - imgp->args->stringspace),
	    sizeof(char *));

	/*
	 * Install LINUX_PLATFORM
	 */
	copyout(linux_platform, ((caddr_t)arginfo - linux_szplatform),
	    linux_szplatform);

	/*
	 * If we have a valid auxargs ptr, prepare some room
	 * on the stack.
	 */
	if (imgp->auxargs) {
		/*
		 * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
		 * lower compatibility.
		 */
		imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size :
		    (LINUX_AT_COUNT * 2);
		/*
		 * The '+ 2' is for the null pointers at the end of each of
		 * the arg and env vector sets,and imgp->auxarg_size is room
		 * for argument of Runtime loader.
		 */
		vectp = (u_int32_t *) (destp - (imgp->args->argc +
		    imgp->args->envc + 2 + imgp->auxarg_size) *
		    sizeof(u_int32_t));

	} else
		/*
		 * The '+ 2' is for the null pointers at the end of each of
		 * the arg and env vector sets
		 */
		vectp = (u_int32_t *)(destp - (imgp->args->argc +
		    imgp->args->envc + 2) * sizeof(u_int32_t));

	/*
	 * vectp also becomes our initial stack base
	 */
	stack_base = vectp;

	stringp = imgp->args->begin_argv;
	argc = imgp->args->argc;
	envc = imgp->args->envc;
	/*
	 * Copy out strings - arguments and environment.
	 */
	copyout(stringp, destp, ARG_MAX - imgp->args->stringspace);

	/*
	 * Fill in "ps_strings" struct for ps, w, etc.
	 */
	suword32(&arginfo->ps_argvstr, (uint32_t)(intptr_t)vectp);
	suword32(&arginfo->ps_nargvstr, argc);

	/*
	 * Fill in argument portion of vector table.
	 */
	for (; argc > 0; --argc) {
		suword32(vectp++, (uint32_t)(intptr_t)destp);
		while (*stringp++ != 0)
			destp++;
		destp++;
	}

	/* a null vector table pointer separates the argp's from the envp's */
	suword32(vectp++, 0);

	suword32(&arginfo->ps_envstr, (uint32_t)(intptr_t)vectp);
	suword32(&arginfo->ps_nenvstr, envc);

	/*
	 * Fill in environment portion of vector table.
	 */
	for (; envc > 0; --envc) {
		suword32(vectp++, (uint32_t)(intptr_t)destp);
		while (*stringp++ != 0)
			destp++;
		destp++;
	}

	/* end of vector table is a null pointer */
	suword32(vectp, 0);

	return ((register_t *)stack_base);
}
예제 #12
0
/* XXX may be freebsd32 MI */
static register_t *
ia32_copyout_strings(struct image_params *imgp)
{
	int argc, envc;
	u_int32_t *vectp;
	char *stringp, *destp;
	u_int32_t *stack_base;
	struct freebsd32_ps_strings *arginfo;
	size_t execpath_len;
	int szsigcode;

	/*
	 * Calculate string base and vector table pointers.
	 * Also deal with signal trampoline code for this exec type.
	 */
	if (imgp->execpath != NULL && imgp->auxargs != NULL)
		execpath_len = strlen(imgp->execpath) + 1;
	else
		execpath_len = 0;
	arginfo = (struct freebsd32_ps_strings *)FREEBSD32_PS_STRINGS;
	szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
	destp =	(caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
		roundup(execpath_len, sizeof(char *)) -
		roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));

	/*
	 * install sigcode
	 */
	if (szsigcode)
		copyout(imgp->proc->p_sysent->sv_sigcode,
			((caddr_t)arginfo - szsigcode), szsigcode);

	/*
	 * Copy the image path for the rtld.
	 */
	if (execpath_len != 0) {
		imgp->execpathp = (uintptr_t)arginfo - szsigcode - execpath_len;
		copyout(imgp->execpath, (void *)imgp->execpathp,
		    execpath_len);
	}

	/*
	 * If we have a valid auxargs ptr, prepare some room
	 * on the stack.
	 */
	if (imgp->auxargs) {
		/*
		 * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
		 * lower compatibility.
		 */
		imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size
			: (AT_COUNT * 2);
		/*
		 * The '+ 2' is for the null pointers at the end of each of
		 * the arg and env vector sets,and imgp->auxarg_size is room
		 * for argument of Runtime loader.
		 */
		vectp = (u_int32_t *) (destp - (imgp->args->argc +
		    imgp->args->envc + 2 + imgp->auxarg_size + execpath_len) *
		    sizeof(u_int32_t));
	} else
		/*
		 * The '+ 2' is for the null pointers at the end of each of
		 * the arg and env vector sets
		 */
		vectp = (u_int32_t *)
			(destp - (imgp->args->argc + imgp->args->envc + 2) * sizeof(u_int32_t));

	/*
	 * vectp also becomes our initial stack base
	 */
	stack_base = vectp;

	stringp = imgp->args->begin_argv;
	argc = imgp->args->argc;
	envc = imgp->args->envc;
	/*
	 * Copy out strings - arguments and environment.
	 */
	copyout(stringp, destp, ARG_MAX - imgp->args->stringspace);

	/*
	 * Fill in "ps_strings" struct for ps, w, etc.
	 */
	suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp);
	suword32(&arginfo->ps_nargvstr, argc);

	/*
	 * Fill in argument portion of vector table.
	 */
	for (; argc > 0; --argc) {
		suword32(vectp++, (u_int32_t)(intptr_t)destp);
		while (*stringp++ != 0)
			destp++;
		destp++;
	}

	/* a null vector table pointer separates the argp's from the envp's */
	suword32(vectp++, 0);

	suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp);
	suword32(&arginfo->ps_nenvstr, envc);

	/*
	 * Fill in environment portion of vector table.
	 */
	for (; envc > 0; --envc) {
		suword32(vectp++, (u_int32_t)(intptr_t)destp);
		while (*stringp++ != 0)
			destp++;
		destp++;
	}

	/* end of vector table is a null pointer */
	suword32(vectp, 0);

	return ((register_t *)stack_base);
}
예제 #13
0
static int
lwp_getprivate(klwp_t *lwp, int which, uintptr_t base)
{
	pcb_t *pcb = &lwp->lwp_pcb;
	struct regs *rp = lwptoregs(lwp);
	uintptr_t sbase;
	int error = 0;

	ASSERT(lwptot(lwp) == curthread);

	kpreempt_disable();
	switch (which) {
#if defined(__amd64)

	case _LWP_FSBASE:
		if ((sbase = pcb->pcb_fsbase) != 0) {
			if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) {
				if (pcb->pcb_rupdate == 1) {
					if (pcb->pcb_fs == 0)
						break;
				} else {
					if (rp->r_fs == 0)
						break;
				}
			} else {
				if (pcb->pcb_rupdate == 1) {
					if (pcb->pcb_fs == LWPFS_SEL)
						break;
				} else {
					if (rp->r_fs == LWPFS_SEL)
						break;
				}
			}
		}
		error = EINVAL;
		break;
	case _LWP_GSBASE:
		if ((sbase = pcb->pcb_gsbase) != 0) {
			if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) {
				if (pcb->pcb_rupdate == 1) {
					if (pcb->pcb_gs == 0)
						break;
				} else {
					if (rp->r_gs == 0)
						break;
				}
			} else {
				if (pcb->pcb_rupdate == 1) {
					if (pcb->pcb_gs == LWPGS_SEL)
						break;
				} else {
					if (rp->r_gs == LWPGS_SEL)
						break;
				}
			}
		}
		error = EINVAL;
		break;

#elif defined(__i386)

	case _LWP_FSBASE:
		if (rp->r_fs == LWPFS_SEL) {
			sbase = USEGD_GETBASE(&pcb->pcb_fsdesc);
			break;
		}
		error = EINVAL;
		break;
	case _LWP_GSBASE:
		if (rp->r_gs == LWPGS_SEL) {
			sbase = USEGD_GETBASE(&pcb->pcb_gsdesc);
			break;
		}
		error = EINVAL;
		break;

#endif	/* __i386 */

	default:
		error = ENOTSUP;
		break;
	}
	kpreempt_enable();

	if (error != 0)
		return (error);

	if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) {
		if (sulword((void *)base, sbase) == -1)
			error = EFAULT;
#if defined(_SYSCALL32_IMPL)
	} else {
		if (suword32((void *)base, (uint32_t)sbase) == -1)
			error = EFAULT;
#endif
	}
	return (error);
}
예제 #14
0
/*
 * XXX copied from ia32_sysvec.c.
 */
static register_t *
linux_copyout_strings(struct image_params *imgp)
{
	int argc, envc;
	u_int32_t *vectp;
	char *stringp, *destp;
	u_int32_t *stack_base;
	struct linux32_ps_strings *arginfo;
	char canary[LINUX_AT_RANDOM_LEN];
	size_t execpath_len;

	/*
	 * Calculate string base and vector table pointers.
	 */
	if (imgp->execpath != NULL && imgp->auxargs != NULL)
		execpath_len = strlen(imgp->execpath) + 1;
	else
		execpath_len = 0;

	arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS;
	destp =	(caddr_t)arginfo - SPARE_USRSPACE -
	    roundup(sizeof(canary), sizeof(char *)) -
	    roundup(execpath_len, sizeof(char *)) -
	    roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));

	if (execpath_len != 0) {
		imgp->execpathp = (uintptr_t)arginfo - execpath_len;
		copyout(imgp->execpath, (void *)imgp->execpathp, execpath_len);
	}

	/*
	 * Prepare the canary for SSP.
	 */
	arc4rand(canary, sizeof(canary), 0);
	imgp->canary = (uintptr_t)arginfo -
	    roundup(execpath_len, sizeof(char *)) -
	    roundup(sizeof(canary), sizeof(char *));
	copyout(canary, (void *)imgp->canary, sizeof(canary));

	/*
	 * If we have a valid auxargs ptr, prepare some room
	 * on the stack.
	 */
	if (imgp->auxargs) {
		/*
		 * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
		 * lower compatibility.
		 */
		imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size :
		    (LINUX_AT_COUNT * 2);
		/*
		 * The '+ 2' is for the null pointers at the end of each of
		 * the arg and env vector sets,and imgp->auxarg_size is room
		 * for argument of Runtime loader.
		 */
		vectp = (u_int32_t *) (destp - (imgp->args->argc +
		    imgp->args->envc + 2 + imgp->auxarg_size) *
		    sizeof(u_int32_t));

	} else
		/*
		 * The '+ 2' is for the null pointers at the end of each of
		 * the arg and env vector sets
		 */
		vectp = (u_int32_t *)(destp - (imgp->args->argc +
		    imgp->args->envc + 2) * sizeof(u_int32_t));

	/*
	 * vectp also becomes our initial stack base
	 */
	stack_base = vectp;

	stringp = imgp->args->begin_argv;
	argc = imgp->args->argc;
	envc = imgp->args->envc;
	/*
	 * Copy out strings - arguments and environment.
	 */
	copyout(stringp, destp, ARG_MAX - imgp->args->stringspace);

	/*
	 * Fill in "ps_strings" struct for ps, w, etc.
	 */
	suword32(&arginfo->ps_argvstr, (uint32_t)(intptr_t)vectp);
	suword32(&arginfo->ps_nargvstr, argc);

	/*
	 * Fill in argument portion of vector table.
	 */
	for (; argc > 0; --argc) {
		suword32(vectp++, (uint32_t)(intptr_t)destp);
		while (*stringp++ != 0)
			destp++;
		destp++;
	}

	/* a null vector table pointer separates the argp's from the envp's */
	suword32(vectp++, 0);

	suword32(&arginfo->ps_envstr, (uint32_t)(intptr_t)vectp);
	suword32(&arginfo->ps_nenvstr, envc);

	/*
	 * Fill in environment portion of vector table.
	 */
	for (; envc > 0; --envc) {
		suword32(vectp++, (uint32_t)(intptr_t)destp);
		while (*stringp++ != 0)
			destp++;
		destp++;
	}

	/* end of vector table is a null pointer */
	suword32(vectp, 0);

	return ((register_t *)stack_base);
}