Break cdir/rdir/cmask info out of struct filedesc, and put it in a new

substructure, `cwdinfo'.  Implement optional sharing of this substructure.

This is required for clone(2).
This commit is contained in:
thorpej 1999-04-30 18:42:58 +00:00
parent c7ca008189
commit 16936c9565
9 changed files with 169 additions and 84 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: init_main.c,v 1.147 1999/04/25 02:56:30 simonb Exp $ */
/* $NetBSD: init_main.c,v 1.148 1999/04/30 18:42:59 thorpej Exp $ */
/*
* Copyright (c) 1995 Christopher G. Demetriou. All rights reserved.
@ -115,6 +115,7 @@ struct pgrp pgrp0;
struct proc proc0;
struct pcred cred0;
struct filedesc0 filedesc0;
struct cwdinfo cwdi0;
struct plimit limit0;
struct vmspace vmspace0;
#ifndef curproc
@ -256,6 +257,11 @@ main()
p->p_fd = &filedesc0.fd_fd;
fdinit1(&filedesc0);
/* Create the CWD info. */
p->p_cwdi = &cwdi0;
cwdi0.cwdi_cmask = cmask;
cwdi0.cwdi_refcnt = 1;
/* Create the limits structures. */
p->p_limit = &limit0;
for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++)
@ -375,10 +381,10 @@ main()
*/
if (VFS_ROOT(mountlist.cqh_first, &rootvnode))
panic("cannot find root vnode");
filedesc0.fd_fd.fd_cdir = rootvnode;
VREF(filedesc0.fd_fd.fd_cdir);
cwdi0.cwdi_cdir = rootvnode;
VREF(cwdi0.cwdi_cdir);
VOP_UNLOCK(rootvnode, 0);
filedesc0.fd_fd.fd_rdir = NULL;
cwdi0.cwdi_rdir = NULL;
uvm_swap_init();
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_descrip.c,v 1.57 1999/03/24 05:51:22 mrg Exp $ */
/* $NetBSD: kern_descrip.c,v 1.58 1999/04/30 18:42:59 thorpej Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1991, 1993
@ -70,6 +70,7 @@
struct filelist filehead; /* head of list of open files */
int nfiles; /* actual number of open files */
struct pool file_pool; /* memory pool for file structures */
struct pool cwdi_pool; /* memory pool for cwdinfo structures */
static __inline void fd_used __P((struct filedesc *, int));
static __inline void fd_unused __P((struct filedesc *, int));
@ -576,6 +577,8 @@ finit()
pool_init(&file_pool, sizeof(struct file), 0, 0, 0, "filepl",
0, pool_page_alloc_nointr, pool_page_free_nointr, M_FILE);
pool_init(&cwdi_pool, sizeof(struct cwdinfo), 0, 0, 0, "cwdipl",
0, pool_page_alloc_nointr, pool_page_free_nointr, M_FILEDESC);
}
/*
@ -638,6 +641,80 @@ ffree(fp)
pool_put(&file_pool, fp);
}
/*
* Create an initial cwdinfo structure, using the same current and root
* directories as p.
*/
struct cwdinfo *
cwdinit(p)
struct proc *p;
{
struct cwdinfo *cwdi;
extern int cmask;
cwdi = pool_get(&cwdi_pool, PR_WAITOK);
cwdi->cwdi_cdir = p->p_cwdi->cwdi_cdir;
VREF(cwdi->cwdi_cdir);
cwdi->cwdi_rdir = p->p_cwdi->cwdi_rdir;
if (cwdi->cwdi_rdir)
VREF(cwdi->cwdi_rdir);
cwdi->cwdi_cmask = cmask;
cwdi->cwdi_refcnt = 1;
return (cwdi);
}
/*
* Make p2 share p1's cwdinfo.
*/
void
cwdshare(p1, p2)
struct proc *p1, *p2;
{
p2->p_cwdi = p1->p_cwdi;
p1->p_cwdi->cwdi_refcnt++;
}
/*
* Make this process not share its cwdinfo structure, maintaining
* all cwdinfo state.
*/
void
cwdunshare(p)
struct proc *p;
{
struct cwdinfo *newcwdi;
if (p->p_cwdi->cwdi_refcnt == 1)
return;
newcwdi = cwdinit(p);
cwdfree(p);
p->p_cwdi = newcwdi;
}
/*
* Release a cwdinfo structure.
*/
void
cwdfree(p)
struct proc *p;
{
struct cwdinfo *cwdi = p->p_cwdi;
if (--cwdi->cwdi_refcnt > 0)
return;
p->p_cwdi = NULL;
vrele(cwdi->cwdi_cdir);
if (cwdi->cwdi_rdir)
vrele(cwdi->cwdi_rdir);
pool_put(&cwdi_pool, cwdi);
}
/*
* Create an initial filedesc structure, using the same current and root
* directories as p.
@ -647,16 +724,10 @@ fdinit(p)
struct proc *p;
{
struct filedesc0 *newfdp;
struct filedesc *fdp = p->p_fd;
MALLOC(newfdp, struct filedesc0 *, sizeof(struct filedesc0),
M_FILEDESC, M_WAITOK);
memset(newfdp, 0, sizeof(struct filedesc0));
newfdp->fd_fd.fd_cdir = fdp->fd_cdir;
VREF(newfdp->fd_fd.fd_cdir);
newfdp->fd_fd.fd_rdir = fdp->fd_rdir;
if (newfdp->fd_fd.fd_rdir)
VREF(newfdp->fd_fd.fd_rdir);
fdinit1(newfdp);
@ -670,10 +741,8 @@ void
fdinit1(newfdp)
struct filedesc0 *newfdp;
{
extern int cmask; /* init_main.c */
newfdp->fd_fd.fd_refcnt = 1;
newfdp->fd_fd.fd_cmask = cmask;
newfdp->fd_fd.fd_ofiles = newfdp->fd_dfiles;
newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags;
newfdp->fd_fd.fd_nfiles = NDFILE;
@ -737,9 +806,6 @@ fdcopy(p)
MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0),
M_FILEDESC, M_WAITOK);
memcpy(newfdp, fdp, sizeof(struct filedesc));
VREF(newfdp->fd_cdir);
if (newfdp->fd_rdir)
VREF(newfdp->fd_rdir);
newfdp->fd_refcnt = 1;
/*
@ -800,9 +866,6 @@ fdfree(p)
p->p_fd = NULL;
if (fdp->fd_nfiles > NDFILE)
FREE(fdp->fd_ofiles, M_FILEDESC);
vrele(fdp->fd_cdir);
if (fdp->fd_rdir)
vrele(fdp->fd_rdir);
FREE(fdp, M_FILEDESC);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_fork.c,v 1.54 1999/03/24 05:51:23 mrg Exp $ */
/* $NetBSD: kern_fork.c,v 1.55 1999/04/30 18:42:59 thorpej Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1991, 1993
@ -276,6 +276,8 @@ again:
VREF(p2->p_textvp);
p2->p_fd = fdcopy(p1);
p2->p_cwdi = cwdinit(p1);
/*
* If p_limit is still copy-on-write, bump refcnt,
* otherwise get a copy that won't be modified.

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_sig.c,v 1.87 1999/03/24 05:51:23 mrg Exp $ */
/* $NetBSD: kern_sig.c,v 1.88 1999/04/30 18:43:00 thorpej Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1991, 1993
@ -1205,7 +1205,7 @@ coredump(p)
* sure that the directory is still there and that the mount flags
* allow us to write core dumps there.
*/
vp = p->p_fd->fd_cdir;
vp = p->p_cwdi->cwdi_cdir;
if (vp->v_mount == NULL ||
(vp->v_mount->mnt_flag & MNT_NOCOREDUMP) != 0)
return (EPERM);

View File

@ -1,4 +1,4 @@
/* $NetBSD: uipc_usrreq.c,v 1.41 1999/04/21 02:37:07 mrg Exp $ */
/* $NetBSD: uipc_usrreq.c,v 1.42 1999/04/30 18:43:00 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -810,7 +810,7 @@ unp_externalize(rights)
int f, error = 0;
/* Make sure the recipient should be able to see the descriptors.. */
if (p->p_fd->fd_rdir != NULL) {
if (p->p_cwdi->cwdi_rdir != NULL) {
rp = (struct file **)ALIGN(cm + 1);
for (i = 0; i < nfds; i++) {
fp = *rp++;
@ -823,7 +823,7 @@ unp_externalize(rights)
if (fp->f_type == DTYPE_VNODE) {
struct vnode *vp = (struct vnode *)fp->f_data;
if ((vp->v_type == VDIR) &&
!vn_isunder(vp, p->p_fd->fd_rdir, p)) {
!vn_isunder(vp, p->p_cwdi->cwdi_rdir, p)) {
error = EPERM;
break;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: vfs_getcwd.c,v 1.5 1999/04/26 20:33:18 is Exp $ */
/* $NetBSD: vfs_getcwd.c,v 1.6 1999/04/30 18:43:00 thorpej Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -320,13 +320,13 @@ static int getcwd_common (dvp, rvp, bpp, bufp, limit, flags, p)
int flags;
struct proc *p;
{
struct filedesc *fdp = p->p_fd;
struct cwdinfo *cwdi = p->p_cwdi;
struct vnode *pvp = NULL;
char *bp = NULL;
int error;
if (rvp == NULL) {
rvp = fdp->fd_rdir;
rvp = cwdi->cwdi_rdir;
if (rvp == NULL)
rvp = rootvnode;
}
@ -470,8 +470,8 @@ int proc_isunder (p1, p2)
struct proc *p1;
struct proc *p2;
{
struct vnode *r1 = p1->p_fd->fd_rdir;
struct vnode *r2 = p2->p_fd->fd_rdir;
struct vnode *r1 = p1->p_cwdi->cwdi_rdir;
struct vnode *r2 = p2->p_cwdi->cwdi_rdir;
if (r1 == NULL)
return (r2 == NULL);
@ -509,7 +509,7 @@ int sys___getcwd(p, v, retval)
bend = bp;
*(--bp) = '\0';
error = getcwd_common (p->p_fd->fd_cdir, NULL, &bp, path, len/2,
error = getcwd_common (p->p_cwdi->cwdi_cdir, NULL, &bp, path, len/2,
GETCWD_CHECK_ACCESS, p);
if (error)
@ -552,7 +552,7 @@ sys___getcwd(p, v, retval)
syscallarg(size_t) length;
} */ *uap = v;
struct filedesc *fdp = p->p_fd;
struct cwdinfo *cwdi = p->p_cwdi;
struct vnode *cvp = NULL, *pvp = NULL, *rootvp = NULL;
int error;
char *path;
@ -571,11 +571,11 @@ sys___getcwd(p, v, retval)
bend = bp;
*(--bp) = '\0';
rootvp = fdp->fd_rdir;
rootvp = cwdi->cwdi_rdir;
if (rootvp == NULL)
rootvp = rootvnode;
cvp = fdp->fd_cdir;
cvp = cwdi->cwdi_cdir;
VREF(rootvp);
VREF(cvp);

View File

@ -1,4 +1,4 @@
/* $NetBSD: vfs_lookup.c,v 1.29 1999/04/07 05:47:37 wrstuden Exp $ */
/* $NetBSD: vfs_lookup.c,v 1.30 1999/04/30 18:43:00 thorpej Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -82,7 +82,7 @@ int
namei(ndp)
register struct nameidata *ndp;
{
register struct filedesc *fdp; /* pointer to file descriptor state */
struct cwdinfo *cwdi; /* pointer to cwd state */
register char *cp; /* pointer into pathname argument */
register struct vnode *dp; /* the directory we are searching */
struct iovec aiov; /* uio for reading symbolic links */
@ -99,7 +99,7 @@ namei(ndp)
if (cnp->cn_flags & OPMASK)
panic ("namei: flags contaminated with nameiops");
#endif
fdp = cnp->cn_proc->p_fd;
cwdi = cnp->cn_proc->p_cwdi;
/*
* Get a buffer for the name to be translated, and copy the
@ -135,7 +135,7 @@ namei(ndp)
/*
* Get starting point for the translation.
*/
if ((ndp->ni_rootdir = fdp->fd_rdir) == NULL)
if ((ndp->ni_rootdir = cwdi->cwdi_rdir) == NULL)
ndp->ni_rootdir = rootvnode;
/*
* Check if starting from root directory or current directory.
@ -144,7 +144,7 @@ namei(ndp)
dp = ndp->ni_rootdir;
VREF(dp);
} else {
dp = fdp->fd_cdir;
dp = cwdi->cwdi_cdir;
VREF(dp);
}
for (;;) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: vfs_syscalls.c,v 1.133 1999/03/31 19:18:45 mycroft Exp $ */
/* $NetBSD: vfs_syscalls.c,v 1.134 1999/04/30 18:43:01 thorpej Exp $ */
/*
* Copyright (c) 1989, 1993
@ -353,7 +353,7 @@ void
checkdirs(olddp)
struct vnode *olddp;
{
struct filedesc *fdp;
struct cwdinfo *cwdi;
struct vnode *newdp;
struct proc *p;
@ -362,16 +362,16 @@ checkdirs(olddp)
if (VFS_ROOT(olddp->v_mountedhere, &newdp))
panic("mount: lost mount");
for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
fdp = p->p_fd;
if (fdp->fd_cdir == olddp) {
vrele(fdp->fd_cdir);
cwdi = p->p_cwdi;
if (cwdi->cwdi_cdir == olddp) {
vrele(cwdi->cwdi_cdir);
VREF(newdp);
fdp->fd_cdir = newdp;
cwdi->cwdi_cdir = newdp;
}
if (fdp->fd_rdir == olddp) {
vrele(fdp->fd_rdir);
if (cwdi->cwdi_rdir == olddp) {
vrele(cwdi->cwdi_rdir);
VREF(newdp);
fdp->fd_rdir = newdp;
cwdi->cwdi_rdir = newdp;
}
}
if (rootvnode == olddp) {
@ -703,7 +703,8 @@ sys_fchdir(p, v, retval)
struct sys_fchdir_args /* {
syscallarg(int) fd;
} */ *uap = v;
register struct filedesc *fdp = p->p_fd;
struct filedesc *fdp = p->p_fd;
struct cwdinfo *cwdi = p->p_cwdi;
struct vnode *vp, *tdp;
struct mount *mp;
struct file *fp;
@ -739,14 +740,14 @@ sys_fchdir(p, v, retval)
* Disallow changing to a directory not under the process's
* current root directory (if there is one).
*/
if (fdp->fd_rdir &&
if (cwdi->cwdi_rdir &&
!vn_isunder(vp, NULL, p)) {
vrele(vp);
return EPERM; /* operation not permitted */
}
vrele(fdp->fd_cdir);
fdp->fd_cdir = vp;
vrele(cwdi->cwdi_cdir);
cwdi->cwdi_cdir = vp;
return (0);
}
@ -761,7 +762,8 @@ sys_fchroot(p, v, retval)
register_t *retval;
{
struct sys_fchroot_args *uap = v;
struct filedesc *fdp = p->p_fd;
struct filedesc *fdp = p->p_fd;
struct cwdinfo *cwdi = p->p_cwdi;
struct vnode *vp;
struct file *fp;
int error;
@ -786,19 +788,19 @@ sys_fchroot(p, v, retval)
* the working directory. Silently chdir to / if we aren't
* already there.
*/
if (!vn_isunder(fdp->fd_cdir, vp, p)) {
if (!vn_isunder(cwdi->cwdi_cdir, vp, p)) {
/*
* XXX would be more failsafe to change directory to a
* deadfs node here instead
*/
vrele(fdp->fd_cdir);
vrele(cwdi->cwdi_cdir);
VREF(vp);
fdp->fd_cdir = vp;
cwdi->cwdi_cdir = vp;
}
if (fdp->fd_rdir != NULL)
vrele(fdp->fd_rdir);
fdp->fd_rdir = vp;
if (cwdi->cwdi_rdir != NULL)
vrele(cwdi->cwdi_rdir);
cwdi->cwdi_rdir = vp;
return 0;
}
@ -817,7 +819,7 @@ sys_chdir(p, v, retval)
struct sys_chdir_args /* {
syscallarg(const char *) path;
} */ *uap = v;
register struct filedesc *fdp = p->p_fd;
struct cwdinfo *cwdi = p->p_cwdi;
int error;
struct nameidata nd;
@ -825,8 +827,8 @@ sys_chdir(p, v, retval)
SCARG(uap, path), p);
if ((error = change_dir(&nd, p)) != 0)
return (error);
vrele(fdp->fd_cdir);
fdp->fd_cdir = nd.ni_vp;
vrele(cwdi->cwdi_cdir);
cwdi->cwdi_cdir = nd.ni_vp;
return (0);
}
@ -843,7 +845,7 @@ sys_chroot(p, v, retval)
struct sys_chroot_args /* {
syscallarg(const char *) path;
} */ *uap = v;
register struct filedesc *fdp = p->p_fd;
struct cwdinfo *cwdi = p->p_cwdi;
struct vnode *vp;
int error;
struct nameidata nd;
@ -854,24 +856,24 @@ sys_chroot(p, v, retval)
SCARG(uap, path), p);
if ((error = change_dir(&nd, p)) != 0)
return (error);
if (fdp->fd_rdir != NULL)
vrele(fdp->fd_rdir);
if (cwdi->cwdi_rdir != NULL)
vrele(cwdi->cwdi_rdir);
vp = nd.ni_vp;
fdp->fd_rdir = vp;
cwdi->cwdi_rdir = vp;
/*
* Prevent escaping from chroot by putting the root under
* the working directory. Silently chdir to / if we aren't
* already there.
*/
if (!vn_isunder(fdp->fd_cdir, vp, p)) {
if (!vn_isunder(cwdi->cwdi_cdir, vp, p)) {
/*
* XXX would be more failsafe to change directory to a
* deadfs node here instead
*/
vrele(fdp->fd_cdir);
vrele(cwdi->cwdi_cdir);
VREF(vp);
fdp->fd_cdir = vp;
cwdi->cwdi_cdir = vp;
}
return (0);
@ -918,6 +920,7 @@ sys_open(p, v, retval)
syscallarg(int) flags;
syscallarg(int) mode;
} */ *uap = v;
struct cwdinfo *cwdi = p->p_cwdi;
register struct filedesc *fdp = p->p_fd;
register struct file *fp;
register struct vnode *vp;
@ -934,7 +937,7 @@ sys_open(p, v, retval)
if ((error = falloc(p, &nfp, &indx)) != 0)
return (error);
fp = nfp;
cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
cmode = ((SCARG(uap, mode) &~ cwdi->cwdi_cmask) & ALLPERMS) &~ S_ISTXT;
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
p->p_dupfd = -indx - 1; /* XXX check for fdopen */
if ((error = vn_open(&nd, flags, cmode)) != 0) {
@ -1016,7 +1019,7 @@ sys_mknod(p, v, retval)
else {
VATTR_NULL(&vattr);
vattr.va_mode =
(SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
(SCARG(uap, mode) & ALLPERMS) &~ p->p_cwdi->cwdi_cmask;
vattr.va_rdev = SCARG(uap, dev);
whiteout = 0;
@ -1093,7 +1096,7 @@ sys_mkfifo(p, v, retval)
}
VATTR_NULL(&vattr);
vattr.va_type = VFIFO;
vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_cwdi->cwdi_cmask;
VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
}
@ -1178,7 +1181,7 @@ sys_symlink(p, v, retval)
goto out;
}
VATTR_NULL(&vattr);
vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
vattr.va_mode = ACCESSPERMS &~ p->p_cwdi->cwdi_cmask;
VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
out:
@ -2472,7 +2475,8 @@ sys_mkdir(p, v, retval)
}
VATTR_NULL(&vattr);
vattr.va_type = VDIR;
vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
vattr.va_mode =
(SCARG(uap, mode) & ACCESSPERMS) &~ p->p_cwdi->cwdi_cmask;
VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
if (!error)
@ -2573,11 +2577,11 @@ sys_umask(p, v, retval)
struct sys_umask_args /* {
syscallarg(mode_t) newmask;
} */ *uap = v;
register struct filedesc *fdp;
struct cwdinfo *cwdi;
fdp = p->p_fd;
*retval = fdp->fd_cmask;
fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
cwdi = p->p_cwdi;
*retval = cwdi->cwdi_cmask;
cwdi->cwdi_cmask = SCARG(uap, newmask) & ALLPERMS;
return (0);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: filedesc.h,v 1.16 1998/01/05 04:51:15 thorpej Exp $ */
/* $NetBSD: filedesc.h,v 1.17 1999/04/30 18:42:58 thorpej Exp $ */
/*
* Copyright (c) 1990, 1993
@ -58,15 +58,20 @@
struct filedesc {
struct file **fd_ofiles; /* file structures for open files */
char *fd_ofileflags; /* per-process open file flags */
struct vnode *fd_cdir; /* current directory */
struct vnode *fd_rdir; /* root directory */
int fd_nfiles; /* number of open files allocated */
int fd_lastfile; /* high-water mark of fd_ofiles */
int fd_freefile; /* approx. next free file */
u_short fd_cmask; /* mask for file creation */
u_short fd_refcnt; /* reference count */
int fd_refcnt; /* reference count */
};
struct cwdinfo {
struct vnode *cwdi_cdir; /* current directory */
struct vnode *cwdi_rdir; /* root directory */
u_short cwdi_cmask; /* mask for file creation */
u_short cwdi_refcnt; /* reference count */
};
/*
* Basic allocation of descriptors:
* one of the above, plus arrays for NDFILE descriptors.
@ -112,6 +117,11 @@ void fdfree __P((struct proc *p));
int fdrelease __P((struct proc *p, int));
void fdcloseexec __P((struct proc *));
struct cwdinfo *cwdinit __P((struct proc *));
void cwdshare __P((struct proc *, struct proc *));
void cwdunshare __P((struct proc *));
void cwdfree __P((struct proc *));
int closef __P((struct file *, struct proc *));
int getsock __P((struct filedesc *, int, struct file **));
#endif /* _KERNEL */