예제 #1
0
int
linux_read_ldt(struct proc *p, struct linux_sys_modify_ldt_args *uap,
    register_t *retval)
{
	struct i386_get_ldt_args gl;
	int error;
	caddr_t sg;
	char *parms;

	if (user_ldt_enable == 0)
		return (ENOSYS);

	sg = stackgap_init(p->p_emul);

	gl.start = 0;
	gl.desc = SCARG(uap, ptr);
	gl.num = SCARG(uap, bytecount) / sizeof(union descriptor);

	parms = stackgap_alloc(&sg, sizeof(gl));

	if ((error = copyout(&gl, parms, sizeof(gl))) != 0)
		return (error);

	if ((error = i386_get_ldt(p, parms, retval)) != 0)
		return (error);

	*retval *= sizeof(union descriptor);
	return (0);
}
예제 #2
0
파일: linux_stats.c 프로젝트: kame/kame
int
linux_newstat(struct proc *p, struct linux_newstat_args *args)
{
    struct stat buf;
    struct nameidata nd;
    int error;
    caddr_t sg;

    sg = stackgap_init();
    CHECKALTEXIST(p, &sg, args->path);

#ifdef DEBUG
    printf("Linux-emul(%ld): newstat(%s, *)\n", (long)p->p_pid,
           args->path);
#endif

    NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
           args->path, p);
    error = namei(&nd);
    if (error)
        return (error);
    NDFREE(&nd, NDF_ONLY_PNBUF);

    error = vn_stat(nd.ni_vp, &buf, p);
    vput(nd.ni_vp);
    if (error)
        return (error);

    return (newstat_copyout(&buf, args->buf));
}
예제 #3
0
static int
linux_check_hdrincl(struct proc *p, int s)
{
    struct getsockopt_args /* {
	int s;
	int level;
	int name;
	caddr_t val;
	int *avalsize;
    } */ bsd_args;
    int error;
    int retval_getsockopt;
    caddr_t sg, val, valsize;
    int size_val = sizeof val;
    int optval;

    sg = stackgap_init();
    val = stackgap_alloc(&sg, sizeof(int));
    valsize = stackgap_alloc(&sg, sizeof(int));

    if ((error=copyout(&size_val, valsize, sizeof(size_val))))
        return error;
    bsd_args.s = s;
    bsd_args.level = IPPROTO_IP;
    bsd_args.name = IP_HDRINCL;
    bsd_args.val = val;
    bsd_args.avalsize = (int *)valsize;
    if ((error=getsockopt(p, &bsd_args, &retval_getsockopt)))
	return error;
    if ((error=copyin(val, &optval, sizeof(optval))))
        return error;
    return optval == 0;
}
예제 #4
0
int
linux_write_ldt(struct proc *p, struct linux_sys_modify_ldt_args *uap,
    register_t *retval)
{
	struct linux_ldt_info ldt_info;
	struct segment_descriptor sd;
	struct i386_set_ldt_args sl;
	int error;
	caddr_t sg;
	char *parms;

	if (user_ldt_enable == 0)
		return (ENOSYS);

	if (SCARG(uap, bytecount) != sizeof(ldt_info))
		return (EINVAL);
	if ((error = copyin(SCARG(uap, ptr), &ldt_info, sizeof(ldt_info))) != 0)
		return error;
	if (ldt_info.contents == 3)
		return (EINVAL);

	sg = stackgap_init(p->p_emul);

	sd.sd_lobase = ldt_info.base_addr & 0xffffff;
	sd.sd_hibase = (ldt_info.base_addr >> 24) & 0xff;
	sd.sd_lolimit = ldt_info.limit & 0xffff;
	sd.sd_hilimit = (ldt_info.limit >> 16) & 0xf;
	sd.sd_type =
	    16 | (ldt_info.contents << 2) | (!ldt_info.read_exec_only << 1);
	sd.sd_dpl = SEL_UPL;
	sd.sd_p = !ldt_info.seg_not_present;
	sd.sd_def32 = ldt_info.seg_32bit;
	sd.sd_gran = ldt_info.limit_in_pages;

	sl.start = ldt_info.entry_number;
	sl.desc = stackgap_alloc(&sg, sizeof(sd));
	sl.num = 1;

#if 0
	printf("linux_write_ldt: idx=%d, base=%x, limit=%x\n",
	    ldt_info.entry_number, ldt_info.base_addr, ldt_info.limit);
#endif

	parms = stackgap_alloc(&sg, sizeof(sl));

	if ((error = copyout(&sd, sl.desc, sizeof(sd))) != 0)
		return (error);
	if ((error = copyout(&sl, parms, sizeof(sl))) != 0)
		return (error);

	if ((error = i386_set_ldt(p, parms, retval)) != 0)
		return (error);

	*retval = 0;
	return (0);
}
예제 #5
0
static int
linux_socket(struct proc *p, struct linux_socket_args *args, int *retval)
{
    struct linux_socket_args linux_args;
    struct socket_args /* {
	int domain;
	int type;
	int protocol;
    } */ bsd_args;
    int error;
    int retval_socket;

    if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
	return error;
    bsd_args.protocol = linux_args.protocol;
    bsd_args.type = linux_args.type;
    bsd_args.domain = linux_to_bsd_domain(linux_args.domain);
    if (bsd_args.domain == -1)
	return EINVAL;

    retval_socket = socket(p, &bsd_args, retval);

    if (retval_socket >= 0
	&& bsd_args.type == SOCK_RAW
	&& bsd_args.domain == AF_INET
	&& (bsd_args.protocol == IPPROTO_RAW || bsd_args.protocol == 0)) {
	/* It's a raw IP socket: set the IP_HDRINCL option. */
	struct setsockopt_args /* {
	    int s;
	    int level;
	    int name;
	    caddr_t val;
	    int valsize;
	} */ bsd_setsockopt_args;

	int retval_setsockopt, r;
	caddr_t sg;
//, hdrincl;
//	int hdrinclval = 1;
	int *hdrincl;

	sg = stackgap_init();
	hdrincl = (int *)stackgap_alloc(&sg, sizeof(*hdrincl));
	*hdrincl = 1;

	bsd_setsockopt_args.s = *retval;
	bsd_setsockopt_args.level = IPPROTO_IP;
	bsd_setsockopt_args.name = IP_HDRINCL;
	bsd_setsockopt_args.val = (caddr_t)hdrincl;
	bsd_setsockopt_args.valsize = sizeof(*hdrincl);
	r = setsockopt(p, &bsd_setsockopt_args, &retval_setsockopt);
    }
    return retval_socket;
}
예제 #6
0
int
linux_writev(struct thread *td, struct linux_writev_args *uap)
{
	int error, i, nsize, osize;
	caddr_t sg;
	struct writev_args /* {
		syscallarg(int) fd;
		syscallarg(struct iovec *) iovp;
		syscallarg(u_int) iovcnt;
	} */ a;
	struct iovec32 *oio;
	struct iovec *nio;

	sg = stackgap_init();

	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
		return (EINVAL);

	osize = uap->iovcnt * sizeof (struct iovec32);
	nsize = uap->iovcnt * sizeof (struct iovec);

	oio = malloc(osize, M_TEMP, M_WAITOK);
	nio = malloc(nsize, M_TEMP, M_WAITOK);

	error = 0;
	if ((error = copyin(uap->iovp, oio, osize)))
		goto punt;
	for (i = 0; i < uap->iovcnt; i++) {
		nio[i].iov_base = PTRIN(oio[i].iov_base);
		nio[i].iov_len = oio[i].iov_len;
	}

	a.fd = uap->fd;
	a.iovp = stackgap_alloc(&sg, nsize);
	a.iovcnt = uap->iovcnt;

	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
		goto punt;
	error = writev(td, &a);

punt:
	free(oio, M_TEMP);
	free(nio, M_TEMP);
	return (error);
}
예제 #7
0
/*
 * Execve(2). Just check the alternate emulation path, and pass it on
 * to the regular execve().
 */
