git: d7a517eb6d77 - main - jaildesc: add an accessor for the struct prison in a jaildesc

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Fri, 16 Jan 2026 00:24:20 UTC
The branch main has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=d7a517eb6d770e22db6a46a46677db27f565767c

commit d7a517eb6d770e22db6a46a46677db27f565767c
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2025-10-26 01:42:30 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2026-01-16 00:23:39 +0000

    jaildesc: add an accessor for the struct prison in a jaildesc
    
    We'll subsequently use this in the MAC framework to get a struct prison
    when we already have the struct file in question, rather than an fd.
    
    Reviewed by:    jamie, olce
    Differential Revision:  https://reviews.freebsd.org/D53955
---
 sys/kern/kern_jaildesc.c | 77 +++++++++++++++++++++++++++++++++++-------------
 sys/sys/jaildesc.h       |  1 +
 2 files changed, 57 insertions(+), 21 deletions(-)

diff --git a/sys/kern/kern_jaildesc.c b/sys/kern/kern_jaildesc.c
index f4e31801201f..80d0f3d07d7c 100644
--- a/sys/kern/kern_jaildesc.c
+++ b/sys/kern/kern_jaildesc.c
@@ -72,42 +72,66 @@ static const struct fileops jaildesc_ops = {
 };
 
 /*
- * Given a jail descriptor number, return its prison and/or its
- * credential.  They are returned held, and will need to be released
- * by the caller.
+ * Retrieve a prison from a jail descriptor.  If prp is not NULL, then the
+ * prison will be held and subsequently returned, and must be released by the
+ * caller.  This differs from jaildesc_get_prison in that it doesn't actually
+ * require the caller to take the struct prison, which we use internally when
+ * the caller doesn't necessarily need it- it might just want to check validity.
  */
-int
-jaildesc_find(struct thread *td, int fd, struct prison **prp,
-    struct ucred **ucredp)
+static int
+jaildesc_get_prison_impl(struct file *fp, struct prison **prp)
 {
-	struct file *fp;
-	struct jaildesc *jd;
 	struct prison *pr;
-	int error;
+	struct jaildesc *jd;
+
+	if (fp->f_type != DTYPE_JAILDESC)
+		return (EINVAL);
 
-	error = fget(td, fd, &cap_no_rights, &fp);
-	if (error != 0)
-		return (error);
-	if (fp->f_type != DTYPE_JAILDESC) {
-		error = EINVAL;
-		goto out;
-	}
 	jd = fp->f_data;
 	JAILDESC_LOCK(jd);
 	pr = jd->jd_prison;
 	if (pr == NULL || !prison_isvalid(pr)) {
-		error = ENOENT;
 		JAILDESC_UNLOCK(jd);
-		goto out;
+		return (ENOENT);
 	}
+
 	if (prp != NULL) {
 		prison_hold(pr);
 		*prp = pr;
 	}
+
 	JAILDESC_UNLOCK(jd);
-	if (ucredp != NULL)
-		*ucredp = crhold(fp->f_cred);
- out:
+
+	return (0);
+}
+
+/*
+ * Given a jail descriptor number, return its prison and/or its
+ * credential.  They are returned held, and will need to be released
+ * by the caller.
+ */
+int
+jaildesc_find(struct thread *td, int fd, struct prison **prp,
+    struct ucred **ucredp)
+{
+	struct file *fp;
+	int error;
+
+	error = fget(td, fd, &cap_no_rights, &fp);
+	if (error != 0)
+		return (error);
+
+	error = jaildesc_get_prison_impl(fp, prp);
+	if (error == 0) {
+		/*
+		 * jaildesc_get_prison validated the file and held the prison
+		 * for us if the caller wants it, so we just need to grab the
+		 * ucred on the way out.
+		 */
+		if (ucredp != NULL)
+			*ucredp = crhold(fp->f_cred);
+	}
+
 	fdrop(fp, td);
 	return (error);
 }
@@ -145,6 +169,17 @@ jaildesc_alloc(struct thread *td, struct file **fpp, int *fdp, int owning)
 	return (0);
 }
 
+/*
+ * Retrieve a prison from a jail descriptor.  It will be returned held, and must
+ * be released by the caller.
+ */
+int
+jaildesc_get_prison(struct file *fp, struct prison **prp)
+{
+	MPASS(prp != NULL);
+	return (jaildesc_get_prison_impl(fp, prp));
+}
+
 /*
  * Assocate a jail descriptor with its prison.
  */
diff --git a/sys/sys/jaildesc.h b/sys/sys/jaildesc.h
index fda270d62e70..b0a1a6238cc9 100644
--- a/sys/sys/jaildesc.h
+++ b/sys/sys/jaildesc.h
@@ -78,6 +78,7 @@ struct jaildesc {
 int jaildesc_find(struct thread *td, int fd, struct prison **prp,
     struct ucred **ucredp);
 int jaildesc_alloc(struct thread *td, struct file **fpp, int *fdp, int owning);
+int jaildesc_get_prison(struct file *jd, struct prison **prp);
 void jaildesc_set_prison(struct file *jd, struct prison *pr);
 void jaildesc_prison_cleanup(struct prison *pr);
 void jaildesc_knote(struct prison *pr, long hint);