1/* 2 * Copyright (c) 2006-2007 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 30 * Copyright (c) 2001 Ilmar S. Habibulin 31 * Copyright (c) 2001, 2002, 2003, 2004 Networks Associates Technology, Inc. 32 * 33 * This software was developed by Robert Watson and Ilmar Habibulin for the 34 * TrustedBSD Project. 35 * 36 * This software was developed for the FreeBSD Project in part by Network 37 * Associates Laboratories, the Security Research Division of Network 38 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 39 * as part of the DARPA CHATS research program. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 50 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 60 * SUCH DAMAGE. 61 * 62 */ 63#include <sys/param.h> 64#include <sys/types.h> 65#include <sys/vnode.h> 66#include <sys/vnode_internal.h> 67#include <sys/kauth.h> 68#include <sys/queue.h> 69#include <security/mac_internal.h> 70#include <bsd/bsm/audit.h> 71#include <bsd/security/audit/audit.h> 72#include <bsd/sys/malloc.h> 73#include <vm/vm_kern.h> 74#include <kern/kalloc.h> 75#include <kern/zalloc.h> 76 77#if CONFIG_AUDIT 78 79/* The zone allocator is initialized in mac_base.c. */ 80zone_t mac_audit_data_zone; 81 82int 83mac_system_check_audit(struct ucred *cred, void *record, int length) 84{ 85 int error; 86 87 MAC_CHECK(system_check_audit, cred, record, length); 88 89 return (error); 90} 91 92int 93mac_system_check_auditon(struct ucred *cred, int cmd) 94{ 95 int error; 96 97 MAC_CHECK(system_check_auditon, cred, cmd); 98 99 return (error); 100} 101 102int 103mac_system_check_auditctl(struct ucred *cred, struct vnode *vp) 104{ 105 int error; 106 struct label *vl = vp ? vp->v_label : NULL; 107 108 MAC_CHECK(system_check_auditctl, cred, vp, vl); 109 110 return (error); 111} 112 113int 114mac_proc_check_getauid(struct proc *curp) 115{ 116 kauth_cred_t cred; 117 int error; 118 119 if (!mac_proc_enforce || 120 !mac_proc_check_enforce(curp, MAC_PROC_ENFORCE)) 121 return 0; 122 123 cred = kauth_cred_proc_ref(curp); 124 MAC_CHECK(proc_check_getauid, cred); 125 kauth_cred_unref(&cred); 126 127 return (error); 128} 129 130int 131mac_proc_check_setauid(struct proc *curp, uid_t auid) 132{ 133 kauth_cred_t cred; 134 int error; 135 136 if (!mac_proc_enforce || 137 !mac_proc_check_enforce(curp, MAC_PROC_ENFORCE)) 138 return 0; 139 140 cred = kauth_cred_proc_ref(curp); 141 MAC_CHECK(proc_check_setauid, cred, auid); 142 kauth_cred_unref(&cred); 143 144 return (error); 145} 146 147int 148mac_proc_check_getaudit(struct proc *curp) 149{ 150 kauth_cred_t cred; 151 int error; 152 153 if (!mac_proc_enforce || 154 !mac_proc_check_enforce(curp, MAC_PROC_ENFORCE)) 155 return 0; 156 157 cred = kauth_cred_proc_ref(curp); 158 MAC_CHECK(proc_check_getaudit, cred); 159 kauth_cred_unref(&cred); 160 161 return (error); 162} 163 164int 165mac_proc_check_setaudit(struct proc *curp, struct auditinfo_addr *ai) 166{ 167 kauth_cred_t cred; 168 int error; 169 170 if (!mac_proc_enforce || 171 !mac_proc_check_enforce(curp, MAC_PROC_ENFORCE)) 172 return 0; 173 174 cred = kauth_cred_proc_ref(curp); 175 MAC_CHECK(proc_check_setaudit, cred, ai); 176 kauth_cred_unref(&cred); 177 178 return (error); 179} 180 181#if 0 182/* 183 * This is the framework entry point for MAC policies to use to add 184 * arbitrary data to the current audit record. 185 * (Currently not supported, as no existing audit viewers would 186 * display this format) 187 * 188 */ 189int 190mac_audit_data(int len, u_char *data, mac_policy_handle_t handle) 191{ 192 char *sanitized; 193 194 if ((len <= 0) || (len > MAC_AUDIT_DATA_LIMIT)) 195 return (EINVAL); 196 197 sanitized = (char *)zalloc(mac_audit_data_zone); 198 199 bcopy(data, sanitized, len); 200 return (audit_mac_data(MAC_AUDIT_DATA_TYPE, len, sanitized)); 201} 202#endif 203 204/* 205 * This is the entry point a MAC policy will call to add NULL- 206 * terminated ASCII text to the current audit record. 207 */ 208int 209mac_audit_text(char *text, mac_policy_handle_t handle) 210{ 211 char *sanitized; 212 const char *name; 213 int i, size, plen, len; 214 215 name = mac_get_mpc(handle)->mpc_name; 216 len = strlen(text); 217 plen = 2 + strlen(name); 218 if (plen + len >= MAC_AUDIT_DATA_LIMIT) 219 return (EINVAL); 220 221 /* 222 * Make sure the text is only composed of only ASCII printable 223 * characters. 224 */ 225 for (i=0; i < len; i++) 226 if (text[i] < (char) 32 || text[i] > (char) 126) 227 return (EINVAL); 228 229 size = len + plen + 1; 230 sanitized = (char *)zalloc(mac_audit_data_zone); 231 232 strlcpy(sanitized, name, MAC_AUDIT_DATA_LIMIT); 233 strncat(sanitized, ": ", MAC_AUDIT_DATA_LIMIT - plen + 2); 234 strncat(sanitized, text, MAC_AUDIT_DATA_LIMIT - plen); 235 236 return (audit_mac_data(MAC_AUDIT_TEXT_TYPE, size, (u_char *)sanitized)); 237} 238 239int 240mac_audit_check_preselect(struct ucred *cred, unsigned short syscode, void *args) 241{ 242 struct mac_policy_conf *mpc; 243 int ret, error; 244 u_int i; 245 246 ret = MAC_AUDIT_DEFAULT; 247 for (i = 0; i < mac_policy_list.staticmax; i++) { 248 mpc = mac_policy_list.entries[i].mpc; 249 if (mpc == NULL) 250 continue; 251 252 if (mpc->mpc_ops->mpo_audit_check_preselect != NULL) { 253 error = mpc->mpc_ops->mpo_audit_check_preselect(cred, 254 syscode, args); 255 ret = (ret > error ? ret : error); 256 } 257 } 258 if (mac_policy_list_conditional_busy() != 0) { 259 for (; i <= mac_policy_list.maxindex; i++) { 260 mpc = mac_policy_list.entries[i].mpc; 261 if (mpc == NULL) 262 continue; 263 264 if (mpc->mpc_ops->mpo_audit_check_preselect != NULL) { 265 error = mpc->mpc_ops->mpo_audit_check_preselect(cred, 266 syscode, args); 267 ret = (ret > error ? ret : error); 268 } 269 } 270 mac_policy_list_unbusy(); 271 } 272 273 return (ret); 274} 275 276int 277mac_audit_check_postselect(struct ucred *cred, unsigned short syscode, 278 void *args, int error, int retval, int mac_forced) 279{ 280 struct mac_policy_conf *mpc; 281 int ret, mac_error; 282 u_int i; 283 284 /* 285 * If the audit was forced by a MAC policy by mac_audit_check_preselect(), 286 * echo that. 287 */ 288 if (mac_forced) 289 return (MAC_AUDIT_YES); 290 291 ret = MAC_AUDIT_DEFAULT; 292 for (i = 0; i < mac_policy_list.staticmax; i++) { 293 mpc = mac_policy_list.entries[i].mpc; 294 if (mpc == NULL) 295 continue; 296 297 if (mpc->mpc_ops->mpo_audit_check_postselect != NULL) { 298 mac_error = mpc->mpc_ops->mpo_audit_check_postselect(cred, 299 syscode, args, error, retval); 300 ret = (ret > mac_error ? ret : mac_error); 301 } 302 } 303 if (mac_policy_list_conditional_busy() != 0) { 304 for (; i <= mac_policy_list.maxindex; i++) { 305 mpc = mac_policy_list.entries[i].mpc; 306 if (mpc == NULL) 307 continue; 308 309 if (mpc->mpc_ops->mpo_audit_check_postselect != NULL) { 310 mac_error = mpc->mpc_ops->mpo_audit_check_postselect(cred, 311 syscode, args, error, retval); 312 ret = (ret > mac_error ? ret : mac_error); 313 } 314 } 315 mac_policy_list_unbusy(); 316 } 317 318 return (ret); 319} 320 321#else /* !CONFIG_AUDIT */ 322 323/* 324 * Function stubs for when AUDIT isn't defined. 325 */ 326 327int 328mac_system_check_audit(__unused struct ucred *cred, __unused void *record, __unused int length) 329{ 330 331 return (0); 332} 333 334int 335mac_system_check_auditon(__unused struct ucred *cred, __unused int cmd) 336{ 337 338 return (0); 339} 340 341int 342mac_system_check_auditctl(__unused struct ucred *cred, __unused struct vnode *vp) 343{ 344 345 return (0); 346} 347 348int 349mac_proc_check_getauid(__unused struct proc *curp) 350{ 351 352 return (0); 353} 354 355int 356mac_proc_check_setauid(__unused struct proc *curp, __unused uid_t auid) 357{ 358 359 return (0); 360} 361 362int 363mac_proc_check_getaudit(__unused struct proc *curp) 364{ 365 366 return (0); 367} 368 369int 370mac_proc_check_setaudit(__unused struct proc *curp, 371 __unused struct auditinfo_addr *ai) 372{ 373 374 return (0); 375} 376 377int 378mac_audit_check_preselect(__unused struct ucred *cred, __unused unsigned short syscode, 379 __unused void *args) 380{ 381 382 return (MAC_AUDIT_DEFAULT); 383} 384 385int 386mac_audit_check_postselect(__unused struct ucred *cred, __unused unsigned short syscode, 387 __unused void *args, __unused int error, __unused int retval, __unused int mac_forced) 388{ 389 390 return (MAC_AUDIT_DEFAULT); 391} 392 393int 394mac_audit_text(__unused char *text, __unused mac_policy_handle_t handle) 395{ 396 return (0); 397} 398#endif /* !CONFIG_AUDIT */ 399