The branch main has been updated by kevans: URL: https://cgit.FreeBSD.org/src/commit/?id=d7a517eb6d770e22db6a46a46677db27f565767c
commit d7a517eb6d770e22db6a46a46677db27f565767c Author: Kyle Evans <[email protected]> AuthorDate: 2025-10-26 01:42:30 +0000 Commit: Kyle Evans <[email protected]> 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);
