audit_syscalls.c (5ec681997d06c5b37f9875aafde0a9ab9bd038b9) | audit_syscalls.c (871499fef514fd9934f9a8a07194e8ef86c07bd5) |
---|---|
1/* 2 * Copyright (c) 1999-2005 Apple Computer, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 32 unchanged lines hidden (view full) --- 41#include <security/audit/audit.h> 42#include <security/audit/audit_private.h> 43 44#ifdef AUDIT 45 46/* 47 * MPSAFE 48 * | 1/* 2 * Copyright (c) 1999-2005 Apple Computer, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 32 unchanged lines hidden (view full) --- 41#include <security/audit/audit.h> 42#include <security/audit/audit_private.h> 43 44#ifdef AUDIT 45 46/* 47 * MPSAFE 48 * |
49 * System call to allow a user space application to submit a BSM audit 50 * record to the kernel for inclusion in the audit log. This function 51 * does little verification on the audit record that is submitted. | 49 * System call to allow a user space application to submit a BSM audit record 50 * to the kernel for inclusion in the audit log. This function does little 51 * verification on the audit record that is submitted. |
52 * | 52 * |
53 * XXXAUDIT: Audit preselection for user records does not currently 54 * work, since we pre-select only based on the AUE_audit event type, 55 * not the event type submitted as part of the user audit data. | 53 * XXXAUDIT: Audit preselection for user records does not currently work, 54 * since we pre-select only based on the AUE_audit event type, not the event 55 * type submitted as part of the user audit data. |
56 */ 57/* ARGSUSED */ 58int 59audit(struct thread *td, struct audit_args *uap) 60{ 61 int error; 62 void * rec; 63 struct kaudit_record *ar; 64 65 error = suser(td); 66 if (error) 67 return (error); 68 69 if ((uap->length <= 0) || (uap->length > audit_qctrl.aq_bufsz)) 70 return (EINVAL); 71 72 ar = currecord(); 73 | 56 */ 57/* ARGSUSED */ 58int 59audit(struct thread *td, struct audit_args *uap) 60{ 61 int error; 62 void * rec; 63 struct kaudit_record *ar; 64 65 error = suser(td); 66 if (error) 67 return (error); 68 69 if ((uap->length <= 0) || (uap->length > audit_qctrl.aq_bufsz)) 70 return (EINVAL); 71 72 ar = currecord(); 73 |
74 /* If there's no current audit record (audit() itself not audited) | 74 /* 75 * If there's no current audit record (audit() itself not audited) |
75 * commit the user audit record. 76 */ 77 if (ar == NULL) { 78 | 76 * commit the user audit record. 77 */ 78 if (ar == NULL) { 79 |
79 /* This is not very efficient; we're required to allocate 80 * a complete kernel audit record just so the user record 81 * can tag along. | 80 /* 81 * This is not very efficient; we're required to allocate a 82 * complete kernel audit record just so the user record can 83 * tag along. |
82 * 83 * XXXAUDIT: Maybe AUE_AUDIT in the system call context and 84 * special pre-select handling? 85 */ 86 td->td_ar = audit_new(AUE_NULL, td); 87 if (td->td_ar == NULL) 88 return (ENOTSUP); 89 ar = td->td_ar; 90 } 91 | 84 * 85 * XXXAUDIT: Maybe AUE_AUDIT in the system call context and 86 * special pre-select handling? 87 */ 88 td->td_ar = audit_new(AUE_NULL, td); 89 if (td->td_ar == NULL) 90 return (ENOTSUP); 91 ar = td->td_ar; 92 } 93 |
92 if (uap->length > MAX_AUDIT_RECORD_SIZE) | 94 if (uap->length > MAX_AUDIT_RECORD_SIZE) |
93 return (EINVAL); 94 95 rec = malloc(uap->length, M_AUDITDATA, M_WAITOK); 96 97 error = copyin(uap->record, rec, uap->length); 98 if (error) 99 goto free_out; 100 | 95 return (EINVAL); 96 97 rec = malloc(uap->length, M_AUDITDATA, M_WAITOK); 98 99 error = copyin(uap->record, rec, uap->length); 100 if (error) 101 goto free_out; 102 |
101 /* Verify the record */ | 103 /* Verify the record. */ |
102 if (bsm_rec_verify(rec) == 0) { 103 error = EINVAL; 104 goto free_out; 105 } 106 | 104 if (bsm_rec_verify(rec) == 0) { 105 error = EINVAL; 106 goto free_out; 107 } 108 |
107 /* Attach the user audit record to the kernel audit record. Because | 109 /* 110 * Attach the user audit record to the kernel audit record. Because |
108 * this system call is an auditable event, we will write the user 109 * record along with the record for this audit event. 110 * 111 * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen, 112 * k_ar_commit & AR_COMMIT_USER? 113 */ 114 ar->k_udata = rec; 115 ar->k_ulen = uap->length; 116 ar->k_ar_commit |= AR_COMMIT_USER; 117 return (0); 118 119free_out: | 111 * this system call is an auditable event, we will write the user 112 * record along with the record for this audit event. 113 * 114 * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen, 115 * k_ar_commit & AR_COMMIT_USER? 116 */ 117 ar->k_udata = rec; 118 ar->k_ulen = uap->length; 119 ar->k_ar_commit |= AR_COMMIT_USER; 120 return (0); 121 122free_out: |
120 /* audit_syscall_exit() will free the audit record on the thread 121 * even if we allocated it above. | 123 /* 124 * audit_syscall_exit() will free the audit record on the thread even 125 * if we allocated it above. |
122 */ 123 free(rec, M_AUDITDATA); 124 return (error); 125} 126 127/* 128 * MPSAFE 129 * --- 12 unchanged lines hidden (view full) --- 142 if (error) 143 return (error); 144 145 if ((uap->length <= 0) || (uap->length > sizeof(union auditon_udata))) 146 return (EINVAL); 147 148 memset((void *)&udata, 0, sizeof(udata)); 149 | 126 */ 127 free(rec, M_AUDITDATA); 128 return (error); 129} 130 131/* 132 * MPSAFE 133 * --- 12 unchanged lines hidden (view full) --- 146 if (error) 147 return (error); 148 149 if ((uap->length <= 0) || (uap->length > sizeof(union auditon_udata))) 150 return (EINVAL); 151 152 memset((void *)&udata, 0, sizeof(udata)); 153 |
154 /* 155 * Some of the GET commands use the arguments too. 156 */ |
|
150 switch (uap->cmd) { | 157 switch (uap->cmd) { |
151 /* Some of the GET commands use the arguments too */ | |
152 case A_SETPOLICY: 153 case A_SETKMASK: 154 case A_SETQCTRL: 155 case A_SETSTAT: 156 case A_SETUMASK: 157 case A_SETSMASK: 158 case A_SETCOND: 159 case A_SETCLASS: --- 6 unchanged lines hidden (view full) --- 166 case A_SENDTRIGGER: 167 error = copyin(uap->data, (void *)&udata, uap->length); 168 if (error) 169 return (error); 170 AUDIT_ARG(auditon, &udata); 171 break; 172 } 173 | 158 case A_SETPOLICY: 159 case A_SETKMASK: 160 case A_SETQCTRL: 161 case A_SETSTAT: 162 case A_SETUMASK: 163 case A_SETSMASK: 164 case A_SETCOND: 165 case A_SETCLASS: --- 6 unchanged lines hidden (view full) --- 172 case A_SENDTRIGGER: 173 error = copyin(uap->data, (void *)&udata, uap->length); 174 if (error) 175 return (error); 176 AUDIT_ARG(auditon, &udata); 177 break; 178 } 179 |
174 /* XXX Need to implement these commands by accessing the global | 180 /* 181 * XXX Need to implement these commands by accessing the global |
175 * values associated with the commands. 176 * 177 * XXXAUDIT: Locking? 178 */ 179 switch (uap->cmd) { 180 case A_GETPOLICY: 181 if (!audit_fail_stop) 182 udata.au_policy |= AUDIT_CNT; --- 63 unchanged lines hidden (view full) --- 246 case A_GETCOND: 247 if (audit_enabled && !audit_suspended) 248 udata.au_cond = AUC_AUDITING; 249 else 250 udata.au_cond = AUC_NOAUDIT; 251 break; 252 253 case A_SETCOND: | 182 * values associated with the commands. 183 * 184 * XXXAUDIT: Locking? 185 */ 186 switch (uap->cmd) { 187 case A_GETPOLICY: 188 if (!audit_fail_stop) 189 udata.au_policy |= AUDIT_CNT; --- 63 unchanged lines hidden (view full) --- 253 case A_GETCOND: 254 if (audit_enabled && !audit_suspended) 255 udata.au_cond = AUC_AUDITING; 256 else 257 udata.au_cond = AUC_NOAUDIT; 258 break; 259 260 case A_SETCOND: |
254 if (udata.au_cond == AUC_NOAUDIT) | 261 if (udata.au_cond == AUC_NOAUDIT) |
255 audit_suspended = 1; | 262 audit_suspended = 1; |
256 if (udata.au_cond == AUC_AUDITING) | 263 if (udata.au_cond == AUC_AUDITING) |
257 audit_suspended = 0; 258 if (udata.au_cond == AUC_DISABLED) { 259 audit_suspended = 1; 260 audit_shutdown(NULL, 0); 261 } 262 break; 263 264 case A_GETCLASS: | 264 audit_suspended = 0; 265 if (udata.au_cond == AUC_DISABLED) { 266 audit_suspended = 1; 267 audit_shutdown(NULL, 0); 268 } 269 break; 270 271 case A_GETCLASS: |
265 udata.au_evclass.ec_class = 266 au_event_class(udata.au_evclass.ec_number); | 272 udata.au_evclass.ec_class = au_event_class( 273 udata.au_evclass.ec_number); |
267 break; 268 269 case A_SETCLASS: 270 au_evclassmap_insert(udata.au_evclass.ec_number, | 274 break; 275 276 case A_SETCLASS: 277 au_evclassmap_insert(udata.au_evclass.ec_number, |
271 udata.au_evclass.ec_class); | 278 udata.au_evclass.ec_class); |
272 break; 273 274 case A_GETPINFO: | 279 break; 280 281 case A_GETPINFO: |
275 if (udata.au_aupinfo.ap_pid < 1) | 282 if (udata.au_aupinfo.ap_pid < 1) |
276 return (EINVAL); 277 278 /* XXXAUDIT: p_cansee()? */ 279 if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) 280 return (EINVAL); 281 282 udata.au_aupinfo.ap_auid = tp->p_au->ai_auid; | 283 return (EINVAL); 284 285 /* XXXAUDIT: p_cansee()? */ 286 if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) 287 return (EINVAL); 288 289 udata.au_aupinfo.ap_auid = tp->p_au->ai_auid; |
283 udata.au_aupinfo.ap_mask.am_success = 284 tp->p_au->ai_mask.am_success; 285 udata.au_aupinfo.ap_mask.am_failure = 286 tp->p_au->ai_mask.am_failure; 287 udata.au_aupinfo.ap_termid.machine = 288 tp->p_au->ai_termid.machine; 289 udata.au_aupinfo.ap_termid.port = 290 tp->p_au->ai_termid.port; | 290 udata.au_aupinfo.ap_mask.am_success = 291 tp->p_au->ai_mask.am_success; 292 udata.au_aupinfo.ap_mask.am_failure = 293 tp->p_au->ai_mask.am_failure; 294 udata.au_aupinfo.ap_termid.machine = 295 tp->p_au->ai_termid.machine; 296 udata.au_aupinfo.ap_termid.port = tp->p_au->ai_termid.port; |
291 udata.au_aupinfo.ap_asid = tp->p_au->ai_asid; 292 PROC_UNLOCK(tp); 293 break; 294 295 case A_SETPMASK: | 297 udata.au_aupinfo.ap_asid = tp->p_au->ai_asid; 298 PROC_UNLOCK(tp); 299 break; 300 301 case A_SETPMASK: |
296 if (udata.au_aupinfo.ap_pid < 1) | 302 if (udata.au_aupinfo.ap_pid < 1) |
297 return (EINVAL); 298 299 /* XXXAUDIT: p_cansee()? */ 300 if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) 301 return (EINVAL); 302 | 303 return (EINVAL); 304 305 /* XXXAUDIT: p_cansee()? */ 306 if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) 307 return (EINVAL); 308 |
303 tp->p_au->ai_mask.am_success = 304 udata.au_aupinfo.ap_mask.am_success; 305 tp->p_au->ai_mask.am_failure = 306 udata.au_aupinfo.ap_mask.am_failure; | 309 tp->p_au->ai_mask.am_success = 310 udata.au_aupinfo.ap_mask.am_success; 311 tp->p_au->ai_mask.am_failure = 312 udata.au_aupinfo.ap_mask.am_failure; |
307 PROC_UNLOCK(tp); 308 break; 309 310 case A_SETFSIZE: 311 if ((udata.au_fstat.af_filesz != 0) && 312 (udata.au_fstat.af_filesz < MIN_AUDIT_FILE_SIZE)) 313 return (EINVAL); 314 audit_fstat.af_filesz = udata.au_fstat.af_filesz; --- 16 unchanged lines hidden (view full) --- 331 return (ENOSYS); 332 break; 333 334 case A_SENDTRIGGER: 335 if ((udata.au_trigger < AUDIT_TRIGGER_MIN) || 336 (udata.au_trigger > AUDIT_TRIGGER_MAX)) 337 return (EINVAL); 338 return (send_trigger(udata.au_trigger)); | 313 PROC_UNLOCK(tp); 314 break; 315 316 case A_SETFSIZE: 317 if ((udata.au_fstat.af_filesz != 0) && 318 (udata.au_fstat.af_filesz < MIN_AUDIT_FILE_SIZE)) 319 return (EINVAL); 320 audit_fstat.af_filesz = udata.au_fstat.af_filesz; --- 16 unchanged lines hidden (view full) --- 337 return (ENOSYS); 338 break; 339 340 case A_SENDTRIGGER: 341 if ((udata.au_trigger < AUDIT_TRIGGER_MIN) || 342 (udata.au_trigger > AUDIT_TRIGGER_MAX)) 343 return (EINVAL); 344 return (send_trigger(udata.au_trigger)); |
339 break; | |
340 } | 345 } |
341 /* Copy data back to userspace for the GET comands */ | 346 347 /* 348 * Copy data back to userspace for the GET comands. 349 */ |
342 switch (uap->cmd) { 343 case A_GETPOLICY: 344 case A_GETKMASK: 345 case A_GETQCTRL: 346 case A_GETCWD: 347 case A_GETCAR: 348 case A_GETSTAT: 349 case A_GETCOND: --- 6 unchanged lines hidden (view full) --- 356 if (error) 357 return (error); 358 break; 359 } 360 361 return (0); 362} 363 | 350 switch (uap->cmd) { 351 case A_GETPOLICY: 352 case A_GETKMASK: 353 case A_GETQCTRL: 354 case A_GETCWD: 355 case A_GETCAR: 356 case A_GETSTAT: 357 case A_GETCOND: --- 6 unchanged lines hidden (view full) --- 364 if (error) 365 return (error); 366 break; 367 } 368 369 return (0); 370} 371 |
364/* | 372/* |
365 * MPSAFE 366 * 367 * System calls to manage the user audit information. 368 */ 369/* ARGSUSED */ 370int 371getauid(struct thread *td, struct getauid_args *uap) 372{ 373 int error; 374 au_id_t id; 375 376 error = suser(td); 377 if (error) 378 return (error); 379 380 /* | 373 * MPSAFE 374 * 375 * System calls to manage the user audit information. 376 */ 377/* ARGSUSED */ 378int 379getauid(struct thread *td, struct getauid_args *uap) 380{ 381 int error; 382 au_id_t id; 383 384 error = suser(td); 385 if (error) 386 return (error); 387 388 /* |
381 * XXX: 382 * Integer read on static pointer dereference: doesn't need locking? | 389 * XXX: Integer read on static pointer dereference: doesn't need 390 * locking? |
383 */ 384 PROC_LOCK(td->td_proc); 385 id = td->td_proc->p_au->ai_auid; 386 PROC_UNLOCK(td->td_proc); 387 return copyout(&id, uap->auid, sizeof(id)); 388} 389 390/* MPSAFE */ --- 10 unchanged lines hidden (view full) --- 401 402 error = copyin(uap->auid, &id, sizeof(id)); 403 if (error) 404 return (error); 405 406 audit_arg_auid(id); 407 408 /* | 391 */ 392 PROC_LOCK(td->td_proc); 393 id = td->td_proc->p_au->ai_auid; 394 PROC_UNLOCK(td->td_proc); 395 return copyout(&id, uap->auid, sizeof(id)); 396} 397 398/* MPSAFE */ --- 10 unchanged lines hidden (view full) --- 409 410 error = copyin(uap->auid, &id, sizeof(id)); 411 if (error) 412 return (error); 413 414 audit_arg_auid(id); 415 416 /* |
409 * XXX: 410 * Integer write on static pointer dereference: doesn't need locking? | 417 * XXX: Integer write on static pointer dereference: doesn't need 418 * locking? |
411 * 412 * XXXAUDIT: Might need locking to serialize audit events in the same 413 * order as change events? Or maybe that's an under-solveable 414 * problem. 415 * 416 * XXXRW: Test privilege while holding the proc lock? | 419 * 420 * XXXAUDIT: Might need locking to serialize audit events in the same 421 * order as change events? Or maybe that's an under-solveable 422 * problem. 423 * 424 * XXXRW: Test privilege while holding the proc lock? |
417 */ | 425 */ |
418 PROC_LOCK(td->td_proc); 419 td->td_proc->p_au->ai_auid = id; 420 PROC_UNLOCK(td->td_proc); 421 422 return (0); 423} 424 425/* 426 * MPSAFE | 426 PROC_LOCK(td->td_proc); 427 td->td_proc->p_au->ai_auid = id; 428 PROC_UNLOCK(td->td_proc); 429 430 return (0); 431} 432 433/* 434 * MPSAFE |
427 * System calls to get and set process audit information. | 435 * System calls to get and set process audit information. |
428 */ 429/* ARGSUSED */ 430int 431getaudit(struct thread *td, struct getaudit_args *uap) 432{ 433 struct auditinfo ai; 434 int error; 435 --- 217 unchanged lines hidden --- | 436 */ 437/* ARGSUSED */ 438int 439getaudit(struct thread *td, struct getaudit_args *uap) 440{ 441 struct auditinfo ai; 442 int error; 443 --- 217 unchanged lines hidden --- |