git: 31c2728185d1 - main - mac_set_fd(3): add support for jail descriptors

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

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

commit 31c2728185d1705634ff84c93936a4c91a651b22
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2025-10-26 01:57:33 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2026-01-16 00:23:39 +0000

    mac_set_fd(3): add support for jail descriptors
    
    We'll still add an old-fashioned jail param to configure jail MAC
    labels, but for testing it's really easy to grab a jaildesc and use
    that.
    
    Reviewed by:    jamie, olce
    Differential Revision:  https://reviews.freebsd.org/D53956
---
 sys/security/mac/mac_internal.h  |  5 +++++
 sys/security/mac/mac_policy.h    |  3 +++
 sys/security/mac/mac_prison.c    | 28 +++++++++++++++++++++++--
 sys/security/mac/mac_syscalls.c  | 44 ++++++++++++++++++++++++++++++++++++++++
 sys/security/mac_stub/mac_stub.c |  1 +
 sys/security/mac_test/mac_test.c | 11 ++++++++++
 6 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/sys/security/mac/mac_internal.h b/sys/security/mac/mac_internal.h
index a07bf01da6f6..3f032ed3934a 100644
--- a/sys/security/mac/mac_internal.h
+++ b/sys/security/mac/mac_internal.h
@@ -242,6 +242,8 @@ struct label	*mac_cred_label_alloc(void);
 void		 mac_cred_label_free(struct label *label);
 struct label	*mac_pipe_label_alloc(void);
 void		 mac_pipe_label_free(struct label *label);
+struct label	*mac_prison_label_alloc(int flags);
+void		 mac_prison_label_free(struct label *label);
 struct label	*mac_socket_label_alloc(int flag);
 void		 mac_socket_label_free(struct label *label);
 void		 mac_socketpeer_label_free(struct label *label);
@@ -261,8 +263,11 @@ 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_label_set(struct ucred *cred, struct prison *pr,
+	    struct label *label);
 int	mac_prison_check_relabel(struct ucred *cred, struct prison *pr,
 	    struct label *newlabel);
+void	mac_prison_copy_label(struct label *src, struct label *dest);
 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);
diff --git a/sys/security/mac/mac_policy.h b/sys/security/mac/mac_policy.h
index 7693eb309534..0078138d472f 100644
--- a/sys/security/mac/mac_policy.h
+++ b/sys/security/mac/mac_policy.h
@@ -414,6 +414,8 @@ 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 void	(*mpo_prison_copy_label_t)(struct label *src,
+		    struct label *dest);
 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,
@@ -897,6 +899,7 @@ struct mac_policy_ops {
 	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_copy_label_t			mpo_prison_copy_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;
diff --git a/sys/security/mac/mac_prison.c b/sys/security/mac/mac_prison.c
index 3f787c6b3647..68ffd7a3cda3 100644
--- a/sys/security/mac/mac_prison.c
+++ b/sys/security/mac/mac_prison.c
@@ -30,7 +30,7 @@
 #include <security/mac/mac_internal.h>
 #include <security/mac/mac_policy.h>
 
-static void
+void
 mac_prison_label_free(struct label *label)
 {
 	if (label == NULL)
@@ -40,7 +40,7 @@ mac_prison_label_free(struct label *label)
 	mac_labelzone_free(label);
 }
 
-static struct label *
+struct label *
 mac_prison_label_alloc(int flag)
 {
 	struct label *label;
@@ -98,6 +98,13 @@ mac_prison_destroy(struct prison *pr)
 	pr->pr_label = NULL;
 }
 
+void
+mac_prison_copy_label(struct label *src, struct label *dest)
+{
+
+	MAC_POLICY_PERFORM_NOSLEEP(prison_copy_label, src, dest);
+}
+
 int
 mac_prison_externalize_label(struct label *label, char *elements,
     char *outbuf, size_t outbuflen)
@@ -126,6 +133,23 @@ mac_prison_relabel(struct ucred *cred, struct prison *pr,
 	    newlabel);
 }
 
+int
+mac_prison_label_set(struct ucred *cred, struct prison *pr,
+    struct label *label)
+{
+	int error;
+
+	mtx_assert(&pr->pr_mtx, MA_OWNED);
+
+	error = mac_prison_check_relabel(cred, pr, label);
+	if (error)
+		return (error);
+
+	mac_prison_relabel(cred, pr, label);
+
+	return (0);
+}
+
 MAC_CHECK_PROBE_DEFINE4(prison_check_relabel, "struct ucred *",
     "struct prison *", "struct label *", "struct label *");
 int
