summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--sys/sys/syscallsubr.h76
-rw-r--r--sys/sys/vnode.h1
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);
OpenPOWER on IntegriCloud