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 @@ -234,6 +234,8 @@ 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); @@ -253,8 +255,11 @@ 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 --- a/sys/security/mac/mac_policy.h +++ b/sys/security/mac/mac_policy.h @@ -415,6 +415,8 @@ 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, @@ -902,6 +904,7 @@ 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_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 --- a/sys/security/mac/mac_prison.c +++ b/sys/security/mac/mac_prison.c @@ -30,7 +30,7 @@ #include #include -static struct label * +struct label * mac_prison_label_alloc(int flag) { struct label *label; @@ -66,7 +66,7 @@ return (0); } -static void +void mac_prison_label_free(struct label *label) { if (label == NULL) @@ -83,6 +83,13 @@ pr->pr_label = NULL; } +void +mac_prison_copy_label(struct label *src, struct label *dest) +{ + + MAC_POLICY_PERFORM_NOSLEEP(prison_copy_label, src, dest); +} + /* * Initialize MAC label for prison0 */ @@ -120,6 +127,23 @@ 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 --- a/sys/security/mac/mac_syscalls.c +++ b/sys/security/mac/mac_syscalls.c @@ -49,6 +49,8 @@ #include #include #include +#include +#include #include #include #include @@ -339,6 +341,7 @@ 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 @@ 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 @@ { struct label *intlabel; struct pipe *pipe; + struct prison *pr; struct socket *so; struct file *fp; struct mount *mp; @@ -548,6 +571,27 @@ 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_socket_label_free(intlabel); + break; + default: error = EINVAL; }