int
linux_sys_execve(struct proc *p, void *v, register_t *retval)
{
	struct linux_sys_execve_args /* {
		syscallarg(char *) path;
		syscallarg(char **) argv;
		syscallarg(char **) envp;
        } */ *uap = v;
	struct sys_execve_args ap;
	caddr_t sg;

	sg = stackgap_init(p->p_emul);
	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));

	SCARG(&ap, path) = SCARG(uap, path);
	SCARG(&ap, argp) = SCARG(uap, argp);
	SCARG(&ap, envp) = SCARG(uap, envp);

	return (sys_execve(p, &ap, retval));
}
예제 #8
0
int
linux_lchown16(struct proc *p, struct linux_lchown16_args *args)
{
	struct lchown_args bsd;
	caddr_t sg;

	sg = stackgap_init();
	CHECKALTEXIST(p, &sg, args->path);

#ifdef DEBUG
	if (ldebug(lchown16))
		printf(ARGS(lchown16, "%s, %d, %d"), args->path, args->uid,
		    args->gid);
#endif

	bsd.path = args->path;
	bsd.uid = CAST_NOCHG(args->uid);
	bsd.gid = CAST_NOCHG(args->gid);
	return (lchown(p, &bsd));
}
예제 #9
0
int
spx_open(struct proc *p, void *uap)
{
	struct socket_args sock;
	struct connect_args conn;
	struct sockaddr_un *Xaddr;
	int fd, error;
	caddr_t sg = stackgap_init();

	/* obtain a socket. */
	DPRINTF(("SPX: open socket\n"));
	sock.domain = AF_UNIX;
	sock.type = SOCK_STREAM;
	sock.protocol = 0;
	error = socket(p, &sock);
	if (error)
		return error;

	/* connect the socket to standard X socket */
	DPRINTF(("SPX: connect to /tmp/X11-unix/X0\n"));
	Xaddr = stackgap_alloc(&sg, sizeof(struct sockaddr_un));
	Xaddr->sun_family = AF_UNIX;
	Xaddr->sun_len = sizeof(struct sockaddr_un) - sizeof(Xaddr->sun_path) +
	  strlen(Xaddr->sun_path) + 1;
	copyout("/tmp/.X11-unix/X0", Xaddr->sun_path, 18);

	conn.s = fd = p->p_retval[0];
	conn.name = (caddr_t)Xaddr;
	conn.namelen = sizeof(struct sockaddr_un);
	error = connect(p, &conn);
	if (error) {
		struct close_args cl;
		cl.fd = fd;
		close(p, &cl);
		return error;
	}
	p->p_retval[0] = fd;
	return 0;
}
예제 #10
0
/*
 * We come here in a last attempt to satisfy a Linux ioctl() call
 */
