Author: cem
Date: Tue Nov 17 21:14:13 2020
New Revision: 367777
URL: https://svnweb.freebsd.org/changeset/base/367777

Log:
  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

Modified:
  head/lib/libkvm/kvm_proc.c
  head/lib/libprocstat/libprocstat.c
  head/sys/compat/cloudabi/cloudabi_file.c
  head/sys/fs/fuse/fuse_internal.c
  head/sys/fs/fuse/fuse_vnops.c
  head/sys/fs/unionfs/union_subr.c
  head/sys/kern/imgact_elf.c
  head/sys/kern/init_main.c
  head/sys/kern/kern_descrip.c
  head/sys/kern/kern_exec.c
  head/sys/kern/kern_exit.c
  head/sys/kern/kern_fork.c
  head/sys/kern/kern_proc.c
  head/sys/kern/kern_thread.c
  head/sys/kern/uipc_mqueue.c
  head/sys/kern/uipc_sem.c
  head/sys/kern/uipc_shm.c
  head/sys/kern/uipc_usrreq.c
  head/sys/kern/vfs_syscalls.c
  head/sys/sys/filedesc.h
  head/sys/sys/param.h
  head/sys/sys/proc.h
  head/sys/sys/user.h

Modified: head/lib/libkvm/kvm_proc.c
==============================================================================
--- head/lib/libkvm/kvm_proc.c  Tue Nov 17 20:01:21 2020        (r367776)
+++ head/lib/libkvm/kvm_proc.c  Tue Nov 17 21:14:13 2020        (r367777)
@@ -221,6 +221,7 @@ kvm_proclist(kvm_t *kd, int what, int arg, struct proc
                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)) {

Modified: head/lib/libprocstat/libprocstat.c
==============================================================================
--- head/lib/libprocstat/libprocstat.c  Tue Nov 17 20:01:21 2020        
(r367776)
+++ head/lib/libprocstat/libprocstat.c  Tue Nov 17 21:14:13 2020        
(r367777)
@@ -460,6 +460,7 @@ procstat_getfiles_kvm(struct procstat *procstat, struc
 {
        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, struc
        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
 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);
 }
 

Modified: head/sys/compat/cloudabi/cloudabi_file.c
==============================================================================
--- head/sys/compat/cloudabi/cloudabi_file.c    Tue Nov 17 20:01:21 2020        
(r367776)
+++ head/sys/compat/cloudabi/cloudabi_file.c    Tue Nov 17 21:14:13 2020        
(r367777)
@@ -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. */

Modified: head/sys/fs/fuse/fuse_internal.c
==============================================================================
--- head/sys/fs/fuse/fuse_internal.c    Tue Nov 17 20:01:21 2020        
(r367776)
+++ head/sys/fs/fuse/fuse_internal.c    Tue Nov 17 21:14:13 2020        
(r367777)
@@ -497,7 +497,7 @@ fuse_internal_mknod(struct vnode *dvp, struct vnode **
        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;
        }

Modified: head/sys/fs/fuse/fuse_vnops.c
==============================================================================
--- head/sys/fs/fuse/fuse_vnops.c       Tue Nov 17 20:01:21 2020        
(r367776)
+++ head/sys/fs/fuse/fuse_vnops.c       Tue Nov 17 21:14:13 2020        
(r367777)
@@ -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));

Modified: head/sys/fs/unionfs/union_subr.c
==============================================================================
--- head/sys/fs/unionfs/union_subr.c    Tue Nov 17 20:01:21 2020        
(r367776)
+++ head/sys/fs/unionfs/union_subr.c    Tue Nov 17 21:14:13 2020        
(r367777)
@@ -486,7 +486,7 @@ unionfs_create_uppervattr_core(struct unionfs_mount *u
                }
                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;

Modified: head/sys/kern/imgact_elf.c
==============================================================================
--- head/sys/kern/imgact_elf.c  Tue Nov 17 20:01:21 2020        (r367776)
+++ head/sys/kern/imgact_elf.c  Tue Nov 17 21:14:13 2020        (r367777)
@@ -2507,12 +2507,12 @@ note_procstat_umask(void *arg, struct sbuf *sb, size_t
        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;
 }

Modified: head/sys/kern/init_main.c
==============================================================================
--- head/sys/kern/init_main.c   Tue Nov 17 20:01:21 2020        (r367776)
+++ head/sys/kern/init_main.c   Tue Nov 17 21:14:13 2020        (r367777)
@@ -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;
 

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c        Tue Nov 17 20:01:21 2020        
(r367776)
+++ head/sys/kern/kern_descrip.c        Tue Nov 17 21:14:13 2020        
(r367777)
@@ -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, 
 
 /*
  * 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 *last
 {
        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 *last
        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 *last
        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.
  */
@@ -2120,6 +2179,16 @@ fdshare(struct filedesc *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
  */
 void
@@ -2136,7 +2205,26 @@ 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,12 +2264,27 @@ 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, 
                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);
+       fdescfree_fds(td, fdp, 1);
+}
 
-       pwd_drop(pwd);
+void
+pdescfree(struct thread *td)
+{
+       struct proc *p;
+       struct pwddesc *pdp;
 
-       fdescfree_fds(td, fdp, 1);
+       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 *newd
        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 *newd
                        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 ff
 
 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 fflag
 
        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 *s
 {
        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 *s
                        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 *s
                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 *s
                        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 *s
                        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_o
 
 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, fil
 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, ss
 
        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, ss
                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);
 }

Modified: head/sys/kern/kern_exec.c
==============================================================================
--- head/sys/kern/kern_exec.c   Tue Nov 17 20:01:21 2020        (r367776)
+++ head/sys/kern/kern_exec.c   Tue Nov 17 21:14:13 2020        (r367777)
@@ -700,6 +700,7 @@ interpret:
                 * cannot be shared after an exec.
                 */
                fdunshare(td);
+               pdunshare(td);
                /* close files on exec */
                fdcloseexec(td);
        }

Modified: head/sys/kern/kern_exit.c
==============================================================================
--- head/sys/kern/kern_exit.c   Tue Nov 17 20:01:21 2020        (r367776)
+++ head/sys/kern/kern_exit.c   Tue Nov 17 21:14:13 2020        (r367777)
@@ -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);
 
        /*

Modified: head/sys/kern/kern_fork.c
==============================================================================
--- head/sys/kern/kern_fork.c   Tue Nov 17 20:01:21 2020        (r367776)
+++ head/sys/kern/kern_fork.c   Tue Nov 17 21:14:13 2020        (r367777)
@@ -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
        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
         * 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
        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;

Modified: head/sys/kern/kern_proc.c
==============================================================================
--- head/sys/kern/kern_proc.c   Tue Nov 17 20:01:21 2020        (r367776)
+++ head/sys/kern/kern_proc.c   Tue Nov 17 21:14:13 2020        (r367777)
@@ -1144,6 +1144,7 @@ fill_kinfo_proc_only(struct proc *p, struct kinfo_proc
        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);
 }
 

Modified: head/sys/kern/kern_thread.c
==============================================================================
--- head/sys/kern/kern_thread.c Tue Nov 17 20:01:21 2020        (r367776)
+++ head/sys/kern/kern_thread.c Tue Nov 17 21:14:13 2020        (r367777)
@@ -88,15 +88,15 @@ _Static_assert(offsetof(struct thread, td_frame) == 0x
     "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

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to