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