int
linux_machdepioctl(struct proc *p, void *v, register_t *retval)
{
	struct linux_sys_ioctl_args /* {
		syscallarg(int) fd;
		syscallarg(u_long) com;
		syscallarg(caddr_t) data;
	} */ *uap = v;
	struct sys_ioctl_args bia;
	u_long com;
	int error;
#if (NWSDISPLAY > 0 && defined(WSDISPLAY_COMPAT_USL))
	struct vt_mode lvt;
	caddr_t bvtp, sg;
#endif
	struct filedesc *fdp;
	struct file *fp;
	int fd;
	int (*ioctlf)(struct file *, u_long, caddr_t, struct proc *);
	struct ioctl_pt pt;

	fd = SCARG(uap, fd);
	SCARG(&bia, fd) = SCARG(uap, fd);
	SCARG(&bia, data) = SCARG(uap, data);
	com = SCARG(uap, com);

	fdp = p->p_fd;
	if ((fp = fd_getfile(fdp, fd)) == NULL)
		return (EBADF);

	switch (com) {
#if (NWSDISPLAY > 0 && defined(WSDISPLAY_COMPAT_USL))
	case LINUX_KDGKBMODE:
		com = KDGKBMODE;
		break;
	case LINUX_KDSKBMODE:
		com = KDSKBMODE;
		if ((unsigned)SCARG(uap, data) == LINUX_K_MEDIUMRAW)
			SCARG(&bia, data) = (caddr_t)K_RAW;
		break;
	case LINUX_KIOCSOUND:
		SCARG(&bia, data) =
			(caddr_t)(((unsigned long)SCARG(&bia, data)) & 0xffff);
		/* FALLTHROUGH */
	case LINUX_KDMKTONE:
		com = KDMKTONE;
		break;
	case LINUX_KDSETMODE:
		com = KDSETMODE;
		break;
	case LINUX_KDGETMODE:
#if NWSDISPLAY > 0 && defined(WSDISPLAY_COMPAT_USL)
		com = WSDISPLAYIO_GMODE;
#else
		com = KDGETMODE;
#endif
		break;
	case LINUX_KDENABIO:
		com = KDENABIO;
		break;
	case LINUX_KDDISABIO:
		com = KDDISABIO;
		break;
	case LINUX_KDGETLED:
		com = KDGETLED;
		break;
	case LINUX_KDSETLED:
		com = KDSETLED;
		break;
	case LINUX_VT_OPENQRY:
		com = VT_OPENQRY;
		break;
	case LINUX_VT_GETMODE: {
		int sig;

		SCARG(&bia, com) = VT_GETMODE;
		if ((error = sys_ioctl(p, &bia, retval)))
			return error;
		if ((error = copyin(SCARG(uap, data), (caddr_t)&lvt,
		    sizeof (struct vt_mode))))
			return error;
		/* We need to bounds check here in case there
		   is a race with another thread */
		if ((error = bsd_to_linux_signal(lvt.relsig, &sig)))
			return error;
		lvt.relsig = sig;

		if ((error = bsd_to_linux_signal(lvt.acqsig, &sig)))
			return error;
		lvt.acqsig = sig;
		
		if ((error = bsd_to_linux_signal(lvt.frsig, &sig)))
			return error;
		lvt.frsig = sig;

		return copyout((caddr_t)&lvt, SCARG(uap, data),
		    sizeof (struct vt_mode));
	}
	case LINUX_VT_SETMODE: {
		int sig;

		com = VT_SETMODE;
		if ((error = copyin(SCARG(uap, data), (caddr_t)&lvt,
		    sizeof (struct vt_mode))))
			return error;
		if ((error = linux_to_bsd_signal(lvt.relsig, &sig)))
			return error;
		lvt.relsig = sig;

		if ((error = linux_to_bsd_signal(lvt.acqsig, &sig)))
			return error;
		lvt.acqsig = sig;

		if ((error = linux_to_bsd_signal(lvt.frsig, &sig)))
			return error;
		lvt.frsig = sig;

		sg = stackgap_init(p->p_emul);
		bvtp = stackgap_alloc(&sg, sizeof (struct vt_mode));
		if ((error = copyout(&lvt, bvtp, sizeof (struct vt_mode))))
			return error;
		SCARG(&bia, data) = bvtp;
		break;
	}
	case LINUX_VT_DISALLOCATE:
		/* XXX should use WSDISPLAYIO_DELSCREEN */
		return 0;
	case LINUX_VT_RELDISP:
		com = VT_RELDISP;
		break;
	case LINUX_VT_ACTIVATE:
		com = VT_ACTIVATE;
		break;
	case LINUX_VT_WAITACTIVE:
		com = VT_WAITACTIVE;
		break;
	case LINUX_VT_GETSTATE:
		com = VT_GETSTATE;
		break;
	case LINUX_KDGKBTYPE:
	{
		char tmp = KB_101;

		/* This is what Linux does */
		return copyout(&tmp, SCARG(uap, data), sizeof(char));
	}
#endif
	default:
		/*
		 * Unknown to us. If it's on a device, just pass it through
		 * using PTIOCLINUX, the device itself might be able to
		 * make some sense of it.
		 * XXX hack: if the function returns EJUSTRETURN,
		 * it has stuffed a sysctl return value in pt.data.
		 */
		FREF(fp);
		ioctlf = fp->f_ops->fo_ioctl;
		pt.com = SCARG(uap, com);
		pt.data = SCARG(uap, data);
		error = ioctlf(fp, PTIOCLINUX, (caddr_t)&pt, p);
		FRELE(fp);
		if (error == EJUSTRETURN) {
			retval[0] = (register_t)pt.data;
			error = 0;
		}

		if (error == ENOTTY)
			printf("linux_machdepioctl: invalid ioctl %08lx\n",
			    com);
		return (error);
	}
	SCARG(&bia, com) = com;
	return sys_ioctl(p, &bia, retval);
}
예제 #11
0
static int
linux_connect(struct proc *p, struct linux_connect_args *args, int *retval)
{
    struct linux_connect_args linux_args;
    struct connect_args /* {
	int s;
	caddr_t name;
	int namelen;
    } */ bsd_args;
    int error;

    if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
	return error;
    bsd_args.s = linux_args.s;
    bsd_args.name = (caddr_t)linux_args.name;
    bsd_args.namelen = linux_args.namelen;
    error = connect(p, &bsd_args, retval);
    if (error == EISCONN) {
	/*
	 * Linux doesn't return EISCONN the first time it occurs,
	 * when on a non-blocking socket. Instead it returns the
	 * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD.
	 */
	struct fcntl_args /* {
	    int fd;
	    int cmd;
	    int arg;
	} */ bsd_fcntl_args;
	struct getsockopt_args /* {
	    int s;
	    int level;
	    int name;
	    caddr_t val;
	    int *avalsize;
	} */ bsd_getsockopt_args;
	void *status, *statusl;
	int stat, statl = sizeof stat;
	caddr_t sg;

	/* Check for non-blocking */
	bsd_fcntl_args.fd = linux_args.s;
	bsd_fcntl_args.cmd = F_GETFL;
	bsd_fcntl_args.arg = 0;
	error = fcntl(p, &bsd_fcntl_args, retval);
	if (error == 0 && (*retval & O_NONBLOCK)) {
	    sg = stackgap_init();
	    status = stackgap_alloc(&sg, sizeof stat);
	    statusl = stackgap_alloc(&sg, sizeof statusl);

	    if ((error = copyout(&statl, statusl, sizeof statl)))
		return error;

	    bsd_getsockopt_args.s = linux_args.s;
	    bsd_getsockopt_args.level = SOL_SOCKET;
	    bsd_getsockopt_args.name = SO_ERROR;
	    bsd_getsockopt_args.val = status;
	    bsd_getsockopt_args.avalsize = statusl;

	    error = getsockopt(p, &bsd_getsockopt_args, retval);
	    if (error)
		return error;
	    if ((error = copyin(status, &stat, sizeof stat)))
		return error;
	    *retval = stat;
	    return 0;
	}
    }
    return error;
}
/*
 * Process debugging system call.
 */
