Date: Tue, 17 Nov 2020 21:14:14 +0000 (UTC) From: Conrad Meyer <cem@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r367777 - in head: lib/libkvm lib/libprocstat sys/compat/cloudabi sys/fs/fuse sys/fs/unionfs sys/kern sys/sys Message-ID: <202011172114.0AHLEE7v068072@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202011172114.0AHLEE7v068072>