diff --git a/sys/conf/files b/sys/conf/files --- a/sys/conf/files +++ b/sys/conf/files @@ -5245,6 +5245,7 @@ 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 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -275,6 +275,10 @@ char buf[sizeof(prison0.pr_hostuuid)]; bool valid; +#ifdef MAC + mac_prison_init(&prison0, M_WAITOK); + mac_prison_create_init(&prison0); +#endif prison0.pr_cpuset = cpuset_ref(thread0.td_cpuset); prison0.pr_osreldate = osreldate; strlcpy(prison0.pr_osrelease, osrelease, sizeof(prison0.pr_osrelease)); @@ -1826,6 +1830,10 @@ if (error) goto done_deref; +#ifdef MAC + mac_prison_init(pr, M_WAITOK); +#endif + mtx_lock(&pr->pr_mtx); drflags |= PD_LOCKED; } else { diff --git a/sys/security/mac/mac_framework.h b/sys/security/mac/mac_framework.h --- a/sys/security/mac/mac_framework.h +++ b/sys/security/mac/mac_framework.h @@ -73,6 +73,7 @@ struct msg; struct msqid_kernel; struct pipepair; +struct prison; struct proc; struct semid_kernel; struct shmfd; @@ -346,6 +347,12 @@ void mac_posixshm_destroy(struct shmfd *); void mac_posixshm_init(struct shmfd *); +int mac_prison_init(struct prison *pr, int flag); +void mac_prison_create_init(struct prison *pr); +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_framework.c b/sys/security/mac/mac_framework.c --- a/sys/security/mac/mac_framework.c +++ b/sys/security/mac/mac_framework.c @@ -374,6 +374,7 @@ 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_internal.h b/sys/security/mac/mac_internal.h --- a/sys/security/mac/mac_internal.h +++ b/sys/security/mac/mac_internal.h @@ -177,6 +177,7 @@ #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 @@ 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 --- a/sys/security/mac/mac_policy.h +++ b/sys/security/mac/mac_policy.h @@ -88,6 +88,7 @@ struct msg; struct msqid_kernel; struct pipepair; +struct prison; struct proc; struct sbuf; struct semid_kernel; @@ -407,6 +408,19 @@ 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 void (*mpo_prison_create_init_t)(struct prison *pr); +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 +877,14 @@ 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_create_init_t mpo_prison_create_init; + 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 --- /dev/null +++ b/sys/security/mac/mac_prison.c @@ -0,0 +1,137 @@ +/*- + * Copyright (c) 2025 Kyle Evans + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include "opt_mac.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +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_POLICY_PERFORM_NOSLEEP(prison_destroy_label, label); + mac_labelzone_free(label); + return (NULL); + } + return (label); +} + +int +mac_prison_init(struct prison *pr, int flag) +{ + if ((mac_labeled & MPC_OBJECT_PRISON) == 0) { + pr->pr_label = NULL; + return (0); + } + + pr->pr_label = mac_prison_label_alloc(flag); + if (pr->pr_label == NULL) + return (ENOMEM); + return (0); +} + +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); +} + +void +mac_prison_destroy(struct prison *pr) +{ + mac_prison_label_free(pr->pr_label); + pr->pr_label = NULL; +} + +/* + * Initialize MAC label for prison0 + */ +void +mac_prison_create_init(struct prison *pr) +{ + + MAC_POLICY_PERFORM_NOSLEEP(prison_create_init, pr); +} + +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) +{ + 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; + + 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 --- a/sys/sys/jail.h +++ b/sys/sys/jail.h @@ -198,6 +198,7 @@ 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 */