int
freebsd_sys_ptrace(struct lwp *l, const struct freebsd_sys_ptrace_args *uap, register_t *retval)
{
	/* {
		syscallarg(int) req;
		syscallarg(pid_t) pid;
		syscallarg(void *) addr;
		syscallarg(int) data;
	} */
	struct sys_ptrace_args npa;
	sy_call_t *fn = sysent[SYS_ptrace].sy_call;

	switch (SCARG(uap, req)) {
#ifdef PT_STEP
	case FREEBSD_PT_STEP:
		SCARG(&npa, req) = PT_STEP;
		SCARG(&npa, pid) = SCARG(uap, pid);
		SCARG(&npa, addr) = SCARG(uap, addr);
		SCARG(&npa, data) = SCARG(uap, data);
		return (*fn)(l, &npa, retval);
#endif
	case FREEBSD_PT_TRACE_ME:
	case FREEBSD_PT_READ_I:
	case FREEBSD_PT_READ_D:
	case FREEBSD_PT_WRITE_I:
	case FREEBSD_PT_WRITE_D:
	case FREEBSD_PT_CONTINUE:
	case FREEBSD_PT_KILL:
		/* These requests are compatible with NetBSD */
		return (*fn)(l, (const void *)uap, retval);

#if 0
/*
 * XXX: I've commented out this code, it is broken on too many fronts to fix.
 *	1) It is doing an unlocked read-modify-write cycle on process that
 *	   I assume might be running!
 *	   and in code that might sleep (due to a pagefault), never mind
 *	   what happens on an SMP system
 *      2) It accesses data in userspace without using copyin/out.
 *	3) It all looks like a nasty hack that isn't likely to work.
 *	4) It uses the stackgap.
 * dsl June 2007
 */
	case FREEBSD_PT_READ_U:
	case FREEBSD_PT_WRITE_U:
    {
	int error;
	struct {
		struct reg regs;
		struct fpreg fpregs;
	} *nrp;
	struct freebsd_ptrace_reg fr;
		sg = stackgap_init(p, 0);
		nrp = stackgap_alloc(p, &sg, sizeof(*nrp));
#ifdef PT_GETREGS
		SCARG(&npa, req) = PT_GETREGS;
		SCARG(&npa, pid) = SCARG(uap, pid);
		SCARG(&npa, addr) = (void *)&nrp->regs;
		if ((error = (*fn)(l, &npa, retval)) != 0)
			return error;
#endif
#ifdef PT_GETFPREGS
		SCARG(&npa, req) = PT_GETFPREGS;
		SCARG(&npa, pid) = SCARG(uap, pid);
		SCARG(&npa, addr) = (void *)&nrp->fpregs;
		if ((error = (*fn)(l, &npa, retval)) != 0)
			return error;
#endif
		netbsd_to_freebsd_ptrace_regs(&nrp->regs, &nrp->fpregs, &fr);
		switch (SCARG(uap, req)) {
		case FREEBSD_PT_READ_U:
			return freebsd_ptrace_getregs(&fr, SCARG(uap, addr),
						      retval);

		case FREEBSD_PT_WRITE_U:
			error = freebsd_ptrace_setregs(&fr,
			    SCARG(uap, addr), SCARG(uap, data));
			if (error)
				return error;
			freebsd_to_netbsd_ptrace_regs(&fr,
						&nrp->regs, &nrp->fpregs);
#ifdef PT_SETREGS
			SCARG(&npa, req) = PT_SETREGS;
			SCARG(&npa, pid) = SCARG(uap, pid);
			SCARG(&npa, addr) = (void *)&nrp->regs;
			if ((error = (*fn)(l, &npa, retval)) != 0)
				return error;
#endif
#ifdef PT_SETFPREGS
			SCARG(&npa, req) = PT_SETFPREGS;
			SCARG(&npa, pid) = SCARG(uap, pid);
			SCARG(&npa, addr) = (void *)&nrp->fpregs;
			if ((error = (*fn)(l, &npa, retval)) != 0)
				return error;
#endif
			return 0;
		}
    }
#endif

	default:			/* It was not a legal request. */
		return (EINVAL);
	}

#ifdef DIAGNOSTIC
	panic("freebsd_ptrace: impossible");
#endif
}
예제 #13
0
static void
darwin_e_proc_exit(struct proc *p)
{
	struct darwin_emuldata *ded;
	int error, mode;
	struct lwp *l;

	ded = p->p_emuldata;
	l = LIST_FIRST(&p->p_lwps);
	/*
	 * mach_init is setting the bootstrap port for other processes.
	 * If mach_init dies, we want to restore the original bootstrap
	 * port.
	 */
	if (ded->ded_fakepid == 2)
		mach_bootstrap_port = mach_saved_bootstrap_port;

	/*
	 * Terminate the iohidsystem kernel thread.
	 * We need to post a fake event in case
	 * the thread is sleeping for an event.
	 */
	if (ded->ded_hidsystem_finished != NULL) {
		*ded->ded_hidsystem_finished = 1;
		darwin_iohidsystem_postfake(l);
		wakeup(ded->ded_hidsystem_finished);
	}

	/*
	 * Restore text mode and black and white colormap
	 */
	if (ded->ded_wsdev != NODEV) {
		mode = WSDISPLAYIO_MODE_EMUL;
		error = (*wsdisplay_cdevsw.d_ioctl)(ded->ded_wsdev,
		    WSDISPLAYIO_SMODE, (void *)&mode, 0, l);
#ifdef DEBUG_DARWIN
		if (error != 0)
			printf("Unable to switch back to text mode\n");
#endif
#if 0	/* Comment out stackgap use - this needs to be done another way */
	    {
		void *sg = stackgap_init(p, 0);
		struct wsdisplay_cmap cmap;
		u_char *red;
		u_char *green;
		u_char *blue;
		u_char kred[256];
		u_char kgreen[256];
		u_char kblue[256];
		red = stackgap_alloc(p, &sg, 256);
		green = stackgap_alloc(p, &sg, 256);
		blue = stackgap_alloc(p, &sg, 256);

		(void)memset(kred, 255, 256);
		(void)memset(kgreen, 255, 256);
		(void)memset(kblue, 255, 256);

		kred[0] = 0;
		kgreen[0] = 0;
		kblue[0] = 0;

		cmap.index = 0;
		cmap.count = 256;
		cmap.red = red;
		cmap.green = green;
		cmap.blue = blue;

		if (((error = copyout(kred, red, 256)) != 0) ||
		    ((error = copyout(kgreen, green, 256)) != 0) ||
		    ((error = copyout(kblue, blue, 256)) != 0))
			error = (*wsdisplay_cdevsw.d_ioctl)(ded->ded_wsdev,
			    WSDISPLAYIO_PUTCMAP, (void *)&cmap, 0, l);
#ifdef DEBUG_DARWIN
		if (error != 0)
			printf("Cannot revert colormap (error %d)\n", error);
#endif
	    }
#endif

	}

	/*
	 * Cleanup mach_emuldata part of darwin_emuldata
	 * It will also free p->p_emuldata.
	 */
	mach_e_proc_exit(p);

	return;
}
예제 #14
0
int
linux_execve(struct thread *td, struct linux_execve_args *args)
{
	struct execve_args ap;
	caddr_t sg;
	int error;
	u_int32_t *p32, arg;
	char **p, *p64;
	int count;

	sg = stackgap_init();
	CHECKALTEXIST(td, &sg, args->path);

#ifdef DEBUG
	if (ldebug(execve))
		printf(ARGS(execve, "%s"), args->path);
#endif

	ap.fname = args->path;

	if (args->argp != NULL) {
		count = 0;
		p32 = (u_int32_t *)args->argp;
		do {
			error = copyin(p32++, &arg, sizeof(arg));
			if (error)
				return error;
			count++;
		} while (arg != 0);
		p = stackgap_alloc(&sg, count * sizeof(char *));
		ap.argv = p;
		p32 = (u_int32_t *)args->argp;
		do {
			error = copyin(p32++, &arg, sizeof(arg));
			if (error)
				return error;
			p64 = PTRIN(arg);
			error = copyout(&p64, p++, sizeof(p64));
			if (error)
				return error;
		} while (arg != 0);
	}
	if (args->envp != NULL) {
		count = 0;
		p32 = (u_int32_t *)args->envp;
		do {
			error = copyin(p32++, &arg, sizeof(arg));
			if (error)
				return error;
			count++;
		} while (arg != 0);
		p = stackgap_alloc(&sg, count * sizeof(char *));
		ap.envv = p;
		p32 = (u_int32_t *)args->envp;
		do {
			error = copyin(p32++, &arg, sizeof(arg));
			if (error)
				return error;
			p64 = PTRIN(arg);
			error = copyout(&p64, p++, sizeof(p64));
			if (error)
				return error;
		} while (arg != 0);
	}

	return (execve(td, &ap));
}
예제 #15
0
int
linux_ioctl_hdio(struct proc *p, struct linux_sys_ioctl_args *uap,
		 register_t *retval)
{
	u_long com;
	int error, error1;
	caddr_t sg;
	struct filedesc *fdp;
	struct file *fp;
	int (*ioctlf)(struct file *, u_long, caddr_t, struct proc *);
	struct ataparams *atap, ata;
	struct atareq req;
	struct disklabel label, *labp;
	struct partinfo partp;
	struct linux_hd_geometry hdg;
	struct linux_hd_big_geometry hdg_big;

	fdp = p->p_fd;
	if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
		return (EBADF);

	FREF(fp);
	com = SCARG(uap, com);
	ioctlf = fp->f_ops->fo_ioctl;
	retval[0] = error = 0;

	com = SCARG(uap, com);

	switch (com) {
	case LINUX_HDIO_OBSOLETE_IDENTITY:
	case LINUX_HDIO_GET_IDENTITY:
		sg = stackgap_init(p->p_emul);
		atap = stackgap_alloc(&sg, DEV_BSIZE);
		if (atap == NULL) {
			error = ENOMEM;
			break;
		}

		req.flags = ATACMD_READ;
		req.command = WDCC_IDENTIFY;
		req.databuf = (caddr_t)atap;
		req.datalen = DEV_BSIZE;
		req.timeout = 1000;
		error = ioctlf(fp, ATAIOCCOMMAND, (caddr_t)&req, p);
		if (error != 0)
			break;
		if (req.retsts != ATACMD_OK) {
			error = EIO;
			break;
		}
		error = copyin(atap, &ata, sizeof ata);
		if (error != 0)
			break;
		/*
		 * 142 is the size of the old structure used by Linux,
		 * which doesn't seem to be defined anywhere anymore.
		 */
		error = copyout(&ata, SCARG(uap, data),
		    com == LINUX_HDIO_GET_IDENTITY ? sizeof ata : 142);
		break;
	case LINUX_HDIO_GETGEO:
		error = linux_machdepioctl(p, uap, retval);
		if (error == 0)
			break;
		error = ioctlf(fp, DIOCGDINFO, (caddr_t)&label, p);
		error1 = ioctlf(fp, DIOCGPART, (caddr_t)&partp, p);
		if (error != 0 && error1 != 0) {
			error = error1;
			break;
		}
		labp = error != 0 ? &label : partp.disklab;
		hdg.start = error1 != 0 ? partp.part->p_offset : 0;
		hdg.heads = labp->d_ntracks;
		hdg.cylinders = labp->d_ncylinders;
		hdg.sectors = labp->d_nsectors;
		error = copyout(&hdg, SCARG(uap, data), sizeof hdg);
		break;
	case LINUX_HDIO_GETGEO_BIG:
		error = linux_machdepioctl(p, uap, retval);
		if (error == 0)
			break;
	case LINUX_HDIO_GETGEO_BIG_RAW:
		error = ioctlf(fp, DIOCGDINFO, (caddr_t)&label, p);
		error1 = ioctlf(fp, DIOCGPART, (caddr_t)&partp, p);
		if (error != 0 && error1 != 0) {
			error = error1;
			break;
		}
		labp = error != 0 ? &label : partp.disklab;
		hdg_big.start = error1 != 0 ? partp.part->p_offset : 0;
		hdg_big.heads = labp->d_ntracks;
		hdg_big.cylinders = labp->d_ncylinders;
		hdg_big.sectors = labp->d_nsectors;
		error = copyout(&hdg_big, SCARG(uap, data), sizeof hdg_big);
		break;
	case LINUX_HDIO_GET_UNMASKINTR:
	case LINUX_HDIO_GET_MULTCOUNT:
	case LINUX_HDIO_GET_KEEPSETTINGS:
	case LINUX_HDIO_GET_32BIT:
	case LINUX_HDIO_GET_NOWERR:
	case LINUX_HDIO_GET_DMA:
	case LINUX_HDIO_GET_NICE:
	case LINUX_HDIO_DRIVE_RESET:
	case LINUX_HDIO_TRISTATE_HWIF:
	case LINUX_HDIO_DRIVE_TASK:
	case LINUX_HDIO_DRIVE_CMD:
	case LINUX_HDIO_SET_MULTCOUNT:
	case LINUX_HDIO_SET_UNMASKINTR:
	case LINUX_HDIO_SET_KEEPSETTINGS:
	case LINUX_HDIO_SET_32BIT:
	case LINUX_HDIO_SET_NOWERR:
	case LINUX_HDIO_SET_DMA:
	case LINUX_HDIO_SET_PIO_MODE:
	case LINUX_HDIO_SCAN_HWIF:
	case LINUX_HDIO_SET_NICE:
	case LINUX_HDIO_UNREGISTER_HWIF:
		error = EINVAL;
	}

	FRELE(fp);
	return error;
}
예제 #16
0
static int
linux_sendto_hdrincl(struct proc *p, struct sendto_args *bsd_args, int *retval)
{
/*
 * linux_ip_copysize defines how many bytes we should copy
 * from the beginning of the IP packet before we customize it for BSD.
 * It should include all the fields we modify (ip_len and ip_off)
 * and be as small as possible to minimize copying overhead.
 */
#define linux_ip_copysize	8

    caddr_t sg;
    struct ip *packet;
    struct msghdr *msg;
    struct iovec *iov;

    int error;
    struct  sendmsg_args /* {
        int s;
        caddr_t msg;
        int flags;
    } */ sendmsg_args;

    /* Check the packet isn't too small before we mess with it */
    if (bsd_args->len < linux_ip_copysize)
	return EINVAL;

    /*
     * Tweaking the user buffer in place would be bad manners.
     * We create a corrected IP header with just the needed length,
     * then use an iovec to glue it to the rest of the user packet
     * when calling sendmsg().
     */
    sg = stackgap_init();
    packet = (struct ip *)stackgap_alloc(&sg, linux_ip_copysize);
    msg = (struct msghdr *)stackgap_alloc(&sg, sizeof(*msg));
    iov = (struct iovec *)stackgap_alloc(&sg, sizeof(*iov)*2);

    /* Make a copy of the beginning of the packet to be sent */
    if ((error = copyin(bsd_args->buf, (caddr_t)packet, linux_ip_copysize)))
        return error;

    /* Convert fields from Linux to BSD raw IP socket format */
    packet->ip_len = bsd_args->len;
    packet->ip_off = ntohs(packet->ip_off);

    /* Prepare the msghdr and iovec structures describing the new packet */
    msg->msg_name = bsd_args->to;
    msg->msg_namelen = bsd_args->tolen;
    msg->msg_iov = iov;
    msg->msg_iovlen = 2;
    msg->msg_control = NULL;
    msg->msg_controllen = 0;
    msg->msg_flags = 0;
    iov[0].iov_base = (char *)packet;
    iov[0].iov_len = linux_ip_copysize;
    iov[1].iov_base = (char *)(bsd_args->buf) + linux_ip_copysize;
    iov[1].iov_len = bsd_args->len - linux_ip_copysize;

    sendmsg_args.s = bsd_args->s;
    sendmsg_args.msg = (caddr_t)msg;
    sendmsg_args.flags = bsd_args->flags;
    return sendmsg(p, &sendmsg_args, retval);
}
예제 #17
0
int
linux_semctl(struct proc *p, struct linux_semctl_args *args)
{
	struct linux_semid_ds	linux_semid;
	struct semid_ds	bsd_semid;
	struct __semctl_args /* {
	int		semid;
	int		semnum;
	int		cmd;
	union	semun *arg;
	} */ bsd_args;
	int	error;
	caddr_t sg, unptr, dsp, ldsp;

	sg = stackgap_init();
	bsd_args.semid = args->arg1;
	bsd_args.semnum = args->arg2;
	bsd_args.cmd = args->arg3;
	bsd_args.arg = (union semun *)args->ptr;

	switch (args->arg3) {
	case LINUX_IPC_RMID:
		bsd_args.cmd = IPC_RMID;
		break;
	case LINUX_GETNCNT:
		bsd_args.cmd = GETNCNT;
		break;
	case LINUX_GETPID:
		bsd_args.cmd = GETPID;
		break;
	case LINUX_GETVAL:
		bsd_args.cmd = GETVAL;
		break;
	case LINUX_GETZCNT:
		bsd_args.cmd = GETZCNT;
		break;
	case LINUX_SETVAL:
		bsd_args.cmd = SETVAL;
		break;
	case LINUX_IPC_SET:
		bsd_args.cmd = IPC_SET;
		error = copyin(args->ptr, &ldsp, sizeof(ldsp));
		if (error)
			return error;
		error = copyin(ldsp, (caddr_t)&linux_semid, sizeof(linux_semid));
		if (error)
			return error;
		linux_to_bsd_semid_ds(&linux_semid, &bsd_semid);
		unptr = stackgap_alloc(&sg, sizeof(union semun));
		dsp = stackgap_alloc(&sg, sizeof(struct semid_ds));
		error = copyout((caddr_t)&bsd_semid, dsp, sizeof(bsd_semid));
		if (error)
			return error;
		error = copyout((caddr_t)&dsp, unptr, sizeof(dsp));
		if (error)
			return error;
		bsd_args.arg = (union semun *)unptr;
		return __semctl(p, &bsd_args);
	case LINUX_IPC_STAT:
		bsd_args.cmd = IPC_STAT;
		unptr = stackgap_alloc(&sg, sizeof(union semun *));
		dsp = stackgap_alloc(&sg, sizeof(struct semid_ds));
		error = copyout((caddr_t)&dsp, unptr, sizeof(dsp));
		if (error)
			return error;
		bsd_args.arg = (union semun *)unptr;
		error = __semctl(p, &bsd_args);
		if (error)
			return error;
		error = copyin(dsp, (caddr_t)&bsd_semid, sizeof(bsd_semid));
		if (error)
			return error;
		bsd_to_linux_semid_ds(&bsd_semid, &linux_semid);
		error = copyin(args->ptr, &ldsp, sizeof(ldsp));
		if (error)
			return error;
		return copyout((caddr_t)&linux_semid, ldsp, sizeof(linux_semid));
	case LINUX_GETALL:
		/* FALLTHROUGH */
	case LINUX_SETALL:
		/* FALLTHROUGH */
	default:
		uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->arg3);
		return EINVAL;
	}
	return __semctl(p, &bsd_args);
}
예제 #18
0
int
linux_sys_uselib(struct proc *p, void *v, register_t *retval)
{
	struct linux_sys_uselib_args /* {
		syscallarg(char *) path;
	} */ *uap = v;
	caddr_t sg;
	long bsize, dsize, tsize, taddr, baddr, daddr;
	struct nameidata ni;
	struct vnode *vp;
	struct exec hdr;
	struct exec_vmcmd_set vcset;
	int i, magic, error;
	size_t rem;

	sg = stackgap_init(p->p_emul);
	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));

	NDINIT(&ni, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);

	if ((error = namei(&ni)))
		return (error);

	vp = ni.ni_vp;

	if ((error = vn_rdwr(UIO_READ, vp, (caddr_t) &hdr, LINUX_AOUT_HDR_SIZE,
			     0, UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred,
			     &rem, p))) {
		vrele(vp);
		return (error);
	}

	if (rem != 0) {
		vrele(vp);
		return (ENOEXEC);
	}

	if (LINUX_N_MACHTYPE(&hdr) != LINUX_MID_MACHINE)
		return (ENOEXEC);

	magic = LINUX_N_MAGIC(&hdr);
	taddr = trunc_page(hdr.a_entry);
	tsize = hdr.a_text;
	daddr = taddr + tsize;
	dsize = hdr.a_data + hdr.a_bss;

	if ((hdr.a_text != 0 || hdr.a_data != 0) && vp->v_writecount != 0) {
		vrele(vp);
                return (ETXTBSY);
        }
	vn_marktext(vp);

	VMCMDSET_INIT(&vcset);

	NEW_VMCMD(
	    &vcset, magic == ZMAGIC ? vmcmd_map_readvn : vmcmd_map_pagedvn,
	    hdr.a_text + hdr.a_data, taddr, vp, LINUX_N_TXTOFF(hdr, magic),
	    VM_PROT_READ|VM_PROT_EXECUTE|VM_PROT_WRITE);

	baddr = round_page(daddr + hdr.a_data);
	bsize = daddr + dsize - baddr;
        if (bsize > 0) {
                NEW_VMCMD(&vcset, vmcmd_map_zero, bsize, baddr,
                    NULLVP, 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
	}

	for (i = 0; i < vcset.evs_used && !error; i++) {
		struct exec_vmcmd *vcp;

		vcp = &vcset.evs_cmds[i];
		error = (*vcp->ev_proc)(p, vcp);
	}

	kill_vmcmds(&vcset);

	vrele(vp);

	return (error);
}
예제 #19
0
int
linux_shmctl(struct proc *p, struct linux_shmctl_args *args)
{
    struct shmid_ds bsd_shmid;
    struct linux_shmid_ds linux_shmid;
    struct shmctl_args /* {
	int shmid;
	int cmd;
	struct shmid_ds *buf;
    } */ bsd_args;
    int error;
    caddr_t sg = stackgap_init();

    switch (args->arg2) {
    case LINUX_IPC_STAT:
	bsd_args.shmid = args->arg1;
	bsd_args.cmd = IPC_STAT;
	bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
	if ((error = shmctl(p, &bsd_args)))
	    return error;
	if ((error = copyin((caddr_t)bsd_args.buf, (caddr_t)&bsd_shmid,
		    	    sizeof(struct shmid_ds))))
	    return error;
	bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid);
	return copyout((caddr_t)&linux_shmid, args->ptr, sizeof(linux_shmid));

    case LINUX_IPC_SET:
	if ((error = copyin(args->ptr, (caddr_t)&linux_shmid,
		    	    sizeof(linux_shmid))))
	    return error;
	linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
	bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
	if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
		     	     sizeof(struct shmid_ds))))
	    return error;
	bsd_args.shmid = args->arg1;
	bsd_args.cmd = IPC_SET;
	return shmctl(p, &bsd_args);

    case LINUX_IPC_RMID:
	bsd_args.shmid = args->arg1;
	bsd_args.cmd = IPC_RMID;
	if (NULL == args->ptr)
	    bsd_args.buf = NULL;
	else {
	    if ((error = copyin(args->ptr, (caddr_t)&linux_shmid, 
		    		sizeof(linux_shmid))))
		return error;
	    linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
	    bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
	    if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
		     		 sizeof(struct shmid_ds))))
		return error;
	}
	return shmctl(p, &bsd_args);

    case LINUX_IPC_INFO:
    case LINUX_SHM_STAT:
    case LINUX_SHM_INFO:
    case LINUX_SHM_LOCK:
    case LINUX_SHM_UNLOCK:
    default:
	uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->arg2);
	return EINVAL;
    }
}
예제 #20
0
/*
 * sysi86
 */
