Page MenuHomeFreeBSD

D52757.id162998.diff
No OneTemporary

D52757.id162998.diff

diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile
--- a/share/man/man9/Makefile
+++ b/share/man/man9/Makefile
@@ -2455,6 +2455,7 @@
MLINKS+=vm_page_wire.9 vm_page_unwire.9 \
vm_page_wire.9 vm_page_unwire_noq.9 \
vm_page_wire.9 vm_page_wire_mapped.9
+MLINKS+=vn_fullpath.9 vn_fullpath_jail.9
MLINKS+=VOP_ACCESS.9 VOP_ACCESSX.9
MLINKS+=VOP_ATTRIB.9 VOP_GETATTR.9 \
VOP_ATTRIB.9 VOP_SETATTR.9 \
diff --git a/share/man/man9/vn_fullpath.9 b/share/man/man9/vn_fullpath.9
--- a/share/man/man9/vn_fullpath.9
+++ b/share/man/man9/vn_fullpath.9
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
.\" DAMAGE.
.\"
-.Dd June 15, 2021
+.Dd September 28, 2025
.Dt VN_FULLPATH 9
.Os
.Sh NAME
@@ -35,9 +35,9 @@
.In sys/param.h
.In sys/vnode.h
.Ft int
-.Fo vn_fullpath
-.Fa "struct vnode *vp" "char **retbuf" "char **freebuf"
-.Fc
+.Fn vn_fullpath "struct vnode *vp" "char **retbuf" "char **freebuf"
+.Ft int
+.Fn vn_fullpath_jail "struct vnode *vp" "char **retbuf" "char **freebuf"
.Sh DESCRIPTION
The
.Fn vn_fullpath
@@ -46,12 +46,15 @@
attempt to generate a string pathname for
the passed vnode; the resulting path, if any, will be relative to
the root directory of the process associated with the passed thread pointer.
-The
-.Fn vn_fullpath
-function
-is implemented by inspecting the VFS name cache, and attempting to
-reconstruct a path from the process root to the object.
.Pp
+The
+.Fn vn_fullpath_jail
+function works similarly as
+.Fn vn_fullpath ,
+but instead returns a path relative to the current jail's root.
+.Pp
+Both functions are implemented by inspecting the VFS name cache, and attempting
+to reconstruct a path from the process root to the object.
This process is necessarily unreliable for several reasons: intermediate
entries in the path may not be found in the cache; files may have more
than one name (hard links), not all file systems use the name cache
@@ -64,7 +67,7 @@
Code consuming the results of this function should anticipate (and
properly handle) failure.
.Pp
-Its arguments are:
+These functions take the following arguments:
.Bl -tag -width ".Fa freebuf"
.It Fa vp
The vnode to search for.
@@ -72,17 +75,13 @@
.It Fa retbuf
Pointer to a
.Vt "char *"
-that
-.Fn vn_fullpath
-may (on success) point at a newly
-allocated buffer containing the resulting pathname.
+that may be set (on success) to point at a newly allocated buffer containing the
+resulting pathname.
.It Fa freebuf
Pointer to a
.Vt "char *"
-that
-.Fn vn_fullpath
-may (on success) point at a buffer
-to be freed, when the caller is done with
+that may be set (on success) to point at a buffer to be freed, when the caller
+is done with
.Fa retbuf .
.El
.Pp
@@ -116,5 +115,10 @@
.Sh SEE ALSO
.Xr free 9
.Sh AUTHORS
+.An -nosplit
This manual page was written by
.An Robert Watson Aq Mt rwatson@FreeBSD.org .
+The
+.Fn vn_fullpath_jail
+function was added by
+.An Olivier Certner Aq Mt olce@FreeBSD.org .
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -3340,12 +3340,10 @@
uap->flags, UIO_USERSPACE));
}
-/*
- * Retrieve the full filesystem path that correspond to a vnode from the name
- * cache (if available)
- */
-int
-vn_fullpath(struct vnode *vp, char **retbuf, char **freebuf)
+static int
+vn_fullpath_up_to_pwd_vnode(struct vnode *vp,
+ struct vnode *(*get_pwd_vnode)(const struct pwd *),
+ char **retbuf, char **freebuf)
{
struct pwd *pwd;
char *buf;
@@ -3359,11 +3357,13 @@
buf = malloc(buflen, M_TEMP, M_WAITOK);
vfs_smr_enter();
pwd = pwd_get_smr();
- error = vn_fullpath_any_smr(vp, pwd->pwd_rdir, buf, retbuf, &buflen, 0);
+ error = vn_fullpath_any_smr(vp, get_pwd_vnode(pwd), buf, retbuf,
+ &buflen, 0);
VFS_SMR_ASSERT_NOT_ENTERED();
if (error < 0) {
pwd = pwd_hold(curthread);
- error = vn_fullpath_any(vp, pwd->pwd_rdir, buf, retbuf, &buflen);
+ error = vn_fullpath_any(vp, get_pwd_vnode(pwd), buf, retbuf,
+ &buflen);
pwd_drop(pwd);
}
if (error == 0)
@@ -3373,6 +3373,42 @@
return (error);
}
+static inline struct vnode *
+get_rdir(const struct pwd *pwd)
+{
+ return (pwd->pwd_rdir);
+}
+
+/*
+ * Produce a filesystem path that starts from the current chroot directory and
+ * corresponds to the passed vnode, using the name cache (if available).
+ */
+int
+vn_fullpath(struct vnode *vp, char **retbuf, char **freebuf)
+{
+ return (vn_fullpath_up_to_pwd_vnode(vp, get_rdir, retbuf, freebuf));
+}
+
+static inline struct vnode *
+get_jdir(const struct pwd *pwd)
+{
+ return (pwd->pwd_jdir);
+}
+
+/*
+ * Produce a filesystem path that starts from the current jail's root directory
+ * and corresponds to the passed vnode, using the name cache (if available).
+ *
+ * This function allows to ignore chroots done inside a jail (or the host),
+ * allowing path checks to remain unaffected by privileged or unprivileged
+ * chroot calls.
+ */
+int
+vn_fullpath_jail(struct vnode *vp, char **retbuf, char **freebuf)
+{
+ return (vn_fullpath_up_to_pwd_vnode(vp, get_jdir, retbuf, freebuf));
+}
+
/*
* This function is similar to vn_fullpath, but it attempts to lookup the
* pathname relative to the global root mount point. This is required for the
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -714,6 +714,7 @@
int vn_vptocnp(struct vnode **vp, char *buf, size_t *buflen);
int vn_getcwd(char *buf, char **retbuf, size_t *buflen);
int vn_fullpath(struct vnode *vp, char **retbuf, char **freebuf);
+int vn_fullpath_jail(struct vnode *vp, char **retbuf, char **freebuf);
int vn_fullpath_global(struct vnode *vp, char **retbuf, char **freebuf);
int vn_fullpath_hardlink(struct vnode *vp, struct vnode *dvp,
const char *hdrl_name, size_t hrdl_name_length, char **retbuf,

File Metadata

Mime Type
text/plain
Expires
Mon, Feb 9, 2:46 AM (16 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28528363
Default Alt Text
D52757.id162998.diff (5 KB)

Event Timeline