Split out cwd/root/jail, cmask state from filedesc table
No functional change intended. Tracking these structures separately for each proc enables future work to correctly emulate clone(2) in linux(4). __FreeBSD_version is bumped (to 1300130) for consumption by, e.g., lsof. Reviewed by: kib Discussed with: markj, mjg Differential Revision: https://reviews.freebsd.org/D27037
This commit is contained in:
parent
ede4af47ae
commit
85078b8573
@ -221,6 +221,7 @@ kvm_proclist(kvm_t *kd, int what, int arg, struct proc *p,
|
||||
kp->ki_tracep = proc.p_tracevp;
|
||||
kp->ki_textvp = proc.p_textvp;
|
||||
kp->ki_fd = proc.p_fd;
|
||||
kp->ki_pd = proc.p_pd;
|
||||
kp->ki_vmspace = proc.p_vmspace;
|
||||
if (proc.p_sigacts != NULL) {
|
||||
if (KREAD(kd, (u_long)proc.p_sigacts, &sigacts)) {
|
||||
|
@ -460,6 +460,7 @@ procstat_getfiles_kvm(struct procstat *procstat, struct kinfo_proc *kp, int mmap
|
||||
{
|
||||
struct file file;
|
||||
struct filedesc filed;
|
||||
struct pwddesc pathsd;
|
||||
struct fdescenttbl *fdt;
|
||||
struct pwd pwd;
|
||||
unsigned long pwd_addr;
|
||||
@ -484,15 +485,20 @@ procstat_getfiles_kvm(struct procstat *procstat, struct kinfo_proc *kp, int mmap
|
||||
kd = procstat->kd;
|
||||
if (kd == NULL)
|
||||
return (NULL);
|
||||
if (kp->ki_fd == NULL)
|
||||
if (kp->ki_fd == NULL || kp->ki_pd == NULL)
|
||||
return (NULL);
|
||||
if (!kvm_read_all(kd, (unsigned long)kp->ki_fd, &filed,
|
||||
sizeof(filed))) {
|
||||
warnx("can't read filedesc at %p", (void *)kp->ki_fd);
|
||||
return (NULL);
|
||||
}
|
||||
if (!kvm_read_all(kd, (unsigned long)kp->ki_pd, &pathsd,
|
||||
sizeof(pathsd))) {
|
||||
warnx("can't read pwddesc at %p", (void *)kp->ki_pd);
|
||||
return (NULL);
|
||||
}
|
||||
haspwd = false;
|
||||
pwd_addr = (unsigned long)(FILEDESC_KVM_LOAD_PWD(&filed));
|
||||
pwd_addr = (unsigned long)(PWDDESC_KVM_LOAD_PWD(&pathsd));
|
||||
if (pwd_addr != 0) {
|
||||
if (!kvm_read_all(kd, pwd_addr, &pwd, sizeof(pwd))) {
|
||||
warnx("can't read fd_pwd at %p", (void *)pwd_addr);
|
||||
@ -2086,18 +2092,18 @@ procstat_freegroups(struct procstat *procstat __unused, gid_t *groups)
|
||||
static int
|
||||
procstat_getumask_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned short *maskp)
|
||||
{
|
||||
struct filedesc fd;
|
||||
struct pwddesc pd;
|
||||
|
||||
assert(kd != NULL);
|
||||
assert(kp != NULL);
|
||||
if (kp->ki_fd == NULL)
|
||||
if (kp->ki_pd == NULL)
|
||||
return (-1);
|
||||
if (!kvm_read_all(kd, (unsigned long)kp->ki_fd, &fd, sizeof(fd))) {
|
||||
warnx("can't read filedesc at %p for pid %d", kp->ki_fd,
|
||||
if (!kvm_read_all(kd, (unsigned long)kp->ki_pd, &pd, sizeof(pd))) {
|
||||
warnx("can't read pwddesc at %p for pid %d", kp->ki_pd,
|
||||
kp->ki_pid);
|
||||
return (-1);
|
||||
}
|
||||
*maskp = fd.fd_cmask;
|
||||
*maskp = pd.pd_cmask;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -265,7 +265,7 @@ cloudabi_sys_file_open(struct thread *td,
|
||||
}
|
||||
NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, uap->dirfd.fd,
|
||||
&rights, td);
|
||||
error = vn_open(&nd, &fflags, 0777 & ~td->td_proc->p_fd->fd_cmask, fp);
|
||||
error = vn_open(&nd, &fflags, 0777 & ~td->td_proc->p_pd->pd_cmask, fp);
|
||||
cloudabi_freestr(path);
|
||||
if (error != 0) {
|
||||
/* Custom operations provided. */
|
||||
|
@ -497,7 +497,7 @@ fuse_internal_mknod(struct vnode *dvp, struct vnode **vpp,
|
||||
fmni.rdev = vap->va_rdev;
|
||||
if (fuse_libabi_geq(data, 7, 12)) {
|
||||
insize = sizeof(fmni);
|
||||
fmni.umask = curthread->td_proc->p_fd->fd_cmask;
|
||||
fmni.umask = curthread->td_proc->p_pd->pd_cmask;
|
||||
} else {
|
||||
insize = FUSE_COMPAT_MKNOD_IN_SIZE;
|
||||
}
|
||||
|
@ -668,7 +668,7 @@ fuse_vnop_create(struct vop_create_args *ap)
|
||||
fci->flags = O_CREAT | flags;
|
||||
if (fuse_libabi_geq(data, 7, 12)) {
|
||||
insize = sizeof(*fci);
|
||||
fci->umask = td->td_proc->p_fd->fd_cmask;
|
||||
fci->umask = td->td_proc->p_pd->pd_cmask;
|
||||
} else {
|
||||
insize = sizeof(struct fuse_open_in);
|
||||
}
|
||||
@ -1269,7 +1269,7 @@ fuse_vnop_mkdir(struct vop_mkdir_args *ap)
|
||||
return ENXIO;
|
||||
}
|
||||
fmdi.mode = MAKEIMODE(vap->va_type, vap->va_mode);
|
||||
fmdi.umask = curthread->td_proc->p_fd->fd_cmask;
|
||||
fmdi.umask = curthread->td_proc->p_pd->pd_cmask;
|
||||
|
||||
return (fuse_internal_newentry(dvp, vpp, cnp, FUSE_MKDIR, &fmdi,
|
||||
sizeof(fmdi), VDIR));
|
||||
|
@ -486,7 +486,7 @@ unionfs_create_uppervattr_core(struct unionfs_mount *ump,
|
||||
}
|
||||
break;
|
||||
default: /* UNIONFS_TRADITIONAL */
|
||||
uva->va_mode = 0777 & ~td->td_proc->p_fd->fd_cmask;
|
||||
uva->va_mode = 0777 & ~td->td_proc->p_pd->pd_cmask;
|
||||
uva->va_uid = ump->um_uid;
|
||||
uva->va_gid = ump->um_gid;
|
||||
break;
|
||||
|
@ -2507,12 +2507,12 @@ note_procstat_umask(void *arg, struct sbuf *sb, size_t *sizep)
|
||||
int structsize;
|
||||
|
||||
p = (struct proc *)arg;
|
||||
size = sizeof(structsize) + sizeof(p->p_fd->fd_cmask);
|
||||
size = sizeof(structsize) + sizeof(p->p_pd->pd_cmask);
|
||||
if (sb != NULL) {
|
||||
KASSERT(*sizep == size, ("invalid size"));
|
||||
structsize = sizeof(p->p_fd->fd_cmask);
|
||||
structsize = sizeof(p->p_pd->pd_cmask);
|
||||
sbuf_bcat(sb, &structsize, sizeof(structsize));
|
||||
sbuf_bcat(sb, &p->p_fd->fd_cmask, sizeof(p->p_fd->fd_cmask));
|
||||
sbuf_bcat(sb, &p->p_pd->pd_cmask, sizeof(p->p_pd->pd_cmask));
|
||||
}
|
||||
*sizep = size;
|
||||
}
|
||||
|
@ -555,6 +555,7 @@ proc0_init(void *dummy __unused)
|
||||
siginit(&proc0);
|
||||
|
||||
/* Create the file descriptor table. */
|
||||
p->p_pd = pdinit(NULL, false);
|
||||
p->p_fd = fdinit(NULL, false, NULL);
|
||||
p->p_fdtol = NULL;
|
||||
|
||||
|
@ -93,6 +93,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
static MALLOC_DEFINE(M_FILEDESC, "filedesc", "Open file descriptor table");
|
||||
static MALLOC_DEFINE(M_PWD, "pwd", "Descriptor table vnodes");
|
||||
static MALLOC_DEFINE(M_PWDDESC, "pwddesc", "Pwd descriptors");
|
||||
static MALLOC_DEFINE(M_FILEDESC_TO_LEADER, "filedesc_to_leader",
|
||||
"file desc to leader structures");
|
||||
static MALLOC_DEFINE(M_SIGIO, "sigio", "sigio structures");
|
||||
@ -2029,7 +2030,6 @@ finstall(struct thread *td, struct file *fp, int *fd, int flags,
|
||||
|
||||
/*
|
||||
* Build a new filedesc structure from another.
|
||||
* Copy the current, root, and jail root vnode references.
|
||||
*
|
||||
* If fdp is not NULL, return with it shared locked.
|
||||
*/
|
||||
@ -2038,7 +2038,6 @@ fdinit(struct filedesc *fdp, bool prepfiles, int *lastfile)
|
||||
{
|
||||
struct filedesc0 *newfdp0;
|
||||
struct filedesc *newfdp;
|
||||
struct pwd *newpwd;
|
||||
|
||||
if (prepfiles)
|
||||
MPASS(lastfile != NULL);
|
||||
@ -2052,20 +2051,14 @@ fdinit(struct filedesc *fdp, bool prepfiles, int *lastfile)
|
||||
FILEDESC_LOCK_INIT(newfdp);
|
||||
refcount_init(&newfdp->fd_refcnt, 1);
|
||||
refcount_init(&newfdp->fd_holdcnt, 1);
|
||||
newfdp->fd_cmask = CMASK;
|
||||
newfdp->fd_map = newfdp0->fd_dmap;
|
||||
newfdp->fd_files = (struct fdescenttbl *)&newfdp0->fd_dfiles;
|
||||
newfdp->fd_files->fdt_nfiles = NDFILE;
|
||||
|
||||
if (fdp == NULL) {
|
||||
newpwd = pwd_alloc();
|
||||
smr_serialized_store(&newfdp->fd_pwd, newpwd, true);
|
||||
if (fdp == NULL)
|
||||
return (newfdp);
|
||||
}
|
||||
|
||||
FILEDESC_SLOCK(fdp);
|
||||
newpwd = pwd_hold_filedesc(fdp);
|
||||
smr_serialized_store(&newfdp->fd_pwd, newpwd, true);
|
||||
if (!prepfiles) {
|
||||
FILEDESC_SUNLOCK(fdp);
|
||||
return (newfdp);
|
||||
@ -2083,6 +2076,38 @@ fdinit(struct filedesc *fdp, bool prepfiles, int *lastfile)
|
||||
return (newfdp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Build a pwddesc structure from another.
|
||||
* Copy the current, root, and jail root vnode references.
|
||||
*
|
||||
* If pdp is not NULL, return with it shared locked.
|
||||
*/
|
||||
struct pwddesc *
|
||||
pdinit(struct pwddesc *pdp, bool keeplock)
|
||||
{
|
||||
struct pwddesc *newpdp;
|
||||
struct pwd *newpwd;
|
||||
|
||||
newpdp = malloc(sizeof(*newpdp), M_PWDDESC, M_WAITOK | M_ZERO);
|
||||
|
||||
PWDDESC_LOCK_INIT(newpdp);
|
||||
refcount_init(&newpdp->pd_refcount, 1);
|
||||
newpdp->pd_cmask = CMASK;
|
||||
|
||||
if (pdp == NULL) {
|
||||
newpwd = pwd_alloc();
|
||||
smr_serialized_store(&newpdp->pd_pwd, newpwd, true);
|
||||
return (newpdp);
|
||||
}
|
||||
|
||||
PWDDESC_XLOCK(pdp);
|
||||
newpwd = pwd_hold_pwddesc(pdp);
|
||||
smr_serialized_store(&newpdp->pd_pwd, newpwd, true);
|
||||
if (!keeplock)
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
return (newpdp);
|
||||
}
|
||||
|
||||
static struct filedesc *
|
||||
fdhold(struct proc *p)
|
||||
{
|
||||
@ -2095,6 +2120,18 @@ fdhold(struct proc *p)
|
||||
return (fdp);
|
||||
}
|
||||
|
||||
static struct pwddesc *
|
||||
pdhold(struct proc *p)
|
||||
{
|
||||
struct pwddesc *pdp;
|
||||
|
||||
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||
pdp = p->p_pd;
|
||||
if (pdp != NULL)
|
||||
refcount_acquire(&pdp->pd_refcount);
|
||||
return (pdp);
|
||||
}
|
||||
|
||||
static void
|
||||
fddrop(struct filedesc *fdp)
|
||||
{
|
||||
@ -2108,6 +2145,28 @@ fddrop(struct filedesc *fdp)
|
||||
uma_zfree(filedesc0_zone, fdp);
|
||||
}
|
||||
|
||||
static void
|
||||
pddrop(struct pwddesc *pdp)
|
||||
{
|
||||
struct pwd *pwd;
|
||||
|
||||
if (refcount_release_if_not_last(&pdp->pd_refcount))
|
||||
return;
|
||||
|
||||
PWDDESC_XLOCK(pdp);
|
||||
if (refcount_release(&pdp->pd_refcount) == 0) {
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
return;
|
||||
}
|
||||
pwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
|
||||
pwd_set(pdp, NULL);
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
pwd_drop(pwd);
|
||||
|
||||
PWDDESC_LOCK_DESTROY(pdp);
|
||||
free(pdp, M_PWDDESC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Share a filedesc structure.
|
||||
*/
|
||||
@ -2119,6 +2178,16 @@ fdshare(struct filedesc *fdp)
|
||||
return (fdp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Share a pwddesc structure.
|
||||
*/
|
||||
struct pwddesc *
|
||||
pdshare(struct pwddesc *pdp)
|
||||
{
|
||||
refcount_acquire(&pdp->pd_refcount);
|
||||
return (pdp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unshare a filedesc structure, if necessary by making a copy
|
||||
*/
|
||||
@ -2136,6 +2205,25 @@ fdunshare(struct thread *td)
|
||||
p->p_fd = tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unshare a pwddesc structure.
|
||||
*/
|
||||
void
|
||||
pdunshare(struct thread *td)
|
||||
{
|
||||
struct pwddesc *pdp;
|
||||
struct proc *p;
|
||||
|
||||
p = td->td_proc;
|
||||
/* Not shared. */
|
||||
if (p->p_pd->pd_refcount == 1)
|
||||
return;
|
||||
|
||||
pdp = pdcopy(p->p_pd);
|
||||
pdescfree(td);
|
||||
p->p_pd = pdp;
|
||||
}
|
||||
|
||||
void
|
||||
fdinstall_remapped(struct thread *td, struct filedesc *fdp)
|
||||
{
|
||||
@ -2176,11 +2264,26 @@ fdcopy(struct filedesc *fdp)
|
||||
}
|
||||
if (newfdp->fd_freefile == -1)
|
||||
newfdp->fd_freefile = i;
|
||||
newfdp->fd_cmask = fdp->fd_cmask;
|
||||
FILEDESC_SUNLOCK(fdp);
|
||||
return (newfdp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a pwddesc structure.
|
||||
*/
|
||||
struct pwddesc *
|
||||
pdcopy(struct pwddesc *pdp)
|
||||
{
|
||||
struct pwddesc *newpdp;
|
||||
|
||||
MPASS(pdp != NULL);
|
||||
|
||||
newpdp = pdinit(pdp, true);
|
||||
newpdp->pd_cmask = pdp->pd_cmask;
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
return (newpdp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies a filedesc structure, while remapping all file descriptors
|
||||
* stored inside using a translation table.
|
||||
@ -2232,7 +2335,6 @@ fdcopy_remapped(struct filedesc *fdp, const int *fds, size_t nfds,
|
||||
filecaps_copy(&ofde->fde_caps, &nfde->fde_caps, true);
|
||||
fdused_init(newfdp, i);
|
||||
}
|
||||
newfdp->fd_cmask = fdp->fd_cmask;
|
||||
FILEDESC_SUNLOCK(fdp);
|
||||
*ret = newfdp;
|
||||
return (0);
|
||||
@ -2366,7 +2468,6 @@ fdescfree(struct thread *td)
|
||||
{
|
||||
struct proc *p;
|
||||
struct filedesc *fdp;
|
||||
struct pwd *pwd;
|
||||
|
||||
p = td->td_proc;
|
||||
fdp = p->p_fd;
|
||||
@ -2387,21 +2488,29 @@ fdescfree(struct thread *td)
|
||||
if (refcount_release(&fdp->fd_refcnt) == 0)
|
||||
return;
|
||||
|
||||
FILEDESC_XLOCK(fdp);
|
||||
pwd = FILEDESC_XLOCKED_LOAD_PWD(fdp);
|
||||
pwd_set(fdp, NULL);
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
|
||||
pwd_drop(pwd);
|
||||
|
||||
fdescfree_fds(td, fdp, 1);
|
||||
}
|
||||
|
||||
void
|
||||
pdescfree(struct thread *td)
|
||||
{
|
||||
struct proc *p;
|
||||
struct pwddesc *pdp;
|
||||
|
||||
p = td->td_proc;
|
||||
pdp = p->p_pd;
|
||||
MPASS(pdp != NULL);
|
||||
|
||||
PROC_LOCK(p);
|
||||
p->p_pd = NULL;
|
||||
PROC_UNLOCK(p);
|
||||
|
||||
pddrop(pdp);
|
||||
}
|
||||
|
||||
void
|
||||
fdescfree_remapped(struct filedesc *fdp)
|
||||
{
|
||||
|
||||
pwd_drop(smr_serialized_load(&fdp->fd_pwd, true));
|
||||
fdescfree_fds(curthread, fdp, 0);
|
||||
}
|
||||
|
||||
@ -3452,12 +3561,12 @@ pwd_fill(struct pwd *oldpwd, struct pwd *newpwd)
|
||||
}
|
||||
|
||||
struct pwd *
|
||||
pwd_hold_filedesc(struct filedesc *fdp)
|
||||
pwd_hold_pwddesc(struct pwddesc *pdp)
|
||||
{
|
||||
struct pwd *pwd;
|
||||
|
||||
FILEDESC_LOCK_ASSERT(fdp);
|
||||
pwd = FILEDESC_LOCKED_LOAD_PWD(fdp);
|
||||
PWDDESC_ASSERT_XLOCKED(pdp);
|
||||
pwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
|
||||
if (pwd != NULL)
|
||||
refcount_acquire(&pwd->pwd_refcount);
|
||||
return (pwd);
|
||||
@ -3477,22 +3586,22 @@ pwd_hold_smr(struct pwd *pwd)
|
||||
struct pwd *
|
||||
pwd_hold(struct thread *td)
|
||||
{
|
||||
struct filedesc *fdp;
|
||||
struct pwddesc *pdp;
|
||||
struct pwd *pwd;
|
||||
|
||||
fdp = td->td_proc->p_fd;
|
||||
pdp = td->td_proc->p_pd;
|
||||
|
||||
vfs_smr_enter();
|
||||
pwd = vfs_smr_entered_load(&fdp->fd_pwd);
|
||||
pwd = vfs_smr_entered_load(&pdp->pd_pwd);
|
||||
if (pwd_hold_smr(pwd)) {
|
||||
vfs_smr_exit();
|
||||
return (pwd);
|
||||
}
|
||||
vfs_smr_exit();
|
||||
FILEDESC_SLOCK(fdp);
|
||||
pwd = pwd_hold_filedesc(fdp);
|
||||
PWDDESC_XLOCK(pdp);
|
||||
pwd = pwd_hold_pwddesc(pdp);
|
||||
MPASS(pwd != NULL);
|
||||
FILEDESC_SUNLOCK(fdp);
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
return (pwd);
|
||||
}
|
||||
|
||||
@ -3501,7 +3610,7 @@ pwd_get_smr(void)
|
||||
{
|
||||
struct pwd *pwd;
|
||||
|
||||
pwd = vfs_smr_entered_load(&curproc->p_fd->fd_pwd);
|
||||
pwd = vfs_smr_entered_load(&curproc->p_pd->pd_pwd);
|
||||
MPASS(pwd != NULL);
|
||||
return (pwd);
|
||||
}
|
||||
@ -3541,23 +3650,29 @@ pwd_drop(struct pwd *pwd)
|
||||
int
|
||||
pwd_chroot(struct thread *td, struct vnode *vp)
|
||||
{
|
||||
struct pwddesc *pdp;
|
||||
struct filedesc *fdp;
|
||||
struct pwd *newpwd, *oldpwd;
|
||||
int error;
|
||||
|
||||
fdp = td->td_proc->p_fd;
|
||||
pdp = td->td_proc->p_pd;
|
||||
newpwd = pwd_alloc();
|
||||
FILEDESC_XLOCK(fdp);
|
||||
oldpwd = FILEDESC_XLOCKED_LOAD_PWD(fdp);
|
||||
FILEDESC_SLOCK(fdp);
|
||||
PWDDESC_XLOCK(pdp);
|
||||
oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
|
||||
if (chroot_allow_open_directories == 0 ||
|
||||
(chroot_allow_open_directories == 1 &&
|
||||
oldpwd->pwd_rdir != rootvnode)) {
|
||||
error = chroot_refuse_vdir_fds(fdp);
|
||||
FILEDESC_SUNLOCK(fdp);
|
||||
if (error != 0) {
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
pwd_drop(newpwd);
|
||||
return (error);
|
||||
}
|
||||
} else {
|
||||
FILEDESC_SUNLOCK(fdp);
|
||||
}
|
||||
|
||||
vrefact(vp);
|
||||
@ -3567,8 +3682,8 @@ pwd_chroot(struct thread *td, struct vnode *vp)
|
||||
newpwd->pwd_jdir = vp;
|
||||
}
|
||||
pwd_fill(oldpwd, newpwd);
|
||||
pwd_set(fdp, newpwd);
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
pwd_set(pdp, newpwd);
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
pwd_drop(oldpwd);
|
||||
return (0);
|
||||
}
|
||||
@ -3576,40 +3691,40 @@ pwd_chroot(struct thread *td, struct vnode *vp)
|
||||
void
|
||||
pwd_chdir(struct thread *td, struct vnode *vp)
|
||||
{
|
||||
struct filedesc *fdp;
|
||||
struct pwddesc *pdp;
|
||||
struct pwd *newpwd, *oldpwd;
|
||||
|
||||
VNPASS(vp->v_usecount > 0, vp);
|
||||
|
||||
newpwd = pwd_alloc();
|
||||
fdp = td->td_proc->p_fd;
|
||||
FILEDESC_XLOCK(fdp);
|
||||
oldpwd = FILEDESC_XLOCKED_LOAD_PWD(fdp);
|
||||
pdp = td->td_proc->p_pd;
|
||||
PWDDESC_XLOCK(pdp);
|
||||
oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
|
||||
newpwd->pwd_cdir = vp;
|
||||
pwd_fill(oldpwd, newpwd);
|
||||
pwd_set(fdp, newpwd);
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
pwd_set(pdp, newpwd);
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
pwd_drop(oldpwd);
|
||||
}
|
||||
|
||||
void
|
||||
pwd_ensure_dirs(void)
|
||||
{
|
||||
struct filedesc *fdp;
|
||||
struct pwddesc *pdp;
|
||||
struct pwd *oldpwd, *newpwd;
|
||||
|
||||
fdp = curproc->p_fd;
|
||||
FILEDESC_XLOCK(fdp);
|
||||
oldpwd = FILEDESC_XLOCKED_LOAD_PWD(fdp);
|
||||
pdp = curproc->p_pd;
|
||||
PWDDESC_XLOCK(pdp);
|
||||
oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
|
||||
if (oldpwd->pwd_cdir != NULL && oldpwd->pwd_rdir != NULL) {
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
return;
|
||||
}
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
|
||||
newpwd = pwd_alloc();
|
||||
FILEDESC_XLOCK(fdp);
|
||||
oldpwd = FILEDESC_XLOCKED_LOAD_PWD(fdp);
|
||||
PWDDESC_XLOCK(pdp);
|
||||
oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
|
||||
pwd_fill(oldpwd, newpwd);
|
||||
if (newpwd->pwd_cdir == NULL) {
|
||||
vrefact(rootvnode);
|
||||
@ -3619,29 +3734,29 @@ pwd_ensure_dirs(void)
|
||||
vrefact(rootvnode);
|
||||
newpwd->pwd_rdir = rootvnode;
|
||||
}
|
||||
pwd_set(fdp, newpwd);
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
pwd_set(pdp, newpwd);
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
pwd_drop(oldpwd);
|
||||
}
|
||||
|
||||
void
|
||||
pwd_set_rootvnode(void)
|
||||
{
|
||||
struct filedesc *fdp;
|
||||
struct pwddesc *pdp;
|
||||
struct pwd *oldpwd, *newpwd;
|
||||
|
||||
fdp = curproc->p_fd;
|
||||
pdp = curproc->p_pd;
|
||||
|
||||
newpwd = pwd_alloc();
|
||||
FILEDESC_XLOCK(fdp);
|
||||
oldpwd = FILEDESC_XLOCKED_LOAD_PWD(fdp);
|
||||
PWDDESC_XLOCK(pdp);
|
||||
oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
|
||||
vrefact(rootvnode);
|
||||
newpwd->pwd_cdir = rootvnode;
|
||||
vrefact(rootvnode);
|
||||
newpwd->pwd_rdir = rootvnode;
|
||||
pwd_fill(oldpwd, newpwd);
|
||||
pwd_set(fdp, newpwd);
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
pwd_set(pdp, newpwd);
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
pwd_drop(oldpwd);
|
||||
}
|
||||
|
||||
@ -3652,7 +3767,7 @@ pwd_set_rootvnode(void)
|
||||
void
|
||||
mountcheckdirs(struct vnode *olddp, struct vnode *newdp)
|
||||
{
|
||||
struct filedesc *fdp;
|
||||
struct pwddesc *pdp;
|
||||
struct pwd *newpwd, *oldpwd;
|
||||
struct prison *pr;
|
||||
struct proc *p;
|
||||
@ -3665,18 +3780,18 @@ mountcheckdirs(struct vnode *olddp, struct vnode *newdp)
|
||||
sx_slock(&allproc_lock);
|
||||
FOREACH_PROC_IN_SYSTEM(p) {
|
||||
PROC_LOCK(p);
|
||||
fdp = fdhold(p);
|
||||
pdp = pdhold(p);
|
||||
PROC_UNLOCK(p);
|
||||
if (fdp == NULL)
|
||||
if (pdp == NULL)
|
||||
continue;
|
||||
FILEDESC_XLOCK(fdp);
|
||||
oldpwd = FILEDESC_XLOCKED_LOAD_PWD(fdp);
|
||||
PWDDESC_XLOCK(pdp);
|
||||
oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
|
||||
if (oldpwd == NULL ||
|
||||
(oldpwd->pwd_cdir != olddp &&
|
||||
oldpwd->pwd_rdir != olddp &&
|
||||
oldpwd->pwd_jdir != olddp)) {
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
fddrop(fdp);
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
pddrop(pdp);
|
||||
continue;
|
||||
}
|
||||
if (oldpwd->pwd_cdir == olddp) {
|
||||
@ -3692,10 +3807,10 @@ mountcheckdirs(struct vnode *olddp, struct vnode *newdp)
|
||||
newpwd->pwd_jdir = newdp;
|
||||
}
|
||||
pwd_fill(oldpwd, newpwd);
|
||||
pwd_set(fdp, newpwd);
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
pwd_set(pdp, newpwd);
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
pwd_drop(oldpwd);
|
||||
fddrop(fdp);
|
||||
pddrop(pdp);
|
||||
newpwd = pwd_alloc();
|
||||
}
|
||||
sx_sunlock(&allproc_lock);
|
||||
@ -3968,6 +4083,7 @@ export_vnode_to_kinfo(struct vnode *vp, int fd, int fflags,
|
||||
|
||||
struct export_fd_buf {
|
||||
struct filedesc *fdp;
|
||||
struct pwddesc *pdp;
|
||||
struct sbuf *sb;
|
||||
ssize_t remainder;
|
||||
struct kinfo_file kif;
|
||||
@ -4015,12 +4131,12 @@ export_vnode_to_sb(struct vnode *vp, int fd, int fflags,
|
||||
|
||||
if (efbuf->remainder == 0)
|
||||
return (0);
|
||||
if (efbuf->fdp != NULL)
|
||||
FILEDESC_SUNLOCK(efbuf->fdp);
|
||||
if (efbuf->pdp != NULL)
|
||||
PWDDESC_XUNLOCK(efbuf->pdp);
|
||||
export_vnode_to_kinfo(vp, fd, fflags, &efbuf->kif, efbuf->flags);
|
||||
error = export_kinfo_to_sb(efbuf);
|
||||
if (efbuf->fdp != NULL)
|
||||
FILEDESC_SLOCK(efbuf->fdp);
|
||||
if (efbuf->pdp != NULL)
|
||||
PWDDESC_XLOCK(efbuf->pdp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -4035,6 +4151,7 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen,
|
||||
{
|
||||
struct file *fp;
|
||||
struct filedesc *fdp;
|
||||
struct pwddesc *pdp;
|
||||
struct export_fd_buf *efbuf;
|
||||
struct vnode *cttyvp, *textvp, *tracevp;
|
||||
struct pwd *pwd;
|
||||
@ -4059,9 +4176,11 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen,
|
||||
vrefact(cttyvp);
|
||||
}
|
||||
fdp = fdhold(p);
|
||||
pdp = pdhold(p);
|
||||
PROC_UNLOCK(p);
|
||||
efbuf = malloc(sizeof(*efbuf), M_TEMP, M_WAITOK);
|
||||
efbuf->fdp = NULL;
|
||||
efbuf->pdp = NULL;
|
||||
efbuf->sb = sb;
|
||||
efbuf->remainder = maxlen;
|
||||
efbuf->flags = flags;
|
||||
@ -4074,11 +4193,12 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen,
|
||||
export_vnode_to_sb(cttyvp, KF_FD_TYPE_CTTY, FREAD | FWRITE,
|
||||
efbuf);
|
||||
error = 0;
|
||||
if (fdp == NULL)
|
||||
if (pdp == NULL || fdp == NULL)
|
||||
goto fail;
|
||||
efbuf->fdp = fdp;
|
||||
FILEDESC_SLOCK(fdp);
|
||||
pwd = pwd_hold_filedesc(fdp);
|
||||
efbuf->pdp = pdp;
|
||||
PWDDESC_XLOCK(pdp);
|
||||
pwd = pwd_hold_pwddesc(pdp);
|
||||
if (pwd != NULL) {
|
||||
/* working directory */
|
||||
if (pwd->pwd_cdir != NULL) {
|
||||
@ -4096,6 +4216,10 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen,
|
||||
export_vnode_to_sb(pwd->pwd_jdir, KF_FD_TYPE_JAIL, FREAD, efbuf);
|
||||
}
|
||||
}
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
if (pwd != NULL)
|
||||
pwd_drop(pwd);
|
||||
FILEDESC_SLOCK(fdp);
|
||||
lastfile = fdlastfile(fdp);
|
||||
for (i = 0; fdp->fd_refcnt > 0 && i <= lastfile; i++) {
|
||||
if ((fp = fdp->fd_ofiles[i].fde_file) == NULL)
|
||||
@ -4116,10 +4240,11 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen,
|
||||
break;
|
||||
}
|
||||
FILEDESC_SUNLOCK(fdp);
|
||||
if (pwd != NULL)
|
||||
pwd_drop(pwd);
|
||||
fddrop(fdp);
|
||||
fail:
|
||||
if (fdp != NULL)
|
||||
fddrop(fdp);
|
||||
if (pdp != NULL)
|
||||
pddrop(pdp);
|
||||
free(efbuf, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
@ -4190,16 +4315,16 @@ kinfo_to_okinfo(struct kinfo_file *kif, struct kinfo_ofile *okif)
|
||||
|
||||
static int
|
||||
export_vnode_for_osysctl(struct vnode *vp, int type, struct kinfo_file *kif,
|
||||
struct kinfo_ofile *okif, struct filedesc *fdp, struct sysctl_req *req)
|
||||
struct kinfo_ofile *okif, struct pwddesc *pdp, struct sysctl_req *req)
|
||||
{
|
||||
int error;
|
||||
|
||||
vrefact(vp);
|
||||
FILEDESC_SUNLOCK(fdp);
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
export_vnode_to_kinfo(vp, type, 0, kif, KERN_FILEDESC_PACK_KINFO);
|
||||
kinfo_to_okinfo(kif, okif);
|
||||
error = SYSCTL_OUT(req, okif, sizeof(*okif));
|
||||
FILEDESC_SLOCK(fdp);
|
||||
PWDDESC_XLOCK(pdp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -4212,6 +4337,7 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
|
||||
struct kinfo_ofile *okif;
|
||||
struct kinfo_file *kif;
|
||||
struct filedesc *fdp;
|
||||
struct pwddesc *pdp;
|
||||
struct pwd *pwd;
|
||||
int error, i, lastfile, *name;
|
||||
struct file *fp;
|
||||
@ -4222,24 +4348,33 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
|
||||
if (error != 0)
|
||||
return (error);
|
||||
fdp = fdhold(p);
|
||||
if (fdp != NULL)
|
||||
pdp = pdhold(p);
|
||||
PROC_UNLOCK(p);
|
||||
if (fdp == NULL)
|
||||
if (fdp == NULL || pdp == NULL) {
|
||||
if (fdp != NULL)
|
||||
fddrop(fdp);
|
||||
return (ENOENT);
|
||||
}
|
||||
kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK);
|
||||
okif = malloc(sizeof(*okif), M_TEMP, M_WAITOK);
|
||||
FILEDESC_SLOCK(fdp);
|
||||
pwd = pwd_hold_filedesc(fdp);
|
||||
PWDDESC_XLOCK(pdp);
|
||||
pwd = pwd_hold_pwddesc(pdp);
|
||||
if (pwd != NULL) {
|
||||
if (pwd->pwd_cdir != NULL)
|
||||
export_vnode_for_osysctl(pwd->pwd_cdir, KF_FD_TYPE_CWD, kif,
|
||||
okif, fdp, req);
|
||||
okif, pdp, req);
|
||||
if (pwd->pwd_rdir != NULL)
|
||||
export_vnode_for_osysctl(pwd->pwd_rdir, KF_FD_TYPE_ROOT, kif,
|
||||
okif, fdp, req);
|
||||
okif, pdp, req);
|
||||
if (pwd->pwd_jdir != NULL)
|
||||
export_vnode_for_osysctl(pwd->pwd_jdir, KF_FD_TYPE_JAIL, kif,
|
||||
okif, fdp, req);
|
||||
okif, pdp, req);
|
||||
}
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
if (pwd != NULL)
|
||||
pwd_drop(pwd);
|
||||
FILEDESC_SLOCK(fdp);
|
||||
lastfile = fdlastfile(fdp);
|
||||
for (i = 0; fdp->fd_refcnt > 0 && i <= lastfile; i++) {
|
||||
if ((fp = fdp->fd_ofiles[i].fde_file) == NULL)
|
||||
@ -4254,9 +4389,8 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
|
||||
break;
|
||||
}
|
||||
FILEDESC_SUNLOCK(fdp);
|
||||
if (pwd != NULL)
|
||||
pwd_drop(pwd);
|
||||
fddrop(fdp);
|
||||
pddrop(pdp);
|
||||
free(kif, M_TEMP);
|
||||
free(okif, M_TEMP);
|
||||
return (0);
|
||||
@ -4308,7 +4442,7 @@ static SYSCTL_NODE(_kern_proc, KERN_PROC_FILEDESC, filedesc,
|
||||
int
|
||||
kern_proc_cwd_out(struct proc *p, struct sbuf *sb, ssize_t maxlen)
|
||||
{
|
||||
struct filedesc *fdp;
|
||||
struct pwddesc *pdp;
|
||||
struct pwd *pwd;
|
||||
struct export_fd_buf *efbuf;
|
||||
struct vnode *cdir;
|
||||
@ -4316,18 +4450,18 @@ kern_proc_cwd_out(struct proc *p, struct sbuf *sb, ssize_t maxlen)
|
||||
|
||||
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||
|
||||
fdp = fdhold(p);
|
||||
pdp = pdhold(p);
|
||||
PROC_UNLOCK(p);
|
||||
if (fdp == NULL)
|
||||
if (pdp == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
efbuf = malloc(sizeof(*efbuf), M_TEMP, M_WAITOK);
|
||||
efbuf->fdp = fdp;
|
||||
efbuf->pdp = pdp;
|
||||
efbuf->sb = sb;
|
||||
efbuf->remainder = maxlen;
|
||||
|
||||
FILEDESC_SLOCK(fdp);
|
||||
pwd = FILEDESC_LOCKED_LOAD_PWD(fdp);
|
||||
PWDDESC_XLOCK(pdp);
|
||||
pwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
|
||||
cdir = pwd->pwd_cdir;
|
||||
if (cdir == NULL) {
|
||||
error = EINVAL;
|
||||
@ -4335,8 +4469,8 @@ kern_proc_cwd_out(struct proc *p, struct sbuf *sb, ssize_t maxlen)
|
||||
vrefact(cdir);
|
||||
error = export_vnode_to_sb(cdir, KF_FD_TYPE_CWD, FREAD, efbuf);
|
||||
}
|
||||
FILEDESC_SUNLOCK(fdp);
|
||||
fddrop(fdp);
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
pddrop(pdp);
|
||||
free(efbuf, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
|
@ -700,6 +700,7 @@ do_execve(struct thread *td, struct image_args *args, struct mac *mac_p,
|
||||
* cannot be shared after an exec.
|
||||
*/
|
||||
fdunshare(td);
|
||||
pdunshare(td);
|
||||
/* close files on exec */
|
||||
fdcloseexec(td);
|
||||
}
|
||||
|
@ -367,6 +367,7 @@ exit1(struct thread *td, int rval, int signo)
|
||||
* Close open files and release open-file table.
|
||||
* This may block!
|
||||
*/
|
||||
pdescfree(td);
|
||||
fdescfree(td);
|
||||
|
||||
/*
|
||||
|
@ -332,16 +332,22 @@ fork_norfproc(struct thread *td, int flags)
|
||||
*/
|
||||
if (flags & RFCFDG) {
|
||||
struct filedesc *fdtmp;
|
||||
struct pwddesc *pdtmp;
|
||||
pdtmp = pdinit(td->td_proc->p_pd, false);
|
||||
fdtmp = fdinit(td->td_proc->p_fd, false, NULL);
|
||||
pdescfree(td);
|
||||
fdescfree(td);
|
||||
p1->p_fd = fdtmp;
|
||||
p1->p_pd = pdtmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unshare file descriptors (from parent).
|
||||
*/
|
||||
if (flags & RFFDG)
|
||||
if (flags & RFFDG) {
|
||||
fdunshare(td);
|
||||
pdunshare(td);
|
||||
}
|
||||
|
||||
fail:
|
||||
if (((p1->p_flag & (P_HADTHREADS|P_SYSTEM)) == P_HADTHREADS) &&
|
||||
@ -360,6 +366,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *
|
||||
struct proc *p1, *pptr;
|
||||
struct filedesc *fd;
|
||||
struct filedesc_to_leader *fdtol;
|
||||
struct pwddesc *pd;
|
||||
struct sigacts *newsigacts;
|
||||
|
||||
p1 = td->td_proc;
|
||||
@ -403,12 +410,15 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *
|
||||
* Copy filedesc.
|
||||
*/
|
||||
if (fr->fr_flags & RFCFDG) {
|
||||
pd = pdinit(p1->p_pd, false);
|
||||
fd = fdinit(p1->p_fd, false, NULL);
|
||||
fdtol = NULL;
|
||||
} else if (fr->fr_flags & RFFDG) {
|
||||
pd = pdcopy(p1->p_pd);
|
||||
fd = fdcopy(p1->p_fd);
|
||||
fdtol = NULL;
|
||||
} else {
|
||||
pd = pdshare(p1->p_pd);
|
||||
fd = fdshare(p1->p_fd);
|
||||
if (p1->p_fdtol == NULL)
|
||||
p1->p_fdtol = filedesc_to_leader_alloc(NULL, NULL,
|
||||
@ -498,6 +508,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *
|
||||
p2->p_textvp = p1->p_textvp;
|
||||
p2->p_fd = fd;
|
||||
p2->p_fdtol = fdtol;
|
||||
p2->p_pd = pd;
|
||||
|
||||
if (p1->p_flag2 & P2_INHERIT_PROTECTED) {
|
||||
p2->p_flag |= P_PROTECTED;
|
||||
|
@ -1144,6 +1144,7 @@ fill_kinfo_proc_only(struct proc *p, struct kinfo_proc *kp)
|
||||
kp->ki_traceflag = p->p_traceflag;
|
||||
#endif
|
||||
kp->ki_fd = p->p_fd;
|
||||
kp->ki_pd = p->p_pd;
|
||||
kp->ki_vmspace = p->p_vmspace;
|
||||
kp->ki_flag = p->p_flag;
|
||||
kp->ki_flag2 = p->p_flag2;
|
||||
@ -2967,7 +2968,7 @@ sysctl_kern_proc_umask(SYSCTL_HANDLER_ARGS)
|
||||
u_int namelen = arg2;
|
||||
struct proc *p;
|
||||
int error;
|
||||
u_short fd_cmask;
|
||||
u_short cmask;
|
||||
pid_t pid;
|
||||
|
||||
if (namelen != 1)
|
||||
@ -2976,7 +2977,7 @@ sysctl_kern_proc_umask(SYSCTL_HANDLER_ARGS)
|
||||
pid = (pid_t)name[0];
|
||||
p = curproc;
|
||||
if (pid == p->p_pid || pid == 0) {
|
||||
fd_cmask = p->p_fd->fd_cmask;
|
||||
cmask = p->p_pd->pd_cmask;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -2984,10 +2985,10 @@ sysctl_kern_proc_umask(SYSCTL_HANDLER_ARGS)
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
fd_cmask = p->p_fd->fd_cmask;
|
||||
cmask = p->p_pd->pd_cmask;
|
||||
PRELE(p);
|
||||
out:
|
||||
error = SYSCTL_OUT(req, &fd_cmask, sizeof(fd_cmask));
|
||||
error = SYSCTL_OUT(req, &cmask, sizeof(cmask));
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
@ -88,15 +88,15 @@ _Static_assert(offsetof(struct thread, td_frame) == 0x4a0,
|
||||
"struct thread KBI td_frame");
|
||||
_Static_assert(offsetof(struct thread, td_emuldata) == 0x6b0,
|
||||
"struct thread KBI td_emuldata");
|
||||
_Static_assert(offsetof(struct proc, p_flag) == 0xb0,
|
||||
_Static_assert(offsetof(struct proc, p_flag) == 0xb8,
|
||||
"struct proc KBI p_flag");
|
||||
_Static_assert(offsetof(struct proc, p_pid) == 0xbc,
|
||||
_Static_assert(offsetof(struct proc, p_pid) == 0xc4,
|
||||
"struct proc KBI p_pid");
|
||||
_Static_assert(offsetof(struct proc, p_filemon) == 0x3b8,
|
||||
_Static_assert(offsetof(struct proc, p_filemon) == 0x3c0,
|
||||
"struct proc KBI p_filemon");
|
||||
_Static_assert(offsetof(struct proc, p_comm) == 0x3d0,
|
||||
_Static_assert(offsetof(struct proc, p_comm) == 0x3d8,
|
||||
"struct proc KBI p_comm");
|
||||
_Static_assert(offsetof(struct proc, p_emuldata) == 0x4b0,
|
||||
_Static_assert(offsetof(struct proc, p_emuldata) == 0x4b8,
|
||||
"struct proc KBI p_emuldata");
|
||||
#endif
|
||||
#ifdef __i386__
|
||||
@ -108,15 +108,15 @@ _Static_assert(offsetof(struct thread, td_frame) == 0x300,
|
||||
"struct thread KBI td_frame");
|
||||
_Static_assert(offsetof(struct thread, td_emuldata) == 0x344,
|
||||
"struct thread KBI td_emuldata");
|
||||
_Static_assert(offsetof(struct proc, p_flag) == 0x68,
|
||||
_Static_assert(offsetof(struct proc, p_flag) == 0x6c,
|
||||
"struct proc KBI p_flag");
|
||||
_Static_assert(offsetof(struct proc, p_pid) == 0x74,
|
||||
_Static_assert(offsetof(struct proc, p_pid) == 0x78,
|
||||
"struct proc KBI p_pid");
|
||||
_Static_assert(offsetof(struct proc, p_filemon) == 0x268,
|
||||
_Static_assert(offsetof(struct proc, p_filemon) == 0x26c,
|
||||
"struct proc KBI p_filemon");
|
||||
_Static_assert(offsetof(struct proc, p_comm) == 0x27c,
|
||||
_Static_assert(offsetof(struct proc, p_comm) == 0x280,
|
||||
"struct proc KBI p_comm");
|
||||
_Static_assert(offsetof(struct proc, p_emuldata) == 0x308,
|
||||
_Static_assert(offsetof(struct proc, p_emuldata) == 0x30c,
|
||||
"struct proc KBI p_emuldata");
|
||||
#endif
|
||||
|
||||
|
@ -2011,7 +2011,7 @@ kern_kmq_open(struct thread *td, const char *upath, int flags, mode_t mode,
|
||||
{
|
||||
char path[MQFS_NAMELEN + 1];
|
||||
struct mqfs_node *pn;
|
||||
struct filedesc *fdp;
|
||||
struct pwddesc *pdp;
|
||||
struct file *fp;
|
||||
struct mqueue *mq;
|
||||
int fd, error, len, cmode;
|
||||
@ -2019,8 +2019,8 @@ kern_kmq_open(struct thread *td, const char *upath, int flags, mode_t mode,
|
||||
AUDIT_ARG_FFLAGS(flags);
|
||||
AUDIT_ARG_MODE(mode);
|
||||
|
||||
fdp = td->td_proc->p_fd;
|
||||
cmode = (((mode & ~fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT);
|
||||
pdp = td->td_proc->p_pd;
|
||||
cmode = (((mode & ~pdp->pd_cmask) & ALLPERMS) & ~S_ISTXT);
|
||||
mq = NULL;
|
||||
if ((flags & O_CREAT) != 0 && attr != NULL) {
|
||||
if (attr->mq_maxmsg <= 0 || attr->mq_maxmsg > maxmsg)
|
||||
|
@ -465,7 +465,7 @@ static int
|
||||
ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode,
|
||||
unsigned int value, int flags, int compat32)
|
||||
{
|
||||
struct filedesc *fdp;
|
||||
struct pwddesc *pdp;
|
||||
struct ksem *ks;
|
||||
struct file *fp;
|
||||
char *path;
|
||||
@ -481,8 +481,8 @@ ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode,
|
||||
if (value > SEM_VALUE_MAX)
|
||||
return (EINVAL);
|
||||
|
||||
fdp = td->td_proc->p_fd;
|
||||
mode = (mode & ~fdp->fd_cmask) & ACCESSPERMS;
|
||||
pdp = td->td_proc->p_pd;
|
||||
mode = (mode & ~pdp->pd_cmask) & ACCESSPERMS;
|
||||
error = falloc(td, &fp, &fd, O_CLOEXEC);
|
||||
if (error) {
|
||||
if (name == NULL)
|
||||
|
@ -1031,7 +1031,7 @@ int
|
||||
kern_shm_open2(struct thread *td, const char *userpath, int flags, mode_t mode,
|
||||
int shmflags, struct filecaps *fcaps, const char *name __unused)
|
||||
{
|
||||
struct filedesc *fdp;
|
||||
struct pwddesc *pdp;
|
||||
struct shmfd *shmfd;
|
||||
struct file *fp;
|
||||
char *path;
|
||||
@ -1081,8 +1081,8 @@ kern_shm_open2(struct thread *td, const char *userpath, int flags, mode_t mode,
|
||||
if ((initial_seals & ~F_SEAL_SEAL) != 0)
|
||||
return (EINVAL);
|
||||
|
||||
fdp = td->td_proc->p_fd;
|
||||
cmode = (mode & ~fdp->fd_cmask) & ACCESSPERMS;
|
||||
pdp = td->td_proc->p_pd;
|
||||
cmode = (mode & ~pdp->pd_cmask) & ACCESSPERMS;
|
||||
|
||||
/*
|
||||
* shm_open(2) created shm should always have O_CLOEXEC set, as mandated
|
||||
|
@ -660,7 +660,7 @@ uipc_bindat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td)
|
||||
}
|
||||
VATTR_NULL(&vattr);
|
||||
vattr.va_type = VSOCK;
|
||||
vattr.va_mode = (ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask);
|
||||
vattr.va_mode = (ACCESSPERMS & ~td->td_proc->p_pd->pd_cmask);
|
||||
#ifdef MAC
|
||||
error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
|
||||
&vattr);
|
||||
|
@ -1098,7 +1098,8 @@ kern_openat(struct thread *td, int fd, const char *path, enum uio_seg pathseg,
|
||||
int flags, int mode)
|
||||
{
|
||||
struct proc *p = td->td_proc;
|
||||
struct filedesc *fdp = p->p_fd;
|
||||
struct filedesc *fdp;
|
||||
struct pwddesc *pdp;
|
||||
struct file *fp;
|
||||
struct vnode *vp;
|
||||
struct nameidata nd;
|
||||
@ -1106,6 +1107,8 @@ kern_openat(struct thread *td, int fd, const char *path, enum uio_seg pathseg,
|
||||
int cmode, error, indx;
|
||||
|
||||
indx = -1;
|
||||
fdp = p->p_fd;
|
||||
pdp = p->p_pd;
|
||||
|
||||
AUDIT_ARG_FFLAGS(flags);
|
||||
AUDIT_ARG_MODE(mode);
|
||||
@ -1137,7 +1140,7 @@ kern_openat(struct thread *td, int fd, const char *path, enum uio_seg pathseg,
|
||||
*/
|
||||
/* Set the flags early so the finit in devfs can pick them up. */
|
||||
fp->f_flag = flags & FMASK;
|
||||
cmode = ((mode & ~fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT;
|
||||
cmode = ((mode & ~pdp->pd_cmask) & ALLPERMS) & ~S_ISTXT;
|
||||
NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, fd,
|
||||
&rights, td);
|
||||
td->td_dupfd = -1; /* XXX check for fdopen */
|
||||
@ -1339,7 +1342,7 @@ kern_mknodat(struct thread *td, int fd, const char *path, enum uio_seg pathseg,
|
||||
} else {
|
||||
VATTR_NULL(&vattr);
|
||||
vattr.va_mode = (mode & ALLPERMS) &
|
||||
~td->td_proc->p_fd->fd_cmask;
|
||||
~td->td_proc->p_pd->pd_cmask;
|
||||
vattr.va_rdev = dev;
|
||||
whiteout = 0;
|
||||
|
||||
@ -1454,7 +1457,7 @@ kern_mkfifoat(struct thread *td, int fd, const char *path,
|
||||
}
|
||||
VATTR_NULL(&vattr);
|
||||
vattr.va_type = VFIFO;
|
||||
vattr.va_mode = (mode & ALLPERMS) & ~td->td_proc->p_fd->fd_cmask;
|
||||
vattr.va_mode = (mode & ALLPERMS) & ~td->td_proc->p_pd->pd_cmask;
|
||||
#ifdef MAC
|
||||
error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
|
||||
&vattr);
|
||||
@ -1726,7 +1729,7 @@ kern_symlinkat(struct thread *td, const char *path1, int fd, const char *path2,
|
||||
goto restart;
|
||||
}
|
||||
VATTR_NULL(&vattr);
|
||||
vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask;
|
||||
vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_pd->pd_cmask;
|
||||
#ifdef MAC
|
||||
vattr.va_type = VLNK;
|
||||
error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
|
||||
@ -3803,7 +3806,7 @@ kern_mkdirat(struct thread *td, int fd, const char *path, enum uio_seg segflg,
|
||||
}
|
||||
VATTR_NULL(&vattr);
|
||||
vattr.va_type = VDIR;
|
||||
vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask;
|
||||
vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_pd->pd_cmask;
|
||||
#ifdef MAC
|
||||
error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
|
||||
&vattr);
|
||||
@ -4207,13 +4210,13 @@ struct umask_args {
|
||||
int
|
||||
sys_umask(struct thread *td, struct umask_args *uap)
|
||||
{
|
||||
struct filedesc *fdp;
|
||||
struct pwddesc *pdp;
|
||||
|
||||
fdp = td->td_proc->p_fd;
|
||||
FILEDESC_XLOCK(fdp);
|
||||
td->td_retval[0] = fdp->fd_cmask;
|
||||
fdp->fd_cmask = uap->newmask & ALLPERMS;
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
pdp = td->td_proc->p_pd;
|
||||
PWDDESC_XLOCK(pdp);
|
||||
td->td_retval[0] = pdp->pd_cmask;
|
||||
pdp->pd_cmask = uap->newmask & ALLPERMS;
|
||||
PWDDESC_XUNLOCK(pdp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <sys/queue.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/priority.h>
|
||||
#include <sys/seqc.h>
|
||||
#include <sys/sx.h>
|
||||
@ -92,12 +93,17 @@ struct pwd {
|
||||
};
|
||||
typedef SMR_POINTER(struct pwd *) smrpwd_t;
|
||||
|
||||
struct pwddesc {
|
||||
struct mtx pd_lock; /* protects members of this struct */
|
||||
smrpwd_t pd_pwd; /* directories */
|
||||
volatile u_int pd_refcount;
|
||||
u_short pd_cmask; /* mask for file creation */
|
||||
};
|
||||
|
||||
struct filedesc {
|
||||
struct fdescenttbl *fd_files; /* open files table */
|
||||
smrpwd_t fd_pwd; /* directories */
|
||||
NDSLOTTYPE *fd_map; /* bitmap of free fds */
|
||||
int fd_freefile; /* approx. next free file */
|
||||
u_short fd_cmask; /* mask for file creation */
|
||||
int fd_refcnt; /* thread reference count */
|
||||
int fd_holdcnt; /* hold count on structure + mutex */
|
||||
struct sx fd_sx; /* protects members of this struct */
|
||||
@ -134,6 +140,28 @@ struct filedesc_to_leader {
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
/* Lock a paths descriptor table. */
|
||||
#define PWDDESC_LOCK(pdp) (&(pdp)->pd_lock)
|
||||
#define PWDDESC_LOCK_INIT(pdp) \
|
||||
mtx_init(PWDDESC_LOCK(pdp), "pwddesc", NULL, MTX_DEF)
|
||||
#define PWDDESC_LOCK_DESTROY(pdp) mtx_destroy(PWDDESC_LOCK(pdp))
|
||||
#define PWDDESC_XLOCK(pdp) mtx_lock(PWDDESC_LOCK(pdp))
|
||||
#define PWDDESC_XUNLOCK(pdp) mtx_unlock(PWDDESC_LOCK(pdp))
|
||||
#define PWDDESC_LOCK_ASSERT(pdp, what) \
|
||||
mtx_assert(PWDDESC_LOCK(pdp), (what))
|
||||
#define PWDDESC_ASSERT_XLOCKED(pdp) \
|
||||
PWDDESC_LOCK_ASSERT((pdp), MA_OWNED)
|
||||
#define PWDDESC_ASSERT_UNLOCKED(pdp) \
|
||||
PWDDESC_LOCK_ASSERT((pdp), MA_NOTOWNED)
|
||||
|
||||
#define PWDDESC_XLOCKED_LOAD_PWD(pdp) ({ \
|
||||
struct pwddesc *_pdp = (pdp); \
|
||||
struct pwd *_pwd; \
|
||||
_pwd = smr_serialized_load(&(_pdp)->pd_pwd, \
|
||||
(PWDDESC_ASSERT_XLOCKED(_pdp), true)); \
|
||||
_pwd; \
|
||||
})
|
||||
|
||||
/* Lock a file descriptor table. */
|
||||
#define FILEDESC_LOCK_INIT(fdp) sx_init(&(fdp)->fd_sx, "filedesc structure")
|
||||
#define FILEDESC_LOCK_DESTROY(fdp) sx_destroy(&(fdp)->fd_sx)
|
||||
@ -149,31 +177,15 @@ struct filedesc_to_leader {
|
||||
SX_NOTRECURSED)
|
||||
#define FILEDESC_UNLOCK_ASSERT(fdp) sx_assert(&(fdp)->fd_sx, SX_UNLOCKED)
|
||||
|
||||
#define FILEDESC_LOCKED_LOAD_PWD(fdp) ({ \
|
||||
struct filedesc *_fdp = (fdp); \
|
||||
struct pwd *_pwd; \
|
||||
_pwd = smr_serialized_load(&(_fdp)->fd_pwd, \
|
||||
(FILEDESC_LOCK_ASSERT(_fdp), true)); \
|
||||
_pwd; \
|
||||
})
|
||||
|
||||
#define FILEDESC_XLOCKED_LOAD_PWD(fdp) ({ \
|
||||
struct filedesc *_fdp = (fdp); \
|
||||
struct pwd *_pwd; \
|
||||
_pwd = smr_serialized_load(&(_fdp)->fd_pwd, \
|
||||
(FILEDESC_XLOCK_ASSERT(_fdp), true)); \
|
||||
_pwd; \
|
||||
})
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Accessor for libkvm et al.
|
||||
*/
|
||||
#define FILEDESC_KVM_LOAD_PWD(fdp) ({ \
|
||||
struct filedesc *_fdp = (fdp); \
|
||||
#define PWDDESC_KVM_LOAD_PWD(pdp) ({ \
|
||||
struct pwddesc *_pdp = (pdp); \
|
||||
struct pwd *_pwd; \
|
||||
_pwd = smr_kvm_load(&(_fdp)->fd_pwd); \
|
||||
_pwd = smr_kvm_load(&(_pdp)->pd_pwd); \
|
||||
_pwd; \
|
||||
})
|
||||
|
||||
@ -296,21 +308,26 @@ fd_modified(struct filedesc *fdp, int fd, seqc_t seqc)
|
||||
#endif
|
||||
|
||||
/* cdir/rdir/jdir manipulation functions. */
|
||||
struct pwddesc *pdcopy(struct pwddesc *pdp);
|
||||
void pdescfree(struct thread *td);
|
||||
struct pwddesc *pdinit(struct pwddesc *pdp, bool keeplock);
|
||||
struct pwddesc *pdshare(struct pwddesc *pdp);
|
||||
void pdunshare(struct thread *td);
|
||||
|
||||
void pwd_chdir(struct thread *td, struct vnode *vp);
|
||||
int pwd_chroot(struct thread *td, struct vnode *vp);
|
||||
void pwd_ensure_dirs(void);
|
||||
void pwd_set_rootvnode(void);
|
||||
|
||||
struct pwd *pwd_hold_filedesc(struct filedesc *fdp);
|
||||
struct pwd *pwd_hold_pwddesc(struct pwddesc *pdp);
|
||||
bool pwd_hold_smr(struct pwd *pwd);
|
||||
struct pwd *pwd_hold(struct thread *td);
|
||||
void pwd_drop(struct pwd *pwd);
|
||||
static inline void
|
||||
pwd_set(struct filedesc *fdp, struct pwd *newpwd)
|
||||
pwd_set(struct pwddesc *pdp, struct pwd *newpwd)
|
||||
{
|
||||
|
||||
smr_serialized_store(&fdp->fd_pwd, newpwd,
|
||||
(FILEDESC_XLOCK_ASSERT(fdp), true));
|
||||
smr_serialized_store(&pdp->pd_pwd, newpwd,
|
||||
(PWDDESC_ASSERT_XLOCKED(pdp), true));
|
||||
}
|
||||
struct pwd *pwd_get_smr(void);
|
||||
|
||||
|
@ -60,7 +60,7 @@
|
||||
* in the range 5 to 9.
|
||||
*/
|
||||
#undef __FreeBSD_version
|
||||
#define __FreeBSD_version 1300129 /* Master, propagated to newvers */
|
||||
#define __FreeBSD_version 1300130 /* Master, propagated to newvers */
|
||||
|
||||
/*
|
||||
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
|
||||
|
@ -597,6 +597,7 @@ struct proc {
|
||||
struct ucred *p_ucred; /* (c) Process owner's identity. */
|
||||
struct filedesc *p_fd; /* (b) Open files. */
|
||||
struct filedesc_to_leader *p_fdtol; /* (b) Tracking node */
|
||||
struct pwddesc *p_pd; /* (b) Cwd, chroot, jail, umask */
|
||||
struct pstats *p_stats; /* (b) Accounting/statistics (CPU). */
|
||||
struct plimit *p_limit; /* (c) Resource limits. */
|
||||
struct callout p_limco; /* (c) Limit callout handle */
|
||||
|
@ -88,7 +88,7 @@
|
||||
*/
|
||||
#define KI_NSPARE_INT 2
|
||||
#define KI_NSPARE_LONG 12
|
||||
#define KI_NSPARE_PTR 6
|
||||
#define KI_NSPARE_PTR 5
|
||||
|
||||
#ifndef _KERNEL
|
||||
#ifndef KINFO_PROC_SIZE
|
||||
@ -213,6 +213,7 @@ struct kinfo_proc {
|
||||
* front of ki_spareptrs, and longs from the end of ki_sparelongs.
|
||||
* That way the spare room from both arrays will remain contiguous.
|
||||
*/
|
||||
struct pwddesc *ki_pd; /* pointer to process paths info */
|
||||
void *ki_spareptrs[KI_NSPARE_PTR]; /* spare room for growth */
|
||||
long ki_sparelongs[KI_NSPARE_LONG]; /* spare room for growth */
|
||||
long ki_sflag; /* PS_* flags */
|
||||
|
Loading…
Reference in New Issue
Block a user