diff options
-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); |