[Bug 258729] linprocfs regression: /compat/linux/proc/*/cwd wrongly points to calling process's cwd for all PIDs

From: <bugzilla-noreply_at_freebsd.org>
Date: Sun, 26 Sep 2021 12:26:43 UTC

Damjan Jovanovic <damjan.jov@gmail.com> changed:

           What    |Removed                     |Added
                 CC|                            |kib@FreeBSD.org,
                   |                            |mjg@FreeBSD.org

--- Comment #1 from Damjan Jovanovic <damjan.jov@gmail.com> ---
This is the commit that caused the regression:

commit 8d03b99b9dafe92896f405c79f846667637c0194
Author: Mateusz Guzik <mjg@FreeBSD.org>
Date:   Sun Mar 1 21:53:46 2020 +0000

    fd: move vnodes out of filedesc into a dedicated structure

    The new structure is copy-on-write. With the assumption that path lookups
    significantly more frequent than chdirs and chrooting this is a win.

    This provides stable root and jail root vnodes without the need to
    them on lookup, which in turn means less work on globally shared
    Note this also happens to fix a bug where jail vnode was never referenced,
    meaning subsequent access on lookup could run into use-after-free.

    Reviewed by:    kib
    Differential Revision:  https://reviews.freebsd.org/D23884

It changed linprocfs_doproccwd() from returning the cwd of the passed "struct
proc" (p), to returning the cwd of the calling thread (td) instead:

 static int
-       struct filedesc *fdp;
-       struct vnode *vp;
+       struct pwd *pwd;
        char *fullpath = "unknown";
        char *freepath = NULL;

-       fdp = p->p_fd;
-       FILEDESC_SLOCK(fdp);
-       vp = fdp->fd_cdir;
-       if (vp != NULL)
-               VREF(vp);
-       FILEDESC_SUNLOCK(fdp);
-       vn_fullpath(td, vp, &fullpath, &freepath);
-       if (vp != NULL)
-               vrele(vp);
+       pwd = pwd_hold(td);
+       vn_fullpath(td, pwd->pwd_cdir, &fullpath, &freepath);
        sbuf_printf(sb, "%s", fullpath);
        if (freepath)
                free(freepath, M_TEMP);
+       pwd_drop(pwd);
        return (0);

This patch fixes it (although it still needs proper locking and possibly
security checks):

diff --git a/sys/compat/linprocfs/linprocfs.c
index 79ffc4dfd5a..ee94268a4b6 100644
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -1169,7 +1169,7 @@ linprocfs_doproccwd(PFS_FILL_ARGS)
        char *fullpath = "unknown";
        char *freepath = NULL;

-       pwd = pwd_hold(td);
+       pwd = pwd_hold_pwddesc(p->p_pd);
        vn_fullpath(pwd->pwd_cdir, &fullpath, &freepath);
        sbuf_printf(sb, "%s", fullpath);
        if (freepath)

Other functions may be similarly broken, eg. linprocfs_doprocroot() also looks

Adding author and reviewer to CC.

You are receiving this mail because:
You are the assignee for the bug.