diff options
author | iedowse <iedowse@FreeBSD.org> | 2002-09-01 20:37:28 +0000 |
---|---|---|
committer | iedowse <iedowse@FreeBSD.org> | 2002-09-01 20:37:28 +0000 |
commit | be17b12cb696a0d3f7deed6d1b2201b472b6f85c (patch) | |
tree | ec81ad0e54c0e056c6214598679ec3e70c089905 | |
parent | 84a9d83087b5c82ac362ac1c686726ba0657c506 (diff) | |
download | FreeBSD-src-be17b12cb696a0d3f7deed6d1b2201b472b6f85c.zip FreeBSD-src-be17b12cb696a0d3f7deed6d1b2201b472b6f85c.tar.gz |
Split out a number of mostly VFS and signal related syscalls into
a kernel-internal kern_*() version and a wrapper that is called via
the syscall vector table. For paths and structure pointers, the
internal version either takes a uio_seg parameter or requires the
caller to copyin() the data to kernel memory as appropiate. This
will permit emulation layers to use these syscalls without having
to copy out translated arguments to the stack gap.
Discussed on: -arch
Review/suggestions: bde, jhb, peter, marcel
-rw-r--r-- | sys/kern/init_main.c | 3 | ||||
-rw-r--r-- | sys/kern/kern_sig.c | 76 | ||||
-rw-r--r-- | sys/kern/sys_generic.c | 59 | ||||
-rw-r--r-- | sys/kern/vfs_extattr.c | 296 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 296 | ||||
-rw-r--r-- | sys/sys/syscallsubr.h | 76 | ||||
-rw-r--r-- | sys/sys/vnode.h | 1 |
7 files changed, 591 insertions, 216 deletions
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index b01e0c7..f386085 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -54,6 +54,7 @@ #include <sys/mac.h> #include <sys/mount.h> #include <sys/mutex.h> +#include <sys/syscallsubr.h> #include <sys/sysctl.h> #include <sys/proc.h> #include <sys/resourcevar.h> @@ -529,7 +530,7 @@ start_init(void *dummy) * since the fs will be read-only. But a NFS root * might be ok. It is worth a shot. */ - error = vn_mkdir("/dev", 0700, UIO_SYSSPACE, td); + error = kern_mkdir(td, "/dev", UIO_SYSSPACE, 0700); if (error == EEXIST) error = 0; if (error == 0) diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index c5d8825..b652127 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -64,6 +64,7 @@ #include <sys/smp.h> #include <sys/stat.h> #include <sys/sx.h> +#include <sys/syscallsubr.h> #include <sys/syslog.h> #include <sys/sysent.h> #include <sys/sysctl.h> @@ -75,8 +76,6 @@ #define ONSIG 32 /* NSIG for osig* syscalls. XXX. */ static int coredump(struct thread *); -static int do_sigaction(struct proc *p, int sig, struct sigaction *act, - struct sigaction *oact, int old); static int do_sigprocmask(struct proc *p, int how, sigset_t *set, sigset_t *oset, int old); static char *expand_name(const char *, uid_t, pid_t); @@ -221,18 +220,19 @@ sig_ffs(sigset_t *set) } /* - * do_sigaction + * kern_sigaction * sigaction * osigaction */ -static int -do_sigaction(p, sig, act, oact, old) - struct proc *p; +int +kern_sigaction(td, sig, act, oact, old) + struct thread *td; register int sig; struct sigaction *act, *oact; int old; { register struct sigacts *ps; + struct proc *p = td->td_proc; if (!_SIG_VALID(sig)) return (EINVAL); @@ -374,7 +374,6 @@ sigaction(td, uap) struct thread *td; register struct sigaction_args *uap; { - struct proc *p = td->td_proc; struct sigaction act, oact; register struct sigaction *actp, *oactp; int error; @@ -388,7 +387,7 @@ sigaction(td, uap) if (error) goto done2; } - error = do_sigaction(p, uap->sig, actp, oactp, 0); + error = kern_sigaction(td, uap->sig, actp, oactp, 0); if (oactp && !error) { error = copyout(oactp, uap->oact, sizeof(oact)); } @@ -414,7 +413,6 @@ osigaction(td, uap) struct thread *td; register struct osigaction_args *uap; { - struct proc *p = td->td_proc; struct osigaction sa; struct sigaction nsa, osa; register struct sigaction *nsap, *osap; @@ -436,7 +434,7 @@ osigaction(td, uap) nsap->sa_flags = sa.sa_flags; OSIG2SIG(sa.sa_mask, nsap->sa_mask); } - error = do_sigaction(p, uap->signum, nsap, osap, 1); + error = kern_sigaction(td, uap->signum, nsap, osap, 1); if (osap && !error) { sa.sa_handler = osap->sa_handler; sa.sa_flags = osap->sa_flags; @@ -689,7 +687,6 @@ osigvec(td, uap) struct thread *td; register struct osigvec_args *uap; { - struct proc *p = td->td_proc; struct sigvec vec; struct sigaction nsa, osa; register struct sigaction *nsap, *osap; @@ -712,7 +709,7 @@ osigvec(td, uap) #endif } mtx_lock(&Giant); - error = do_sigaction(p, uap->signum, nsap, osap, 1); + error = kern_sigaction(td, uap->signum, nsap, osap, 1); mtx_unlock(&Giant); if (osap && !error) { vec.sv_handler = osap->sa_handler; @@ -806,14 +803,20 @@ sigsuspend(td, uap) struct thread *td; struct sigsuspend_args *uap; { - struct proc *p = td->td_proc; sigset_t mask; - register struct sigacts *ps; int error; error = copyin(uap->sigmask, &mask, sizeof(mask)); if (error) return (error); + return (kern_sigsuspend(td, mask)); +} + +int +kern_sigsuspend(struct thread *td, sigset_t mask) +{ + struct proc *p = td->td_proc; + register struct sigacts *ps; /* * When returning from sigsuspend, we want @@ -939,8 +942,27 @@ sigaltstack(td, uap) struct thread *td; register struct sigaltstack_args *uap; { + stack_t ss, oss; + int error; + + if (uap->ss != NULL) { + error = copyin(uap->ss, &ss, sizeof(ss)); + if (error) + return (error); + } + error = kern_sigaltstack(td, (uap->ss != NULL) ? &ss : NULL, + (uap->oss != NULL) ? &oss : NULL); + if (error) + return (error); + if (uap->oss != NULL) + error = copyout(&oss, uap->oss, sizeof(stack_t)); + return (error); +} + +int +kern_sigaltstack(struct thread *td, stack_t *ss, stack_t *oss) +{ struct proc *p = td->td_proc; - stack_t ss; int oonstack; int error = 0; @@ -948,34 +970,30 @@ sigaltstack(td, uap) oonstack = sigonstack(cpu_getstack(td)); - if (uap->oss != NULL) { + if (oss != NULL) { PROC_LOCK(p); - ss = p->p_sigstk; - ss.ss_flags = (p->p_flag & P_ALTSTACK) + *oss = p->p_sigstk; + oss->ss_flags = (p->p_flag & P_ALTSTACK) ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; PROC_UNLOCK(p); - if ((error = copyout(&ss, uap->oss, sizeof(stack_t))) != 0) - goto done2; } - if (uap->ss != NULL) { + if (ss != NULL) { if (oonstack) { error = EPERM; goto done2; } - if ((error = copyin(uap->ss, &ss, sizeof(ss))) != 0) - goto done2; - if ((ss.ss_flags & ~SS_DISABLE) != 0) { + if ((ss->ss_flags & ~SS_DISABLE) != 0) { error = EINVAL; goto done2; } - if (!(ss.ss_flags & SS_DISABLE)) { - if (ss.ss_size < p->p_sysent->sv_minsigstksz) { + if (!(ss->ss_flags & SS_DISABLE)) { + if (ss->ss_size < p->p_sysent->sv_minsigstksz) { error = ENOMEM; goto done2; } PROC_LOCK(p); - p->p_sigstk = ss; + p->p_sigstk = *ss; p->p_flag |= P_ALTSTACK; PROC_UNLOCK(p); } else { @@ -1211,7 +1229,7 @@ trapsignal(p, sig, code) SIGADDSET(p->p_sigmask, sig); if (SIGISMEMBER(ps->ps_sigreset, sig)) { /* - * See do_sigaction() for origin of this code. + * See kern_sigaction() for origin of this code. */ SIGDELSET(p->p_sigcatch, sig); if (sig != SIGCONT && @@ -1793,7 +1811,7 @@ postsig(sig) if (SIGISMEMBER(ps->ps_sigreset, sig)) { /* - * See do_sigaction() for origin of this code. + * See kern_sigaction() for origin of this code. */ SIGDELSET(p->p_sigcatch, sig); if (sig != SIGCONT && diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index 54214e8..ec9958d 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -57,6 +57,7 @@ #include <sys/poll.h> #include <sys/resourcevar.h> #include <sys/selinfo.h> +#include <sys/syscallsubr.h> #include <sys/sysctl.h> #include <sys/sysent.h> #include <sys/bio.h> @@ -713,6 +714,24 @@ select(td, uap) register struct thread *td; register struct select_args *uap; { + struct timeval tv, *tvp; + int error; + + if (uap->tv != NULL) { + error = copyin(uap->tv, &tv, sizeof(tv)); + if (error) + return (error); + tvp = &tv; + } else + tvp = NULL; + + return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp)); +} + +int +kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou, + fd_set *fd_ex, struct timeval *tvp) +{ struct filedesc *fdp; /* * The magic 2048 here is chosen to be just enough for FD_SETSIZE @@ -726,28 +745,28 @@ select(td, uap) int error, timo; u_int ncoll, nbufbytes, ncpbytes, nfdbits; - if (uap->nd < 0) + if (nd < 0) return (EINVAL); fdp = td->td_proc->p_fd; mtx_lock(&Giant); FILEDESC_LOCK(fdp); - if (uap->nd > td->td_proc->p_fd->fd_nfiles) - uap->nd = td->td_proc->p_fd->fd_nfiles; /* forgiving; slightly wrong */ + if (nd > td->td_proc->p_fd->fd_nfiles) + nd = td->td_proc->p_fd->fd_nfiles; /* forgiving; slightly wrong */ FILEDESC_UNLOCK(fdp); /* * Allocate just enough bits for the non-null fd_sets. Use the * preallocated auto buffer if possible. */ - nfdbits = roundup(uap->nd, NFDBITS); + nfdbits = roundup(nd, NFDBITS); ncpbytes = nfdbits / NBBY; nbufbytes = 0; - if (uap->in != NULL) + if (fd_in != NULL) nbufbytes += 2 * ncpbytes; - if (uap->ou != NULL) + if (fd_ou != NULL) nbufbytes += 2 * ncpbytes; - if (uap->ex != NULL) + if (fd_ex != NULL) nbufbytes += 2 * ncpbytes; if (nbufbytes <= sizeof s_selbits) selbits = &s_selbits[0]; @@ -762,28 +781,26 @@ select(td, uap) sbp = selbits; #define getbits(name, x) \ do { \ - if (uap->name == NULL) \ + if (name == NULL) \ ibits[x] = NULL; \ else { \ ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp; \ obits[x] = sbp; \ sbp += ncpbytes / sizeof *sbp; \ - error = copyin(uap->name, ibits[x], ncpbytes); \ + error = copyin(name, ibits[x], ncpbytes); \ if (error != 0) \ goto done_nosellock; \ } \ } while (0) - getbits(in, 0); - getbits(ou, 1); - getbits(ex, 2); + getbits(fd_in, 0); + getbits(fd_ou, 1); + getbits(fd_ex, 2); #undef getbits if (nbufbytes != 0) bzero(selbits, nbufbytes / 2); - if (uap->tv) { - error = copyin(uap->tv, &atv, sizeof (atv)); - if (error) - goto done_nosellock; + if (tvp != NULL) { + atv = *tvp; if (itimerfix(&atv)) { error = EINVAL; goto done_nosellock; @@ -804,7 +821,7 @@ retry: mtx_unlock_spin(&sched_lock); mtx_unlock(&sellock); - error = selscan(td, ibits, obits, uap->nd); + error = selscan(td, ibits, obits, nd); mtx_lock(&sellock); if (error || td->td_retval[0]) goto done; @@ -853,14 +870,14 @@ done_nosellock: if (error == EWOULDBLOCK) error = 0; #define putbits(name, x) \ - if (uap->name && (error2 = copyout(obits[x], uap->name, ncpbytes))) \ + if (name && (error2 = copyout(obits[x], name, ncpbytes))) \ error = error2; if (error == 0) { int error2; - putbits(in, 0); - putbits(ou, 1); - putbits(ex, 2); + putbits(fd_in, 0); + putbits(fd_ou, 1); + putbits(fd_ex, 2); #undef putbits } if (selbits != &s_selbits[0]) diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index 48c0151..3015105 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -67,6 +67,7 @@ #include <sys/dirent.h> #include <sys/extattr.h> #include <sys/jail.h> +#include <sys/syscallsubr.h> #include <sys/sysctl.h> #include <machine/limits.h> @@ -79,7 +80,7 @@ static int change_dir(struct nameidata *ndp, struct thread *td); static int chroot_refuse_vdir_fds(struct filedesc *fdp); -static int getutimes(const struct timeval *, struct timespec *); +static int getutimes(const struct timeval *, enum uio_seg, struct timespec *); static int setfown(struct thread *td, struct vnode *, uid_t, gid_t); static int setfmode(struct thread *td, struct vnode *, int); static int setfflags(struct thread *td, struct vnode *, int); @@ -442,13 +443,19 @@ chdir(td, uap) syscallarg(char *) path; } */ *uap; { + + return (kern_chdir(td, uap->path, UIO_USERSPACE)); +} + +int +kern_chdir(struct thread *td, char *path, enum uio_seg pathseg) +{ register struct filedesc *fdp = td->td_proc->p_fd; int error; struct nameidata nd; struct vnode *vp; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, - SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, pathseg, path, td); if ((error = change_dir(&nd, td)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); @@ -608,30 +615,38 @@ open(td, uap) syscallarg(int) mode; } */ *uap; { + + return (kern_open(td, uap->path, UIO_USERSPACE, uap->flags, uap->mode)); +} + +int +kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags, + int mode) +{ struct proc *p = td->td_proc; struct filedesc *fdp = p->p_fd; struct file *fp; struct vnode *vp; struct vattr vat; struct mount *mp; - int cmode, flags, oflags; + int cmode, oflags; struct file *nfp; int type, indx, error; struct flock lf; struct nameidata nd; - oflags = SCARG(uap, flags); - if ((oflags & O_ACCMODE) == O_ACCMODE) + if ((flags & O_ACCMODE) == O_ACCMODE) return (EINVAL); - flags = FFLAGS(oflags); + oflags = flags; + flags = FFLAGS(flags); error = falloc(td, &nfp, &indx); if (error) return (error); fp = nfp; FILEDESC_LOCK(fdp); - cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; + cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; FILEDESC_UNLOCK(fdp); - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td); td->td_dupfd = -indx - 1; /* XXX check for fdopen */ /* * Bump the ref count to prevent another process from closing @@ -812,6 +827,14 @@ mknod(td, uap) syscallarg(int) dev; } */ *uap; { + + return (kern_mknod(td, uap->path, UIO_USERSPACE, uap->mode, uap->dev)); +} + +int +kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode, + int dev) +{ struct vnode *vp; struct mount *mp; struct vattr vattr; @@ -819,7 +842,7 @@ mknod(td, uap) int whiteout = 0; struct nameidata nd; - switch (SCARG(uap, mode) & S_IFMT) { + switch (mode & S_IFMT) { case S_IFCHR: case S_IFBLK: error = suser(td); @@ -832,8 +855,7 @@ mknod(td, uap) return (error); restart: bwillwrite(); - NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, UIO_USERSPACE, - SCARG(uap, path), td); + NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; @@ -843,12 +865,13 @@ restart: } else { VATTR_NULL(&vattr); FILEDESC_LOCK(td->td_proc->p_fd); - vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ td->td_proc->p_fd->fd_cmask; + vattr.va_mode = (mode & ALLPERMS) & + ~td->td_proc->p_fd->fd_cmask; FILEDESC_UNLOCK(td->td_proc->p_fd); - vattr.va_rdev = SCARG(uap, dev); + vattr.va_rdev = dev; whiteout = 0; - switch (SCARG(uap, mode) & S_IFMT) { + switch (mode & S_IFMT) { case S_IFMT: /* used by badsect to flag bad sectors */ vattr.va_type = VBAD; break; @@ -910,6 +933,13 @@ mkfifo(td, uap) syscallarg(int) mode; } */ *uap; { + + return (kern_mkfifo(td, uap->path, UIO_USERSPACE, uap->mode)); +} + +int +kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode) +{ struct mount *mp; struct vattr vattr; int error; @@ -917,8 +947,7 @@ mkfifo(td, uap) restart: bwillwrite(); - NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, UIO_USERSPACE, - SCARG(uap, path), td); + NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); if (nd.ni_vp != NULL) { @@ -937,7 +966,7 @@ restart: VATTR_NULL(&vattr); vattr.va_type = VFIFO; FILEDESC_LOCK(td->td_proc->p_fd); - vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ td->td_proc->p_fd->fd_cmask; + vattr.va_mode = (mode & ALLPERMS) & ~td->td_proc->p_fd->fd_cmask; FILEDESC_UNLOCK(td->td_proc->p_fd); VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); @@ -967,13 +996,20 @@ link(td, uap) syscallarg(char *) link; } */ *uap; { + + return (kern_link(td, uap->path, uap->link, UIO_USERSPACE)); +} + +int +kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg) +{ struct vnode *vp; struct mount *mp; struct nameidata nd; int error; bwillwrite(); - NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, segflg, path, td); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); @@ -986,8 +1022,7 @@ link(td, uap) vrele(vp); return (error); } - NDINIT(&nd, CREATE, LOCKPARENT | NOOBJ | SAVENAME, UIO_USERSPACE, - SCARG(uap, link), td); + NDINIT(&nd, CREATE, LOCKPARENT | NOOBJ | SAVENAME, segflg, link, td); if ((error = namei(&nd)) == 0) { if (nd.ni_vp != NULL) { vrele(nd.ni_vp); @@ -1025,19 +1060,29 @@ symlink(td, uap) syscallarg(char *) link; } */ *uap; { + + return (kern_symlink(td, uap->path, uap->link, UIO_USERSPACE)); +} + +int +kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg) +{ struct mount *mp; struct vattr vattr; - char *path; + char *syspath; int error; struct nameidata nd; - path = uma_zalloc(namei_zone, M_WAITOK); - if ((error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) != 0) - goto out; + if (segflg == UIO_SYSSPACE) { + syspath = path; + } else { + syspath = uma_zalloc(namei_zone, M_WAITOK); + if ((error = copyinstr(path, syspath, MAXPATHLEN, NULL)) != 0) + goto out; + } restart: bwillwrite(); - NDINIT(&nd, CREATE, LOCKPARENT | NOOBJ | SAVENAME, UIO_USERSPACE, - SCARG(uap, link), td); + NDINIT(&nd, CREATE, LOCKPARENT | NOOBJ | SAVENAME, segflg, link, td); if ((error = namei(&nd)) != 0) goto out; if (nd.ni_vp) { @@ -1059,7 +1104,7 @@ restart: vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask; FILEDESC_UNLOCK(td->td_proc->p_fd); VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); - error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); + error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, syspath); NDFREE(&nd, NDF_ONLY_PNBUF); if (error == 0) vput(nd.ni_vp); @@ -1068,7 +1113,8 @@ restart: ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink"); ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink"); out: - uma_zfree(namei_zone, path); + if (segflg != UIO_SYSSPACE) + uma_zfree(namei_zone, syspath); return (error); } @@ -1135,6 +1181,13 @@ unlink(td, uap) syscallarg(char *) path; } */ *uap; { + + return (kern_unlink(td, SCARG(uap, path), UIO_USERSPACE)); +} + +int +kern_unlink(struct thread *td, char *path, enum uio_seg pathseg) +{ struct mount *mp; struct vnode *vp; int error; @@ -1142,8 +1195,7 @@ unlink(td, uap) restart: bwillwrite(); - NDINIT(&nd, DELETE, LOCKPARENT|LOCKLEAF, UIO_USERSPACE, - SCARG(uap, path), td); + NDINIT(&nd, DELETE, LOCKPARENT|LOCKLEAF, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; @@ -1343,6 +1395,13 @@ access(td, uap) syscallarg(int) flags; } */ *uap; { + + return (kern_access(td, uap->path, UIO_USERSPACE, uap->flags)); +} + +int +kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags) +{ struct ucred *cred, *tmpcred; register struct vnode *vp; int error; @@ -1362,13 +1421,12 @@ access(td, uap) tmpcred->cr_uid = cred->cr_ruid; tmpcred->cr_groups[0] = cred->cr_rgid; td->td_ucred = tmpcred; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, - SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, pathseg, path, td); if ((error = namei(&nd)) != 0) goto out1; vp = nd.ni_vp; - error = vn_access(vp, SCARG(uap, flags), tmpcred, td); + error = vn_access(vp, flags, tmpcred, td); NDFREE(&nd, NDF_ONLY_PNBUF); vput(vp); out1: @@ -1749,14 +1807,22 @@ readlink(td, uap) syscallarg(int) count; } */ *uap; { + + return (kern_readlink(td, uap->path, UIO_USERSPACE, uap->buf, + UIO_USERSPACE, uap->count)); +} + +int +kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf, + enum uio_seg bufseg, int count) +{ register struct vnode *vp; struct iovec aiov; struct uio auio; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, - SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); @@ -1771,19 +1837,19 @@ readlink(td, uap) if (vp->v_type != VLNK) error = EINVAL; else { - aiov.iov_base = SCARG(uap, buf); - aiov.iov_len = SCARG(uap, count); + aiov.iov_base = buf; + aiov.iov_len = count; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_offset = 0; auio.uio_rw = UIO_READ; - auio.uio_segflg = UIO_USERSPACE; + auio.uio_segflg = bufseg; auio.uio_td = td; - auio.uio_resid = SCARG(uap, count); + auio.uio_resid = count; error = VOP_READLINK(vp, &auio, td->td_ucred); } vput(vp); - td->td_retval[0] = SCARG(uap, count) - auio.uio_resid; + td->td_retval[0] = count - auio.uio_resid; return (error); } @@ -1959,14 +2025,21 @@ chmod(td, uap) syscallarg(int) mode; } */ *uap; { + + return (kern_chmod(td, uap->path, UIO_USERSPACE, uap->mode)); +} + +int +kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, int mode) +{ int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); - error = setfmode(td, nd.ni_vp, SCARG(uap, mode)); + error = setfmode(td, nd.ni_vp, mode); vrele(nd.ni_vp); return error; } @@ -2083,14 +2156,22 @@ chown(td, uap) syscallarg(int) gid; } */ *uap; { + + return (kern_chown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid)); +} + +int +kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid, + int gid) +{ int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); - error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid)); + error = setfown(td, nd.ni_vp, uid, gid); vrele(nd.ni_vp); return (error); } @@ -2115,14 +2196,22 @@ lchown(td, uap) syscallarg(int) gid; } */ *uap; { + + return (kern_lchown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid)); +} + +int +kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid, + int gid) +{ int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, NOFOLLOW, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); - error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid)); + error = setfown(td, nd.ni_vp, uid, gid); vrele(nd.ni_vp); return (error); } @@ -2164,11 +2253,13 @@ fchown(td, uap) * Common implementation code for utimes(), lutimes(), and futimes(). */ static int -getutimes(usrtvp, tsp) +getutimes(usrtvp, tvpseg, tsp) const struct timeval *usrtvp; + enum uio_seg tvpseg; struct timespec *tsp; { struct timeval tv[2]; + const struct timeval *tvp; int error; if (usrtvp == NULL) { @@ -2176,10 +2267,16 @@ getutimes(usrtvp, tsp) TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); tsp[1] = tsp[0]; } else { - if ((error = copyin(usrtvp, tv, sizeof (tv))) != 0) - return (error); - TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); - TIMEVAL_TO_TIMESPEC(&tv[1], &tsp[1]); + if (tvpseg == UIO_SYSSPACE) { + tvp = usrtvp; + } else { + if ((error = copyin(usrtvp, tv, sizeof(tv))) != 0) + return (error); + tvp = tv; + } + + TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]); + TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]); } return 0; } @@ -2245,19 +2342,26 @@ utimes(td, uap) syscallarg(struct timeval *) tptr; } */ *uap; { + + return (kern_utimes(td, uap->path, UIO_USERSPACE, uap->tptr, + UIO_USERSPACE)); +} + +int +kern_utimes(struct thread *td, char *path, enum uio_seg pathseg, + struct timeval *tptr, enum uio_seg tptrseg) +{ struct timespec ts[2]; - struct timeval *usrtvp; int error; struct nameidata nd; - usrtvp = SCARG(uap, tptr); - if ((error = getutimes(usrtvp, ts)) != 0) + if ((error = getutimes(tptr, tptrseg, ts)) != 0) return (error); - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); - error = setutimes(td, nd.ni_vp, ts, 2, usrtvp == NULL); + error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL); vrele(nd.ni_vp); return (error); } @@ -2280,19 +2384,26 @@ lutimes(td, uap) syscallarg(struct timeval *) tptr; } */ *uap; { + + return (kern_lutimes(td, uap->path, UIO_USERSPACE, uap->tptr, + UIO_USERSPACE)); +} + +int +kern_lutimes(struct thread *td, char *path, enum uio_seg pathseg, + struct timeval *tptr, enum uio_seg tptrseg) +{ struct timespec ts[2]; - struct timeval *usrtvp; int error; struct nameidata nd; - usrtvp = SCARG(uap, tptr); - if ((error = getutimes(usrtvp, ts)) != 0) + if ((error = getutimes(tptr, tptrseg, ts)) != 0) return (error); - NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, NOFOLLOW, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); - error = setutimes(td, nd.ni_vp, ts, 2, usrtvp == NULL); + error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL); vrele(nd.ni_vp); return (error); } @@ -2315,17 +2426,23 @@ futimes(td, uap) syscallarg(struct timeval *) tptr; } */ *uap; { + + return (kern_futimes(td, uap->fd, uap->tptr, UIO_USERSPACE)); +} + +int +kern_futimes(struct thread *td, int fd, struct timeval *tptr, + enum uio_seg tptrseg) +{ struct timespec ts[2]; struct file *fp; - struct timeval *usrtvp; int error; - usrtvp = SCARG(uap, tptr); - if ((error = getutimes(usrtvp, ts)) != 0) + if ((error = getutimes(tptr, tptrseg, ts)) != 0) return (error); - if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) + if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0) return (error); - error = setutimes(td, (struct vnode *)fp->f_data, ts, 2, usrtvp==NULL); + error = setutimes(td, (struct vnode *)fp->f_data, ts, 2, tptr == NULL); fdrop(fp, td); return (error); } @@ -2350,15 +2467,22 @@ truncate(td, uap) syscallarg(off_t) length; } */ *uap; { + + return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length)); +} + +int +kern_truncate(struct thread *td, char *path, enum uio_seg pathseg, off_t length) +{ struct mount *mp; struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; - if (uap->length < 0) + if (length < 0) return(EINVAL); - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; @@ -2378,7 +2502,7 @@ truncate(td, uap) else if ((error = vn_writechk(vp)) == 0 && (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) { VATTR_NULL(&vattr); - vattr.va_size = SCARG(uap, length); + vattr.va_size = length; error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); } vput(vp); @@ -2570,14 +2694,20 @@ rename(td, uap) syscallarg(char *) to; } */ *uap; { + + return (kern_rename(td, uap->from, uap->to, UIO_USERSPACE)); +} + +int +kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg) +{ struct mount *mp; struct vnode *tvp, *fvp, *tdvp; struct nameidata fromnd, tond; int error; bwillwrite(); - NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, - SCARG(uap, from), td); + NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, pathseg, from, td); if ((error = namei(&fromnd)) != 0) return (error); fvp = fromnd.ni_vp; @@ -2587,8 +2717,8 @@ rename(td, uap) vrele(fvp); goto out1; } - NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ, - UIO_USERSPACE, SCARG(uap, to), td); + NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | + NOOBJ, pathseg, to, td); if (fromnd.ni_vp->v_type == VDIR) tond.ni_cnd.cn_flags |= WILLBEDIR; if ((error = namei(&tond)) != 0) { @@ -2681,15 +2811,11 @@ mkdir(td, uap) } */ *uap; { - return vn_mkdir(uap->path, uap->mode, UIO_USERSPACE, td); + return (kern_mkdir(td, uap->path, UIO_USERSPACE, uap->mode)); } int -vn_mkdir(path, mode, segflg, td) - char *path; - int mode; - enum uio_seg segflg; - struct thread *td; +kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode) { struct mount *mp; struct vnode *vp; @@ -2758,6 +2884,13 @@ rmdir(td, uap) syscallarg(char *) path; } */ *uap; { + + return (kern_rmdir(td, uap->path, UIO_USERSPACE)); +} + +int +kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg) +{ struct mount *mp; struct vnode *vp; int error; @@ -2765,8 +2898,7 @@ rmdir(td, uap) restart: bwillwrite(); - NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, - SCARG(uap, path), td); + NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 48c0151..3015105 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -67,6 +67,7 @@ #include <sys/dirent.h> #include <sys/extattr.h> #include <sys/jail.h> +#include <sys/syscallsubr.h> #include <sys/sysctl.h> #include <machine/limits.h> @@ -79,7 +80,7 @@ static int change_dir(struct nameidata *ndp, struct thread *td); static int chroot_refuse_vdir_fds(struct filedesc *fdp); -static int getutimes(const struct timeval *, struct timespec *); +static int getutimes(const struct timeval *, enum uio_seg, struct timespec *); static int setfown(struct thread *td, struct vnode *, uid_t, gid_t); static int setfmode(struct thread *td, struct vnode *, int); static int setfflags(struct thread *td, struct vnode *, int); @@ -442,13 +443,19 @@ chdir(td, uap) syscallarg(char *) path; } */ *uap; { + + return (kern_chdir(td, uap->path, UIO_USERSPACE)); +} + +int +kern_chdir(struct thread *td, char *path, enum uio_seg pathseg) +{ register struct filedesc *fdp = td->td_proc->p_fd; int error; struct nameidata nd; struct vnode *vp; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, - SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, pathseg, path, td); if ((error = change_dir(&nd, td)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); @@ -608,30 +615,38 @@ open(td, uap) syscallarg(int) mode; } */ *uap; { + + return (kern_open(td, uap->path, UIO_USERSPACE, uap->flags, uap->mode)); +} + +int +kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags, + int mode) +{ struct proc *p = td->td_proc; struct filedesc *fdp = p->p_fd; struct file *fp; struct vnode *vp; struct vattr vat; struct mount *mp; - int cmode, flags, oflags; + int cmode, oflags; struct file *nfp; int type, indx, error; struct flock lf; struct nameidata nd; - oflags = SCARG(uap, flags); - if ((oflags & O_ACCMODE) == O_ACCMODE) + if ((flags & O_ACCMODE) == O_ACCMODE) return (EINVAL); - flags = FFLAGS(oflags); + oflags = flags; + flags = FFLAGS(flags); error = falloc(td, &nfp, &indx); if (error) return (error); fp = nfp; FILEDESC_LOCK(fdp); - cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; + cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; FILEDESC_UNLOCK(fdp); - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td); td->td_dupfd = -indx - 1; /* XXX check for fdopen */ /* * Bump the ref count to prevent another process from closing @@ -812,6 +827,14 @@ mknod(td, uap) syscallarg(int) dev; } */ *uap; { + + return (kern_mknod(td, uap->path, UIO_USERSPACE, uap->mode, uap->dev)); +} + +int +kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode, + int dev) +{ struct vnode *vp; struct mount *mp; struct vattr vattr; @@ -819,7 +842,7 @@ mknod(td, uap) int whiteout = 0; struct nameidata nd; - switch (SCARG(uap, mode) & S_IFMT) { + switch (mode & S_IFMT) { case S_IFCHR: case S_IFBLK: error = suser(td); @@ -832,8 +855,7 @@ mknod(td, uap) return (error); restart: bwillwrite(); - NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, UIO_USERSPACE, - SCARG(uap, path), td); + NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; @@ -843,12 +865,13 @@ restart: } else { VATTR_NULL(&vattr); FILEDESC_LOCK(td->td_proc->p_fd); - vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ td->td_proc->p_fd->fd_cmask; + vattr.va_mode = (mode & ALLPERMS) & + ~td->td_proc->p_fd->fd_cmask; FILEDESC_UNLOCK(td->td_proc->p_fd); - vattr.va_rdev = SCARG(uap, dev); + vattr.va_rdev = dev; whiteout = 0; - switch (SCARG(uap, mode) & S_IFMT) { + switch (mode & S_IFMT) { case S_IFMT: /* used by badsect to flag bad sectors */ vattr.va_type = VBAD; break; @@ -910,6 +933,13 @@ mkfifo(td, uap) syscallarg(int) mode; } */ *uap; { + + return (kern_mkfifo(td, uap->path, UIO_USERSPACE, uap->mode)); +} + +int +kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode) +{ struct mount *mp; struct vattr vattr; int error; @@ -917,8 +947,7 @@ mkfifo(td, uap) restart: bwillwrite(); - NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, UIO_USERSPACE, - SCARG(uap, path), td); + NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); if (nd.ni_vp != NULL) { @@ -937,7 +966,7 @@ restart: VATTR_NULL(&vattr); vattr.va_type = VFIFO; FILEDESC_LOCK(td->td_proc->p_fd); - vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ td->td_proc->p_fd->fd_cmask; + vattr.va_mode = (mode & ALLPERMS) & ~td->td_proc->p_fd->fd_cmask; FILEDESC_UNLOCK(td->td_proc->p_fd); VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); @@ -967,13 +996,20 @@ link(td, uap) syscallarg(char *) link; } */ *uap; { + + return (kern_link(td, uap->path, uap->link, UIO_USERSPACE)); +} + +int +kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg) +{ struct vnode *vp; struct mount *mp; struct nameidata nd; int error; bwillwrite(); - NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, segflg, path, td); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); @@ -986,8 +1022,7 @@ link(td, uap) vrele(vp); return (error); } - NDINIT(&nd, CREATE, LOCKPARENT | NOOBJ | SAVENAME, UIO_USERSPACE, - SCARG(uap, link), td); + NDINIT(&nd, CREATE, LOCKPARENT | NOOBJ | SAVENAME, segflg, link, td); if ((error = namei(&nd)) == 0) { if (nd.ni_vp != NULL) { vrele(nd.ni_vp); @@ -1025,19 +1060,29 @@ symlink(td, uap) syscallarg(char *) link; } */ *uap; { + + return (kern_symlink(td, uap->path, uap->link, UIO_USERSPACE)); +} + +int +kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg) +{ struct mount *mp; struct vattr vattr; - char *path; + char *syspath; int error; struct nameidata nd; - path = uma_zalloc(namei_zone, M_WAITOK); - if ((error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) != 0) - goto out; + if (segflg == UIO_SYSSPACE) { + syspath = path; + } else { + syspath = uma_zalloc(namei_zone, M_WAITOK); + if ((error = copyinstr(path, syspath, MAXPATHLEN, NULL)) != 0) + goto out; + } restart: bwillwrite(); - NDINIT(&nd, CREATE, LOCKPARENT | NOOBJ | SAVENAME, UIO_USERSPACE, - SCARG(uap, link), td); + NDINIT(&nd, CREATE, LOCKPARENT | NOOBJ | SAVENAME, segflg, link, td); if ((error = namei(&nd)) != 0) goto out; if (nd.ni_vp) { @@ -1059,7 +1104,7 @@ restart: vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask; FILEDESC_UNLOCK(td->td_proc->p_fd); VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); - error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); + error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, syspath); NDFREE(&nd, NDF_ONLY_PNBUF); if (error == 0) vput(nd.ni_vp); @@ -1068,7 +1113,8 @@ restart: ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink"); ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink"); out: - uma_zfree(namei_zone, path); + if (segflg != UIO_SYSSPACE) + uma_zfree(namei_zone, syspath); return (error); } @@ -1135,6 +1181,13 @@ unlink(td, uap) syscallarg(char *) path; } */ *uap; { + + return (kern_unlink(td, SCARG(uap, path), UIO_USERSPACE)); +} + +int +kern_unlink(struct thread *td, char *path, enum uio_seg pathseg) +{ struct mount *mp; struct vnode *vp; int error; @@ -1142,8 +1195,7 @@ unlink(td, uap) restart: bwillwrite(); - NDINIT(&nd, DELETE, LOCKPARENT|LOCKLEAF, UIO_USERSPACE, - SCARG(uap, path), td); + NDINIT(&nd, DELETE, LOCKPARENT|LOCKLEAF, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; @@ -1343,6 +1395,13 @@ access(td, uap) syscallarg(int) flags; } */ *uap; { + + return (kern_access(td, uap->path, UIO_USERSPACE, uap->flags)); +} + +int +kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags) +{ struct ucred *cred, *tmpcred; register struct vnode *vp; int error; @@ -1362,13 +1421,12 @@ access(td, uap) tmpcred->cr_uid = cred->cr_ruid; tmpcred->cr_groups[0] = cred->cr_rgid; td->td_ucred = tmpcred; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, - SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, pathseg, path, td); if ((error = namei(&nd)) != 0) goto out1; vp = nd.ni_vp; - error = vn_access(vp, SCARG(uap, flags), tmpcred, td); + error = vn_access(vp, flags, tmpcred, td); NDFREE(&nd, NDF_ONLY_PNBUF); vput(vp); out1: @@ -1749,14 +1807,22 @@ readlink(td, uap) syscallarg(int) count; } */ *uap; { + + return (kern_readlink(td, uap->path, UIO_USERSPACE, uap->buf, + UIO_USERSPACE, uap->count)); +} + +int +kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf, + enum uio_seg bufseg, int count) +{ register struct vnode *vp; struct iovec aiov; struct uio auio; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, - SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); @@ -1771,19 +1837,19 @@ readlink(td, uap) if (vp->v_type != VLNK) error = EINVAL; else { - aiov.iov_base = SCARG(uap, buf); - aiov.iov_len = SCARG(uap, count); + aiov.iov_base = buf; + aiov.iov_len = count; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_offset = 0; auio.uio_rw = UIO_READ; - auio.uio_segflg = UIO_USERSPACE; + auio.uio_segflg = bufseg; auio.uio_td = td; - auio.uio_resid = SCARG(uap, count); + auio.uio_resid = count; error = VOP_READLINK(vp, &auio, td->td_ucred); } vput(vp); - td->td_retval[0] = SCARG(uap, count) - auio.uio_resid; + td->td_retval[0] = count - auio.uio_resid; return (error); } @@ -1959,14 +2025,21 @@ chmod(td, uap) syscallarg(int) mode; } */ *uap; { + + return (kern_chmod(td, uap->path, UIO_USERSPACE, uap->mode)); +} + +int +kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, int mode) +{ int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); - error = setfmode(td, nd.ni_vp, SCARG(uap, mode)); + error = setfmode(td, nd.ni_vp, mode); vrele(nd.ni_vp); return error; } @@ -2083,14 +2156,22 @@ chown(td, uap) syscallarg(int) gid; } */ *uap; { + + return (kern_chown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid)); +} + +int +kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid, + int gid) +{ int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); - error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid)); + error = setfown(td, nd.ni_vp, uid, gid); vrele(nd.ni_vp); return (error); } @@ -2115,14 +2196,22 @@ lchown(td, uap) syscallarg(int) gid; } */ *uap; { + + return (kern_lchown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid)); +} + +int +kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid, + int gid) +{ int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, NOFOLLOW, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); - error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid)); + error = setfown(td, nd.ni_vp, uid, gid); vrele(nd.ni_vp); return (error); } @@ -2164,11 +2253,13 @@ fchown(td, uap) * Common implementation code for utimes(), lutimes(), and futimes(). */ static int -getutimes(usrtvp, tsp) +getutimes(usrtvp, tvpseg, tsp) const struct timeval *usrtvp; + enum uio_seg tvpseg; struct timespec *tsp; { struct timeval tv[2]; + const struct timeval *tvp; int error; if (usrtvp == NULL) { @@ -2176,10 +2267,16 @@ getutimes(usrtvp, tsp) TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); tsp[1] = tsp[0]; } else { - if ((error = copyin(usrtvp, tv, sizeof (tv))) != 0) - return (error); - TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); - TIMEVAL_TO_TIMESPEC(&tv[1], &tsp[1]); + if (tvpseg == UIO_SYSSPACE) { + tvp = usrtvp; + } else { + if ((error = copyin(usrtvp, tv, sizeof(tv))) != 0) + return (error); + tvp = tv; + } + + TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]); + TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]); } return 0; } @@ -2245,19 +2342,26 @@ utimes(td, uap) syscallarg(struct timeval *) tptr; } */ *uap; { + + return (kern_utimes(td, uap->path, UIO_USERSPACE, uap->tptr, + UIO_USERSPACE)); +} + +int +kern_utimes(struct thread *td, char *path, enum uio_seg pathseg, + struct timeval *tptr, enum uio_seg tptrseg) +{ struct timespec ts[2]; - struct timeval *usrtvp; int error; struct nameidata nd; - usrtvp = SCARG(uap, tptr); - if ((error = getutimes(usrtvp, ts)) != 0) + if ((error = getutimes(tptr, tptrseg, ts)) != 0) return (error); - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); - error = setutimes(td, nd.ni_vp, ts, 2, usrtvp == NULL); + error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL); vrele(nd.ni_vp); return (error); } @@ -2280,19 +2384,26 @@ lutimes(td, uap) syscallarg(struct timeval *) tptr; } */ *uap; { + + return (kern_lutimes(td, uap->path, UIO_USERSPACE, uap->tptr, + UIO_USERSPACE)); +} + +int +kern_lutimes(struct thread *td, char *path, enum uio_seg pathseg, + struct timeval *tptr, enum uio_seg tptrseg) +{ struct timespec ts[2]; - struct timeval *usrtvp; int error; struct nameidata nd; - usrtvp = SCARG(uap, tptr); - if ((error = getutimes(usrtvp, ts)) != 0) + if ((error = getutimes(tptr, tptrseg, ts)) != 0) return (error); - NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, NOFOLLOW, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); - error = setutimes(td, nd.ni_vp, ts, 2, usrtvp == NULL); + error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL); vrele(nd.ni_vp); return (error); } @@ -2315,17 +2426,23 @@ futimes(td, uap) syscallarg(struct timeval *) tptr; } */ *uap; { + + return (kern_futimes(td, uap->fd, uap->tptr, UIO_USERSPACE)); +} + +int +kern_futimes(struct thread *td, int fd, struct timeval *tptr, + enum uio_seg tptrseg) +{ struct timespec ts[2]; struct file *fp; - struct timeval *usrtvp; int error; - usrtvp = SCARG(uap, tptr); - if ((error = getutimes(usrtvp, ts)) != 0) + if ((error = getutimes(tptr, tptrseg, ts)) != 0) return (error); - if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) + if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0) return (error); - error = setutimes(td, (struct vnode *)fp->f_data, ts, 2, usrtvp==NULL); + error = setutimes(td, (struct vnode *)fp->f_data, ts, 2, tptr == NULL); fdrop(fp, td); return (error); } @@ -2350,15 +2467,22 @@ truncate(td, uap) syscallarg(off_t) length; } */ *uap; { + + return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length)); +} + +int +kern_truncate(struct thread *td, char *path, enum uio_seg pathseg, off_t length) +{ struct mount *mp; struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; - if (uap->length < 0) + if (length < 0) return(EINVAL); - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); + NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; @@ -2378,7 +2502,7 @@ truncate(td, uap) else if ((error = vn_writechk(vp)) == 0 && (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) { VATTR_NULL(&vattr); - vattr.va_size = SCARG(uap, length); + vattr.va_size = length; error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); } vput(vp); @@ -2570,14 +2694,20 @@ rename(td, uap) syscallarg(char *) to; } */ *uap; { + + return (kern_rename(td, uap->from, uap->to, UIO_USERSPACE)); +} + +int +kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg) +{ struct mount *mp; struct vnode *tvp, *fvp, *tdvp; struct nameidata fromnd, tond; int error; bwillwrite(); - NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, - SCARG(uap, from), td); + NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, pathseg, from, td); if ((error = namei(&fromnd)) != 0) return (error); fvp = fromnd.ni_vp; @@ -2587,8 +2717,8 @@ rename(td, uap) vrele(fvp); goto out1; } - NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ, - UIO_USERSPACE, SCARG(uap, to), td); + NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | + NOOBJ, pathseg, to, td); if (fromnd.ni_vp->v_type == VDIR) tond.ni_cnd.cn_flags |= WILLBEDIR; if ((error = namei(&tond)) != 0) { @@ -2681,15 +2811,11 @@ mkdir(td, uap) } */ *uap; { - return vn_mkdir(uap->path, uap->mode, UIO_USERSPACE, td); + return (kern_mkdir(td, uap->path, UIO_USERSPACE, uap->mode)); } int -vn_mkdir(path, mode, segflg, td) - char *path; - int mode; - enum uio_seg segflg; - struct thread *td; +kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode) { struct mount *mp; struct vnode *vp; @@ -2758,6 +2884,13 @@ rmdir(td, uap) syscallarg(char *) path; } */ *uap; { + + return (kern_rmdir(td, uap->path, UIO_USERSPACE)); +} + +int +kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg) +{ struct mount *mp; struct vnode *vp; int error; @@ -2765,8 +2898,7 @@ rmdir(td, uap) restart: bwillwrite(); - NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, - SCARG(uap, path), td); + NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h new file mode 100644 index 0000000..cab4479 --- /dev/null +++ b/sys/sys/syscallsubr.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2002 Ian Dowse. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_SYSCALLSUBR_H_ +#define _SYS_SYSCALLSUBR_H_ + +#include <sys/signal.h> +#include <sys/uio.h> + +int kern_access(struct thread *td, char *path, enum uio_seg pathseg, + int flags); +int kern_chdir(struct thread *td, char *path, enum uio_seg pathseg); +int kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, + int mode); +int kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid, + int gid); +int kern_futimes(struct thread *td, int fd, struct timeval *tptr, + enum uio_seg tptrseg); +int kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, + int uid, int gid); +int kern_link(struct thread *td, char *path, char *link, + enum uio_seg segflg); +int kern_lutimes(struct thread *td, char *path, enum uio_seg pathseg, + struct timeval *tptr, enum uio_seg tptrseg); +int kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, + int mode); +int kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, + int mode); +int kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, + int mode, int dev); +int kern_open(struct thread *td, char *path, enum uio_seg pathseg, + int flags, int mode); +int kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, + char *buf, enum uio_seg bufseg, int count); +int kern_rename(struct thread *td, char *from, char *to, + enum uio_seg pathseg); +int kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg); +int kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou, + fd_set *fd_ex, struct timeval *tvp); +int kern_sigaction(struct thread *td, int sig, struct sigaction *act, + struct sigaction *oact, int old); +int kern_sigaltstack(struct thread *td, stack_t *ss, stack_t *oss); +int kern_sigsuspend(struct thread *td, sigset_t mask); +int kern_symlink(struct thread *td, char *path, char *link, + enum uio_seg segflg); +int kern_truncate(struct thread *td, char *path, enum uio_seg pathseg, + off_t length); +int kern_unlink(struct thread *td, char *path, enum uio_seg pathseg); +int kern_utimes(struct thread *td, char *path, enum uio_seg pathseg, + struct timeval *tptr, enum uio_seg tptrseg); + +#endif /* !_SYS_SYSCALLSUBR_H_ */ diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 261d6eb..abfb342 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -734,7 +734,6 @@ int debug_vn_lock(struct vnode *vp, int flags, struct thread *p, const char *filename, int line); #define vn_lock(vp,flags,p) debug_vn_lock(vp,flags,p,__FILE__,__LINE__) #endif -int vn_mkdir(char *path, int mode, enum uio_seg segflg, struct thread *td); int vn_open(struct nameidata *ndp, int *flagp, int cmode); int vn_open_cred(struct nameidata *ndp, int *flagp, int cmode, struct ucred *cred); |