summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2002-09-01 20:37:28 +0000
committeriedowse <iedowse@FreeBSD.org>2002-09-01 20:37:28 +0000
commitbe17b12cb696a0d3f7deed6d1b2201b472b6f85c (patch)
treeec81ad0e54c0e056c6214598679ec3e70c089905 /sys/kern
parent84a9d83087b5c82ac362ac1c686726ba0657c506 (diff)
downloadFreeBSD-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
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/init_main.c3
-rw-r--r--sys/kern/kern_sig.c76
-rw-r--r--sys/kern/sys_generic.c59
-rw-r--r--sys/kern/vfs_extattr.c296
-rw-r--r--sys/kern/vfs_syscalls.c296
5 files changed, 515 insertions, 215 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;
OpenPOWER on IntegriCloud