1 /*- 2 * Copyright (c) 2025 Kyle Evans <kevans@FreeBSD.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7 #include <sys/cdefs.h> 8 #include "opt_mac.h" 9 10 #include <sys/param.h> 11 #include <sys/condvar.h> 12 #include <sys/imgact.h> 13 #include <sys/jail.h> 14 #include <sys/kernel.h> 15 #include <sys/lock.h> 16 #include <sys/malloc.h> 17 #include <sys/mutex.h> 18 #include <sys/mac.h> 19 #include <sys/proc.h> 20 #include <sys/sbuf.h> 21 #include <sys/sdt.h> 22 #include <sys/systm.h> 23 #include <sys/vnode.h> 24 #include <sys/mount.h> 25 #include <sys/file.h> 26 #include <sys/namei.h> 27 #include <sys/sysctl.h> 28 29 #include <security/mac/mac_framework.h> 30 #include <security/mac/mac_internal.h> 31 #include <security/mac/mac_policy.h> 32 33 void 34 mac_prison_label_free(struct label *label) 35 { 36 if (label == NULL) 37 return; 38 39 MAC_POLICY_PERFORM_NOSLEEP(prison_destroy_label, label); 40 mac_labelzone_free(label); 41 } 42 43 struct label * 44 mac_prison_label_alloc(int flag) 45 { 46 struct label *label; 47 int error; 48 49 label = mac_labelzone_alloc(flag); 50 if (label == NULL) 51 return (NULL); 52 53 if (flag & M_WAITOK) 54 MAC_POLICY_CHECK(prison_init_label, label, flag); 55 else 56 MAC_POLICY_CHECK_NOSLEEP(prison_init_label, label, flag); 57 if (error) { 58 mac_prison_label_free(label); 59 return (NULL); 60 } 61 return (label); 62 } 63 64 /* 65 * The caller's expecting us to return with the prison locked if we were 66 * successful, since we're also setting pr->pr_label. On error, it remains 67 * unlocked. 68 */ 69 int 70 mac_prison_init(struct prison *pr, int flag) 71 { 72 struct label *prlabel; 73 74 mtx_assert(&pr->pr_mtx, MA_NOTOWNED); 75 if ((mac_labeled & MPC_OBJECT_PRISON) == 0) { 76 mtx_lock(&pr->pr_mtx); 77 pr->pr_label = NULL; 78 return (0); 79 } 80 81 prlabel = mac_prison_label_alloc(flag); 82 if (prlabel == NULL) { 83 KASSERT((flag & M_WAITOK) == 0, 84 ("MAC policy prison_init_label failed under M_WAITOK")); 85 return (ENOMEM); 86 } 87 88 mtx_lock(&pr->pr_mtx); 89 pr->pr_label = prlabel; 90 return (0); 91 } 92 93 void 94 mac_prison_destroy(struct prison *pr) 95 { 96 mtx_assert(&pr->pr_mtx, MA_OWNED); 97 98 /* Symmetry with prison_created */ 99 MAC_POLICY_PERFORM_NOSLEEP(prison_cleanup, curthread->td_ucred, pr); 100 mac_prison_label_free(pr->pr_label); 101 pr->pr_label = NULL; 102 } 103 104 void 105 mac_prison_copy_label(struct label *src, struct label *dest) 106 { 107 108 MAC_POLICY_PERFORM_NOSLEEP(prison_copy_label, src, dest); 109 } 110 111 int 112 mac_prison_externalize_label(struct label *label, char *elements, 113 char *outbuf, size_t outbuflen) 114 { 115 int error; 116 117 MAC_POLICY_EXTERNALIZE(prison, label, elements, outbuf, outbuflen); 118 return (error); 119 } 120 121 int 122 mac_prison_internalize_label(struct label *label, char *string) 123 { 124 int error; 125 126 MAC_POLICY_INTERNALIZE(prison, label, string); 127 return (error); 128 } 129 130 void 131 mac_prison_relabel(struct ucred *cred, struct prison *pr, 132 struct label *newlabel) 133 { 134 mtx_assert(&pr->pr_mtx, MA_OWNED); 135 MAC_POLICY_PERFORM_NOSLEEP(prison_relabel, cred, pr, pr->pr_label, 136 newlabel); 137 } 138 139 int 140 mac_prison_label_set(struct ucred *cred, struct prison *pr, 141 struct label *label) 142 { 143 int error; 144 145 mtx_assert(&pr->pr_mtx, MA_OWNED); 146 147 error = mac_prison_check_relabel(cred, pr, label); 148 if (error) 149 return (error); 150 151 mac_prison_relabel(cred, pr, label); 152 153 return (0); 154 } 155 156 MAC_CHECK_PROBE_DEFINE4(prison_check_relabel, "struct ucred *", 157 "struct prison *", "struct label *", "struct label *"); 158 int 159 mac_prison_check_relabel(struct ucred *cred, struct prison *pr, 160 struct label *newlabel) 161 { 162 int error; 163 164 mtx_assert(&pr->pr_mtx, MA_OWNED); 165 MAC_POLICY_CHECK_NOSLEEP(prison_check_relabel, cred, pr, 166 pr->pr_label, newlabel); 167 MAC_CHECK_PROBE4(prison_check_relabel, error, cred, pr, 168 pr->pr_label, newlabel); 169 170 return (error); 171 } 172 173 MAC_CHECK_PROBE_DEFINE3(prison_check_attach, "struct ucred *", 174 "struct prison *", "struct label *"); 175 int 176 mac_prison_check_attach(struct ucred *cred, struct prison *pr) 177 { 178 int error; 179 180 MAC_POLICY_CHECK_NOSLEEP(prison_check_attach, cred, pr, pr->pr_label); 181 MAC_CHECK_PROBE3(prison_check_attach, error, cred, pr, pr->pr_label); 182 183 return (error); 184 } 185 186 MAC_CHECK_PROBE_DEFINE3(prison_check_create, "struct ucred *", 187 "struct vfsoptlist *", "int"); 188 int 189 mac_prison_check_create(struct ucred *cred, struct vfsoptlist *opts, 190 int flags) 191 { 192 int error; 193 194 MAC_POLICY_CHECK_NOSLEEP(prison_check_create, cred, opts, flags); 195 MAC_CHECK_PROBE3(prison_check_create, error, cred, opts, flags); 196 197 return (error); 198 } 199 200 MAC_CHECK_PROBE_DEFINE5(prison_check_get, "struct ucred *", 201 "struct prison *", "struct label *", "struct vfsoptlist *", "int"); 202 int 203 mac_prison_check_get(struct ucred *cred, struct prison *pr, 204 struct vfsoptlist *opts, int flags) 205 { 206 int error; 207 208 MAC_POLICY_CHECK_NOSLEEP(prison_check_get, cred, pr, pr->pr_label, 209 opts, flags); 210 MAC_CHECK_PROBE5(prison_check_get, error, cred, pr, pr->pr_label, opts, 211 flags); 212 213 return (error); 214 } 215 216 MAC_CHECK_PROBE_DEFINE5(prison_check_set, "struct ucred *", 217 "struct prison *", "struct label *", "struct vfsoptlist *", "int"); 218 int 219 mac_prison_check_set(struct ucred *cred, struct prison *pr, 220 struct vfsoptlist *opts, int flags) 221 { 222 int error; 223 224 MAC_POLICY_CHECK_NOSLEEP(prison_check_set, cred, pr, pr->pr_label, 225 opts, flags); 226 MAC_CHECK_PROBE5(prison_check_set, error, cred, pr, pr->pr_label, opts, 227 flags); 228 229 return (error); 230 } 231 232 MAC_CHECK_PROBE_DEFINE3(prison_check_remove, "struct ucred *", 233 "struct prison *", "struct label *"); 234 int 235 mac_prison_check_remove(struct ucred *cred, struct prison *pr) 236 { 237 int error; 238 239 MAC_POLICY_CHECK_NOSLEEP(prison_check_remove, cred, pr, pr->pr_label); 240 MAC_CHECK_PROBE3(prison_check_remove, error, cred, pr, pr->pr_label); 241 242 return (error); 243 } 244 245 void 246 mac_prison_created(struct ucred *cred, struct prison *pr) 247 { 248 249 MAC_POLICY_PERFORM(prison_created, cred, pr, pr->pr_label); 250 } 251 252 void 253 mac_prison_attached(struct ucred *cred, struct prison *pr, struct proc *p) 254 { 255 256 MAC_POLICY_PERFORM(prison_attached, cred, pr, pr->pr_label, p, 257 p->p_label); 258 } 259