aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Evans <kevans@FreeBSD.org>2025-10-26 01:42:30 +0000
committerKyle Evans <kevans@FreeBSD.org>2026-01-16 00:23:39 +0000
commitd7a517eb6d770e22db6a46a46677db27f565767c (patch)
tree80fa37cbc5c8e454f1191aa1515efa3088272c33
parent8254b0dec02b376dae259cd2043513842d827bd8 (diff)
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
-rw-r--r--sys/kern/kern_jaildesc.c77
-rw-r--r--sys/sys/jaildesc.h1
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);
}
@@ -146,6 +170,17 @@ jaildesc_alloc(struct thread *td, struct file **fpp, int *fdp, int owning)
}
/*
+ * 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.
*/
void
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);