int linux_sys_sched_get_priority_min(struct lwp *l, const struct linux_sys_sched_get_priority_min_args *uap, register_t *retval) { /* { syscallarg(int) policy; } */ switch (SCARG(uap, policy)) { case LINUX_SCHED_OTHER: *retval = 0; break; case LINUX_SCHED_FIFO: case LINUX_SCHED_RR: *retval = LINUX_SCHED_RTPRIO_MIN; break; default: return EINVAL; } return 0; }
int ultrix_sys_sigvec(struct lwp *l, const struct ultrix_sys_sigvec_args *uap, register_t *retval) { struct sigvec nsv, osv; struct sigaction nsa, osa; int error; if (SCARG(uap, nsv)) { error = copyin(SCARG(uap, nsv), &nsv, sizeof(nsv)); if (error) return error; nsa.sa_handler = nsv.sv_handler; #if 0 /* documentation */ /* ONSTACK is identical */ nsa.sa_flags = nsv.sv_flags & ULTRIX_SV_ONSTACK; if ((nsv.sv_flags & ULTRIX_SV_OLDSIG) /* old signal() - always restart */ || (!(nsv.sv_flags & ULTRIX_SV_INTERRUPT)) /* inverted meaning (same bit) */ ) nsa.sa_flags |= SA_RESTART; #else /* optimized - assuming ULTRIX_SV_OLDSIG=>!ULTRIX_SV_INTERRUPT */ nsa.sa_flags = nsv.sv_flags & ~ULTRIX_SV_OLDSIG; nsa.sa_flags ^= SA_RESTART; #endif native_sigset13_to_sigset(&nsv.sv_mask, &nsa.sa_mask); } error = sigaction1(l, SCARG(uap, signum), SCARG(uap, nsv) ? &nsa : 0, SCARG(uap, osv) ? &osa : 0, NULL, 0); if (error) return error; if (SCARG(uap, osv)) { osv.sv_handler = osa.sa_handler; osv.sv_flags = osa.sa_flags ^ SA_RESTART; osv.sv_flags &= (ULTRIX_SV_ONSTACK | ULTRIX_SV_INTERRUPT); native_sigset_to_sigset13(&osa.sa_mask, &osv.sv_mask); error = copyout(&osv, SCARG(uap, osv), sizeof(osv)); if (error) return error; } return 0; }
int darwin_sys_socket(struct lwp *l, const struct darwin_sys_socket_args *uap, register_t *retval) { /* { syscallarg(int) domain; syscallarg(int) type; syscallarg(int) protocol; } */ struct compat_30_sys_socket_args cup; if ((unsigned)SCARG(uap, domain) >= __arraycount(darwin_to_native_af)) return (EPROTONOSUPPORT); SCARG(&cup, domain) = darwin_to_native_af[SCARG(uap, domain)]; SCARG(&cup, type) = SCARG(uap, type); SCARG(&cup, protocol) = SCARG(uap, protocol); return compat_30_sys_socket(l, &cup, retval); }
/* * Return the process group ID of the session leader (session ID) * for the specified process. */ int sys_getsid(struct lwp *l, const struct sys_getsid_args *uap, register_t *retval) { /* { syscalldarg(pid_t) pid; } */ pid_t pid = SCARG(uap, pid); struct proc *p; int error = 0; mutex_enter(proc_lock); if (pid == 0) *retval = l->l_proc->p_session->s_sid; else if ((p = proc_find(pid)) != NULL) *retval = p->p_session->s_sid; else error = ESRCH; mutex_exit(proc_lock); return error; }
int svr4_ustat(struct lwp *l, const struct svr4_ustat_args *uap, register_t *retval) { /* { syscallarg(svr4_dev_t) dev; syscallarg(struct svr4_ustat *) name; } */ struct svr4_ustat us; int error; memset(&us, 0, sizeof us); /* * XXX: should set f_tfree and f_tinode at least * How do we translate dev -> fstat? (and then to svr4_ustat) */ if ((error = copyout(&us, SCARG(uap, name), sizeof us)) != 0) return (error); return 0; }
/* * Once more: only a signal conversion is needed. * Note: also used as sys_rt_queueinfo. The info field is ignored. */ int linux_sys_rt_queueinfo(struct lwp *l, const struct linux_sys_rt_queueinfo_args *uap, register_t *retval) { /* syscallarg(int) pid; syscallarg(int) signum; syscallarg(linix_siginfo_t *) uinfo; */ int error; linux_siginfo_t info; error = copyin(SCARG(uap, uinfo), &info, sizeof(info)); if (error) return error; if (info.lsi_code >= 0) return EPERM; /* XXX To really implement this we need to */ /* XXX keep a list of queued signals somewhere. */ return (linux_sys_kill(l, (const void *)uap, retval)); }
int netbsd32_sigqueueinfo(struct lwp *l, const struct netbsd32_sigqueueinfo_args *uap, register_t *retval) { /* { syscallarg(pid_t) pid; syscallarg(const netbsd32_siginfop_t) info; } */ struct __ksiginfo32 ksi32; ksiginfo_t ksi; int error; if ((error = copyin(SCARG_P32(uap, info), &ksi32, sizeof(ksi32))) != 0) return error; KSI_INIT(&ksi); netbsd32_ksi32_to_ksi(&ksi.ksi_info, &ksi32); return kill1(l, SCARG(uap, pid), &ksi, retval); }
int ultrix_sys_execve(struct lwp *l, const struct ultrix_sys_execve_args *uap, register_t *retval) { /* { syscallarg(const char *) path; syscallarg(char **) argv; syscallarg(char **) envp; } */ struct sys_execve_args ap; SCARG(&ap, path) = SCARG(uap, path); SCARG(&ap, argp) = SCARG(uap, argp); SCARG(&ap, envp) = SCARG(uap, envp); return sys_execve(l, &ap, retval); }
int netbsd32_sigaction(struct lwp *l, const struct netbsd32_sigaction_args *uap, register_t *retval) { /* { syscallarg(int) signum; syscallarg(const netbsd32_sigactionp_t) nsa; syscallarg(netbsd32_sigactionp_t) osa; } */ struct sigaction nsa, osa; struct netbsd32_sigaction13 *sa32p, sa32; int error; if (SCARG_P32(uap, nsa)) { sa32p = SCARG_P32(uap, nsa); if (copyin(sa32p, &sa32, sizeof(sa32))) return EFAULT; nsa.sa_handler = (void *)NETBSD32PTR64(sa32.netbsd32_sa_handler); memset(&nsa.sa_mask, 0, sizeof(nsa.sa_mask)); nsa.sa_mask.__bits[0] = sa32.netbsd32_sa_mask; nsa.sa_flags = sa32.netbsd32_sa_flags; } error = sigaction1(l, SCARG(uap, signum), SCARG_P32(uap, nsa) ? &nsa : 0, SCARG_P32(uap, osa) ? &osa : 0, NULL, 0); if (error) return (error); if (SCARG_P32(uap, osa)) { NETBSD32PTR32(sa32.netbsd32_sa_handler, osa.sa_handler); sa32.netbsd32_sa_mask = osa.sa_mask.__bits[0]; sa32.netbsd32_sa_flags = osa.sa_flags; sa32p = SCARG_P32(uap, osa); if (copyout(&sa32, sa32p, sizeof(sa32))) return EFAULT; } return (0); }
int linux32_sys_fstat64(struct lwp *l, const struct linux32_sys_fstat64_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(linux32_stat64p) sp; } */ int error; struct stat st; struct linux32_stat64 st32; struct linux32_stat64 *st32p; error = do_sys_fstat(SCARG(uap, fd), &st); if (error != 0) return error; linux32_from_stat(&st, &st32); st32p = SCARG_P32(uap, sp); return copyout(&st32, st32p, sizeof(*st32p)); }
int linux_sys_modify_ldt(struct proc *p, void *v, register_t *retval) { struct linux_sys_modify_ldt_args /* { syscallarg(int) func; syscallarg(void *) ptr; syscallarg(size_t) bytecount; } */ *uap = v; switch (SCARG(uap, func)) { #ifdef USER_LDT case 0: return (linux_read_ldt(p, uap, retval)); case 1: return (linux_write_ldt(p, uap, retval)); #endif /* USER_LDT */ default: return (ENOSYS); } }
int ultrix_sys_setpgrp(struct lwp *l, const struct ultrix_sys_setpgrp_args *uap, register_t *retval) { struct proc *p = l->l_proc; struct sys_setpgid_args ap; SCARG(&ap, pid) = SCARG(uap, pid); SCARG(&ap, pgid) = SCARG(uap, pgid); /* * difference to our setpgid call is to include backwards * compatibility to pre-setsid() binaries. Do setsid() * instead of setpgid() in those cases where the process * tries to create a new session the old way. */ if (!SCARG(&ap, pgid) && (!SCARG(&ap, pid) || SCARG(&ap, pid) == p->p_pid)) return sys_setsid(l, &ap, retval); else return sys_setpgid(l, &ap, retval); }
/* * The following three functions fiddle with a process' signal mask. * Convert the signal masks because of the different signal * values for Linux. The need for this is the reason why * they are here, and have not been mapped directly. */ int linux_sys_sigsetmask(struct lwp *l, const struct linux_sys_sigsetmask_args *uap, register_t *retval) { /* { syscallarg(linux_old_sigset_t) mask; } */ sigset_t nbss, obss; linux_old_sigset_t nlss, olss; struct proc *p = l->l_proc; int error; nlss = SCARG(uap, mask); linux_old_to_native_sigset(&nbss, &nlss); mutex_enter(p->p_lock); error = sigprocmask1(l, SIG_SETMASK, &nbss, &obss); mutex_exit(p->p_lock); if (error) return (error); native_to_linux_old_sigset(&olss, &obss); *retval = olss; return (0); }
int netbsd32___clock_getres50(struct lwp *l, const struct netbsd32___clock_getres50_args *uap, register_t *retval) { /* { syscallarg(netbsd32_clockid_t) clock_id; syscallarg(netbsd32_timespecp_t) tp; } */ struct netbsd32_timespec ts32; struct timespec ts; int error = 0; error = clock_getres1(SCARG(uap, clock_id), &ts); if (error != 0) return error; if (SCARG_P32(uap, tp)) { netbsd32_from_timespec(&ts, &ts32); error = copyout(&ts32, SCARG_P32(uap, tp), sizeof(ts32)); } return error; }
int kldload(struct proc* p, struct kldload_args* uap) { char* filename = NULL, *modulename; linker_file_t lf; int error = 0; p->p_retval[0] = -1; if (securelevel > 0) return EPERM; if (error = suser(p->p_ucred, &p->p_acflag)) return error; filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); if (error = copyinstr(SCARG(uap, file), filename, MAXPATHLEN, NULL)) goto out; /* Can't load more than one module with the same name */ modulename = rindex(filename, '/'); if (modulename == NULL) modulename = filename; if (linker_find_file_by_name(modulename)) { error = EEXIST; goto out; } if (error = linker_load_file(filename, &lf)) goto out; lf->userrefs++; p->p_retval[0] = lf->id; out: if (filename) free(filename, M_TEMP); return error; }
int linux_sys_sched_setaffinity(struct lwp *l, const struct linux_sys_sched_setaffinity_args *uap, register_t *retval) { /* { syscallarg(linux_pid_t) pid; syscallarg(unsigned int) len; syscallarg(unsigned long *) mask; } */ proc_t *p; /* XXX: Pointless check. TODO: Actually implement this. */ mutex_enter(proc_lock); p = proc_find(SCARG(uap, pid)); mutex_exit(proc_lock); if (p == NULL) { return ESRCH; } /* Let's ignore it */ DPRINTF(("%s\n", __func__)); return 0; }
int linux32_sys_rt_sigsuspend(struct lwp *l, const struct linux32_sys_rt_sigsuspend_args *uap, register_t *retval) { /* { syscallarg(linux32_sigsetp_t) unewset; syscallarg(netbsd32_size_t) sigsetsize; } */ linux32_sigset_t lss; sigset_t bss; int error; if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t)) return EINVAL; if ((error = copyin(SCARG_P32(uap, unewset), &lss, sizeof(linux32_sigset_t))) != 0) return error; linux32_to_native_sigset(&bss, &lss); return sigsuspend1(l, &bss); }
/* * 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 compat_13_sys_sigreturn(struct lwp *l, void *v, register_t *retval) { struct compat_13_sys_sigreturn_args /* { syscallarg(struct sigcontext13 *) sigcntxp; } */ *uap = v; struct proc *p = l->l_proc; struct trapframe *scf; struct sigcontext13 *ucntx; struct sigcontext13 ksc; sigset_t mask; scf = l->l_addr->u_pcb.framep; ucntx = SCARG(uap, sigcntxp); if (copyin((caddr_t)ucntx, (caddr_t)&ksc, sizeof(struct sigcontext))) return EINVAL; /* Compatibility mode? */ if ((ksc.sc_ps & (PSL_IPL | PSL_IS)) || ((ksc.sc_ps & (PSL_U | PSL_PREVU)) != (PSL_U | PSL_PREVU)) || (ksc.sc_ps & PSL_CM)) { return (EINVAL); } if (ksc.sc_onstack & SS_ONSTACK) p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; else p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK; native_sigset13_to_sigset(&ksc.sc_mask, &mask); (void) sigprocmask1(p, SIG_SETMASK, &mask, 0); scf->fp = ksc.sc_fp; scf->ap = ksc.sc_ap; scf->pc = ksc.sc_pc; scf->sp = ksc.sc_sp; scf->psl = ksc.sc_ps; return (EJUSTRETURN); }
int sys__lwp_wakeup(struct lwp *l, const struct sys__lwp_wakeup_args *uap, register_t *retval) { /* { syscallarg(lwpid_t) target; } */ struct lwp *t; struct proc *p; int error; p = l->l_proc; mutex_enter(p->p_lock); if ((t = lwp_find(p, SCARG(uap, target))) == NULL) { mutex_exit(p->p_lock); return ESRCH; } lwp_lock(t); t->l_flag |= (LW_CANCELLED | LW_UNPARKED); if (t->l_stat != LSSLEEP) { lwp_unlock(t); error = ENODEV; } else if ((t->l_flag & LW_SINTR) == 0) { lwp_unlock(t); error = EBUSY; } else { /* Wake it up. lwp_unsleep() will release the LWP lock. */ lwp_unsleep(t, true); error = 0; } mutex_exit(p->p_lock); return error; }
/* Delete a POSIX realtime timer */ int sys_timer_delete(struct lwp *l, const struct sys_timer_delete_args *uap, register_t *retval) { /* { syscallarg(timer_t) timerid; } */ struct proc *p = l->l_proc; timer_t timerid; struct ptimers *pts; struct ptimer *pt, *ptn; timerid = SCARG(uap, timerid); pts = p->p_timers; if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX) return (EINVAL); mutex_spin_enter(&timer_lock); if ((pt = pts->pts_timers[timerid]) == NULL) { mutex_spin_exit(&timer_lock); return (EINVAL); } if (CLOCK_VIRTUAL_P(pt->pt_type)) { if (pt->pt_active) { ptn = LIST_NEXT(pt, pt_list); LIST_REMOVE(pt, pt_list); for ( ; ptn; ptn = LIST_NEXT(ptn, pt_list)) timespecadd(&pt->pt_time.it_value, &ptn->pt_time.it_value, &ptn->pt_time.it_value); pt->pt_active = 0; } } itimerfree(pts, timerid); return (0); }
int linux_sys_unlinkat(struct lwp *l, const struct linux_sys_unlinkat_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(const char *) path; syscallarg(int) flag; } */ struct sys_unlinkat_args ua; int error; SCARG(&ua, fd) = SCARG(uap, fd); SCARG(&ua, path) = SCARG(uap, path); SCARG(&ua, flag) = linux_to_bsd_atflags(SCARG(uap, flag)); error = sys_unlinkat(l, &ua, retval); if (error == EPERM) error = linux_unlink_dircheck(SCARG(uap, path)); return error; }
int linux_sys_sched_getscheduler(struct lwp *l, const struct linux_sys_sched_getscheduler_args *uap, register_t *retval) { /* { syscallarg(linux_pid_t) pid; } */ int error, policy; *retval = -1; error = do_sched_getparam(SCARG(uap, pid), 0, &policy, NULL); if (error) goto out; error = sched_native2linux(policy, NULL, &policy, NULL); if (error) goto out; *retval = policy; out: return error; }
static int filemon_wrapper_execve(struct lwp * l, struct sys_execve_args * uap, register_t * retval) { char fname[MAXPATHLEN]; int ret; int error; size_t done; struct filemon *filemon; error = copyinstr(SCARG(uap, path), fname, sizeof(fname), &done); if ((ret = sys_execve(l, uap, retval)) == EJUSTRETURN && error == 0) { filemon = filemon_lookup(curproc); if (filemon) { filemon_printf(filemon, "E %d %s\n", curproc->p_pid, fname); rw_exit(&filemon->fm_mtx); } } return (ret); }
int linux32_sys_setrlimit(struct lwp *l, const struct linux32_sys_setrlimit_args *uap, register_t *retval) { /* { syscallarg(int) which; syscallarg(netbsd32_orlimitp_t) rlp; } */ struct rlimit rl; struct orlimit orl; int error; int which; if ((error = copyin(SCARG_P32(uap, rlp), &orl, sizeof(orl))) != 0) return error; which = linux_to_bsd_limit(SCARG(uap, which)); if (which < 0) return -which; linux32_to_bsd_rlimit(&rl, &orl); return dosetrlimit(l, l->l_proc, which, &rl); }
int sys_shmdt(struct proc *p, void *v, register_t *retval) { struct sys_shmdt_args /* { syscallarg(const void *) shmaddr; } */ *uap = v; struct shmmap_head *shmmap_h; struct shmmap_state *shmmap_s; int i; shmmap_h = (struct shmmap_head *)p->p_vmspace->vm_shm; if (shmmap_h == NULL) return (EINVAL); for (i = 0, shmmap_s = shmmap_h->state; i < shmmap_h->shmseg; i++, shmmap_s++) if (shmmap_s->shmid != -1 && shmmap_s->va == (vaddr_t)SCARG(uap, shmaddr)) break; if (i == shmmap_h->shmseg) return (EINVAL); return (shm_delete_mapping(p->p_vmspace, shmmap_s)); }
/* ARGSUSED */ int sys_setgid(struct proc *p, void *v, register_t *retval) { struct sys_setgid_args /* { syscallarg(gid_t) gid; } */ *uap = v; struct pcred *pc = p->p_cred; gid_t gid; int error; gid = SCARG(uap, gid); if (pc->pc_ucred->cr_gid == gid && pc->p_rgid == gid && pc->p_svgid == gid) return (0); if (gid != pc->p_rgid && gid != pc->p_svgid && gid != pc->pc_ucred->cr_gid && (error = suser(p, 0))) return (error); if (gid == pc->pc_ucred->cr_gid || suser(p, 0) == 0) { pc->p_rgid = gid; pc->p_svgid = gid; } /* * Copy credentials so other references do not see our changes. */ pc->pc_ucred = crcopy(pc->pc_ucred); pc->pc_ucred->cr_gid = gid; atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); return (0); }
int linux32_sys_fadvise64_64(struct lwp *l, const struct linux32_sys_fadvise64_64_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(uint32_t) offlo; syscallarg(uint32_t) offhi; syscallarg(uint32_t) lenlo; syscallarg(uint32_t) lenhi; syscallarg(int) advice; } */ off_t off = ((off_t)SCARG(uap, offhi) << 32) + SCARG(uap, offlo); off_t len = ((off_t)SCARG(uap, lenhi) << 32) + SCARG(uap, lenlo); return do_posix_fadvise(SCARG(uap, fd), off, len, linux_to_bsd_posix_fadv(SCARG(uap, advice))); }
int linux_semget(struct lwp *l, const struct linux_sys_ipc_args *uap, register_t *retval) { /* { syscallarg(int) what; syscallarg(int) a1; syscallarg(int) a2; syscallarg(int) a3; syscallarg(void *) ptr; } */ struct sys_semget_args bsa; SCARG(&bsa, key) = (key_t)SCARG(uap, a1); SCARG(&bsa, nsems) = SCARG(uap, a2); SCARG(&bsa, semflg) = SCARG(uap, a3); return sys_semget(l, &bsa, retval); }
int linux_semop(struct lwp *l, const struct linux_sys_ipc_args *uap, register_t *retval) { /* { syscallarg(int) what; syscallarg(int) a1; syscallarg(int) a2; syscallarg(int) a3; syscallarg(void *) ptr; } */ struct sys_semop_args bsa; SCARG(&bsa, semid) = SCARG(uap, a1); SCARG(&bsa, sops) = (struct sembuf *)SCARG(uap, ptr); SCARG(&bsa, nsops) = SCARG(uap, a2); return sys_semop(l, &bsa, retval); }