diff --git a/sys/security/mac/mac_syscalls.c b/sys/security/mac/mac_syscalls.c
index 13c7998041f9..3e9908fb9da9 100644
--- a/sys/security/mac/mac_syscalls.c
+++ b/sys/security/mac/mac_syscalls.c
@@ -49,6 +49,8 @@
 #include <sys/abi_compat.h>
 #include <sys/capsicum.h>
 #include <sys/fcntl.h>
+#include <sys/jail.h>
+#include <sys/jaildesc.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
@@ -339,6 +341,7 @@ sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
 	struct mac mac;
 	struct vnode *vp;
 	struct pipe *pipe;
+	struct prison *pr;
 	struct socket *so;
 	cap_rights_t rights;
 	int error;
@@ -400,6 +403,25 @@ sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
 		mac_socket_label_free(intlabel);
 		break;
 
+	case DTYPE_JAILDESC:
+		if (!(mac_labeled & MPC_OBJECT_PRISON)) {
+			error = EINVAL;
+			goto out_fdrop;
+		}
+
+		error = jaildesc_get_prison(fp, &pr);
+		if (error != 0)
+			goto out_fdrop;
+
+		intlabel = mac_prison_label_alloc(M_WAITOK);
+		mac_prison_copy_label(pr->pr_label, intlabel);
+		prison_free(pr);
+
+		error = mac_prison_externalize_label(intlabel, mac.m_string,
+		    buffer, mac.m_buflen);
+		mac_prison_label_free(intlabel);
+		break;
+
 	default:
 		error = EINVAL;
 	}
@@ -473,6 +495,7 @@ sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
 {
 	struct label *intlabel;
 	struct pipe *pipe;
+	struct prison *pr;
 	struct socket *so;
 	struct file *fp;
 	struct mount *mp;
@@ -548,6 +571,27 @@ sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
 		mac_socket_label_free(intlabel);
 		break;
 
+	case DTYPE_JAILDESC:
+		if (!(mac_labeled & MPC_OBJECT_PRISON)) {
+			error = EINVAL;
+			goto out_fdrop;
+		}
+
+		pr = NULL;
+		intlabel = mac_prison_label_alloc(M_WAITOK);
+		error = mac_prison_internalize_label(intlabel, mac.m_string);
+		if (error == 0)
+			error = jaildesc_get_prison(fp, &pr);
+		if (error == 0) {
+			prison_lock(pr);
+			error = mac_prison_label_set(td->td_ucred, pr,
+			    intlabel);
+			prison_free_locked(pr);
+		}
+
+		mac_prison_label_free(intlabel);
+		break;
+
 	default:
 		error = EINVAL;
 	}
diff --git a/sys/security/mac_stub/mac_stub.c b/sys/security/mac_stub/mac_stub.c
index 20b04d4acf58..4a567c68b2be 100644
--- a/sys/security/mac_stub/mac_stub.c
+++ b/sys/security/mac_stub/mac_stub.c
@@ -1912,6 +1912,7 @@ static struct mac_policy_ops stub_ops =
 
 	.mpo_prison_init_label = stub_init_label_waitcheck,
 	.mpo_prison_destroy_label = stub_destroy_label,
+	.mpo_prison_copy_label = stub_copy_label,
 	.mpo_prison_externalize_label = stub_externalize_label,
 	.mpo_prison_internalize_label = stub_internalize_label,
 	.mpo_prison_relabel = stub_prison_relabel,
diff --git a/sys/security/mac_test/mac_test.c b/sys/security/mac_test/mac_test.c
index 72af48edb00f..47dd7d1326a3 100644
--- a/sys/security/mac_test/mac_test.c
+++ b/sys/security/mac_test/mac_test.c
@@ -1617,6 +1617,16 @@ test_prison_destroy_label(struct label *label)
 	COUNTER_INC(prison_destroy_label);
 }
 
+COUNTER_DECL(prison_copy_label);
+static void
+test_prison_copy_label(struct label *src, struct label *dest)
+{
+
+	LABEL_CHECK(src, MAGIC_PRISON);
+	LABEL_CHECK(dest, MAGIC_PRISON);
+	COUNTER_INC(prison_copy_label);
+}
+
 COUNTER_DECL(prison_externalize_label);
 static int
 test_prison_externalize_label(struct label *label, char *element_name,
@@ -3357,6 +3367,7 @@ static struct mac_policy_ops test_ops =
 
 	.mpo_prison_init_label = test_prison_init_label,
 	.mpo_prison_destroy_label = test_prison_destroy_label,
+	.mpo_prison_copy_label = test_prison_copy_label,
 	.mpo_prison_externalize_label = test_prison_externalize_label,
 	.mpo_prison_internalize_label = test_prison_internalize_label,
 	.mpo_prison_relabel = test_prison_relabel,