1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 3679 tz204579 * Common Development and Distribution License (the "License"). 6 3679 tz204579 * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 10210 Paul * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel /* 27 0 stevel * This file contains the auditing system call code. 28 0 stevel * 29 0 stevel */ 30 0 stevel 31 0 stevel 32 0 stevel #include <sys/param.h> 33 0 stevel #include <sys/systm.h> 34 0 stevel #include <sys/user.h> 35 0 stevel #include <sys/vnode.h> 36 0 stevel #include <sys/vfs.h> 37 0 stevel #include <sys/session.h> /* for session structure (auditctl(2) */ 38 0 stevel #include <sys/kmem.h> /* for KM_SLEEP */ 39 11134 Casper #include <sys/cred.h> 40 0 stevel #include <sys/types.h> 41 0 stevel #include <sys/proc.h> 42 0 stevel #include <sys/uio.h> 43 0 stevel #include <sys/file.h> 44 0 stevel #include <sys/stat.h> 45 0 stevel #include <sys/pathname.h> 46 0 stevel #include <sys/acct.h> 47 0 stevel #include <sys/stropts.h> 48 0 stevel #include <sys/exec.h> 49 0 stevel #include <sys/thread.h> 50 0 stevel #include <sys/cmn_err.h> 51 0 stevel #include <sys/debug.h> 52 0 stevel #include <sys/disp.h> 53 0 stevel #include <sys/kobj.h> 54 0 stevel #include <sys/sysmacros.h> 55 0 stevel #include <sys/policy.h> 56 0 stevel #include <sys/taskq.h> 57 0 stevel #include <sys/zone.h> 58 0 stevel 59 0 stevel #include <c2/audit.h> 60 0 stevel #include <c2/audit_kernel.h> 61 0 stevel #include <c2/audit_record.h> 62 0 stevel 63 0 stevel #define CLEAR_VAL -1 64 0 stevel 65 0 stevel #define HEADER_SIZE64 1; 66 0 stevel #define HEADER_SIZE32 0; 67 0 stevel #define AU_MIN_FILE_SZ 0x80000 /* minumum audit file size */ 68 0 stevel #define AUDIT_REC_SIZE 0x8000 /* maximum user audit record size */ 69 0 stevel 70 0 stevel extern kmutex_t pidlock; 71 0 stevel 72 0 stevel extern pri_t minclsyspri; /* priority for taskq */ 73 0 stevel 74 0 stevel extern int audit_load; /* defined in audit_start.c */ 75 0 stevel 76 0 stevel int au_auditstate = AUC_UNSET; /* global audit state */ 77 0 stevel int audit_policy; /* global audit policies in force */ 78 0 stevel static clock_t au_resid = 15; /* wait .15 sec before droping a rec */ 79 0 stevel 80 0 stevel static int getauid(caddr_t); 81 0 stevel static int setauid(caddr_t); 82 0 stevel static int getaudit(caddr_t); 83 0 stevel static int getaudit_addr(caddr_t, int); 84 0 stevel static int setaudit(caddr_t); 85 0 stevel static int setaudit_addr(caddr_t, int); 86 0 stevel static int auditdoor(int); 87 0 stevel static int auditctl(int, caddr_t, int); 88 0 stevel static int audit_modsysent(char *, int, int (*)()); 89 0 stevel static void au_output_thread(); 90 0 stevel /* 91 0 stevel * This is the loadable module wrapper. 92 0 stevel */ 93 0 stevel #include <sys/modctl.h> 94 0 stevel #include "sys/syscall.h" 95 0 stevel 96 0 stevel static struct sysent auditsysent = { 97 0 stevel 6, 98 0 stevel 0, 99 0 stevel _auditsys 100 0 stevel }; 101 0 stevel 102 0 stevel /* 103 0 stevel * Module linkage information for the kernel. 104 0 stevel */ 105 0 stevel extern struct mod_ops mod_syscallops; 106 0 stevel 107 0 stevel static struct modlsys modlsys = { 108 0 stevel &mod_syscallops, "C2 system call", &auditsysent 109 0 stevel }; 110 0 stevel 111 0 stevel static struct modlinkage modlinkage = { 112 0 stevel MODREV_1, (void *)&modlsys, 0 113 0 stevel }; 114 0 stevel 115 0 stevel int 116 0 stevel _init() 117 0 stevel { 118 0 stevel int retval; 119 0 stevel 120 0 stevel if (audit_load == 0) 121 0 stevel return (-1); 122 0 stevel 123 0 stevel /* 124 0 stevel * We are going to do an ugly thing here. 125 0 stevel * Because auditsys is already defined as a regular 126 0 stevel * syscall we have to change the definition for syscall 127 0 stevel * auditsys. Basically or in the SE_LOADABLE flag for 128 0 stevel * auditsys. We no have a static loadable syscall. Also 129 0 stevel * create an rw_lock. 130 0 stevel */ 131 0 stevel 132 5992 gww if ((audit_modsysent("c2audit", SE_LOADABLE|SE_NOUNLOAD, 133 5992 gww _auditsys)) == -1) 134 0 stevel return (-1); 135 0 stevel 136 0 stevel if ((retval = mod_install(&modlinkage)) != 0) 137 0 stevel return (retval); 138 0 stevel 139 0 stevel return (0); 140 0 stevel } 141 0 stevel 142 0 stevel int 143 0 stevel _fini() 144 0 stevel { 145 0 stevel return (EBUSY); 146 0 stevel } 147 0 stevel 148 0 stevel int 149 0 stevel _info(struct modinfo *modinfop) 150 0 stevel { 151 0 stevel return (mod_info(&modlinkage, modinfop)); 152 0 stevel } 153 0 stevel 154 0 stevel /* 155 0 stevel * when auditing is updated to allow enable/disable without 156 0 stevel * reboot (and when the audit stubs are removed) *most* of these 157 0 stevel * calls should return an error when auditing is off -- some 158 0 stevel * for local zones only. 159 0 stevel */ 160 0 stevel 161 0 stevel int 162 0 stevel _auditsys(struct auditcalls *uap, rval_t *rvp) 163 0 stevel { 164 0 stevel int result = 0; 165 0 stevel 166 0 stevel switch (uap->code) { 167 0 stevel case BSM_GETAUID: 168 0 stevel result = getauid((caddr_t)uap->a1); 169 0 stevel break; 170 0 stevel case BSM_SETAUID: 171 0 stevel result = setauid((caddr_t)uap->a1); 172 0 stevel break; 173 0 stevel case BSM_GETAUDIT: 174 0 stevel result = getaudit((caddr_t)uap->a1); 175 0 stevel break; 176 0 stevel case BSM_GETAUDIT_ADDR: 177 0 stevel 178 0 stevel result = getaudit_addr((caddr_t)uap->a1, (int)uap->a2); 179 0 stevel break; 180 0 stevel case BSM_SETAUDIT: 181 0 stevel result = setaudit((caddr_t)uap->a1); 182 0 stevel break; 183 0 stevel case BSM_SETAUDIT_ADDR: 184 0 stevel result = setaudit_addr((caddr_t)uap->a1, (int)uap->a2); 185 0 stevel break; 186 0 stevel case BSM_AUDIT: 187 0 stevel result = audit((caddr_t)uap->a1, (int)uap->a2); 188 0 stevel break; 189 0 stevel case BSM_AUDITDOOR: 190 0 stevel result = auditdoor((int)uap->a1); 191 0 stevel break; 192 0 stevel case BSM_AUDITON: 193 0 stevel case BSM_AUDITCTL: 194 0 stevel result = auditctl((int)uap->a1, (caddr_t)uap->a2, (int)uap->a3); 195 0 stevel break; 196 0 stevel default: 197 0 stevel result = EINVAL; 198 0 stevel } 199 0 stevel rvp->r_vals = result; 200 0 stevel return (result); 201 0 stevel } 202 0 stevel 203 0 stevel /* 204 0 stevel * Return the audit user ID for the current process. Currently only 205 0 stevel * the privileged processes may see the audit id. That may change. 206 0 stevel * If copyout is unsucessful return EFAULT. 207 0 stevel */ 208 0 stevel static int 209 0 stevel getauid(caddr_t auid_p) 210 0 stevel { 211 0 stevel const auditinfo_addr_t *ainfo; 212 0 stevel 213 0 stevel if (secpolicy_audit_getattr(CRED()) != 0) 214 0 stevel return (EPERM); 215 0 stevel 216 0 stevel ainfo = crgetauinfo(CRED()); 217 0 stevel if (ainfo == NULL) 218 0 stevel return (EINVAL); 219 0 stevel 220 0 stevel if (copyout(&ainfo->ai_auid, auid_p, sizeof (au_id_t))) 221 0 stevel return (EFAULT); 222 0 stevel 223 0 stevel return (0); 224 0 stevel } 225 0 stevel 226 0 stevel /* 227 0 stevel * Set the audit userid, for a process. This can only be changed by 228 0 stevel * privileged processes. The audit userid is inherited across forks & execs. 229 0 stevel * Passed in is a pointer to the au_id_t; if copyin unsuccessful return EFAULT. 230 0 stevel */ 231 0 stevel static int 232 0 stevel setauid(caddr_t auid_p) 233 0 stevel { 234 0 stevel proc_t *p; 235 0 stevel au_id_t auid; 236 0 stevel cred_t *newcred; 237 0 stevel auditinfo_addr_t *auinfo; 238 0 stevel 239 0 stevel if (secpolicy_audit_config(CRED()) != 0) 240 0 stevel return (EPERM); 241 0 stevel 242 0 stevel if (copyin(auid_p, &auid, sizeof (au_id_t))) { 243 0 stevel return (EFAULT); 244 0 stevel } 245 0 stevel 246 0 stevel newcred = cralloc(); 247 0 stevel if ((auinfo = crgetauinfo_modifiable(newcred)) == NULL) { 248 0 stevel crfree(newcred); 249 0 stevel return (EINVAL); 250 0 stevel } 251 0 stevel 252 0 stevel /* grab p_crlock and switch to new cred */ 253 0 stevel p = curproc; 254 0 stevel mutex_enter(&p->p_crlock); 255 0 stevel crcopy_to(p->p_cred, newcred); 256 0 stevel p->p_cred = newcred; 257 0 stevel 258 0 stevel auinfo->ai_auid = auid; /* update the auid */ 259 0 stevel 260 0 stevel /* unlock and broadcast the cred changes */ 261 0 stevel mutex_exit(&p->p_crlock); 262 0 stevel crset(p, newcred); 263 0 stevel 264 0 stevel return (0); 265 0 stevel } 266 0 stevel 267 0 stevel /* 268 0 stevel * Get the audit state information from the current process. 269 0 stevel * Return EFAULT if copyout fails. 270 0 stevel */ 271 0 stevel static int 272 0 stevel getaudit(caddr_t info_p) 273 0 stevel { 274 0 stevel STRUCT_DECL(auditinfo, info); 275 0 stevel const auditinfo_addr_t *ainfo; 276 0 stevel model_t model; 277 0 stevel 278 0 stevel if (secpolicy_audit_getattr(CRED()) != 0) 279 0 stevel return (EPERM); 280 0 stevel 281 0 stevel model = get_udatamodel(); 282 0 stevel STRUCT_INIT(info, model); 283 0 stevel 284 0 stevel ainfo = crgetauinfo(CRED()); 285 0 stevel if (ainfo == NULL) 286 0 stevel return (EINVAL); 287 0 stevel 288 0 stevel /* trying to read a process with an IPv6 address? */ 289 0 stevel if (ainfo->ai_termid.at_type == AU_IPv6) 290 0 stevel return (EOVERFLOW); 291 0 stevel 292 0 stevel STRUCT_FSET(info, ai_auid, ainfo->ai_auid); 293 0 stevel STRUCT_FSET(info, ai_mask, ainfo->ai_mask); 294 0 stevel #ifdef _LP64 295 0 stevel if (model == DATAMODEL_ILP32) { 296 0 stevel dev32_t dev; 297 0 stevel /* convert internal 64 bit form to 32 bit version */ 298 0 stevel if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) { 299 0 stevel return (EOVERFLOW); 300 0 stevel } 301 0 stevel STRUCT_FSET(info, ai_termid.port, dev); 302 0 stevel } else 303 0 stevel STRUCT_FSET(info, ai_termid.port, ainfo->ai_termid.at_port); 304 0 stevel #else 305 0 stevel STRUCT_FSET(info, ai_termid.port, ainfo->ai_termid.at_port); 306 0 stevel #endif 307 0 stevel STRUCT_FSET(info, ai_termid.machine, ainfo->ai_termid.at_addr[0]); 308 0 stevel STRUCT_FSET(info, ai_asid, ainfo->ai_asid); 309 0 stevel 310 0 stevel if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info))) 311 0 stevel return (EFAULT); 312 0 stevel 313 0 stevel return (0); 314 0 stevel } 315 0 stevel 316 0 stevel /* 317 0 stevel * Get the audit state information from the current process. 318 0 stevel * Return EFAULT if copyout fails. 319 0 stevel */ 320 0 stevel static int 321 0 stevel getaudit_addr(caddr_t info_p, int len) 322 0 stevel { 323 0 stevel STRUCT_DECL(auditinfo_addr, info); 324 0 stevel const auditinfo_addr_t *ainfo; 325 0 stevel model_t model; 326 0 stevel 327 0 stevel if (secpolicy_audit_getattr(CRED()) != 0) 328 0 stevel return (EPERM); 329 0 stevel 330 0 stevel model = get_udatamodel(); 331 0 stevel STRUCT_INIT(info, model); 332 0 stevel 333 0 stevel if (len < STRUCT_SIZE(info)) 334 0 stevel return (EOVERFLOW); 335 0 stevel 336 0 stevel ainfo = crgetauinfo(CRED()); 337 0 stevel 338 0 stevel if (ainfo == NULL) 339 0 stevel return (EINVAL); 340 0 stevel 341 0 stevel STRUCT_FSET(info, ai_auid, ainfo->ai_auid); 342 0 stevel STRUCT_FSET(info, ai_mask, ainfo->ai_mask); 343 0 stevel #ifdef _LP64 344 0 stevel if (model == DATAMODEL_ILP32) { 345 0 stevel dev32_t dev; 346 0 stevel /* convert internal 64 bit form to 32 bit version */ 347 0 stevel if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) { 348 0 stevel return (EOVERFLOW); 349 0 stevel } 350 0 stevel STRUCT_FSET(info, ai_termid.at_port, dev); 351 0 stevel } else 352 0 stevel STRUCT_FSET(info, ai_termid.at_port, ainfo->ai_termid.at_port); 353 0 stevel #else 354 0 stevel STRUCT_FSET(info, ai_termid.at_port, ainfo->ai_termid.at_port); 355 0 stevel #endif 356 0 stevel STRUCT_FSET(info, ai_termid.at_type, ainfo->ai_termid.at_type); 357 0 stevel STRUCT_FSET(info, ai_termid.at_addr[0], ainfo->ai_termid.at_addr[0]); 358 0 stevel STRUCT_FSET(info, ai_termid.at_addr[1], ainfo->ai_termid.at_addr[1]); 359 0 stevel STRUCT_FSET(info, ai_termid.at_addr[2], ainfo->ai_termid.at_addr[2]); 360 0 stevel STRUCT_FSET(info, ai_termid.at_addr[3], ainfo->ai_termid.at_addr[3]); 361 0 stevel STRUCT_FSET(info, ai_asid, ainfo->ai_asid); 362 0 stevel 363 0 stevel if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info))) 364 0 stevel return (EFAULT); 365 0 stevel 366 0 stevel return (0); 367 0 stevel } 368 0 stevel 369 0 stevel /* 370 0 stevel * Set the audit state information for the current process. 371 0 stevel * Return EFAULT if copyout fails. 372 0 stevel */ 373 0 stevel static int 374 0 stevel setaudit(caddr_t info_p) 375 0 stevel { 376 0 stevel STRUCT_DECL(auditinfo, info); 377 0 stevel proc_t *p; 378 0 stevel cred_t *newcred; 379 0 stevel model_t model; 380 0 stevel auditinfo_addr_t *ainfo; 381 0 stevel 382 0 stevel if (secpolicy_audit_config(CRED()) != 0) 383 0 stevel return (EPERM); 384 0 stevel 385 0 stevel model = get_udatamodel(); 386 0 stevel STRUCT_INIT(info, model); 387 0 stevel 388 0 stevel if (copyin(info_p, STRUCT_BUF(info), STRUCT_SIZE(info))) 389 0 stevel return (EFAULT); 390 0 stevel 391 0 stevel newcred = cralloc(); 392 0 stevel if ((ainfo = crgetauinfo_modifiable(newcred)) == NULL) { 393 0 stevel crfree(newcred); 394 0 stevel return (EINVAL); 395 0 stevel } 396 0 stevel 397 0 stevel /* grab p_crlock and switch to new cred */ 398 0 stevel p = curproc; 399 0 stevel mutex_enter(&p->p_crlock); 400 0 stevel crcopy_to(p->p_cred, newcred); 401 0 stevel p->p_cred = newcred; 402 0 stevel 403 0 stevel /* Set audit mask, id, termid and session id as specified */ 404 0 stevel ainfo->ai_auid = STRUCT_FGET(info, ai_auid); 405 0 stevel #ifdef _LP64 406 0 stevel /* only convert to 64 bit if coming from a 32 bit binary */ 407 0 stevel if (model == DATAMODEL_ILP32) 408 0 stevel ainfo->ai_termid.at_port = 409 5992 gww DEVEXPL(STRUCT_FGET(info, ai_termid.port)); 410 0 stevel else 411 0 stevel ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.port); 412 0 stevel #else 413 0 stevel ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.port); 414 0 stevel #endif 415 0 stevel ainfo->ai_termid.at_type = AU_IPv4; 416 0 stevel ainfo->ai_termid.at_addr[0] = STRUCT_FGET(info, ai_termid.machine); 417 0 stevel ainfo->ai_asid = STRUCT_FGET(info, ai_asid); 418 0 stevel ainfo->ai_mask = STRUCT_FGET(info, ai_mask); 419 0 stevel 420 0 stevel /* unlock and broadcast the cred changes */ 421 0 stevel mutex_exit(&p->p_crlock); 422 0 stevel crset(p, newcred); 423 0 stevel 424 0 stevel return (0); 425 0 stevel } 426 0 stevel 427 0 stevel /* 428 0 stevel * Set the audit state information for the current process. 429 0 stevel * Return EFAULT if copyin fails. 430 0 stevel */ 431 0 stevel static int 432 0 stevel setaudit_addr(caddr_t info_p, int len) 433 0 stevel { 434 0 stevel STRUCT_DECL(auditinfo_addr, info); 435 0 stevel proc_t *p; 436 0 stevel cred_t *newcred; 437 0 stevel model_t model; 438 0 stevel int i; 439 0 stevel int type; 440 0 stevel auditinfo_addr_t *ainfo; 441 0 stevel 442 0 stevel if (secpolicy_audit_config(CRED()) != 0) 443 0 stevel return (EPERM); 444 0 stevel 445 0 stevel model = get_udatamodel(); 446 0 stevel STRUCT_INIT(info, model); 447 0 stevel 448 0 stevel if (len < STRUCT_SIZE(info)) 449 0 stevel return (EOVERFLOW); 450 0 stevel 451 0 stevel if (copyin(info_p, STRUCT_BUF(info), STRUCT_SIZE(info))) 452 0 stevel return (EFAULT); 453 0 stevel 454 0 stevel type = STRUCT_FGET(info, ai_termid.at_type); 455 0 stevel if ((type != AU_IPv4) && (type != AU_IPv6)) 456 0 stevel return (EINVAL); 457 0 stevel 458 0 stevel newcred = cralloc(); 459 0 stevel if ((ainfo = crgetauinfo_modifiable(newcred)) == NULL) { 460 0 stevel crfree(newcred); 461 0 stevel return (EINVAL); 462 0 stevel } 463 0 stevel 464 0 stevel /* grab p_crlock and switch to new cred */ 465 0 stevel p = curproc; 466 0 stevel mutex_enter(&p->p_crlock); 467 0 stevel crcopy_to(p->p_cred, newcred); 468 0 stevel p->p_cred = newcred; 469 0 stevel 470 0 stevel /* Set audit mask, id, termid and session id as specified */ 471 0 stevel ainfo->ai_auid = STRUCT_FGET(info, ai_auid); 472 0 stevel ainfo->ai_mask = STRUCT_FGET(info, ai_mask); 473 0 stevel #ifdef _LP64 474 0 stevel /* only convert to 64 bit if coming from a 32 bit binary */ 475 0 stevel if (model == DATAMODEL_ILP32) 476 0 stevel ainfo->ai_termid.at_port = 477 5992 gww DEVEXPL(STRUCT_FGET(info, ai_termid.at_port)); 478 0 stevel else 479 0 stevel ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.at_port); 480 0 stevel #else 481 0 stevel ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.at_port); 482 0 stevel #endif 483 0 stevel ainfo->ai_termid.at_type = type; 484 0 stevel bzero(&ainfo->ai_termid.at_addr[0], sizeof (ainfo->ai_termid.at_addr)); 485 0 stevel for (i = 0; i < (type/sizeof (int)); i++) 486 0 stevel ainfo->ai_termid.at_addr[i] = 487 5992 gww STRUCT_FGET(info, ai_termid.at_addr[i]); 488 0 stevel 489 0 stevel if (ainfo->ai_termid.at_type == AU_IPv6 && 490 0 stevel IN6_IS_ADDR_V4MAPPED(((in6_addr_t *)ainfo->ai_termid.at_addr))) { 491 0 stevel ainfo->ai_termid.at_type = AU_IPv4; 492 0 stevel ainfo->ai_termid.at_addr[0] = ainfo->ai_termid.at_addr[3]; 493 0 stevel ainfo->ai_termid.at_addr[1] = 0; 494 0 stevel ainfo->ai_termid.at_addr[2] = 0; 495 0 stevel ainfo->ai_termid.at_addr[3] = 0; 496 0 stevel } 497 0 stevel 498 0 stevel ainfo->ai_asid = STRUCT_FGET(info, ai_asid); 499 0 stevel 500 0 stevel /* unlock and broadcast the cred changes */ 501 0 stevel mutex_exit(&p->p_crlock); 502 0 stevel crset(p, newcred); 503 0 stevel 504 0 stevel return (0); 505 0 stevel } 506 0 stevel 507 0 stevel /* 508 0 stevel * The audit system call. Trust what the user has sent down and save it 509 0 stevel * away in the audit file. User passes a complete audit record and its 510 0 stevel * length. We will fill in the time stamp, check the header and the length 511 0 stevel * Put a trailer and a sequence token if policy requires. 512 0 stevel * In the future length might become size_t instead of an int. 513 0 stevel * 514 0 stevel * The call is valid whether or not AUDIT_PERZONE is set (think of 515 0 stevel * login to a zone). When the local audit state (auk_auditstate) is 516 0 stevel * AUC_INIT_AUDIT, records are accepted even though auditd isn't 517 0 stevel * running. 518 0 stevel */ 519 0 stevel int 520 0 stevel audit(caddr_t record, int length) 521 0 stevel { 522 0 stevel char c; 523 0 stevel int count, l; 524 0 stevel token_t *m, *n, *s, *ad; 525 0 stevel int hdrlen, delta; 526 0 stevel adr_t hadr; 527 0 stevel adr_t sadr; 528 0 stevel int size; /* 0: 32 bit utility 1: 64 bit utility */ 529 0 stevel int host_len; 530 0 stevel size_t zlen; 531 4197 paulson au_kcontext_t *kctx = GET_KCTX_PZ; 532 0 stevel 533 0 stevel /* if auditing not enabled, then don't generate an audit record */ 534 0 stevel if (kctx->auk_auditstate != AUC_AUDITING && 535 0 stevel kctx->auk_auditstate != AUC_INIT_AUDIT) 536 0 stevel return (0); 537 0 stevel 538 0 stevel /* Only privileged processes can audit */ 539 0 stevel if (secpolicy_audit_modify(CRED()) != 0) 540 0 stevel return (EPERM); 541 0 stevel 542 0 stevel /* Max user record size is 32K */ 543 0 stevel if (length > AUDIT_REC_SIZE) 544 0 stevel return (E2BIG); 545 0 stevel 546 0 stevel /* 547 0 stevel * The specified length must be at least as big as the smallest 548 0 stevel * possible header token. Later after beginning to scan the 549 0 stevel * header we'll determine the true minimum length according to 550 0 stevel * the header type and attributes. 551 0 stevel */ 552 0 stevel #define AU_MIN_HEADER_LEN (sizeof (char) + sizeof (int32_t) + \ 553 0 stevel sizeof (char) + sizeof (short) + sizeof (short) + \ 554 0 stevel (sizeof (int32_t) * 2)) 555 0 stevel 556 0 stevel if (length < AU_MIN_HEADER_LEN) 557 0 stevel return (EINVAL); 558 0 stevel 559 0 stevel /* Read in user's audit record */ 560 0 stevel count = length; 561 0 stevel m = n = s = ad = NULL; 562 0 stevel while (count) { 563 0 stevel m = au_getclr(); 564 0 stevel if (!s) 565 0 stevel s = n = m; 566 0 stevel else { 567 0 stevel n->next_buf = m; 568 0 stevel n = m; 569 0 stevel } 570 0 stevel l = MIN(count, AU_BUFSIZE); 571 5992 gww if (copyin(record, memtod(m, caddr_t), (size_t)l)) { 572 5992 gww /* copyin failed release au_membuf */ 573 5992 gww au_free_rec(s); 574 5992 gww return (EFAULT); 575 0 stevel } 576 0 stevel record += l; 577 0 stevel count -= l; 578 0 stevel m->len = (uchar_t)l; 579 0 stevel } 580 0 stevel 581 0 stevel /* Now attach the entire thing to ad */ 582 0 stevel au_write((caddr_t *)&(ad), s); 583 0 stevel 584 0 stevel /* validate header token type. trust everything following it */ 585 0 stevel adr_start(&hadr, memtod(s, char *)); 586 0 stevel (void) adr_getchar(&hadr, &c); 587 0 stevel switch (c) { 588 0 stevel case AUT_HEADER32: 589 0 stevel /* size vers+event_ID+event_modifier fields */ 590 0 stevel delta = 1 + 2 + 2; 591 0 stevel hdrlen = 1 + 4 + delta + (sizeof (int32_t) * 2); 592 0 stevel size = HEADER_SIZE32; 593 0 stevel break; 594 0 stevel 595 0 stevel #ifdef _LP64 596 0 stevel case AUT_HEADER64: 597 0 stevel /* size vers+event_ID+event_modifier fields */ 598 0 stevel delta = 1 + 2 + 2; 599 0 stevel hdrlen = 1 + 4 + delta + (sizeof (int64_t) * 2); 600 0 stevel size = HEADER_SIZE64; 601 0 stevel break; 602 0 stevel #endif 603 0 stevel 604 0 stevel case AUT_HEADER32_EX: 605 0 stevel /* 606 0 stevel * Skip over the length/version/type/mod fields and 607 0 stevel * grab the host address type (length), then rewind. 608 0 stevel * This is safe per the previous minimum length check. 609 0 stevel */ 610 0 stevel hadr.adr_now += 9; 611 0 stevel (void) adr_getint32(&hadr, &host_len); 612 0 stevel hadr.adr_now -= 9 + sizeof (int32_t); 613 0 stevel 614 0 stevel /* size: vers+event_ID+event_modifier+IP_type+IP_addr_array */ 615 0 stevel delta = 1 + 2 + 2 + 4 + host_len; 616 0 stevel hdrlen = 1 + 4 + delta + (sizeof (int32_t) * 2); 617 0 stevel size = HEADER_SIZE32; 618 0 stevel break; 619 0 stevel 620 0 stevel #ifdef _LP64 621 0 stevel case AUT_HEADER64_EX: 622 0 stevel /* 623 0 stevel * Skip over the length/version/type/mod fields and grab 624 0 stevel * the host address type (length), then rewind. 625 0 stevel * This is safe per the previous minimum length check. 626 0 stevel */ 627 0 stevel hadr.adr_now += 9; 628 0 stevel (void) adr_getint32(&hadr, &host_len); 629 0 stevel hadr.adr_now -= 9 + sizeof (int32_t); 630 0 stevel 631 0 stevel /* size: vers+event_ID+event_modifier+IP_type+IP_addr_array */ 632 0 stevel delta = 1 + 2 + 2 + 4 + host_len; 633 0 stevel hdrlen = 1 + 4 + delta + (sizeof (int64_t) * 2); 634 0 stevel size = HEADER_SIZE64; 635 0 stevel break; 636 0 stevel #endif 637 0 stevel 638 0 stevel default: 639 0 stevel /* Header is wrong, reject message */ 640 0 stevel au_free_rec(s); 641 0 stevel return (EINVAL); 642 0 stevel } 643 0 stevel 644 0 stevel if (length < hdrlen) { 645 0 stevel au_free_rec(s); 646 0 stevel return (0); 647 0 stevel } 648 0 stevel 649 0 stevel /* advance over header token length field */ 650 0 stevel hadr.adr_now += 4; 651 0 stevel 652 0 stevel /* validate version */ 653 0 stevel (void) adr_getchar(&hadr, &c); 654 0 stevel if (c != TOKEN_VERSION) { 655 0 stevel /* version is wrong, reject message */ 656 0 stevel au_free_rec(s); 657 0 stevel return (EINVAL); 658 0 stevel } 659 0 stevel 660 0 stevel /* backup to header length field (including version field) */ 661 0 stevel hadr.adr_now -= 5; 662 0 stevel 663 0 stevel /* 664 0 stevel * add on the zonename token if policy AUDIT_ZONENAME is set 665 0 stevel */ 666 0 stevel if (kctx->auk_policy & AUDIT_ZONENAME) { 667 4165 tz204579 zlen = au_zonename_length(NULL); 668 0 stevel if (zlen > 0) { 669 0 stevel length += zlen; 670 4165 tz204579 m = au_to_zonename(zlen, NULL); 671 0 stevel (void) au_append_rec(ad, m, AU_PACK); 672 0 stevel } 673 0 stevel } 674 0 stevel /* Add an (optional) sequence token. NULL offset if none */ 675 0 stevel if (kctx->auk_policy & AUDIT_SEQ) { 676 0 stevel /* get the sequnce token */ 677 0 stevel m = au_to_seq(); 678 0 stevel 679 0 stevel /* sequence token 5 bytes long */ 680 0 stevel length += 5; 681 0 stevel 682 0 stevel /* link to audit record (i.e. don't pack the data) */ 683 0 stevel (void) au_append_rec(ad, m, AU_LINK); 684 0 stevel 685 0 stevel /* advance to count field of token */ 686 0 stevel adr_start(&sadr, memtod(m, char *)); 687 0 stevel sadr.adr_now += 1; 688 0 stevel } else 689 0 stevel sadr.adr_now = (char *)NULL; 690 0 stevel 691 0 stevel /* add the (optional) trailer token */ 692 0 stevel if (kctx->auk_policy & AUDIT_TRAIL) { 693 0 stevel /* trailer token is 7 bytes long */ 694 0 stevel length += 7; 695 0 stevel 696 0 stevel /* append to audit record */ 697 0 stevel (void) au_append_rec(ad, au_to_trailer(length), AU_PACK); 698 0 stevel } 699 0 stevel 700 0 stevel /* audit record completely assembled. set the length */ 701 0 stevel adr_int32(&hadr, (int32_t *)&length, 1); 702 0 stevel 703 0 stevel /* advance to date/time field of header */ 704 0 stevel hadr.adr_now += delta; 705 0 stevel 706 0 stevel /* We are done put it on the queue */ 707 0 stevel AS_INC(as_generated, 1, kctx); 708 0 stevel AS_INC(as_audit, 1, kctx); 709 0 stevel 710 0 stevel au_enqueue(kctx, s, &hadr, &sadr, size, 0); 711 0 stevel 712 0 stevel AS_INC(as_totalsize, length, kctx); 713 0 stevel 714 0 stevel return (0); 715 0 stevel } 716 0 stevel 717 0 stevel static void 718 0 stevel audit_dont_stop(void *kctx) 719 0 stevel { 720 0 stevel 721 0 stevel if ((((au_kcontext_t *)kctx)->auk_valid != AUK_VALID) || 722 0 stevel (((au_kcontext_t *)kctx)->auk_auditstate == AUC_NOAUDIT)) 723 0 stevel return; 724 0 stevel 725 0 stevel mutex_enter(&(((au_kcontext_t *)kctx)->auk_queue.lock)); 726 0 stevel cv_broadcast(&(((au_kcontext_t *)kctx)->auk_queue.write_cv)); 727 0 stevel mutex_exit(&(((au_kcontext_t *)kctx)->auk_queue.lock)); 728 0 stevel } 729 0 stevel 730 0 stevel /* 731 0 stevel * auditdoor starts a kernel thread to generate output from the audit 732 0 stevel * queue. The thread terminates when it detects auditing being turned 733 0 stevel * off, such as when auditd exits with a SIGTERM. If a subsequent 734 0 stevel * auditdoor arrives while the thread is running, the door descriptor 735 0 stevel * of the last auditdoor in will be used for output. auditd is responsible 736 0 stevel * for insuring that multiple copies are not running. 737 0 stevel */ 738 0 stevel 739 0 stevel static int 740 0 stevel auditdoor(int fd) 741 0 stevel { 742 0 stevel struct file *fp; 743 0 stevel struct vnode *vp; 744 0 stevel int do_create = 0; 745 0 stevel au_kcontext_t *kctx; 746 0 stevel 747 0 stevel if (secpolicy_audit_config(CRED()) != 0) 748 0 stevel return (EPERM); 749 0 stevel 750 0 stevel if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc)) 751 0 stevel return (EINVAL); 752 0 stevel 753 4197 paulson kctx = GET_KCTX_NGZ; 754 0 stevel 755 0 stevel /* 756 0 stevel * convert file pointer to file descriptor 757 0 stevel * Note: fd ref count incremented here. 758 0 stevel */ 759 0 stevel if ((fp = (struct file *)getf(fd)) == NULL) { 760 5992 gww return (EBADF); 761 0 stevel } 762 0 stevel vp = fp->f_vnode; 763 0 stevel if (vp->v_type != VDOOR) { 764 0 stevel cmn_err(CE_WARN, 765 0 stevel "auditdoor() did not get the expected door descriptor\n"); 766 0 stevel releasef(fd); 767 5992 gww return (EINVAL); 768 0 stevel } 769 0 stevel /* 770 0 stevel * If the output thread is already running, then replace the 771 0 stevel * door descriptor with the new one and continue; otherwise 772 0 stevel * create the thread too. Since au_output_thread makes a call 773 0 stevel * to au_doorio() which also does 774 0 stevel * mutex_lock(&(kctx->auk_svc_lock)), the create/dispatch is 775 0 stevel * done after the unlock... 776 0 stevel */ 777 0 stevel mutex_enter(&(kctx->auk_svc_lock)); 778 0 stevel 779 0 stevel if (kctx->auk_current_vp != NULL) 780 0 stevel VN_RELE(kctx->auk_current_vp); 781 0 stevel 782 0 stevel kctx->auk_current_vp = vp; 783 0 stevel VN_HOLD(kctx->auk_current_vp); 784 0 stevel releasef(fd); 785 0 stevel 786 0 stevel if (!kctx->auk_output_active) { 787 0 stevel kctx->auk_output_active = 1; 788 0 stevel do_create = 1; 789 0 stevel } 790 0 stevel mutex_exit(&(kctx->auk_svc_lock)); 791 0 stevel if (do_create) { 792 0 stevel kctx->auk_taskq = 793 0 stevel taskq_create("output_master", 1, minclsyspri, 1, 1, 0); 794 0 stevel (void) taskq_dispatch(kctx->auk_taskq, 795 0 stevel (task_func_t *)au_output_thread, 796 0 stevel kctx, TQ_SLEEP); 797 0 stevel } 798 5992 gww return (0); 799 0 stevel } 800 0 stevel 801 0 stevel /* 802 0 stevel * au_queue_kick -- wake up the output queue after delay ticks 803 0 stevel */ 804 0 stevel static void 805 0 stevel au_queue_kick(void *kctx) 806 0 stevel { 807 0 stevel /* 808 0 stevel * wakeup reader if its not running and there is something 809 0 stevel * to do. It also helps that kctx still be valid... 810 0 stevel */ 811 0 stevel 812 0 stevel if ((((au_kcontext_t *)kctx)->auk_valid != AUK_VALID) || 813 0 stevel (((au_kcontext_t *)kctx)->auk_auditstate == AUC_NOAUDIT)) 814 0 stevel return; 815 0 stevel 816 0 stevel if (((au_kcontext_t *)kctx)->auk_queue.cnt && 817 0 stevel ((au_kcontext_t *)kctx)->auk_queue.rd_block) 818 0 stevel cv_broadcast(&((au_kcontext_t *)kctx)->auk_queue.read_cv); 819 0 stevel 820 0 stevel /* fire off timeout event to kick audit queue awake */ 821 0 stevel (void) timeout(au_queue_kick, kctx, 822 0 stevel ((au_kcontext_t *)kctx)->auk_queue.delay); 823 0 stevel } 824 0 stevel 825 0 stevel /* 826 0 stevel * output thread 827 0 stevel * 828 0 stevel * this runs "forever" where "forever" means until either auk_auditstate 829 0 stevel * changes from AUC_AUDITING or if the door descriptor becomes invalid. 830 0 stevel * 831 0 stevel * there is one thread per active zone if AUC_PERZONE is set. Since 832 0 stevel * there is the possibility that a zone may go down without auditd 833 0 stevel * terminating properly, a zone shutdown kills its au_output_thread() 834 0 stevel * via taskq_destroy(). 835 0 stevel */ 836 0 stevel 837 0 stevel static void 838 0 stevel au_output_thread(au_kcontext_t *kctx) 839 0 stevel { 840 0 stevel int error = 0; 841 0 stevel 842 0 stevel (void) timeout(au_queue_kick, kctx, kctx->auk_queue.delay); 843 0 stevel 844 0 stevel /* 845 0 stevel * Wait for work, until a signal arrives, 846 0 stevel * or until auditing is disabled. 847 0 stevel */ 848 0 stevel 849 0 stevel while (!error) { 850 5992 gww if (kctx->auk_auditstate == AUC_AUDITING) { 851 5992 gww mutex_enter(&(kctx->auk_queue.lock)); 852 5992 gww while (kctx->auk_queue.head == NULL) { 853 5992 gww /* safety check. kick writer awake */ 854 5992 gww if (kctx->auk_queue.wt_block) { 855 5992 gww cv_broadcast(&(kctx-> 856 5992 gww auk_queue.write_cv)); 857 5992 gww } 858 0 stevel 859 5992 gww kctx->auk_queue.rd_block = 1; 860 5992 gww AS_INC(as_rblocked, 1, kctx); 861 0 stevel 862 5992 gww cv_wait(&(kctx->auk_queue.read_cv), 863 5992 gww &(kctx->auk_queue.lock)); 864 5992 gww kctx->auk_queue.rd_block = 0; 865 0 stevel 866 5992 gww if (kctx->auk_auditstate != AUC_AUDITING) { 867 5992 gww mutex_exit(&(kctx->auk_queue.lock)); 868 5992 gww (void) timeout(audit_dont_stop, kctx, 869 5992 gww au_resid); 870 5992 gww goto output_exit; 871 5992 gww } 872 5992 gww kctx->auk_queue.rd_block = 0; 873 5992 gww } 874 5992 gww mutex_exit(&(kctx->auk_queue.lock)); 875 5992 gww /* 876 5992 gww * au_doorio() calls au_door_upcall which holds 877 5992 gww * auk_svc_lock; au_doorio empties the queue before 878 5992 gww * returning. 879 5992 gww */ 880 0 stevel 881 5992 gww error = au_doorio(kctx); 882 5992 gww } else { 883 5992 gww /* auditing turned off while we slept */ 884 5992 gww break; 885 0 stevel } 886 0 stevel } 887 0 stevel output_exit: 888 0 stevel mutex_enter(&(kctx->auk_svc_lock)); 889 0 stevel 890 0 stevel VN_RELE(kctx->auk_current_vp); 891 0 stevel kctx->auk_current_vp = NULL; 892 0 stevel 893 0 stevel kctx->auk_output_active = 0; 894 0 stevel 895 0 stevel mutex_exit(&(kctx->auk_svc_lock)); 896 0 stevel } 897 0 stevel 898 0 stevel 899 0 stevel /* 900 0 stevel * Get the global policy flag 901 0 stevel */ 902 0 stevel 903 0 stevel static int 904 0 stevel getpolicy(caddr_t data) 905 0 stevel { 906 0 stevel int policy; 907 4197 paulson au_kcontext_t *kctx = GET_KCTX_PZ; 908 0 stevel 909 0 stevel policy = audit_policy | kctx->auk_policy; 910 0 stevel 911 0 stevel if (copyout(&policy, data, sizeof (int))) 912 0 stevel return (EFAULT); 913 0 stevel return (0); 914 0 stevel } 915 0 stevel 916 0 stevel /* 917 0 stevel * Set the global and local policy flags 918 0 stevel * 919 0 stevel * The global flags only make sense from the global zone; 920 0 stevel * the local flags depend on the AUDIT_PERZONE policy: 921 0 stevel * if the perzone policy is set, then policy is set separately 922 0 stevel * per zone, else held only in the global zone. 923 0 stevel * 924 0 stevel * The initial value of a local zone's policy flag is determined 925 0 stevel * by the value of the global zone's flags at the time the 926 0 stevel * local zone is created. 927 0 stevel * 928 0 stevel * While auditconfig(1M) allows setting and unsetting policies one bit 929 0 stevel * at a time, the mask passed in from auditconfig() is created by a 930 0 stevel * syscall to getpolicy and then modified based on the auditconfig() 931 0 stevel * cmd line, so the input policy value is used to replace the existing 932 0 stevel * policy. 933 0 stevel */ 934 0 stevel 935 0 stevel 936 0 stevel static int 937 0 stevel setpolicy(caddr_t data) 938 0 stevel { 939 0 stevel int policy; 940 0 stevel au_kcontext_t *kctx; 941 0 stevel 942 0 stevel if (copyin(data, &policy, sizeof (int))) 943 0 stevel return (EFAULT); 944 0 stevel 945 4197 paulson kctx = GET_KCTX_NGZ; 946 0 stevel 947 0 stevel if (INGLOBALZONE(curproc)) { 948 0 stevel if (policy & ~(AUDIT_GLOBAL | AUDIT_LOCAL)) 949 0 stevel return (EINVAL); 950 0 stevel 951 0 stevel audit_policy = policy & AUDIT_GLOBAL; 952 0 stevel } else { 953 0 stevel if (!(audit_policy & AUDIT_PERZONE)) 954 0 stevel return (EINVAL); 955 0 stevel 956 0 stevel if (policy & ~AUDIT_LOCAL) /* global bits are a no-no */ 957 0 stevel return (EINVAL); 958 0 stevel } 959 0 stevel kctx->auk_policy = policy & AUDIT_LOCAL; 960 0 stevel 961 0 stevel /* 962 0 stevel * auk_current_vp is NULL before auditd starts (or during early 963 0 stevel * auditd starup) or if auditd is halted; in either case, 964 0 stevel * notification of a policy change is not needed, since auditd 965 0 stevel * reads policy as it comes up. The error return from au_doormsg() 966 0 stevel * is ignored to avoid a race condition -- for example if auditd 967 0 stevel * segv's, the audit state may be "auditing" but the door may 968 0 stevel * be closed. Returning an error if the door is open makes it 969 0 stevel * impossible for Greenline to restart auditd. 970 0 stevel */ 971 0 stevel if (kctx->auk_current_vp != NULL) 972 0 stevel (void) au_doormsg(kctx, AU_DBUF_POLICY, &policy); 973 0 stevel 974 0 stevel /* 975 0 stevel * Wake up anyone who might have blocked on full audit 976 0 stevel * partitions. audit daemons need to set AUDIT_FULL when no 977 0 stevel * space so we can tell if we should start dropping records. 978 0 stevel */ 979 0 stevel mutex_enter(&(kctx->auk_queue.lock)); 980 0 stevel 981 0 stevel if ((policy & (AUDIT_CNT | AUDIT_SCNT) && 982 0 stevel (kctx->auk_queue.cnt >= kctx->auk_queue.hiwater))) 983 0 stevel cv_broadcast(&(kctx->auk_queue.write_cv)); 984 0 stevel 985 0 stevel mutex_exit(&(kctx->auk_queue.lock)); 986 0 stevel 987 0 stevel return (0); 988 0 stevel } 989 0 stevel 990 0 stevel static int 991 0 stevel getkmask(caddr_t data) 992 0 stevel { 993 0 stevel au_kcontext_t *kctx; 994 0 stevel 995 4197 paulson kctx = GET_KCTX_PZ; 996 0 stevel 997 0 stevel if (copyout(&kctx->auk_info.ai_mask, data, sizeof (au_mask_t))) 998 0 stevel return (EFAULT); 999 0 stevel return (0); 1000 0 stevel } 1001 0 stevel 1002 0 stevel static int 1003 0 stevel setkmask(caddr_t data) 1004 0 stevel { 1005 0 stevel au_mask_t mask; 1006 0 stevel au_kcontext_t *kctx; 1007 0 stevel 1008 0 stevel if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc)) 1009 0 stevel return (EINVAL); 1010 0 stevel 1011 4197 paulson kctx = GET_KCTX_NGZ; 1012 0 stevel 1013 0 stevel if (copyin(data, &mask, sizeof (au_mask_t))) 1014 0 stevel return (EFAULT); 1015 0 stevel 1016 0 stevel kctx->auk_info.ai_mask = mask; 1017 0 stevel return (0); 1018 0 stevel } 1019 0 stevel 1020 0 stevel static int 1021 0 stevel getkaudit(caddr_t info_p, int len) 1022 0 stevel { 1023 0 stevel STRUCT_DECL(auditinfo_addr, info); 1024 0 stevel model_t model; 1025 4197 paulson au_kcontext_t *kctx = GET_KCTX_PZ; 1026 0 stevel 1027 0 stevel model = get_udatamodel(); 1028 0 stevel STRUCT_INIT(info, model); 1029 0 stevel 1030 0 stevel if (len < STRUCT_SIZE(info)) 1031 0 stevel return (EOVERFLOW); 1032 0 stevel 1033 0 stevel STRUCT_FSET(info, ai_auid, kctx->auk_info.ai_auid); 1034 0 stevel STRUCT_FSET(info, ai_mask, kctx->auk_info.ai_mask); 1035 0 stevel #ifdef _LP64 1036 0 stevel if (model == DATAMODEL_ILP32) { 1037 0 stevel dev32_t dev; 1038 0 stevel /* convert internal 64 bit form to 32 bit version */ 1039 0 stevel if (cmpldev(&dev, kctx->auk_info.ai_termid.at_port) == 0) { 1040 0 stevel return (EOVERFLOW); 1041 0 stevel } 1042 0 stevel STRUCT_FSET(info, ai_termid.at_port, dev); 1043 5992 gww } else { 1044 0 stevel STRUCT_FSET(info, ai_termid.at_port, 1045 5992 gww kctx->auk_info.ai_termid.at_port); 1046 5992 gww } 1047 0 stevel #else 1048 0 stevel STRUCT_FSET(info, ai_termid.at_port, 1049 5992 gww kctx->auk_info.ai_termid.at_port); 1050 0 stevel #endif 1051 0 stevel STRUCT_FSET(info, ai_termid.at_type, 1052 0 stevel kctx->auk_info.ai_termid.at_type); 1053 0 stevel STRUCT_FSET(info, ai_termid.at_addr[0], 1054 0 stevel kctx->auk_info.ai_termid.at_addr[0]); 1055 0 stevel STRUCT_FSET(info, ai_termid.at_addr[1], 1056 0 stevel kctx->auk_info.ai_termid.at_addr[1]); 1057 0 stevel STRUCT_FSET(info, ai_termid.at_addr[2], 1058 0 stevel kctx->auk_info.ai_termid.at_addr[2]); 1059 0 stevel STRUCT_FSET(info, ai_termid.at_addr[3], 1060 0 stevel kctx->auk_info.ai_termid.at_addr[3]); 1061 0 stevel STRUCT_FSET(info, ai_asid, kctx->auk_info.ai_asid); 1062 0 stevel 1063 0 stevel if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info))) 1064 0 stevel return (EFAULT); 1065 0 stevel 1066 0 stevel return (0); 1067 0 stevel } 1068 0 stevel 1069 0 stevel /* 1070 0 stevel * the host address for AUDIT_PERZONE == 0 is that of the global 1071 0 stevel * zone and for local zones it is of the current zone. 1072 0 stevel */ 1073 0 stevel 1074 0 stevel static int 1075 0 stevel setkaudit(caddr_t info_p, int len) 1076 0 stevel { 1077 0 stevel STRUCT_DECL(auditinfo_addr, info); 1078 0 stevel model_t model; 1079 0 stevel au_kcontext_t *kctx; 1080 0 stevel 1081 0 stevel if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc)) 1082 0 stevel return (EINVAL); 1083 0 stevel 1084 4197 paulson kctx = GET_KCTX_NGZ; 1085 0 stevel 1086 0 stevel model = get_udatamodel(); 1087 0 stevel STRUCT_INIT(info, model); 1088 0 stevel 1089 0 stevel if (len < STRUCT_SIZE(info)) 1090 0 stevel return (EOVERFLOW); 1091 0 stevel 1092 0 stevel if (copyin(info_p, STRUCT_BUF(info), STRUCT_SIZE(info))) 1093 0 stevel return (EFAULT); 1094 0 stevel 1095 0 stevel if ((STRUCT_FGET(info, ai_termid.at_type) != AU_IPv4) && 1096 0 stevel (STRUCT_FGET(info, ai_termid.at_type) != AU_IPv6)) 1097 0 stevel return (EINVAL); 1098 0 stevel 1099 0 stevel /* Set audit mask, termid and session id as specified */ 1100 0 stevel kctx->auk_info.ai_auid = STRUCT_FGET(info, ai_auid); 1101 0 stevel kctx->auk_info.ai_mask = STRUCT_FGET(info, ai_mask); 1102 0 stevel #ifdef _LP64 1103 0 stevel /* only convert to 64 bit if coming from a 32 bit binary */ 1104 0 stevel if (model == DATAMODEL_ILP32) 1105 0 stevel kctx->auk_info.ai_termid.at_port = 1106 5992 gww DEVEXPL(STRUCT_FGET(info, ai_termid.at_port)); 1107 0 stevel else 1108 0 stevel kctx->auk_info.ai_termid.at_port = 1109 5992 gww STRUCT_FGET(info, ai_termid.at_port); 1110 0 stevel #else 1111 0 stevel kctx->auk_info.ai_termid.at_port = STRUCT_FGET(info, ai_termid.at_port); 1112 0 stevel #endif 1113 0 stevel kctx->auk_info.ai_termid.at_type = STRUCT_FGET(info, ai_termid.at_type); 1114 0 stevel bzero(&kctx->auk_info.ai_termid.at_addr[0], 1115 5992 gww sizeof (kctx->auk_info.ai_termid.at_addr)); 1116 0 stevel kctx->auk_info.ai_termid.at_addr[0] = 1117 0 stevel STRUCT_FGET(info, ai_termid.at_addr[0]); 1118 0 stevel kctx->auk_info.ai_termid.at_addr[1] = 1119 0 stevel STRUCT_FGET(info, ai_termid.at_addr[1]); 1120 0 stevel kctx->auk_info.ai_termid.at_addr[2] = 1121 0 stevel STRUCT_FGET(info, ai_termid.at_addr[2]); 1122 0 stevel kctx->auk_info.ai_termid.at_addr[3] = 1123 0 stevel STRUCT_FGET(info, ai_termid.at_addr[3]); 1124 0 stevel kctx->auk_info.ai_asid = STRUCT_FGET(info, ai_asid); 1125 0 stevel 1126 0 stevel if (kctx->auk_info.ai_termid.at_type == AU_IPv6 && 1127 0 stevel IN6_IS_ADDR_V4MAPPED( 1128 0 stevel ((in6_addr_t *)kctx->auk_info.ai_termid.at_addr))) { 1129 0 stevel kctx->auk_info.ai_termid.at_type = AU_IPv4; 1130 0 stevel kctx->auk_info.ai_termid.at_addr[0] = 1131 0 stevel kctx->auk_info.ai_termid.at_addr[3]; 1132 0 stevel kctx->auk_info.ai_termid.at_addr[1] = 0; 1133 0 stevel kctx->auk_info.ai_termid.at_addr[2] = 0; 1134 0 stevel kctx->auk_info.ai_termid.at_addr[3] = 0; 1135 0 stevel } 1136 0 stevel if (kctx->auk_info.ai_termid.at_type == AU_IPv6) 1137 0 stevel kctx->auk_hostaddr_valid = IN6_IS_ADDR_UNSPECIFIED( 1138 0 stevel (in6_addr_t *)kctx->auk_info.ai_termid.at_addr) ? 0 : 1; 1139 0 stevel else 1140 0 stevel kctx->auk_hostaddr_valid = 1141 0 stevel (kctx->auk_info.ai_termid.at_addr[0] == 1142 0 stevel htonl(INADDR_ANY)) ? 0 : 1; 1143 0 stevel 1144 0 stevel return (0); 1145 0 stevel } 1146 0 stevel 1147 0 stevel static int 1148 0 stevel getqctrl(caddr_t data) 1149 0 stevel { 1150 4197 paulson au_kcontext_t *kctx = GET_KCTX_PZ; 1151 0 stevel STRUCT_DECL(au_qctrl, qctrl); 1152 0 stevel STRUCT_INIT(qctrl, get_udatamodel()); 1153 0 stevel 1154 0 stevel mutex_enter(&(kctx->auk_queue.lock)); 1155 0 stevel STRUCT_FSET(qctrl, aq_hiwater, kctx->auk_queue.hiwater); 1156 0 stevel STRUCT_FSET(qctrl, aq_lowater, kctx->auk_queue.lowater); 1157 0 stevel STRUCT_FSET(qctrl, aq_bufsz, kctx->auk_queue.bufsz); 1158 0 stevel STRUCT_FSET(qctrl, aq_delay, kctx->auk_queue.delay); 1159 0 stevel mutex_exit(&(kctx->auk_queue.lock)); 1160 0 stevel 1161 0 stevel if (copyout(STRUCT_BUF(qctrl), data, STRUCT_SIZE(qctrl))) 1162 0 stevel return (EFAULT); 1163 0 stevel 1164 0 stevel return (0); 1165 0 stevel } 1166 0 stevel 1167 0 stevel static int 1168 0 stevel setqctrl(caddr_t data) 1169 0 stevel { 1170 0 stevel au_kcontext_t *kctx; 1171 0 stevel struct au_qctrl qctrl_tmp; 1172 0 stevel STRUCT_DECL(au_qctrl, qctrl); 1173 0 stevel STRUCT_INIT(qctrl, get_udatamodel()); 1174 0 stevel 1175 0 stevel if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc)) 1176 0 stevel return (EINVAL); 1177 4197 paulson kctx = GET_KCTX_NGZ; 1178 0 stevel 1179 0 stevel if (copyin(data, STRUCT_BUF(qctrl), STRUCT_SIZE(qctrl))) 1180 0 stevel return (EFAULT); 1181 0 stevel 1182 0 stevel qctrl_tmp.aq_hiwater = (size_t)STRUCT_FGET(qctrl, aq_hiwater); 1183 0 stevel qctrl_tmp.aq_lowater = (size_t)STRUCT_FGET(qctrl, aq_lowater); 1184 0 stevel qctrl_tmp.aq_bufsz = (size_t)STRUCT_FGET(qctrl, aq_bufsz); 1185 0 stevel qctrl_tmp.aq_delay = (clock_t)STRUCT_FGET(qctrl, aq_delay); 1186 0 stevel 1187 0 stevel /* enforce sane values */ 1188 0 stevel 1189 0 stevel if (qctrl_tmp.aq_hiwater <= qctrl_tmp.aq_lowater) 1190 0 stevel return (EINVAL); 1191 0 stevel 1192 0 stevel if (qctrl_tmp.aq_hiwater < AQ_LOWATER) 1193 0 stevel return (EINVAL); 1194 0 stevel 1195 0 stevel if (qctrl_tmp.aq_hiwater > AQ_MAXHIGH) 1196 0 stevel return (EINVAL); 1197 0 stevel 1198 0 stevel if (qctrl_tmp.aq_bufsz < AQ_BUFSZ) 1199 0 stevel return (EINVAL); 1200 0 stevel 1201 0 stevel if (qctrl_tmp.aq_bufsz > AQ_MAXBUFSZ) 1202 0 stevel return (EINVAL); 1203 0 stevel 1204 0 stevel if (qctrl_tmp.aq_delay == 0) 1205 0 stevel return (EINVAL); 1206 0 stevel 1207 0 stevel if (qctrl_tmp.aq_delay > AQ_MAXDELAY) 1208 0 stevel return (EINVAL); 1209 0 stevel 1210 0 stevel /* update everything at once so things are consistant */ 1211 0 stevel mutex_enter(&(kctx->auk_queue.lock)); 1212 0 stevel kctx->auk_queue.hiwater = qctrl_tmp.aq_hiwater; 1213 0 stevel kctx->auk_queue.lowater = qctrl_tmp.aq_lowater; 1214 0 stevel kctx->auk_queue.bufsz = qctrl_tmp.aq_bufsz; 1215 0 stevel kctx->auk_queue.delay = qctrl_tmp.aq_delay; 1216 0 stevel 1217 0 stevel if (kctx->auk_queue.rd_block && 1218 0 stevel kctx->auk_queue.cnt > kctx->auk_queue.lowater) 1219 0 stevel cv_broadcast(&(kctx->auk_queue.read_cv)); 1220 0 stevel 1221 0 stevel if (kctx->auk_queue.wt_block && 1222 0 stevel kctx->auk_queue.cnt < kctx->auk_queue.hiwater) 1223 0 stevel cv_broadcast(&(kctx->auk_queue.write_cv)); 1224 0 stevel 1225 0 stevel mutex_exit(&(kctx->auk_queue.lock)); 1226 0 stevel 1227 0 stevel return (0); 1228 0 stevel } 1229 0 stevel 1230 0 stevel static int 1231 0 stevel getcwd(caddr_t data, int length) 1232 0 stevel { 1233 0 stevel struct p_audit_data *pad; 1234 0 stevel struct audit_path *app; 1235 0 stevel int pathlen; 1236 0 stevel 1237 0 stevel pad = P2A(curproc); 1238 0 stevel ASSERT(pad != NULL); 1239 0 stevel 1240 0 stevel mutex_enter(&(pad->pad_lock)); 1241 0 stevel app = pad->pad_cwd; 1242 0 stevel au_pathhold(app); 1243 0 stevel mutex_exit(&(pad->pad_lock)); 1244 0 stevel 1245 0 stevel pathlen = app->audp_sect[1] - app->audp_sect[0]; 1246 0 stevel if (pathlen > length) { 1247 0 stevel au_pathrele(app); 1248 0 stevel return (E2BIG); 1249 0 stevel } 1250 0 stevel 1251 0 stevel if (copyout(app->audp_sect[0], data, pathlen)) { 1252 0 stevel au_pathrele(app); 1253 0 stevel return (EFAULT); 1254 0 stevel } 1255 0 stevel 1256 0 stevel au_pathrele(app); 1257 0 stevel return (0); 1258 0 stevel } 1259 0 stevel 1260 0 stevel static int 1261 0 stevel getcar(caddr_t data, int length) 1262 0 stevel { 1263 0 stevel struct p_audit_data *pad; 1264 0 stevel struct audit_path *app; 1265 0 stevel int pathlen; 1266 0 stevel 1267 0 stevel pad = P2A(curproc); 1268 0 stevel ASSERT(pad != NULL); 1269 0 stevel 1270 0 stevel mutex_enter(&(pad->pad_lock)); 1271 0 stevel app = pad->pad_root; 1272 0 stevel au_pathhold(app); 1273 0 stevel mutex_exit(&(pad->pad_lock)); 1274 0 stevel 1275 0 stevel pathlen = app->audp_sect[1] - app->audp_sect[0]; 1276 0 stevel if (pathlen > length) { 1277 0 stevel au_pathrele(app); 1278 0 stevel return (E2BIG); 1279 0 stevel } 1280 0 stevel 1281 0 stevel if (copyout(app->audp_sect[0], data, pathlen)) { 1282 0 stevel au_pathrele(app); 1283 0 stevel return (EFAULT); 1284 0 stevel } 1285 0 stevel 1286 0 stevel au_pathrele(app); 1287 0 stevel return (0); 1288 0 stevel } 1289 0 stevel 1290 0 stevel static int 1291 0 stevel getstat(caddr_t data) 1292 0 stevel { 1293 4197 paulson au_kcontext_t *kctx = GET_KCTX_PZ; 1294 0 stevel 1295 0 stevel membar_consumer(); 1296 0 stevel 1297 0 stevel if (copyout((caddr_t)&(kctx->auk_statistics), data, sizeof (au_stat_t))) 1298 0 stevel return (EFAULT); 1299 0 stevel return (0); 1300 0 stevel } 1301 0 stevel 1302 0 stevel 1303 0 stevel static int 1304 0 stevel setstat(caddr_t data) 1305 0 stevel { 1306 4197 paulson au_kcontext_t *kctx = GET_KCTX_PZ; 1307 0 stevel au_stat_t au_stat; 1308 0 stevel 1309 0 stevel if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc)) 1310 0 stevel return (EINVAL); 1311 0 stevel 1312 0 stevel if (copyin(data, &au_stat, sizeof (au_stat_t))) 1313 0 stevel return (EFAULT); 1314 0 stevel 1315 0 stevel if (au_stat.as_generated == CLEAR_VAL) 1316 0 stevel kctx->auk_statistics.as_generated = 0; 1317 0 stevel if (au_stat.as_nonattrib == CLEAR_VAL) 1318 0 stevel kctx->auk_statistics.as_nonattrib = 0; 1319 0 stevel if (au_stat.as_kernel == CLEAR_VAL) 1320 0 stevel kctx->auk_statistics.as_kernel = 0; 1321 0 stevel if (au_stat.as_audit == CLEAR_VAL) 1322 0 stevel kctx->auk_statistics.as_audit = 0; 1323 0 stevel if (au_stat.as_auditctl == CLEAR_VAL) 1324 0 stevel kctx->auk_statistics.as_auditctl = 0; 1325 0 stevel if (au_stat.as_enqueue == CLEAR_VAL) 1326 0 stevel kctx->auk_statistics.as_enqueue = 0; 1327 0 stevel if (au_stat.as_written == CLEAR_VAL) 1328 0 stevel kctx->auk_statistics.as_written = 0; 1329 0 stevel if (au_stat.as_wblocked == CLEAR_VAL) 1330 0 stevel kctx->auk_statistics.as_wblocked = 0; 1331 0 stevel if (au_stat.as_rblocked == CLEAR_VAL) 1332 0 stevel kctx->auk_statistics.as_rblocked = 0; 1333 0 stevel if (au_stat.as_dropped == CLEAR_VAL) 1334 0 stevel kctx->auk_statistics.as_dropped = 0; 1335 0 stevel if (au_stat.as_totalsize == CLEAR_VAL) 1336 0 stevel kctx->auk_statistics.as_totalsize = 0; 1337 0 stevel 1338 0 stevel membar_producer(); 1339 0 stevel 1340 0 stevel return (0); 1341 0 stevel 1342 0 stevel } 1343 0 stevel 1344 0 stevel static int 1345 0 stevel setumask(caddr_t data) 1346 0 stevel { 1347 0 stevel STRUCT_DECL(auditinfo, user_info); 1348 0 stevel struct proc *p; 1349 0 stevel const auditinfo_addr_t *ainfo; 1350 0 stevel model_t model; 1351 0 stevel 1352 8127 Brent /* setumask not applicable in non-global zones without perzone policy */ 1353 8127 Brent if (!(audit_policy & AUDIT_PERZONE) && (!INGLOBALZONE(curproc))) 1354 8127 Brent return (EINVAL); 1355 8127 Brent 1356 0 stevel model = get_udatamodel(); 1357 0 stevel STRUCT_INIT(user_info, model); 1358 0 stevel 1359 0 stevel if (copyin(data, STRUCT_BUF(user_info), STRUCT_SIZE(user_info))) 1360 0 stevel return (EFAULT); 1361 0 stevel 1362 0 stevel mutex_enter(&pidlock); /* lock the process queue against updates */ 1363 0 stevel for (p = practive; p != NULL; p = p->p_next) { 1364 0 stevel cred_t *cr; 1365 0 stevel 1366 8127 Brent /* if in non-global zone only modify processes in same zone */ 1367 8127 Brent if (!HASZONEACCESS(curproc, p->p_zone->zone_id)) 1368 8127 Brent continue; 1369 8127 Brent 1370 0 stevel mutex_enter(&p->p_lock); /* so process doesn't go away */ 1371 8127 Brent 1372 8127 Brent /* skip system processes and ones being created or going away */ 1373 8127 Brent if (p->p_stat == SIDL || p->p_stat == SZOMB || 1374 8127 Brent (p->p_flag & (SSYS | SEXITING | SEXITLWPS))) { 1375 8127 Brent mutex_exit(&p->p_lock); 1376 8127 Brent continue; 1377 8127 Brent } 1378 8127 Brent 1379 0 stevel mutex_enter(&p->p_crlock); 1380 0 stevel crhold(cr = p->p_cred); 1381 0 stevel mutex_exit(&p->p_crlock); 1382 0 stevel ainfo = crgetauinfo(cr); 1383 0 stevel if (ainfo == NULL) { 1384 0 stevel mutex_exit(&p->p_lock); 1385 0 stevel crfree(cr); 1386 0 stevel continue; 1387 0 stevel } 1388 0 stevel 1389 0 stevel if (ainfo->ai_auid == STRUCT_FGET(user_info, ai_auid)) { 1390 0 stevel au_mask_t mask; 1391 0 stevel int err; 1392 0 stevel 1393 0 stevel /* 1394 0 stevel * Here's a process which matches the specified auid. 1395 0 stevel * If its mask doesn't already match the new mask, 1396 0 stevel * save the new mask in the pad, to be picked up 1397 0 stevel * next syscall. 1398 0 stevel */ 1399 0 stevel mask = STRUCT_FGET(user_info, ai_mask); 1400 0 stevel err = bcmp(&mask, &ainfo->ai_mask, sizeof (au_mask_t)); 1401 0 stevel crfree(cr); 1402 0 stevel if (err != 0) { 1403 0 stevel struct p_audit_data *pad = P2A(p); 1404 0 stevel ASSERT(pad != NULL); 1405 0 stevel 1406 0 stevel mutex_enter(&(pad->pad_lock)); 1407 0 stevel pad->pad_flags |= PAD_SETMASK; 1408 0 stevel pad->pad_newmask = mask; 1409 0 stevel mutex_exit(&(pad->pad_lock)); 1410 0 stevel 1411 0 stevel /* 1412 0 stevel * No need to call set_proc_pre_sys(), since 1413 0 stevel * t_pre_sys is ALWAYS on when audit is 1414 0 stevel * enabled...due to syscall auditing. 1415 0 stevel */ 1416 0 stevel } 1417 0 stevel } else { 1418 0 stevel crfree(cr); 1419 0 stevel } 1420 0 stevel mutex_exit(&p->p_lock); 1421 0 stevel } 1422 0 stevel mutex_exit(&pidlock); 1423 0 stevel 1424 0 stevel return (0); 1425 0 stevel } 1426 0 stevel 1427 0 stevel static int 1428 0 stevel setsmask(caddr_t data) 1429 0 stevel { 1430 0 stevel STRUCT_DECL(auditinfo, user_info); 1431 0 stevel struct proc *p; 1432 0 stevel const auditinfo_addr_t *ainfo; 1433 0 stevel model_t model; 1434 0 stevel 1435 8127 Brent /* setsmask not applicable in non-global zones without perzone policy */ 1436 8127 Brent if (!(audit_policy & AUDIT_PERZONE) && (!INGLOBALZONE(curproc))) 1437 8127 Brent return (EINVAL); 1438 8127 Brent 1439 0 stevel model = get_udatamodel(); 1440 0 stevel STRUCT_INIT(user_info, model); 1441 0 stevel 1442 0 stevel if (copyin(data, STRUCT_BUF(user_info), STRUCT_SIZE(user_info))) 1443 0 stevel return (EFAULT); 1444 0 stevel 1445 0 stevel mutex_enter(&pidlock); /* lock the process queue against updates */ 1446 0 stevel for (p = practive; p != NULL; p = p->p_next) { 1447 0 stevel cred_t *cr; 1448 0 stevel 1449 8127 Brent /* if in non-global zone only modify processes in same zone */ 1450 8127 Brent if (!HASZONEACCESS(curproc, p->p_zone->zone_id)) 1451 8127 Brent continue; 1452 8127 Brent 1453 0 stevel mutex_enter(&p->p_lock); /* so process doesn't go away */ 1454 8127 Brent 1455 8127 Brent /* skip system processes and ones being created or going away */ 1456 8127 Brent if (p->p_stat == SIDL || p->p_stat == SZOMB || 1457 8127 Brent (p->p_flag & (SSYS | SEXITING | SEXITLWPS))) { 1458 8127 Brent mutex_exit(&p->p_lock); 1459 8127 Brent continue; 1460 8127 Brent } 1461 8127 Brent 1462 0 stevel mutex_enter(&p->p_crlock); 1463 0 stevel crhold(cr = p->p_cred); 1464 0 stevel mutex_exit(&p->p_crlock); 1465 0 stevel ainfo = crgetauinfo(cr); 1466 0 stevel if (ainfo == NULL) { 1467 0 stevel mutex_exit(&p->p_lock); 1468 0 stevel crfree(cr); 1469 0 stevel continue; 1470 0 stevel } 1471 0 stevel 1472 0 stevel if (ainfo->ai_asid == STRUCT_FGET(user_info, ai_asid)) { 1473 0 stevel au_mask_t mask; 1474 0 stevel int err; 1475 0 stevel 1476 0 stevel /* 1477 0 stevel * Here's a process which matches the specified asid. 1478 0 stevel * If its mask doesn't already match the new mask, 1479 0 stevel * save the new mask in the pad, to be picked up 1480 0 stevel * next syscall. 1481 0 stevel */ 1482 0 stevel mask = STRUCT_FGET(user_info, ai_mask); 1483 0 stevel err = bcmp(&mask, &ainfo->ai_mask, sizeof (au_mask_t)); 1484 0 stevel crfree(cr); 1485 0 stevel if (err != 0) { 1486 0 stevel struct p_audit_data *pad = P2A(p); 1487 0 stevel ASSERT(pad != NULL); 1488 0 stevel 1489 0 stevel mutex_enter(&(pad->pad_lock)); 1490 0 stevel pad->pad_flags |= PAD_SETMASK; 1491 0 stevel pad->pad_newmask = mask; 1492 0 stevel mutex_exit(&(pad->pad_lock)); 1493 0 stevel 1494 0 stevel /* 1495 0 stevel * No need to call set_proc_pre_sys(), since 1496 0 stevel * t_pre_sys is ALWAYS on when audit is 1497 0 stevel * enabled...due to syscall auditing. 1498 0 stevel */ 1499 0 stevel } 1500 0 stevel } else { 1501 0 stevel crfree(cr); 1502 0 stevel } 1503 0 stevel mutex_exit(&p->p_lock); 1504 0 stevel } 1505 0 stevel mutex_exit(&pidlock); 1506 0 stevel 1507 0 stevel return (0); 1508 0 stevel } 1509 0 stevel 1510 0 stevel /* 1511 0 stevel * Get the current audit state of the system 1512 0 stevel */ 1513 0 stevel static int 1514 0 stevel getcond(caddr_t data) 1515 0 stevel { 1516 0 stevel au_kcontext_t *kctx; 1517 0 stevel 1518 0 stevel if (au_auditstate == AUC_DISABLED) 1519 0 stevel if (copyout(&au_auditstate, data, sizeof (int))) 1520 0 stevel return (EFAULT); 1521 0 stevel 1522 4197 paulson kctx = GET_KCTX_PZ; 1523 0 stevel 1524 0 stevel if (copyout(&(kctx->auk_auditstate), data, sizeof (int))) 1525 0 stevel return (EFAULT); 1526 0 stevel 1527 0 stevel return (0); 1528 0 stevel } 1529 0 stevel 1530 0 stevel /* 1531 0 stevel * Set the current audit state of the system to on (AUC_AUDITING) or 1532 0 stevel * off (AUC_NOAUDIT). 1533 0 stevel */ 1534 0 stevel /* ARGSUSED */ 1535 0 stevel static int 1536 0 stevel setcond(caddr_t data) 1537 0 stevel { 1538 0 stevel int auditstate; 1539 0 stevel au_kcontext_t *kctx; 1540 0 stevel 1541 0 stevel if (!(audit_policy & AUDIT_PERZONE) && (!INGLOBALZONE(curproc))) 1542 0 stevel return (EINVAL); 1543 0 stevel 1544 4197 paulson kctx = GET_KCTX_NGZ; 1545 0 stevel 1546 0 stevel if (copyin(data, &auditstate, sizeof (int))) 1547 0 stevel return (EFAULT); 1548 0 stevel 1549 0 stevel switch (auditstate) { 1550 0 stevel case AUC_AUDITING: /* Turn auditing on */ 1551 0 stevel kctx->auk_auditstate = AUC_AUDITING; 1552 0 stevel au_auditstate = AUC_ENABLED; 1553 0 stevel break; 1554 0 stevel 1555 0 stevel case AUC_NOAUDIT: /* Turn auditing off */ 1556 0 stevel if (kctx->auk_auditstate == AUC_NOAUDIT) 1557 0 stevel break; 1558 0 stevel kctx->auk_auditstate = AUC_NOAUDIT; 1559 0 stevel 1560 0 stevel /* clear out the audit queue */ 1561 0 stevel 1562 0 stevel mutex_enter(&(kctx->auk_queue.lock)); 1563 0 stevel if (kctx->auk_queue.wt_block) 1564 0 stevel cv_broadcast(&(kctx->auk_queue.write_cv)); 1565 0 stevel 1566 0 stevel /* unblock au_output_thread */ 1567 0 stevel cv_broadcast(&(kctx->auk_queue.read_cv)); 1568 0 stevel 1569 0 stevel mutex_exit(&(kctx->auk_queue.lock)); 1570 0 stevel break; 1571 0 stevel 1572 0 stevel default: 1573 0 stevel return (EINVAL); 1574 0 stevel } 1575 0 stevel 1576 0 stevel return (0); 1577 0 stevel } 1578 0 stevel 1579 0 stevel static int 1580 0 stevel getclass(caddr_t data) 1581 0 stevel { 1582 0 stevel au_evclass_map_t event; 1583 4197 paulson au_kcontext_t *kctx = GET_KCTX_PZ; 1584 0 stevel 1585 0 stevel if (copyin(data, &event, sizeof (au_evclass_map_t))) 1586 0 stevel return (EFAULT); 1587 0 stevel 1588 7753 Ton if (event.ec_number > MAX_KEVENTS) 1589 0 stevel return (EINVAL); 1590 0 stevel 1591 0 stevel event.ec_class = kctx->auk_ets[event.ec_number]; 1592 0 stevel 1593 0 stevel if (copyout(&event, data, sizeof (au_evclass_map_t))) 1594 0 stevel return (EFAULT); 1595 0 stevel 1596 0 stevel return (0); 1597 0 stevel } 1598 0 stevel 1599 0 stevel static int 1600 0 stevel setclass(caddr_t data) 1601 0 stevel { 1602 0 stevel au_evclass_map_t event; 1603 0 stevel au_kcontext_t *kctx; 1604 0 stevel 1605 0 stevel if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc)) 1606 0 stevel return (EINVAL); 1607 0 stevel 1608 4197 paulson kctx = GET_KCTX_NGZ; 1609 0 stevel 1610 0 stevel if (copyin(data, &event, sizeof (au_evclass_map_t))) 1611 0 stevel return (EFAULT); 1612 0 stevel 1613 7753 Ton if (event.ec_number > MAX_KEVENTS) 1614 0 stevel return (EINVAL); 1615 0 stevel 1616 0 stevel kctx->auk_ets[event.ec_number] = event.ec_class; 1617 0 stevel 1618 0 stevel return (0); 1619 0 stevel } 1620 0 stevel 1621 0 stevel static int 1622 0 stevel getpinfo(caddr_t data) 1623 0 stevel { 1624 0 stevel STRUCT_DECL(auditpinfo, apinfo); 1625 0 stevel proc_t *proc; 1626 0 stevel const auditinfo_addr_t *ainfo; 1627 0 stevel model_t model; 1628 0 stevel cred_t *cr, *newcred; 1629 0 stevel 1630 0 stevel model = get_udatamodel(); 1631 0 stevel STRUCT_INIT(apinfo, model); 1632 0 stevel 1633 0 stevel if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo))) 1634 0 stevel return (EFAULT); 1635 0 stevel 1636 0 stevel newcred = cralloc(); 1637 0 stevel 1638 0 stevel mutex_enter(&pidlock); 1639 0 stevel if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) { 1640 0 stevel mutex_exit(&pidlock); 1641 0 stevel crfree(newcred); 1642 0 stevel return (ESRCH); /* no such process */ 1643 0 stevel } 1644 0 stevel mutex_enter(&proc->p_lock); /* so process doesn't go away */ 1645 0 stevel mutex_exit(&pidlock); 1646 0 stevel 1647 0 stevel audit_update_context(proc, newcred); /* make sure it's up-to-date */ 1648 0 stevel 1649 0 stevel mutex_enter(&proc->p_crlock); 1650 0 stevel crhold(cr = proc->p_cred); 1651 0 stevel mutex_exit(&proc->p_crlock); 1652 0 stevel mutex_exit(&proc->p_lock); 1653 0 stevel 1654 0 stevel ainfo = crgetauinfo(cr); 1655 0 stevel if (ainfo == NULL) { 1656 0 stevel crfree(cr); 1657 0 stevel return (EINVAL); 1658 0 stevel } 1659 0 stevel 1660 0 stevel /* designated process has an ipv6 address? */ 1661 0 stevel if (ainfo->ai_termid.at_type == AU_IPv6) { 1662 0 stevel crfree(cr); 1663 0 stevel return (EOVERFLOW); 1664 0 stevel } 1665 0 stevel 1666 0 stevel STRUCT_FSET(apinfo, ap_auid, ainfo->ai_auid); 1667 0 stevel STRUCT_FSET(apinfo, ap_asid, ainfo->ai_asid); 1668 0 stevel #ifdef _LP64 1669 0 stevel if (model == DATAMODEL_ILP32) { 1670 0 stevel dev32_t dev; 1671 0 stevel /* convert internal 64 bit form to 32 bit version */ 1672 0 stevel if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) { 1673 0 stevel crfree(cr); 1674 0 stevel return (EOVERFLOW); 1675 0 stevel } 1676 0 stevel STRUCT_FSET(apinfo, ap_termid.port, dev); 1677 0 stevel } else 1678 0 stevel STRUCT_FSET(apinfo, ap_termid.port, ainfo->ai_termid.at_port); 1679 0 stevel #else 1680 0 stevel STRUCT_FSET(apinfo, ap_termid.port, ainfo->ai_termid.at_port); 1681 0 stevel #endif 1682 0 stevel STRUCT_FSET(apinfo, ap_termid.machine, ainfo->ai_termid.at_addr[0]); 1683 0 stevel STRUCT_FSET(apinfo, ap_mask, ainfo->ai_mask); 1684 0 stevel 1685 0 stevel crfree(cr); 1686 0 stevel 1687 0 stevel if (copyout(STRUCT_BUF(apinfo), data, STRUCT_SIZE(apinfo))) 1688 0 stevel return (EFAULT); 1689 0 stevel 1690 0 stevel return (0); 1691 0 stevel } 1692 0 stevel 1693 0 stevel static int 1694 0 stevel getpinfo_addr(caddr_t data, int len) 1695 0 stevel { 1696 0 stevel STRUCT_DECL(auditpinfo_addr, apinfo); 1697 0 stevel proc_t *proc; 1698 0 stevel const auditinfo_addr_t *ainfo; 1699 0 stevel model_t model; 1700 0 stevel cred_t *cr, *newcred; 1701 0 stevel 1702 0 stevel model = get_udatamodel(); 1703 0 stevel STRUCT_INIT(apinfo, model); 1704 0 stevel 1705 0 stevel if (len < STRUCT_SIZE(apinfo)) 1706 0 stevel return (EOVERFLOW); 1707 0 stevel 1708 0 stevel if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo))) 1709 0 stevel return (EFAULT); 1710 0 stevel 1711 0 stevel newcred = cralloc(); 1712 0 stevel 1713 0 stevel mutex_enter(&pidlock); 1714 0 stevel if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) { 1715 0 stevel mutex_exit(&pidlock); 1716 0 stevel crfree(newcred); 1717 0 stevel return (ESRCH); 1718 0 stevel } 1719 0 stevel mutex_enter(&proc->p_lock); /* so process doesn't go away */ 1720 0 stevel mutex_exit(&pidlock); 1721 0 stevel 1722 0 stevel audit_update_context(proc, newcred); /* make sure it's up-to-date */ 1723 0 stevel 1724 0 stevel mutex_enter(&proc->p_crlock); 1725 0 stevel crhold(cr = proc->p_cred); 1726 0 stevel mutex_exit(&proc->p_crlock); 1727 0 stevel mutex_exit(&proc->p_lock); 1728 0 stevel 1729 0 stevel ainfo = crgetauinfo(cr); 1730 0 stevel if (ainfo == NULL) { 1731 0 stevel crfree(cr); 1732 0 stevel return (EINVAL); 1733 0 stevel } 1734 0 stevel 1735 0 stevel STRUCT_FSET(apinfo, ap_auid, ainfo->ai_auid); 1736 0 stevel STRUCT_FSET(apinfo, ap_asid, ainfo->ai_asid); 1737 0 stevel #ifdef _LP64 1738 0 stevel if (model == DATAMODEL_ILP32) { 1739 0 stevel dev32_t dev; 1740 0 stevel /* convert internal 64 bit form to 32 bit version */ 1741 0 stevel if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) { 1742 0 stevel crfree(cr); 1743 0 stevel return (EOVERFLOW); 1744 0 stevel } 1745 0 stevel STRUCT_FSET(apinfo, ap_termid.at_port, dev); 1746 0 stevel } else 1747 0 stevel STRUCT_FSET(apinfo, ap_termid.at_port, 1748 0 stevel ainfo->ai_termid.at_port); 1749 0 stevel #else 1750 0 stevel STRUCT_FSET(apinfo, ap_termid.at_port, ainfo->ai_termid.at_port); 1751 0 stevel #endif 1752 0 stevel STRUCT_FSET(apinfo, ap_termid.at_type, ainfo->ai_termid.at_type); 1753 0 stevel STRUCT_FSET(apinfo, ap_termid.at_addr[0], ainfo->ai_termid.at_addr[0]); 1754 0 stevel STRUCT_FSET(apinfo, ap_termid.at_addr[1], ainfo->ai_termid.at_addr[1]); 1755 0 stevel STRUCT_FSET(apinfo, ap_termid.at_addr[2], ainfo->ai_termid.at_addr[2]); 1756 0 stevel STRUCT_FSET(apinfo, ap_termid.at_addr[3], ainfo->ai_termid.at_addr[3]); 1757 0 stevel STRUCT_FSET(apinfo, ap_mask, ainfo->ai_mask); 1758 0 stevel 1759 0 stevel crfree(cr); 1760 0 stevel 1761 0 stevel if (copyout(STRUCT_BUF(apinfo), data, STRUCT_SIZE(apinfo))) 1762 0 stevel return (EFAULT); 1763 0 stevel 1764 0 stevel return (0); 1765 0 stevel } 1766 0 stevel 1767 0 stevel static int 1768 0 stevel setpmask(caddr_t data) 1769 0 stevel { 1770 0 stevel STRUCT_DECL(auditpinfo, apinfo); 1771 0 stevel proc_t *proc; 1772 0 stevel cred_t *newcred; 1773 0 stevel auditinfo_addr_t *ainfo; 1774 0 stevel struct p_audit_data *pad; 1775 0 stevel 1776 0 stevel model_t model; 1777 0 stevel 1778 0 stevel model = get_udatamodel(); 1779 0 stevel STRUCT_INIT(apinfo, model); 1780 0 stevel 1781 0 stevel if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo))) 1782 0 stevel return (EFAULT); 1783 0 stevel 1784 0 stevel mutex_enter(&pidlock); 1785 0 stevel if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) { 1786 0 stevel mutex_exit(&pidlock); 1787 0 stevel return (ESRCH); 1788 0 stevel } 1789 0 stevel mutex_enter(&proc->p_lock); /* so process doesn't go away */ 1790 0 stevel mutex_exit(&pidlock); 1791 0 stevel 1792 0 stevel newcred = cralloc(); 1793 0 stevel if ((ainfo = crgetauinfo_modifiable(newcred)) == NULL) { 1794 0 stevel mutex_exit(&proc->p_lock); 1795 0 stevel crfree(newcred); 1796 0 stevel return (EINVAL); 1797 0 stevel } 1798 0 stevel 1799 0 stevel mutex_enter(&proc->p_crlock); 1800 0 stevel crcopy_to(proc->p_cred, newcred); 1801 0 stevel proc->p_cred = newcred; 1802 0 stevel 1803 0 stevel ainfo->ai_mask = STRUCT_FGET(apinfo, ap_mask); 1804 0 stevel 1805 0 stevel /* 1806 0 stevel * Unlock. No need to broadcast changes via set_proc_pre_sys(), 1807 0 stevel * since t_pre_sys is ALWAYS on when audit is enabled... due to 1808 0 stevel * syscall auditing. 1809 0 stevel */ 1810 0 stevel crfree(newcred); 1811 0 stevel mutex_exit(&proc->p_crlock); 1812 0 stevel 1813 0 stevel /* Reset flag for any previous pending mask change; this supercedes */ 1814 0 stevel pad = P2A(proc); 1815 0 stevel ASSERT(pad != NULL); 1816 0 stevel mutex_enter(&(pad->pad_lock)); 1817 0 stevel pad->pad_flags &= ~PAD_SETMASK; 1818 0 stevel mutex_exit(&(pad->pad_lock)); 1819 0 stevel 1820 0 stevel mutex_exit(&proc->p_lock); 1821 0 stevel 1822 0 stevel return (0); 1823 0 stevel } 1824 0 stevel 1825 0 stevel /* 1826 0 stevel * The out of control system call 1827 0 stevel * This is audit kitchen sink aka auditadm, aka auditon 1828 0 stevel */ 1829 0 stevel static int 1830 0 stevel auditctl( 1831 0 stevel int cmd, 1832 0 stevel caddr_t data, 1833 0 stevel int length) 1834 0 stevel { 1835 0 stevel int result; 1836 0 stevel 1837 0 stevel if (!audit_active) 1838 0 stevel return (EINVAL); 1839 0 stevel 1840 0 stevel switch (cmd) { 1841 0 stevel case A_GETCOND: 1842 0 stevel case A_GETCAR: 1843 0 stevel case A_GETCLASS: 1844 0 stevel case A_GETCWD: 1845 0 stevel case A_GETKAUDIT: 1846 0 stevel case A_GETKMASK: 1847 0 stevel case A_GETPINFO: 1848 0 stevel case A_GETPINFO_ADDR: 1849 0 stevel case A_GETPOLICY: 1850 0 stevel case A_GETQCTRL: 1851 0 stevel case A_GETSTAT: 1852 0 stevel if (secpolicy_audit_getattr(CRED()) != 0) 1853 0 stevel return (EPERM); 1854 0 stevel break; 1855 0 stevel default: 1856 0 stevel if (secpolicy_audit_config(CRED()) != 0) 1857 0 stevel return (EPERM); 1858 0 stevel break; 1859 0 stevel } 1860 0 stevel 1861 0 stevel switch (cmd) { 1862 0 stevel case A_GETPOLICY: 1863 0 stevel result = getpolicy(data); 1864 0 stevel break; 1865 0 stevel case A_SETPOLICY: 1866 0 stevel result = setpolicy(data); 1867 0 stevel break; 1868 0 stevel case A_GETKMASK: 1869 0 stevel result = getkmask(data); 1870 0 stevel break; 1871 0 stevel case A_SETKMASK: 1872 0 stevel result = setkmask(data); 1873 0 stevel break; 1874 0 stevel case A_GETKAUDIT: 1875 0 stevel result = getkaudit(data, length); 1876 0 stevel break; 1877 0 stevel case A_SETKAUDIT: 1878 0 stevel result = setkaudit(data, length); 1879 0 stevel break; 1880 0 stevel case A_GETQCTRL: 1881 0 stevel result = getqctrl(data); 1882 0 stevel break; 1883 0 stevel case A_SETQCTRL: 1884 0 stevel result = setqctrl(data); 1885 0 stevel break; 1886 0 stevel case A_GETCWD: 1887 0 stevel result = getcwd(data, length); 1888 0 stevel break; 1889 0 stevel case A_GETCAR: 1890 0 stevel result = getcar(data, length); 1891 0 stevel break; 1892 0 stevel case A_GETSTAT: 1893 0 stevel result = getstat(data); 1894 0 stevel break; 1895 0 stevel case A_SETSTAT: 1896 0 stevel result = setstat(data); 1897 0 stevel break; 1898 0 stevel case A_SETUMASK: 1899 0 stevel result = setumask(data); 1900 0 stevel break; 1901 0 stevel case A_SETSMASK: 1902 0 stevel result = setsmask(data); 1903 0 stevel break; 1904 0 stevel case A_GETCOND: 1905 0 stevel result = getcond(data); 1906 0 stevel break; 1907 0 stevel case A_SETCOND: 1908 0 stevel result = setcond(data); 1909 0 stevel break; 1910 0 stevel case A_GETCLASS: 1911 0 stevel result = getclass(data); 1912 0 stevel break; 1913 0 stevel case A_SETCLASS: 1914 0 stevel result = setclass(data); 1915 0 stevel break; 1916 0 stevel case A_GETPINFO: 1917 0 stevel result = getpinfo(data); 1918 0 stevel break; 1919 0 stevel case A_GETPINFO_ADDR: 1920 0 stevel result = getpinfo_addr(data, length); 1921 0 stevel break; 1922 0 stevel case A_SETPMASK: 1923 0 stevel result = setpmask(data); 1924 0 stevel break; 1925 0 stevel default: 1926 0 stevel result = EINVAL; 1927 0 stevel break; 1928 0 stevel } 1929 0 stevel return (result); 1930 0 stevel } 1931 0 stevel 1932 0 stevel static int 1933 0 stevel audit_modsysent(char *modname, int flags, int (*func)()) 1934 0 stevel { 1935 0 stevel struct sysent *sysp; 1936 0 stevel int sysnum; 1937 0 stevel krwlock_t *kl; 1938 0 stevel 1939 0 stevel if ((sysnum = mod_getsysnum(modname)) == -1) { 1940 0 stevel cmn_err(CE_WARN, "system call missing from bind file"); 1941 0 stevel return (-1); 1942 0 stevel } 1943 0 stevel 1944 0 stevel kl = (krwlock_t *)kobj_zalloc(sizeof (krwlock_t), KM_SLEEP); 1945 0 stevel 1946 0 stevel sysp = &sysent[sysnum]; 1947 0 stevel sysp->sy_narg = auditsysent.sy_narg; 1948 0 stevel #ifdef _LP64 1949 0 stevel sysp->sy_flags = (unsigned short)flags; 1950 0 stevel #else 1951 0 stevel sysp->sy_flags = (unsigned char)flags; 1952 0 stevel #endif 1953 0 stevel sysp->sy_call = func; 1954 0 stevel sysp->sy_lock = kl; 1955 0 stevel 1956 0 stevel #ifdef _SYSCALL32_IMPL 1957 0 stevel sysp = &sysent32[sysnum]; 1958 0 stevel sysp->sy_narg = auditsysent.sy_narg; 1959 0 stevel sysp->sy_flags = (unsigned short)flags; 1960 0 stevel sysp->sy_call = func; 1961 0 stevel sysp->sy_lock = kl; 1962 0 stevel #endif 1963 0 stevel 1964 0 stevel rw_init(sysp->sy_lock, NULL, RW_DEFAULT, NULL); 1965 0 stevel 1966 0 stevel return (0); 1967 0 stevel } 1968