audit_syscalls.c revision 189570
1181053Srwatson/*- 2180701Srwatson * Copyright (c) 1999-2005 Apple Inc. 3155192Srwatson * All rights reserved. 4155192Srwatson * 5155192Srwatson * Redistribution and use in source and binary forms, with or without 6155192Srwatson * modification, are permitted provided that the following conditions 7155192Srwatson * are met: 8155192Srwatson * 1. Redistributions of source code must retain the above copyright 9155192Srwatson * notice, this list of conditions and the following disclaimer. 10155192Srwatson * 2. Redistributions in binary form must reproduce the above copyright 11155192Srwatson * notice, this list of conditions and the following disclaimer in the 12155192Srwatson * documentation and/or other materials provided with the distribution. 13180701Srwatson * 3. Neither the name of Apple Inc. ("Apple") nor the names of 14155192Srwatson * its contributors may be used to endorse or promote products derived 15155192Srwatson * from this software without specific prior written permission. 16155192Srwatson * 17155192Srwatson * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND 18155192Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19155192Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20155192Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR 21155192Srwatson * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22155192Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23155192Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24155192Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25155192Srwatson * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 26155192Srwatson * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27155192Srwatson * POSSIBILITY OF SUCH DAMAGE. 28155192Srwatson */ 29155192Srwatson 30178186Srwatson#include <sys/cdefs.h> 31178186Srwatson__FBSDID("$FreeBSD: head/sys/security/audit/audit_syscalls.c 189570 2009-03-09 10:45:58Z rwatson $"); 32178186Srwatson 33168933Srwatson#include "opt_mac.h" 34168933Srwatson 35155192Srwatson#include <sys/param.h> 36159318Srwatson#include <sys/mount.h> 37155192Srwatson#include <sys/namei.h> 38164033Srwatson#include <sys/priv.h> 39155192Srwatson#include <sys/proc.h> 40155192Srwatson#include <sys/sysproto.h> 41155192Srwatson#include <sys/systm.h> 42155192Srwatson#include <sys/vnode.h> 43163207Scsjp#include <sys/jail.h> 44155192Srwatson 45155192Srwatson#include <bsm/audit.h> 46155192Srwatson#include <bsm/audit_kevents.h> 47168933Srwatson 48155192Srwatson#include <security/audit/audit.h> 49155192Srwatson#include <security/audit/audit_private.h> 50168933Srwatson#include <security/mac/mac_framework.h> 51155192Srwatson 52155192Srwatson#ifdef AUDIT 53155192Srwatson 54155192Srwatson/* 55156889Srwatson * System call to allow a user space application to submit a BSM audit record 56170127Srwatson * to the kernel for inclusion in the audit log. This function does little 57156889Srwatson * verification on the audit record that is submitted. 58155192Srwatson * 59156889Srwatson * XXXAUDIT: Audit preselection for user records does not currently work, 60156889Srwatson * since we pre-select only based on the AUE_audit event type, not the event 61156889Srwatson * type submitted as part of the user audit data. 62155192Srwatson */ 63155192Srwatson/* ARGSUSED */ 64155192Srwatsonint 65155192Srwatsonaudit(struct thread *td, struct audit_args *uap) 66155192Srwatson{ 67155192Srwatson int error; 68155192Srwatson void * rec; 69155192Srwatson struct kaudit_record *ar; 70155192Srwatson 71163207Scsjp if (jailed(td->td_ucred)) 72163207Scsjp return (ENOSYS); 73164033Srwatson error = priv_check(td, PRIV_AUDIT_SUBMIT); 74155192Srwatson if (error) 75155192Srwatson return (error); 76155192Srwatson 77155192Srwatson if ((uap->length <= 0) || (uap->length > audit_qctrl.aq_bufsz)) 78155192Srwatson return (EINVAL); 79155192Srwatson 80155192Srwatson ar = currecord(); 81155192Srwatson 82156889Srwatson /* 83156889Srwatson * If there's no current audit record (audit() itself not audited) 84155192Srwatson * commit the user audit record. 85155192Srwatson */ 86155192Srwatson if (ar == NULL) { 87155192Srwatson 88156889Srwatson /* 89156889Srwatson * This is not very efficient; we're required to allocate a 90156889Srwatson * complete kernel audit record just so the user record can 91156889Srwatson * tag along. 92155192Srwatson * 93155192Srwatson * XXXAUDIT: Maybe AUE_AUDIT in the system call context and 94155192Srwatson * special pre-select handling? 95155192Srwatson */ 96155192Srwatson td->td_ar = audit_new(AUE_NULL, td); 97155192Srwatson if (td->td_ar == NULL) 98155192Srwatson return (ENOTSUP); 99189570Srwatson td->td_pflags |= TDP_AUDITREC; 100155192Srwatson ar = td->td_ar; 101155192Srwatson } 102155192Srwatson 103156889Srwatson if (uap->length > MAX_AUDIT_RECORD_SIZE) 104155192Srwatson return (EINVAL); 105155192Srwatson 106155192Srwatson rec = malloc(uap->length, M_AUDITDATA, M_WAITOK); 107155192Srwatson 108155192Srwatson error = copyin(uap->record, rec, uap->length); 109155192Srwatson if (error) 110155192Srwatson goto free_out; 111155192Srwatson 112156889Srwatson /* Verify the record. */ 113155192Srwatson if (bsm_rec_verify(rec) == 0) { 114155192Srwatson error = EINVAL; 115155192Srwatson goto free_out; 116155192Srwatson } 117155192Srwatson 118168933Srwatson#ifdef MAC 119172930Srwatson error = mac_system_check_audit(td->td_ucred, rec, uap->length); 120168933Srwatson if (error) 121168933Srwatson goto free_out; 122168933Srwatson#endif 123168933Srwatson 124156889Srwatson /* 125170127Srwatson * Attach the user audit record to the kernel audit record. Because 126155192Srwatson * this system call is an auditable event, we will write the user 127155192Srwatson * record along with the record for this audit event. 128155192Srwatson * 129155192Srwatson * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen, 130155192Srwatson * k_ar_commit & AR_COMMIT_USER? 131155192Srwatson */ 132155192Srwatson ar->k_udata = rec; 133155192Srwatson ar->k_ulen = uap->length; 134155192Srwatson ar->k_ar_commit |= AR_COMMIT_USER; 135162380Scsjp 136162380Scsjp /* 137162380Scsjp * Currently we assume that all preselection has been performed in 138170127Srwatson * userspace. We unconditionally set these masks so that the records 139162380Scsjp * get committed both to the trail and pipe. In the future we will 140162380Scsjp * want to setup kernel based preselection. 141162380Scsjp */ 142162380Scsjp ar->k_ar_commit |= (AR_PRESELECT_USER_TRAIL | AR_PRESELECT_USER_PIPE); 143155192Srwatson return (0); 144155192Srwatson 145155192Srwatsonfree_out: 146156889Srwatson /* 147156889Srwatson * audit_syscall_exit() will free the audit record on the thread even 148156889Srwatson * if we allocated it above. 149155192Srwatson */ 150155192Srwatson free(rec, M_AUDITDATA); 151155192Srwatson return (error); 152155192Srwatson} 153155192Srwatson 154155192Srwatson/* 155155192Srwatson * System call to manipulate auditing. 156155192Srwatson */ 157155192Srwatson/* ARGSUSED */ 158155192Srwatsonint 159155192Srwatsonauditon(struct thread *td, struct auditon_args *uap) 160155192Srwatson{ 161184948Srwatson struct ucred *cred, *newcred, *oldcred; 162155192Srwatson int error; 163155192Srwatson union auditon_udata udata; 164155192Srwatson struct proc *tp; 165155192Srwatson 166163207Scsjp if (jailed(td->td_ucred)) 167163207Scsjp return (ENOSYS); 168155192Srwatson AUDIT_ARG(cmd, uap->cmd); 169168933Srwatson 170168933Srwatson#ifdef MAC 171172930Srwatson error = mac_system_check_auditon(td->td_ucred, uap->cmd); 172168933Srwatson if (error) 173168933Srwatson return (error); 174168933Srwatson#endif 175168933Srwatson 176164033Srwatson error = priv_check(td, PRIV_AUDIT_CONTROL); 177155192Srwatson if (error) 178155192Srwatson return (error); 179155192Srwatson 180155192Srwatson if ((uap->length <= 0) || (uap->length > sizeof(union auditon_udata))) 181155192Srwatson return (EINVAL); 182155192Srwatson 183155192Srwatson memset((void *)&udata, 0, sizeof(udata)); 184155192Srwatson 185156889Srwatson /* 186156889Srwatson * Some of the GET commands use the arguments too. 187156889Srwatson */ 188155192Srwatson switch (uap->cmd) { 189155192Srwatson case A_SETPOLICY: 190155192Srwatson case A_SETKMASK: 191155192Srwatson case A_SETQCTRL: 192155192Srwatson case A_SETSTAT: 193155192Srwatson case A_SETUMASK: 194155192Srwatson case A_SETSMASK: 195155192Srwatson case A_SETCOND: 196155192Srwatson case A_SETCLASS: 197155192Srwatson case A_SETPMASK: 198155192Srwatson case A_SETFSIZE: 199155192Srwatson case A_SETKAUDIT: 200155192Srwatson case A_GETCLASS: 201155192Srwatson case A_GETPINFO: 202155192Srwatson case A_GETPINFO_ADDR: 203155192Srwatson case A_SENDTRIGGER: 204155192Srwatson error = copyin(uap->data, (void *)&udata, uap->length); 205155192Srwatson if (error) 206155192Srwatson return (error); 207155192Srwatson AUDIT_ARG(auditon, &udata); 208155192Srwatson break; 209155192Srwatson } 210155192Srwatson 211156889Srwatson /* 212155192Srwatson * XXXAUDIT: Locking? 213155192Srwatson */ 214155192Srwatson switch (uap->cmd) { 215155192Srwatson case A_GETPOLICY: 216155192Srwatson if (!audit_fail_stop) 217155192Srwatson udata.au_policy |= AUDIT_CNT; 218155192Srwatson if (audit_panic_on_write_fail) 219155192Srwatson udata.au_policy |= AUDIT_AHLT; 220161813Swsalamon if (audit_argv) 221161813Swsalamon udata.au_policy |= AUDIT_ARGV; 222161813Swsalamon if (audit_arge) 223161813Swsalamon udata.au_policy |= AUDIT_ARGE; 224155192Srwatson break; 225155192Srwatson 226155192Srwatson case A_SETPOLICY: 227161813Swsalamon if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT|AUDIT_ARGV| 228161813Swsalamon AUDIT_ARGE)) 229155192Srwatson return (EINVAL); 230155192Srwatson /* 231155192Srwatson * XXX - Need to wake up waiters if the policy relaxes? 232155192Srwatson */ 233155192Srwatson audit_fail_stop = ((udata.au_policy & AUDIT_CNT) == 0); 234155192Srwatson audit_panic_on_write_fail = (udata.au_policy & AUDIT_AHLT); 235161813Swsalamon audit_argv = (udata.au_policy & AUDIT_ARGV); 236161813Swsalamon audit_arge = (udata.au_policy & AUDIT_ARGE); 237155192Srwatson break; 238155192Srwatson 239155192Srwatson case A_GETKMASK: 240155192Srwatson udata.au_mask = audit_nae_mask; 241155192Srwatson break; 242155192Srwatson 243155192Srwatson case A_SETKMASK: 244155192Srwatson audit_nae_mask = udata.au_mask; 245155192Srwatson break; 246155192Srwatson 247155192Srwatson case A_GETQCTRL: 248155192Srwatson udata.au_qctrl = audit_qctrl; 249155192Srwatson break; 250155192Srwatson 251155192Srwatson case A_SETQCTRL: 252155192Srwatson if ((udata.au_qctrl.aq_hiwater > AQ_MAXHIGH) || 253155192Srwatson (udata.au_qctrl.aq_lowater >= udata.au_qctrl.aq_hiwater) || 254155192Srwatson (udata.au_qctrl.aq_bufsz > AQ_MAXBUFSZ) || 255155192Srwatson (udata.au_qctrl.aq_minfree < 0) || 256155192Srwatson (udata.au_qctrl.aq_minfree > 100)) 257155192Srwatson return (EINVAL); 258155192Srwatson 259155192Srwatson audit_qctrl = udata.au_qctrl; 260155192Srwatson /* XXX The queue delay value isn't used with the kernel. */ 261155192Srwatson audit_qctrl.aq_delay = -1; 262155192Srwatson break; 263155192Srwatson 264155192Srwatson case A_GETCWD: 265155192Srwatson return (ENOSYS); 266155192Srwatson break; 267155192Srwatson 268155192Srwatson case A_GETCAR: 269155192Srwatson return (ENOSYS); 270155192Srwatson break; 271155192Srwatson 272155192Srwatson case A_GETSTAT: 273155192Srwatson return (ENOSYS); 274155192Srwatson break; 275155192Srwatson 276155192Srwatson case A_SETSTAT: 277155192Srwatson return (ENOSYS); 278155192Srwatson break; 279155192Srwatson 280155192Srwatson case A_SETUMASK: 281155192Srwatson return (ENOSYS); 282155192Srwatson break; 283155192Srwatson 284155192Srwatson case A_SETSMASK: 285155192Srwatson return (ENOSYS); 286155192Srwatson break; 287155192Srwatson 288155192Srwatson case A_GETCOND: 289155192Srwatson if (audit_enabled && !audit_suspended) 290155192Srwatson udata.au_cond = AUC_AUDITING; 291155192Srwatson else 292155192Srwatson udata.au_cond = AUC_NOAUDIT; 293155192Srwatson break; 294155192Srwatson 295155192Srwatson case A_SETCOND: 296156889Srwatson if (udata.au_cond == AUC_NOAUDIT) 297155192Srwatson audit_suspended = 1; 298156889Srwatson if (udata.au_cond == AUC_AUDITING) 299155192Srwatson audit_suspended = 0; 300155192Srwatson if (udata.au_cond == AUC_DISABLED) { 301155192Srwatson audit_suspended = 1; 302155192Srwatson audit_shutdown(NULL, 0); 303155192Srwatson } 304155192Srwatson break; 305155192Srwatson 306155192Srwatson case A_GETCLASS: 307156889Srwatson udata.au_evclass.ec_class = au_event_class( 308156889Srwatson udata.au_evclass.ec_number); 309155192Srwatson break; 310155192Srwatson 311155192Srwatson case A_SETCLASS: 312155192Srwatson au_evclassmap_insert(udata.au_evclass.ec_number, 313156889Srwatson udata.au_evclass.ec_class); 314155192Srwatson break; 315155192Srwatson 316155192Srwatson case A_GETPINFO: 317156889Srwatson if (udata.au_aupinfo.ap_pid < 1) 318182750Skevlo return (ESRCH); 319155192Srwatson if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) 320182750Skevlo return (ESRCH); 321182754Sdes if ((error = p_cansee(td, tp)) != 0) { 322165624Srwatson PROC_UNLOCK(tp); 323182750Skevlo return (error); 324165624Srwatson } 325184948Srwatson cred = tp->p_ucred; 326184948Srwatson if (cred->cr_audit.ai_termid.at_type == AU_IPv6) { 327168688Scsjp PROC_UNLOCK(tp); 328168688Scsjp return (EINVAL); 329168688Scsjp } 330184948Srwatson udata.au_aupinfo.ap_auid = cred->cr_audit.ai_auid; 331156889Srwatson udata.au_aupinfo.ap_mask.am_success = 332184948Srwatson cred->cr_audit.ai_mask.am_success; 333156889Srwatson udata.au_aupinfo.ap_mask.am_failure = 334184948Srwatson cred->cr_audit.ai_mask.am_failure; 335156889Srwatson udata.au_aupinfo.ap_termid.machine = 336184948Srwatson cred->cr_audit.ai_termid.at_addr[0]; 337168688Scsjp udata.au_aupinfo.ap_termid.port = 338184948Srwatson (dev_t)cred->cr_audit.ai_termid.at_port; 339184948Srwatson udata.au_aupinfo.ap_asid = cred->cr_audit.ai_asid; 340155192Srwatson PROC_UNLOCK(tp); 341155192Srwatson break; 342155192Srwatson 343155192Srwatson case A_SETPMASK: 344156889Srwatson if (udata.au_aupinfo.ap_pid < 1) 345182750Skevlo return (ESRCH); 346170407Srwatson newcred = crget(); 347170407Srwatson if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) { 348170407Srwatson crfree(newcred); 349182750Skevlo return (ESRCH); 350170407Srwatson } 351182754Sdes if ((error = p_cansee(td, tp)) != 0) { 352165624Srwatson PROC_UNLOCK(tp); 353170407Srwatson crfree(newcred); 354182750Skevlo return (error); 355165624Srwatson } 356170407Srwatson oldcred = tp->p_ucred; 357170407Srwatson crcopy(newcred, oldcred); 358170407Srwatson newcred->cr_audit.ai_mask.am_success = 359156889Srwatson udata.au_aupinfo.ap_mask.am_success; 360170407Srwatson newcred->cr_audit.ai_mask.am_failure = 361156889Srwatson udata.au_aupinfo.ap_mask.am_failure; 362170407Srwatson td->td_proc->p_ucred = newcred; 363155192Srwatson PROC_UNLOCK(tp); 364170407Srwatson crfree(oldcred); 365155192Srwatson break; 366155192Srwatson 367155192Srwatson case A_SETFSIZE: 368155192Srwatson if ((udata.au_fstat.af_filesz != 0) && 369155192Srwatson (udata.au_fstat.af_filesz < MIN_AUDIT_FILE_SIZE)) 370155192Srwatson return (EINVAL); 371155192Srwatson audit_fstat.af_filesz = udata.au_fstat.af_filesz; 372155192Srwatson break; 373155192Srwatson 374155192Srwatson case A_GETFSIZE: 375155192Srwatson udata.au_fstat.af_filesz = audit_fstat.af_filesz; 376155192Srwatson udata.au_fstat.af_currsz = audit_fstat.af_currsz; 377155192Srwatson break; 378155192Srwatson 379155192Srwatson case A_GETPINFO_ADDR: 380168688Scsjp if (udata.au_aupinfo_addr.ap_pid < 1) 381182750Skevlo return (ESRCH); 382168688Scsjp if ((tp = pfind(udata.au_aupinfo_addr.ap_pid)) == NULL) 383182750Skevlo return (ESRCH); 384184948Srwatson cred = tp->p_ucred; 385184948Srwatson udata.au_aupinfo_addr.ap_auid = cred->cr_audit.ai_auid; 386168688Scsjp udata.au_aupinfo_addr.ap_mask.am_success = 387184948Srwatson cred->cr_audit.ai_mask.am_success; 388168688Scsjp udata.au_aupinfo_addr.ap_mask.am_failure = 389184948Srwatson cred->cr_audit.ai_mask.am_failure; 390184948Srwatson udata.au_aupinfo_addr.ap_termid = cred->cr_audit.ai_termid; 391184948Srwatson udata.au_aupinfo_addr.ap_asid = cred->cr_audit.ai_asid; 392168688Scsjp PROC_UNLOCK(tp); 393155192Srwatson break; 394155192Srwatson 395155192Srwatson case A_GETKAUDIT: 396184856Scsjp audit_get_kinfo(&udata.au_kau_info); 397155192Srwatson break; 398155192Srwatson 399155192Srwatson case A_SETKAUDIT: 400184856Scsjp if (udata.au_kau_info.ai_termid.at_type != AU_IPv4 && 401184856Scsjp udata.au_kau_info.ai_termid.at_type != AU_IPv6) 402184856Scsjp return (EINVAL); 403184856Scsjp audit_set_kinfo(&udata.au_kau_info); 404155192Srwatson break; 405155192Srwatson 406155192Srwatson case A_SENDTRIGGER: 407155192Srwatson if ((udata.au_trigger < AUDIT_TRIGGER_MIN) || 408155192Srwatson (udata.au_trigger > AUDIT_TRIGGER_MAX)) 409155192Srwatson return (EINVAL); 410176686Srwatson return (audit_send_trigger(udata.au_trigger)); 411176887Scsjp 412176887Scsjp default: 413176887Scsjp return (EINVAL); 414155192Srwatson } 415156889Srwatson 416156889Srwatson /* 417156889Srwatson * Copy data back to userspace for the GET comands. 418156889Srwatson */ 419155192Srwatson switch (uap->cmd) { 420155192Srwatson case A_GETPOLICY: 421155192Srwatson case A_GETKMASK: 422155192Srwatson case A_GETQCTRL: 423155192Srwatson case A_GETCWD: 424155192Srwatson case A_GETCAR: 425155192Srwatson case A_GETSTAT: 426155192Srwatson case A_GETCOND: 427155192Srwatson case A_GETCLASS: 428155192Srwatson case A_GETPINFO: 429155192Srwatson case A_GETFSIZE: 430155192Srwatson case A_GETPINFO_ADDR: 431155192Srwatson case A_GETKAUDIT: 432155192Srwatson error = copyout((void *)&udata, uap->data, uap->length); 433155192Srwatson if (error) 434155192Srwatson return (error); 435155192Srwatson break; 436155192Srwatson } 437155192Srwatson 438155192Srwatson return (0); 439155192Srwatson} 440155192Srwatson 441156889Srwatson/* 442155192Srwatson * System calls to manage the user audit information. 443155192Srwatson */ 444155192Srwatson/* ARGSUSED */ 445155192Srwatsonint 446155192Srwatsongetauid(struct thread *td, struct getauid_args *uap) 447155192Srwatson{ 448155192Srwatson int error; 449155192Srwatson 450163207Scsjp if (jailed(td->td_ucred)) 451163207Scsjp return (ENOSYS); 452164033Srwatson error = priv_check(td, PRIV_AUDIT_GETAUDIT); 453155192Srwatson if (error) 454155192Srwatson return (error); 455170407Srwatson return (copyout(&td->td_ucred->cr_audit.ai_auid, uap->auid, 456170407Srwatson sizeof(td->td_ucred->cr_audit.ai_auid))); 457155192Srwatson} 458155192Srwatson 459155192Srwatson/* ARGSUSED */ 460155192Srwatsonint 461155192Srwatsonsetauid(struct thread *td, struct setauid_args *uap) 462155192Srwatson{ 463170407Srwatson struct ucred *newcred, *oldcred; 464170407Srwatson au_id_t id; 465155192Srwatson int error; 466155192Srwatson 467163207Scsjp if (jailed(td->td_ucred)) 468163207Scsjp return (ENOSYS); 469155192Srwatson error = copyin(uap->auid, &id, sizeof(id)); 470155192Srwatson if (error) 471155192Srwatson return (error); 472155192Srwatson audit_arg_auid(id); 473170407Srwatson newcred = crget(); 474170407Srwatson PROC_LOCK(td->td_proc); 475170407Srwatson oldcred = td->td_proc->p_ucred; 476170407Srwatson crcopy(newcred, oldcred); 477168933Srwatson#ifdef MAC 478189529Srwatson error = mac_cred_check_setauid(oldcred, id); 479168933Srwatson if (error) 480170407Srwatson goto fail; 481168933Srwatson#endif 482170407Srwatson error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0); 483170407Srwatson if (error) 484170407Srwatson goto fail; 485170407Srwatson newcred->cr_audit.ai_auid = id; 486170407Srwatson td->td_proc->p_ucred = newcred; 487155192Srwatson PROC_UNLOCK(td->td_proc); 488170407Srwatson crfree(oldcred); 489155192Srwatson return (0); 490170407Srwatsonfail: 491170407Srwatson PROC_UNLOCK(td->td_proc); 492170407Srwatson crfree(newcred); 493170407Srwatson return (error); 494155192Srwatson} 495155192Srwatson 496155192Srwatson/* 497156889Srwatson * System calls to get and set process audit information. 498155192Srwatson */ 499155192Srwatson/* ARGSUSED */ 500155192Srwatsonint 501155192Srwatsongetaudit(struct thread *td, struct getaudit_args *uap) 502155192Srwatson{ 503155192Srwatson struct auditinfo ai; 504184948Srwatson struct ucred *cred; 505155192Srwatson int error; 506155192Srwatson 507184948Srwatson cred = td->td_ucred; 508184948Srwatson if (jailed(cred)) 509163207Scsjp return (ENOSYS); 510164033Srwatson error = priv_check(td, PRIV_AUDIT_GETAUDIT); 511155192Srwatson if (error) 512155192Srwatson return (error); 513184948Srwatson if (cred->cr_audit.ai_termid.at_type == AU_IPv6) 514185484Scsjp return (E2BIG); 515168688Scsjp bzero(&ai, sizeof(ai)); 516184948Srwatson ai.ai_auid = cred->cr_audit.ai_auid; 517184948Srwatson ai.ai_mask = cred->cr_audit.ai_mask; 518184948Srwatson ai.ai_asid = cred->cr_audit.ai_asid; 519184948Srwatson ai.ai_termid.machine = cred->cr_audit.ai_termid.at_addr[0]; 520184948Srwatson ai.ai_termid.port = cred->cr_audit.ai_termid.at_port; 521171066Scsjp return (copyout(&ai, uap->auditinfo, sizeof(ai))); 522155192Srwatson} 523155192Srwatson 524155192Srwatson/* ARGSUSED */ 525155192Srwatsonint 526155192Srwatsonsetaudit(struct thread *td, struct setaudit_args *uap) 527155192Srwatson{ 528170407Srwatson struct ucred *newcred, *oldcred; 529155192Srwatson struct auditinfo ai; 530155192Srwatson int error; 531155192Srwatson 532163207Scsjp if (jailed(td->td_ucred)) 533163207Scsjp return (ENOSYS); 534155192Srwatson error = copyin(uap->auditinfo, &ai, sizeof(ai)); 535155192Srwatson if (error) 536155192Srwatson return (error); 537155192Srwatson audit_arg_auditinfo(&ai); 538170407Srwatson newcred = crget(); 539170407Srwatson PROC_LOCK(td->td_proc); 540170407Srwatson oldcred = td->td_proc->p_ucred; 541170407Srwatson crcopy(newcred, oldcred); 542168933Srwatson#ifdef MAC 543189529Srwatson error = mac_cred_check_setaudit(oldcred, &ai); 544168933Srwatson if (error) 545170407Srwatson goto fail; 546168933Srwatson#endif 547170407Srwatson error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0); 548170407Srwatson if (error) 549170407Srwatson goto fail; 550170407Srwatson bzero(&newcred->cr_audit, sizeof(newcred->cr_audit)); 551170407Srwatson newcred->cr_audit.ai_auid = ai.ai_auid; 552170407Srwatson newcred->cr_audit.ai_mask = ai.ai_mask; 553170407Srwatson newcred->cr_audit.ai_asid = ai.ai_asid; 554170407Srwatson newcred->cr_audit.ai_termid.at_addr[0] = ai.ai_termid.machine; 555170407Srwatson newcred->cr_audit.ai_termid.at_port = ai.ai_termid.port; 556170407Srwatson newcred->cr_audit.ai_termid.at_type = AU_IPv4; 557170407Srwatson td->td_proc->p_ucred = newcred; 558155192Srwatson PROC_UNLOCK(td->td_proc); 559170407Srwatson crfree(oldcred); 560155192Srwatson return (0); 561170407Srwatsonfail: 562170407Srwatson PROC_UNLOCK(td->td_proc); 563170407Srwatson crfree(newcred); 564170407Srwatson return (error); 565155192Srwatson} 566155192Srwatson 567155192Srwatson/* ARGSUSED */ 568155192Srwatsonint 569155192Srwatsongetaudit_addr(struct thread *td, struct getaudit_addr_args *uap) 570155192Srwatson{ 571155192Srwatson int error; 572155192Srwatson 573163207Scsjp if (jailed(td->td_ucred)) 574163207Scsjp return (ENOSYS); 575170407Srwatson if (uap->length < sizeof(*uap->auditinfo_addr)) 576170407Srwatson return (EOVERFLOW); 577164033Srwatson error = priv_check(td, PRIV_AUDIT_GETAUDIT); 578155192Srwatson if (error) 579155192Srwatson return (error); 580170407Srwatson return (copyout(&td->td_ucred->cr_audit, uap->auditinfo_addr, 581170407Srwatson sizeof(*uap->auditinfo_addr))); 582155192Srwatson} 583155192Srwatson 584155192Srwatson/* ARGSUSED */ 585155192Srwatsonint 586155192Srwatsonsetaudit_addr(struct thread *td, struct setaudit_addr_args *uap) 587155192Srwatson{ 588170407Srwatson struct ucred *newcred, *oldcred; 589168688Scsjp struct auditinfo_addr aia; 590155192Srwatson int error; 591155192Srwatson 592163207Scsjp if (jailed(td->td_ucred)) 593163207Scsjp return (ENOSYS); 594170407Srwatson error = copyin(uap->auditinfo_addr, &aia, sizeof(aia)); 595155192Srwatson if (error) 596155192Srwatson return (error); 597171066Scsjp audit_arg_auditinfo_addr(&aia); 598171066Scsjp if (aia.ai_termid.at_type != AU_IPv6 && 599171066Scsjp aia.ai_termid.at_type != AU_IPv4) 600171066Scsjp return (EINVAL); 601170407Srwatson newcred = crget(); 602170407Srwatson PROC_LOCK(td->td_proc); 603170407Srwatson oldcred = td->td_proc->p_ucred; 604170407Srwatson crcopy(newcred, oldcred); 605168933Srwatson#ifdef MAC 606189529Srwatson error = mac_cred_check_setaudit_addr(oldcred, &aia); 607168933Srwatson if (error) 608170407Srwatson goto fail; 609168933Srwatson#endif 610170407Srwatson error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0); 611168688Scsjp if (error) 612170407Srwatson goto fail; 613170407Srwatson newcred->cr_audit = aia; 614170407Srwatson td->td_proc->p_ucred = newcred; 615168688Scsjp PROC_UNLOCK(td->td_proc); 616170407Srwatson crfree(oldcred); 617170407Srwatson return (0); 618170407Srwatsonfail: 619170777Srwatson PROC_UNLOCK(td->td_proc); 620170407Srwatson crfree(newcred); 621168688Scsjp return (error); 622155192Srwatson} 623155192Srwatson 624155192Srwatson/* 625155192Srwatson * Syscall to manage audit files. 626155192Srwatson */ 627155192Srwatson/* ARGSUSED */ 628155192Srwatsonint 629155192Srwatsonauditctl(struct thread *td, struct auditctl_args *uap) 630155192Srwatson{ 631155192Srwatson struct nameidata nd; 632155192Srwatson struct ucred *cred; 633155192Srwatson struct vnode *vp; 634155192Srwatson int error = 0; 635159318Srwatson int flags, vfslocked; 636155192Srwatson 637163207Scsjp if (jailed(td->td_ucred)) 638163207Scsjp return (ENOSYS); 639164033Srwatson error = priv_check(td, PRIV_AUDIT_CONTROL); 640155192Srwatson if (error) 641155192Srwatson return (error); 642155192Srwatson 643155192Srwatson vp = NULL; 644155192Srwatson cred = NULL; 645155192Srwatson 646155192Srwatson /* 647155192Srwatson * If a path is specified, open the replacement vnode, perform 648155192Srwatson * validity checks, and grab another reference to the current 649155192Srwatson * credential. 650155192Srwatson * 651165624Srwatson * On Darwin, a NULL path argument is also used to disable audit. 652155192Srwatson */ 653155192Srwatson if (uap->path == NULL) 654155192Srwatson return (EINVAL); 655155192Srwatson 656162944Srwatson NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, 657162944Srwatson UIO_USERSPACE, uap->path, td); 658155192Srwatson flags = AUDIT_OPEN_FLAGS; 659170183Skib error = vn_open(&nd, &flags, 0, NULL); 660159318Srwatson if (error) 661159318Srwatson return (error); 662159318Srwatson vfslocked = NDHASGIANT(&nd); 663155192Srwatson vp = nd.ni_vp; 664168933Srwatson#ifdef MAC 665172930Srwatson error = mac_system_check_auditctl(td->td_ucred, vp); 666175294Sattilio VOP_UNLOCK(vp, 0); 667168933Srwatson if (error) { 668168933Srwatson vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td); 669168933Srwatson VFS_UNLOCK_GIANT(vfslocked); 670168933Srwatson return (error); 671168933Srwatson } 672168933Srwatson#else 673175294Sattilio VOP_UNLOCK(vp, 0); 674168933Srwatson#endif 675162944Srwatson NDFREE(&nd, NDF_ONLY_PNBUF); 676155192Srwatson if (vp->v_type != VREG) { 677155192Srwatson vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td); 678159318Srwatson VFS_UNLOCK_GIANT(vfslocked); 679159318Srwatson return (EINVAL); 680155192Srwatson } 681159318Srwatson VFS_UNLOCK_GIANT(vfslocked); 682155192Srwatson cred = td->td_ucred; 683155192Srwatson crhold(cred); 684155192Srwatson 685155192Srwatson /* 686155192Srwatson * XXXAUDIT: Should audit_suspended actually be cleared by 687155192Srwatson * audit_worker? 688155192Srwatson */ 689155192Srwatson audit_suspended = 0; 690155192Srwatson 691155192Srwatson audit_rotate_vnode(cred, vp); 692155192Srwatson 693155192Srwatson return (error); 694155192Srwatson} 695155192Srwatson 696155192Srwatson#else /* !AUDIT */ 697155192Srwatson 698155192Srwatsonint 699155192Srwatsonaudit(struct thread *td, struct audit_args *uap) 700155192Srwatson{ 701155192Srwatson 702155192Srwatson return (ENOSYS); 703155192Srwatson} 704155192Srwatson 705155192Srwatsonint 706155192Srwatsonauditon(struct thread *td, struct auditon_args *uap) 707155192Srwatson{ 708155192Srwatson 709155192Srwatson return (ENOSYS); 710155192Srwatson} 711155192Srwatson 712155192Srwatsonint 713155192Srwatsongetauid(struct thread *td, struct getauid_args *uap) 714155192Srwatson{ 715155192Srwatson 716155192Srwatson return (ENOSYS); 717155192Srwatson} 718155192Srwatson 719155192Srwatsonint 720155192Srwatsonsetauid(struct thread *td, struct setauid_args *uap) 721155192Srwatson{ 722155192Srwatson 723155192Srwatson return (ENOSYS); 724155192Srwatson} 725155192Srwatson 726155192Srwatsonint 727155192Srwatsongetaudit(struct thread *td, struct getaudit_args *uap) 728155192Srwatson{ 729155192Srwatson 730155192Srwatson return (ENOSYS); 731155192Srwatson} 732155192Srwatson 733155192Srwatsonint 734155192Srwatsonsetaudit(struct thread *td, struct setaudit_args *uap) 735155192Srwatson{ 736155192Srwatson 737155192Srwatson return (ENOSYS); 738155192Srwatson} 739155192Srwatson 740155192Srwatsonint 741155192Srwatsongetaudit_addr(struct thread *td, struct getaudit_addr_args *uap) 742155192Srwatson{ 743155192Srwatson 744155192Srwatson return (ENOSYS); 745155192Srwatson} 746155192Srwatson 747155192Srwatsonint 748155192Srwatsonsetaudit_addr(struct thread *td, struct setaudit_addr_args *uap) 749155192Srwatson{ 750155192Srwatson 751155192Srwatson return (ENOSYS); 752155192Srwatson} 753155192Srwatson 754155192Srwatsonint 755155192Srwatsonauditctl(struct thread *td, struct auditctl_args *uap) 756155192Srwatson{ 757155192Srwatson 758155192Srwatson return (ENOSYS); 759155192Srwatson} 760155192Srwatson#endif /* AUDIT */ 761