git: 11d6ea47f06a - main - kern: mac: add a MAC label to struct prison
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 16 Jan 2026 00:24:17 UTC
The branch main has been updated by kevans:
URL: https://cgit.FreeBSD.org/src/commit/?id=11d6ea47f06a38f66536b173e85ddf2674da6aff
commit 11d6ea47f06a38f66536b173e85ddf2674da6aff
Author: Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2025-10-04 03:46:03 +0000
Commit: Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2026-01-16 00:23:39 +0000
kern: mac: add a MAC label to struct prison
Reviewed by: olce
Differential Revision: https://reviews.freebsd.org/D53953
---
sys/conf/files | 1 +
sys/kern/kern_jail.c | 26 +++++++
sys/security/mac/mac_framework.c | 1 +
sys/security/mac/mac_framework.h | 6 ++
sys/security/mac/mac_internal.h | 9 +++
sys/security/mac/mac_policy.h | 20 ++++++
sys/security/mac/mac_prison.c | 144 +++++++++++++++++++++++++++++++++++++++
sys/sys/jail.h | 1 +
8 files changed, 208 insertions(+)
diff --git a/sys/conf/files b/sys/conf/files
index d0c4ea5f544d..a6a76dec433a 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -5264,6 +5264,7 @@ security/mac/mac_net.c optional mac
security/mac/mac_pipe.c optional mac
security/mac/mac_posix_sem.c optional mac
security/mac/mac_posix_shm.c optional mac
+security/mac/mac_prison.c optional mac
security/mac/mac_priv.c optional mac
security/mac/mac_process.c optional mac
security/mac/mac_socket.c optional mac
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index f803be76a70e..8c224597bdf5 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -275,8 +275,17 @@ prison0_init(void)
uint8_t *file, *data;
size_t size;
char buf[sizeof(prison0.pr_hostuuid)];
+#ifdef MAC
+ int error __diagused;
+#endif
bool valid;
+#ifdef MAC
+ error = mac_prison_init(&prison0, M_WAITOK);
+ MPASS(error == 0);
+
+ mtx_unlock(&prison0.pr_mtx);
+#endif
prison0.pr_cpuset = cpuset_ref(thread0.td_cpuset);
prison0.pr_osreldate = osreldate;
strlcpy(prison0.pr_osrelease, osrelease, sizeof(prison0.pr_osrelease));
@@ -1828,7 +1837,14 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
if (error)
goto done_deref;
+#ifdef MAC
+ error = mac_prison_init(pr, M_WAITOK);
+ MPASS(error == 0);
+
+ mtx_assert(&pr->pr_mtx, MA_OWNED);
+#else
mtx_lock(&pr->pr_mtx);
+#endif
drflags |= PD_LOCKED;
} else {
/*
@@ -3540,6 +3556,16 @@ prison_deref(struct prison *pr, int flags)
KASSERT(
refcount_load(&prison0.pr_ref) != 0,
("prison0 pr_ref=0"));
+#ifdef MAC
+ /*
+ * The MAC framework will call into any
+ * policies that want to hook
+ * prison_destroy_label, so ideally we
+ * call this prior to any final state
+ * invalidation to be safe.
+ */
+ mac_prison_destroy(pr);
+#endif
pr->pr_state = PRISON_STATE_INVALID;
TAILQ_REMOVE(&allprison, pr, pr_list);
LIST_REMOVE(pr, pr_sibling);
diff --git a/sys/security/mac/mac_framework.c b/sys/security/mac/mac_framework.c
index b0776160cc74..fec63b99c0e0 100644
--- a/sys/security/mac/mac_framework.c
+++ b/sys/security/mac/mac_framework.c
@@ -374,6 +374,7 @@ mac_policy_getlabeled(struct mac_policy_conf *mpc)
MPC_FLAG(mount_init_label, MPC_OBJECT_MOUNT);
MPC_FLAG(posixsem_init_label, MPC_OBJECT_POSIXSEM);
MPC_FLAG(posixshm_init_label, MPC_OBJECT_POSIXSHM);
+ MPC_FLAG(prison_init_label, MPC_OBJECT_PRISON);
MPC_FLAG(sysvmsg_init_label, MPC_OBJECT_SYSVMSG);
MPC_FLAG(sysvmsq_init_label, MPC_OBJECT_SYSVMSQ);
MPC_FLAG(sysvsem_init_label, MPC_OBJECT_SYSVSEM);
diff --git a/sys/security/mac/mac_framework.h b/sys/security/mac/mac_framework.h
index 1233cd30f211..f14e8d7d1e7d 100644
--- a/sys/security/mac/mac_framework.h
+++ b/sys/security/mac/mac_framework.h
@@ -73,6 +73,7 @@ struct mount;
struct msg;
struct msqid_kernel;
struct pipepair;
+struct prison;
struct proc;
struct semid_kernel;
struct shmfd;
@@ -346,6 +347,11 @@ void mac_posixshm_create(struct ucred *cred, struct shmfd *shmfd);
void mac_posixshm_destroy(struct shmfd *);
void mac_posixshm_init(struct shmfd *);
+int mac_prison_init(struct prison *pr, int flag);
+void mac_prison_relabel(struct ucred *cred, struct prison *pr,
+ struct label *newlabel);
+void mac_prison_destroy(struct prison *pr);
+
int mac_priv_check_impl(struct ucred *cred, int priv);
#ifdef MAC
extern bool mac_priv_check_fp_flag;
diff --git a/sys/security/mac/mac_internal.h b/sys/security/mac/mac_internal.h
index aeef59017d18..a882a476d1b0 100644
--- a/sys/security/mac/mac_internal.h
+++ b/sys/security/mac/mac_internal.h
@@ -177,6 +177,7 @@ struct label {
#define MPC_OBJECT_SYSVSHM 0x0000000000020000
#define MPC_OBJECT_SYNCACHE 0x0000000000040000
#define MPC_OBJECT_IP6Q 0x0000000000080000
+#define MPC_OBJECT_PRISON 0x0000000000100000
/*
* MAC Framework global variables.
@@ -252,6 +253,14 @@ int mac_pipe_externalize_label(struct label *label, char *elements,
char *outbuf, size_t outbuflen);
int mac_pipe_internalize_label(struct label *label, char *string);
+int mac_prison_check_relabel(struct ucred *cred, struct prison *pr,
+ struct label *newlabel);
+int mac_prison_externalize_label(struct label *label, char *elements,
+ char *outbuf, size_t outbuflen);
+int mac_prison_internalize_label(struct label *label, char *string);
+void mac_prison_relabel(struct ucred *cred, struct prison *pr,
+ struct label *newlabel);
+
int mac_socket_label_set(struct ucred *cred, struct socket *so,
struct label *label);
void mac_socket_copy_label(struct label *src, struct label *dest);
diff --git a/sys/security/mac/mac_policy.h b/sys/security/mac/mac_policy.h
index f0a1f0863c96..fba1f4a1c85e 100644
--- a/sys/security/mac/mac_policy.h
+++ b/sys/security/mac/mac_policy.h
@@ -88,6 +88,7 @@ struct mount;
struct msg;
struct msqid_kernel;
struct pipepair;
+struct prison;
struct proc;
struct sbuf;
struct semid_kernel;
@@ -407,6 +408,18 @@ typedef void (*mpo_posixshm_create_t)(struct ucred *cred,
typedef void (*mpo_posixshm_destroy_label_t)(struct label *label);
typedef void (*mpo_posixshm_init_label_t)(struct label *label);
+typedef int (*mpo_prison_init_label_t)(struct label *label, int flag);
+typedef int (*mpo_prison_check_relabel_t)(struct ucred *cred,
+ struct prison *pr, struct label *prlabel,
+ struct label *newlabel);
+typedef void (*mpo_prison_destroy_label_t)(struct label *label);
+typedef int (*mpo_prison_externalize_label_t)(struct label *label,
+ char *element_name, struct sbuf *sb, int *claimed);
+typedef int (*mpo_prison_internalize_label_t)(struct label *label,
+ char *element_name, char *element_data, int *claimed);
+typedef void (*mpo_prison_relabel_t)(struct ucred *cred, struct prison *pr,
+ struct label *prlabel, struct label *newlabel);
+
typedef int (*mpo_priv_check_t)(struct ucred *cred, int priv);
typedef int (*mpo_priv_grant_t)(struct ucred *cred, int priv);
@@ -863,6 +876,13 @@ struct mac_policy_ops {
mpo_posixshm_destroy_label_t mpo_posixshm_destroy_label;
mpo_posixshm_init_label_t mpo_posixshm_init_label;
+ mpo_prison_init_label_t mpo_prison_init_label;
+ mpo_prison_check_relabel_t mpo_prison_check_relabel;
+ mpo_prison_destroy_label_t mpo_prison_destroy_label;
+ mpo_prison_externalize_label_t mpo_prison_externalize_label;
+ mpo_prison_internalize_label_t mpo_prison_internalize_label;
+ mpo_prison_relabel_t mpo_prison_relabel;
+
mpo_priv_check_t mpo_priv_check;
mpo_priv_grant_t mpo_priv_grant;
diff --git a/sys/security/mac/mac_prison.c b/sys/security/mac/mac_prison.c
new file mode 100644
index 000000000000..e24ffa9e698d
--- /dev/null
+++ b/sys/security/mac/mac_prison.c
@@ -0,0 +1,144 @@
+/*-
+ * Copyright (c) 2025 Kyle Evans <kevans@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/cdefs.h>
+#include "opt_mac.h"
+
+#include <sys/param.h>
+#include <sys/condvar.h>
+#include <sys/imgact.h>
+#include <sys/jail.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/mac.h>
+#include <sys/proc.h>
+#include <sys/sbuf.h>
+#include <sys/sdt.h>
+#include <sys/systm.h>
+#include <sys/vnode.h>
+#include <sys/mount.h>
+#include <sys/file.h>
+#include <sys/namei.h>
+#include <sys/sysctl.h>
+
+#include <security/mac/mac_framework.h>
+#include <security/mac/mac_internal.h>
+#include <security/mac/mac_policy.h>
+
+static void
+mac_prison_label_free(struct label *label)
+{
+ if (label == NULL)
+ return;
+
+ MAC_POLICY_PERFORM_NOSLEEP(prison_destroy_label, label);
+ mac_labelzone_free(label);
+}
+
+static struct label *
+mac_prison_label_alloc(int flag)
+{
+ struct label *label;
+ int error;
+
+ label = mac_labelzone_alloc(flag);
+ if (label == NULL)
+ return (NULL);
+
+ if (flag & M_WAITOK)
+ MAC_POLICY_CHECK(prison_init_label, label, flag);
+ else
+ MAC_POLICY_CHECK_NOSLEEP(prison_init_label, label, flag);
+ if (error) {
+ mac_prison_label_free(label);
+ return (NULL);
+ }
+ return (label);
+}
+
+/*
+ * The caller's expecting us to return with the prison locked if we were
+ * successful, since we're also setting pr->pr_label. On error, it remains
+ * unlocked.
+ */
+int
+mac_prison_init(struct prison *pr, int flag)
+{
+ struct label *prlabel;
+
+ mtx_assert(&pr->pr_mtx, MA_NOTOWNED);
+ if ((mac_labeled & MPC_OBJECT_PRISON) == 0) {
+ mtx_lock(&pr->pr_mtx);
+ pr->pr_label = NULL;
+ return (0);
+ }
+
+ prlabel = mac_prison_label_alloc(flag);
+ if (prlabel == NULL) {
+ KASSERT((flag & M_WAITOK) == 0,
+ ("MAC policy prison_init_label failed under M_WAITOK"));
+ return (ENOMEM);
+ }
+
+ mtx_lock(&pr->pr_mtx);
+ pr->pr_label = prlabel;
+ return (0);
+}
+
+void
+mac_prison_destroy(struct prison *pr)
+{
+ mtx_assert(&pr->pr_mtx, MA_OWNED);
+ mac_prison_label_free(pr->pr_label);
+ pr->pr_label = NULL;
+}
+
+int
+mac_prison_externalize_label(struct label *label, char *elements,
+ char *outbuf, size_t outbuflen)
+{
+ int error;
+
+ MAC_POLICY_EXTERNALIZE(prison, label, elements, outbuf, outbuflen);
+ return (error);
+}
+
+int
+mac_prison_internalize_label(struct label *label, char *string)
+{
+ int error;
+
+ MAC_POLICY_INTERNALIZE(prison, label, string);
+ return (error);
+}
+
+void
+mac_prison_relabel(struct ucred *cred, struct prison *pr,
+ struct label *newlabel)
+{
+ mtx_assert(&pr->pr_mtx, MA_OWNED);
+ MAC_POLICY_PERFORM_NOSLEEP(prison_relabel, cred, pr, pr->pr_label,
+ newlabel);
+}
+
+MAC_CHECK_PROBE_DEFINE4(prison_check_relabel, "struct ucred *",
+ "struct prison *", "struct label *", "struct label *");
+int
+mac_prison_check_relabel(struct ucred *cred, struct prison *pr,
+ struct label *newlabel)
+{
+ int error;
+
+ mtx_assert(&pr->pr_mtx, MA_OWNED);
+ MAC_POLICY_CHECK_NOSLEEP(prison_check_relabel, cred, pr,
+ pr->pr_label, newlabel);
+ MAC_CHECK_PROBE4(prison_check_relabel, error, cred, pr,
+ pr->pr_label, newlabel);
+
+ return (error);
+}
diff --git a/sys/sys/jail.h b/sys/sys/jail.h
index e6a13e6719dd..5ac4c5f9008d 100644
--- a/sys/sys/jail.h
+++ b/sys/sys/jail.h
@@ -198,6 +198,7 @@ struct prison {
struct prison_ip *pr_addrs[PR_FAMILY_MAX]; /* (p,n) IPs of jail */
struct prison_racct *pr_prison_racct; /* (c) racct jail proxy */
struct knlist *pr_klist; /* (m) attached knotes */
+ struct label *pr_label; /* (m) MAC label */
LIST_HEAD(, jaildesc) pr_descs; /* (a) attached descriptors */
void *pr_sparep;
int pr_childcount; /* (a) number of child jails */