int
svr4_sys_sysarch(struct proc *p, void *v, register_t *retval)
{
	struct svr4_sys_sysarch_args *uap = v;
	int error;
#ifdef USER_LDT
	caddr_t sg = stackgap_init(p->p_emul);
#endif
	*retval = 0;	/* XXX: What to do */

	switch (SCARG(uap, op)) {
	case SVR4_SYSARCH_FPHW:
		return 0;

	case SVR4_SYSARCH_DSCR:
#ifdef USER_LDT
		if (user_ldt_enable == 0)
			return (ENOSYS);
		else {
			struct i386_set_ldt_args sa, *sap;
			struct sys_sysarch_args ua;

			struct svr4_ssd ssd;
			union descriptor bsd;

			if ((error = copyin(SCARG(uap, a1), &ssd,
					    sizeof(ssd))) != 0) {
				printf("Cannot copy arg1\n");
				return error;
			}

			printf("s=%x, b=%x, l=%x, a1=%x a2=%x\n",
			       ssd.selector, ssd.base, ssd.limit,
			       ssd.access1, ssd.access2);

			/* We can only set ldt's for now. */
			if (!ISLDT(ssd.selector)) {
				printf("Not an ldt\n");
				return EPERM;
			}

			/* Oh, well we don't cleanup either */
			if (ssd.access1 == 0)
				return 0;

			bsd.sd.sd_lobase = ssd.base & 0xffffff;
			bsd.sd.sd_hibase = (ssd.base >> 24) & 0xff;

			bsd.sd.sd_lolimit = ssd.limit & 0xffff;
			bsd.sd.sd_hilimit = (ssd.limit >> 16) & 0xf;

			bsd.sd.sd_type = ssd.access1 & 0x1f;
			bsd.sd.sd_dpl =  (ssd.access1 >> 5) & 0x3;
			bsd.sd.sd_p = (ssd.access1 >> 7) & 0x1;

			bsd.sd.sd_xx = ssd.access2 & 0x3;
			bsd.sd.sd_def32 = (ssd.access2 >> 2) & 0x1;
			bsd.sd.sd_gran = (ssd.access2 >> 3)& 0x1;

			sa.start = IDXSEL(ssd.selector);
			sa.desc = stackgap_alloc(&sg, sizeof(union descriptor));
			sa.num = 1;
			sap = stackgap_alloc(&sg,
					     sizeof(struct i386_set_ldt_args));

			if ((error = copyout(&sa, sap, sizeof(sa))) != 0) {
				printf("Cannot copyout args\n");
				return error;
			}

			SCARG(&ua, op) = I386_SET_LDT;
			SCARG(&ua, parms) = (char *) sap;

			if ((error = copyout(&bsd, sa.desc, sizeof(bsd))) != 0) {
				printf("Cannot copyout desc\n");
				return error;
			}

			return sys_sysarch(p, &ua, retval);
		}
#endif
	case SVR4_SYSARCH_GOSF:
		{
				/* just as SCO Openserver 5.0 says */
			char features[] = {1,1,1,1,1,1,1,1,2,1,1,1};

			if ((error = copyout(features, SCARG(uap, a1),
					     sizeof(features))) != 0) {
				printf("Cannot copyout vector\n");
				return error;
			}

			return 0;
		}

	default:
		printf("svr4_sysarch(%d), a1 %p\n", SCARG(uap, op),
		       SCARG(uap, a1));
		return 0;
	}
}