]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_bsm_audit.c
xnu-517.tar.gz
[apple/xnu.git] / bsd / kern / kern_bsm_audit.c
CommitLineData
55e303ae
A
1/*
2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25#include <sys/types.h>
26#include <sys/vnode.h>
27#include <sys/ipc.h>
28#include <sys/sem.h>
29#include <sys/socketvar.h>
30#include <sys/socket.h>
31#include <sys/queue.h>
32#include <sys/fcntl.h>
33#include <sys/audit.h>
34#include <sys/kern_audit.h>
35#include <sys/bsm_token.h>
36#include <sys/bsm_kevents.h>
37#include <sys/bsm_klib.h>
38#include <sys/user.h>
39#include <netinet/in_systm.h>
40#include <netinet/in.h>
41#include <netinet/ip.h>
42
43#include <kern/lock.h>
44
45/* The number of BSM records allocated. */
46static int bsm_rec_count = 0;
47
48/*
49 * Records that can be recycled are maintained in the list given below
50 * The maximum number of elements that can be present in this list is
51 * bounded by MAX_AUDIT_RECORDS. Memory allocated for these records are never
52 * freed
53 */
54LIST_HEAD(, au_record) bsm_free_q;
55
56/*
57 * Lock for serializing access to the list of audit records.
58 */
59static mutex_t *bsm_audit_mutex;
60
61/*
62 * Initialize the BSM auditing subsystem.
63 */
64void
65kau_init(void)
66{
67 printf("BSM auditing present\n");
68 LIST_INIT(&bsm_free_q);
69 bsm_audit_mutex = mutex_alloc(ETAP_NO_TRACE);
70}
71
72/*
73 * This call reserves memory for the audit record.
74 * Memory must be guaranteed before any auditable event can be
75 * generated.
76 * The au_record structure maintains a reference to the
77 * memory allocated above and also the list of tokens associated
78 * with this record
79 */
80struct au_record *
81kau_open(void)
82{
83 struct au_record *rec = NULL;
84
85 /*
86 * Find an unused record, remove it from the free list, mark as used
87 */
88 mutex_lock(bsm_audit_mutex);
89 if (!LIST_EMPTY(&bsm_free_q)) {
90 rec = LIST_FIRST(&bsm_free_q);
91 LIST_REMOVE(rec, au_rec_q);
92 }
93 mutex_unlock(bsm_audit_mutex);
94
95 if (rec == NULL) {
96 mutex_lock(bsm_audit_mutex);
97 if (bsm_rec_count >= MAX_AUDIT_RECORDS) {
98 /* XXX We need to increase size of MAX_AUDIT_RECORDS */
99 mutex_unlock(bsm_audit_mutex);
100 return NULL;
101 }
102 mutex_unlock(bsm_audit_mutex);
103
104 /*
105 * Create a new BSM kernel record.
106 */
107 kmem_alloc(kernel_map, &rec, sizeof(*rec));
108 if(rec == NULL) {
109 return NULL;
110 }
111 kmem_alloc(kernel_map, &rec->data,
112 MAX_AUDIT_RECORD_SIZE * sizeof(u_char));
113 if((rec->data) == NULL) {
114 kmem_free(kernel_map, rec, sizeof(*rec));
115 return NULL;
116 }
117 mutex_lock(bsm_audit_mutex);
118 bsm_rec_count++;
119 mutex_unlock(bsm_audit_mutex);
120 }
121 memset(rec->data, 0, MAX_AUDIT_RECORD_SIZE);
122
123 TAILQ_INIT(&rec->token_q);
124 rec->len = 0;
125 rec->used = 1;
126
127 return rec;
128}
129
130/*
131 * Store the token with the record descriptor
132 *
133 */
134int kau_write(struct au_record *rec, struct au_token *tok)
135{
136 if(tok == NULL) {
137 return -1; /* Invalid Token */
138 }
139
140 /* Add the token to the tail */
141 /*
142 * XXX Not locking here -- we should not be writing to
143 * XXX the same audit record from different threads
144 */
145 TAILQ_INSERT_TAIL(&rec->token_q, tok, tokens);
146
147 rec->len += tok->len; /* grow record length by token size bytes */
148
149 return 0;
150}
151
152/*
153 * Close out the audit record by adding the header token, identifying
154 * any missing tokens. Write out the tokens to the record memory.
155 */
156int kau_close(struct au_record *rec, struct timespec *ctime, short event)
157{
158 u_char *dptr;
159 size_t tot_rec_size;
160 token_t *cur, *hdr, *trail;
161 int retval = 0;
162
163 tot_rec_size = rec->len + HEADER_SIZE + TRAILER_SIZE;
164 if(tot_rec_size <= MAX_AUDIT_RECORD_SIZE) {
165 /* Create the header token */
166 hdr = kau_to_header32(ctime, tot_rec_size, event, 0);
167
168 if(hdr != NULL) {
169 /* Add to head of list */
170 TAILQ_INSERT_HEAD(&rec->token_q, hdr, tokens);
171
172 trail = au_to_trailer(tot_rec_size);
173 if(trail != NULL) {
174 TAILQ_INSERT_TAIL(&rec->token_q, trail, tokens);
175 }
176 }
177 /* Serialize token data to the record */
178
179 rec->len = tot_rec_size;
180 dptr = rec->data;
181 TAILQ_FOREACH(cur, &rec->token_q, tokens) {
182 memcpy(dptr, cur->t_data, cur->len);
183 dptr += cur->len;
184 }
185 }
186}
187
188/*
189 * Free a BSM audit record by releasing all the tokens and clearing the
190 * audit record information.
191 */
192void kau_free(struct au_record *rec)
193{
194 struct au_token *tok;
195
196 /* Free the token list */
197 while ((tok = TAILQ_FIRST(&rec->token_q))) {
198 TAILQ_REMOVE(&rec->token_q, tok, tokens);
199 kmem_free(kernel_map, tok->t_data, tok->len);
200 kmem_free(kernel_map, tok, sizeof(struct au_token));
201 }
202
203 rec->used = 0;
204 rec->len = 0;
205
206 mutex_lock(bsm_audit_mutex);
207
208 /* Add the record to the freelist */
209 LIST_INSERT_HEAD(&bsm_free_q, rec, au_rec_q);
210
211 mutex_unlock(bsm_audit_mutex);
212
213}
214
215/*
216 * XXX May want turn some (or all) of these macros into functions in order
217 * to reduce the generated code sized.
218 */
219#define UPATH1_TOKENS \
220 do { \
221 if (ar->ar_valid_arg & ARG_UPATH1) { \
222 tok = au_to_path(ar->ar_arg_upath1); \
223 kau_write(rec, tok); \
224 } \
225 } while (0)
226
227#define UPATH2_TOKENS \
228 do { \
229 if (ar->ar_valid_arg & ARG_UPATH2) { \
230 tok = au_to_path(ar->ar_arg_upath2); \
231 kau_write(rec, tok); \
232 } \
233 } while (0)
234
235#define KPATH1_VNODE1_TOKENS \
236 do { \
237 if (ar->ar_valid_arg & ARG_KPATH1) { \
238 tok = au_to_path(ar->ar_arg_kpath1); \
239 kau_write(rec, tok); \
240 } \
241 if (ar->ar_valid_arg & ARG_VNODE1) { \
242 fill_vattr(&vattr, &ar->ar_arg_vnode1); \
243 tok = au_to_attr32(&vattr); \
244 kau_write(rec, tok); \
245 } \
246 } while (0)
247
248#define KPATH1_VNODE1_OR_UPATH1_TOKENS \
249 do { \
250 if (ar->ar_valid_arg & ARG_KPATH1) { \
251 tok = au_to_path(ar->ar_arg_kpath1); \
252 kau_write(rec, tok); \
253 } else { \
254 UPATH1_TOKENS; \
255 } \
256 if (ar->ar_valid_arg & ARG_VNODE1) { \
257 fill_vattr(&vattr, &ar->ar_arg_vnode1); \
258 tok = au_to_attr32(&vattr); \
259 kau_write(rec, tok); \
260 } \
261 } while (0)
262
263#define KPATH2_VNODE2_TOKENS \
264 do { \
265 if (ar->ar_valid_arg & ARG_KPATH2) { \
266 tok = au_to_path(ar->ar_arg_kpath2); \
267 kau_write(rec, tok); \
268 } \
269 if (ar->ar_valid_arg & ARG_VNODE2) { \
270 fill_vattr(&vattr, &ar->ar_arg_vnode2); \
271 tok = au_to_attr32(&vattr); \
272 kau_write(rec, tok); \
273 } \
274 } while (0)
275
276#define FD_KPATH1_VNODE1_TOKENS \
277 do { \
278 if (ar->ar_valid_arg & ARG_KPATH1) { \
279 tok = au_to_path(ar->ar_arg_kpath1); \
280 kau_write(rec, tok); \
281 if (ar->ar_valid_arg & ARG_VNODE1) { \
282 fill_vattr(&vattr, &ar->ar_arg_vnode1); \
283 tok = au_to_attr32(&vattr); \
284 kau_write(rec, tok); \
285 } \
286 } else { \
287 tok = au_to_arg32(1, "no path: fd", ar->ar_arg_fd); \
288 kau_write(rec, tok); \
289 } \
290 } while (0)
291
292/*
293 * Convert an internal kernel audit record to a BSM record and return
294 * a success/failure indicator. The BSM record is passed as an out
295 * parameter to this function.
296 * Return conditions:
297 * BSM_SUCCESS: The BSM record is valid
298 * BSM_FAILURE: Failure; the BSM record is NULL.
299 * BSM_NOAUDIT: The event is not auditable for BSM; the BSM record is NULL.
300 */
301int
302kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
303{
304 struct au_token *tok, *subj_tok;
305 struct au_record *rec;
306 au_tid_t tid;
307 struct audit_record *ar;
308 struct vattr vattr;
309 int sorf;
310 int ctr;
311
312 *pau = NULL;
313 if (kar == NULL)
314 return (BSM_FAILURE);
315
316 ar = &kar->k_ar;
317
318 /*
319 * Decide whether to create the BSM audit record by checking the
320 * error value from the system call and using the appropriate
321 * user audit mask.
322 */
323 if (ar->ar_errno)
324 sorf = AU_PRS_FAILURE;
325 else
326 sorf = AU_PRS_SUCCESS;
327
328 if (au_preselect(ar->ar_event, &ar->ar_subj_amask, sorf) == 0)
329 return (BSM_NOAUDIT);
330
331 rec = kau_open();
332 if (rec == NULL)
333 return (BSM_FAILURE);
334
335 /* Create the subject token */
336 tid.port = ar->ar_subj_term.port;
337 tid.machine = ar->ar_subj_term.machine;
338 subj_tok = au_to_subject32(ar->ar_subj_auid, /* audit ID */
339 ar->ar_subj_cred.cr_uid, /* eff uid */
340 ar->ar_subj_egid, /* eff group id */
341 ar->ar_subj_ruid, /* real uid */
342 ar->ar_subj_rgid, /* real group id */
343 ar->ar_subj_pid, /* process id */
344 ar->ar_subj_asid, /* session ID */
345 &tid);
346
347 /* The logic inside each case fills in the tokens required for the
348 * event, except for the header, trailer, and return tokens. The
349 * header and trailer tokens are added by the kau_close() function.
350 * The return token is added outside of the switch statement.
351 */
352 switch(ar->ar_event) {
353
354 /*
355 * Socket-related events.
356 */
357 case AUE_ACCEPT:
358 case AUE_BIND:
359 case AUE_CONNECT:
360 case AUE_RECVFROM:
361 case AUE_RECVMSG:
362 case AUE_SENDMSG:
363 case AUE_SENDTO:
364 tok = au_to_arg32(1, "fd", ar->ar_arg_fd);
365 kau_write(rec, tok);
366 if (ar->ar_valid_arg & ARG_SADDRINET) {
367 tok = au_to_sock_inet(
368 (struct sockaddr_in *)&ar->ar_arg_sockaddr);
369 kau_write(rec, tok);
370 }
371 if (ar->ar_valid_arg & ARG_SADDRUNIX) {
372 tok = au_to_sock_unix(
373 (struct sockaddr_un *)&ar->ar_arg_sockaddr);
374 kau_write(rec, tok);
375 UPATH1_TOKENS;
376 }
377 /* XXX Need to handle ARG_SADDRINET6 */
378 break;
379
380 case AUE_SOCKET:
381 case AUE_SOCKETPAIR:
382 tok = au_to_arg32(1,"domain", ar->ar_arg_sockinfo.sodomain);
383 kau_write(rec, tok);
384 tok = au_to_arg32(2,"type", ar->ar_arg_sockinfo.sotype);
385 kau_write(rec, tok);
386 tok = au_to_arg32(3,"protocol", ar->ar_arg_sockinfo.soprotocol);
387 kau_write(rec, tok);
388 break;
389
390 case AUE_SETSOCKOPT:
391 case AUE_SHUTDOWN:
392 tok = au_to_arg32(1, "fd", ar->ar_arg_fd);
393 kau_write(rec, tok);
394 break;
395
396 case AUE_SETAUID:
397 tok = au_to_arg32(2, "setauid", ar->ar_arg_auid);
398 kau_write(rec, tok);
399 /* fall through */
400 case AUE_ADJTIME:
401 case AUE_AUDIT:
402 case AUE_EXIT:
403 case AUE_GETAUID:
404 case AUE_GETFSSTAT:
405 case AUE_PIPE:
406 case AUE_SETPGRP:
407 case AUE_SETRLIMIT:
408 /* Header, subject, and return tokens added at end */
409 break;
410
411 case AUE_ACCESS:
412 case AUE_CHDIR:
413 case AUE_CHROOT:
414 case AUE_EXECVE:
415 case AUE_GETATTRLIST:
416 case AUE_GETFH:
417 case AUE_LSTAT:
418 case AUE_MKFIFO:
419 case AUE_PATHCONF:
420 case AUE_READLINK:
421 case AUE_REVOKE:
422 case AUE_RMDIR:
423 case AUE_SEARCHFS:
424 case AUE_SETATTRLIST:
425 case AUE_STAT:
426 case AUE_STATFS:
427 case AUE_TRUNCATE:
428 case AUE_UNDELETE:
429 case AUE_UNLINK:
430 case AUE_UTIMES:
431 KPATH1_VNODE1_OR_UPATH1_TOKENS;
432 break;
433
434 case AUE_CHFLAGS:
435 tok = au_to_arg32(2, "flags", ar->ar_arg_fflags);
436 kau_write(rec, tok);
437 KPATH1_VNODE1_OR_UPATH1_TOKENS;
438 break;
439
440 case AUE_CHMOD:
441 tok = au_to_arg32(2, "new file mode", ar->ar_arg_mode);
442 kau_write(rec, tok);
443 KPATH1_VNODE1_OR_UPATH1_TOKENS;
444 break;
445
446 case AUE_CHOWN:
447 tok = au_to_arg32(2, "new file uid", ar->ar_arg_uid);
448 kau_write(rec, tok);
449 tok = au_to_arg32(3, "new file gid", ar->ar_arg_gid);
450 kau_write(rec, tok);
451 KPATH1_VNODE1_OR_UPATH1_TOKENS;
452 break;
453
454 case AUE_EXCHANGEDATA:
455 KPATH1_VNODE1_OR_UPATH1_TOKENS;
456 KPATH2_VNODE2_TOKENS;
457 break;
458
459/*
460 * XXXAUDIT: Close is not audited in the kernel yet.
461 case AUE_CLOSE:
462 tok = au_to_arg32(2, "fd", ar->ar_arg_fd);
463 kau_write(rec, tok);
464 KPATH1_VNODE1_OR_UPATH1_TOKENS;
465 break;
466*/
467 case AUE_FCHMOD:
468 tok = au_to_arg32(2, "new file mode", ar->ar_arg_mode);
469 kau_write(rec, tok);
470 FD_KPATH1_VNODE1_TOKENS;
471 break;
472
473 case AUE_FCHDIR:
474 case AUE_FPATHCONF:
475 case AUE_FSTAT: /* XXX Need to handle sockets and shm */
476 case AUE_FSTATFS:
477 case AUE_FTRUNCATE:
478 case AUE_FUTIMES:
479 case AUE_GETDIRENTRIES:
480 case AUE_GETDIRENTRIESATTR:
481 FD_KPATH1_VNODE1_TOKENS;
482 break;
483
484 case AUE_FCHOWN:
485 tok = au_to_arg32(2, "new file uid", ar->ar_arg_uid);
486 kau_write(rec, tok);
487 tok = au_to_arg32(3, "new file gid", ar->ar_arg_gid);
488 kau_write(rec, tok);
489 FD_KPATH1_VNODE1_TOKENS;
490 break;
491
492 case AUE_FCNTL:
493 if (ar->ar_arg_cmd == F_GETLK || ar->ar_arg_cmd == F_SETLK ||
494 ar->ar_arg_cmd == F_SETLKW) {
495 tok = au_to_arg32(2, "cmd", ar->ar_arg_cmd);
496 kau_write(rec, tok);
497 FD_KPATH1_VNODE1_TOKENS;
498 }
499 break;
500
501 case AUE_FCHFLAGS:
502 tok = au_to_arg32(2, "flags", ar->ar_arg_fflags);
503 kau_write(rec, tok);
504 FD_KPATH1_VNODE1_TOKENS;
505 break;
506
507 case AUE_FLOCK:
508 tok = au_to_arg32(2, "operation", ar->ar_arg_cmd);
509 kau_write(rec, tok);
510 FD_KPATH1_VNODE1_TOKENS;
511 break;
512
513 case AUE_LINK:
514 case AUE_RENAME:
515 KPATH1_VNODE1_OR_UPATH1_TOKENS;
516 UPATH2_TOKENS;
517 break;
518
519 case AUE_MKDIR:
520 tok = au_to_arg32(2, "mode", ar->ar_arg_mode);
521 kau_write(rec, tok);
522 KPATH1_VNODE1_OR_UPATH1_TOKENS;
523 break;
524
525 case AUE_MKNOD:
526 tok = au_to_arg32(2, "mode", ar->ar_arg_mode);
527 kau_write(rec, tok);
528 tok = au_to_arg32(3, "dev", ar->ar_arg_dev);
529 kau_write(rec, tok);
530 KPATH1_VNODE1_OR_UPATH1_TOKENS;
531 break;
532
533 case AUE_MOUNT:
534 /* XXX Need to handle NFS mounts */
535 tok = au_to_arg32(3, "flags", ar->ar_arg_fflags);
536 kau_write(rec, tok);
537 if (ar->ar_arg_text != NULL) {
538 tok = au_to_text(ar->ar_arg_text);
539 kau_write(rec, tok);
540 }
541 /* fall through */
542 case AUE_UMOUNT:
543 KPATH1_VNODE1_OR_UPATH1_TOKENS;
544 break;
545
546 case AUE_MSGCTL:
547 ar->ar_event = msgctl_to_event(ar->ar_arg_svipc_cmd);
548 /* Fall through */
549 case AUE_MSGRCV:
550 case AUE_MSGSND:
551 tok = au_to_arg32(1, "msg ID", ar->ar_arg_svipc_id);
552 kau_write(rec, tok);
553 if (ar->ar_errno != EINVAL) {
554 tok = au_to_ipc(AT_IPC_MSG, ar->ar_arg_svipc_id);
555 kau_write(rec, tok);
556 }
557 break;
558
559 case AUE_MSGGET:
560 if (ar->ar_errno == 0) {
561 tok = au_to_ipc(AT_IPC_MSG, ar->ar_arg_svipc_id);
562 kau_write(rec, tok);
563 }
564 break;
565
566 case AUE_OPEN_R:
567 case AUE_OPEN_RC:
568 case AUE_OPEN_RTC:
569 case AUE_OPEN_RT:
570 case AUE_OPEN_RW:
571 case AUE_OPEN_RWC:
572 case AUE_OPEN_RWTC:
573 case AUE_OPEN_RWT:
574 case AUE_OPEN_W:
575 case AUE_OPEN_WC:
576 case AUE_OPEN_WTC:
577 case AUE_OPEN_WT:
578 /* The open syscall always writes a OPEN_R event; convert the
579 * file flags to the proper type of event.
580 */
581 ar->ar_event = flags_to_openevent(ar->ar_arg_fflags);
582 UPATH1_TOKENS; /* Save the user space path */
583 KPATH1_VNODE1_TOKENS; /* Audit the kernel path as well */
584 break;
585
586 case AUE_QUOTACTL:
587 tok = au_to_arg32(2, "command", ar->ar_arg_cmd);
588 kau_write(rec, tok);
589 tok = au_to_arg32(3, "uid", ar->ar_arg_uid);
590 kau_write(rec, tok);
591 KPATH1_VNODE1_OR_UPATH1_TOKENS;
592 break;
593
594 case AUE_SEMCTL:
595 ar->ar_event = semctl_to_event(ar->ar_arg_svipc_cmd);
596 /* Fall through */
597 case AUE_SEMOP:
598 tok = au_to_arg32(1, "sem ID", ar->ar_arg_svipc_id);
599 kau_write(rec, tok);
600 if (ar->ar_errno != EINVAL) {
601 tok = au_to_ipc(AT_IPC_SEM, ar->ar_arg_svipc_id);
602 kau_write(rec, tok);
603 }
604 break;
605 case AUE_SEMGET:
606 if (ar->ar_errno == 0) {
607 tok = au_to_ipc(AT_IPC_SEM, ar->ar_arg_svipc_id);
608 kau_write(rec, tok);
609 }
610 break;
611 case AUE_SETEGID:
612 tok = au_to_arg32(1, "gid", ar->ar_arg_egid);
613 kau_write(rec, tok);
614 break;
615 case AUE_SETEUID:
616 tok = au_to_arg32(1, "uid", ar->ar_arg_euid);
617 kau_write(rec, tok);
618 break;
619 case AUE_SETGID:
620 tok = au_to_arg32(1, "gid", ar->ar_arg_gid);
621 kau_write(rec, tok);
622 break;
623 case AUE_SETUID:
624 tok = au_to_arg32(1, "uid", ar->ar_arg_uid);
625 kau_write(rec, tok);
626 break;
627 case AUE_SETGROUPS:
628 if (ar->ar_valid_arg & ARG_GROUPSET) {
629 for(ctr = 0; ctr < ar->ar_arg_groups.gidset_size; ctr++)
630 {
631 tok = au_to_arg32(1, "setgroups", ar->ar_arg_groups.gidset[ctr]);
632 kau_write(rec, tok);
633 }
634 }
635 break;
636 case AUE_SHMAT:
637 tok = au_to_arg32(1, "shmid", ar->ar_arg_svipc_id);
638 kau_write(rec, tok);
639 tok = au_to_arg32(2, "shmaddr", (int)ar->ar_arg_svipc_addr);
640 kau_write(rec, tok);
641 if (ar->ar_valid_arg & ARG_SVIPC_PERM) {
642 tok = au_to_ipc(AT_IPC_SHM, ar->ar_arg_svipc_id);
643 kau_write(rec, tok);
644 tok = au_to_ipc_perm(&ar->ar_arg_svipc_perm);
645 kau_write(rec, tok);
646 }
647 break;
648
649 case AUE_SHMCTL:
650 tok = au_to_arg32(1, "shmid", ar->ar_arg_svipc_id);
651 kau_write(rec, tok);
652 switch (ar->ar_arg_svipc_cmd) {
653 case IPC_STAT:
654 ar->ar_event = AUE_SHMCTL_STAT;
655 if (ar->ar_valid_arg & ARG_SVIPC_PERM) {
656 tok = au_to_ipc(AT_IPC_SHM,
657 ar->ar_arg_svipc_id);
658 kau_write(rec, tok);
659 }
660 break;
661 case IPC_RMID:
662 ar->ar_event = AUE_SHMCTL_RMID;
663 if (ar->ar_valid_arg & ARG_SVIPC_PERM) {
664 tok = au_to_ipc(AT_IPC_SHM,
665 ar->ar_arg_svipc_id);
666 kau_write(rec, tok);
667 }
668 break;
669 case IPC_SET:
670 ar->ar_event = AUE_SHMCTL_SET;
671 if (ar->ar_valid_arg & ARG_SVIPC_PERM) {
672 tok = au_to_ipc(AT_IPC_SHM,
673 ar->ar_arg_svipc_id);
674 kau_write(rec, tok);
675 tok = au_to_ipc_perm(&ar->ar_arg_svipc_perm);
676 kau_write(rec, tok);
677 }
678 break;
679 default:
680 break; /* We will audit a bad command */
681 }
682 break;
683
684 case AUE_SHMDT:
685 tok = au_to_arg32(1, "shmaddr", (int)ar->ar_arg_svipc_addr);
686 kau_write(rec, tok);
687 break;
688
689 case AUE_SHMGET:
690 /* This is unusual; the return value is in an argument token */
691 tok = au_to_arg32(0, "shmid", ar->ar_arg_svipc_id);
692 kau_write(rec, tok);
693 if (ar->ar_valid_arg & ARG_SVIPC_PERM) {
694 tok = au_to_ipc(AT_IPC_SHM, ar->ar_arg_svipc_id);
695 kau_write(rec, tok);
696 tok = au_to_ipc_perm(&ar->ar_arg_svipc_perm);
697 kau_write(rec, tok);
698 }
699 break;
700
701 case AUE_SYMLINK:
702 if (ar->ar_valid_arg & ARG_TEXT) {
703 tok = au_to_text(ar->ar_arg_text);
704 kau_write(rec, tok);
705 }
706 KPATH1_VNODE1_OR_UPATH1_TOKENS;
707 break;
708
709 case AUE_UMASK:
710 tok = au_to_arg32(1, "new mask", ar->ar_arg_mask);
711 kau_write(rec, tok);
712 tok = au_to_arg32(0, "prev mask", ar->ar_retval);
713 kau_write(rec, tok);
714 break;
715
716 default: /* We shouldn't fall through to here. */
717 printf("BSM conversion requested for unknown event %d\n",
718 ar->ar_event);
719 kau_free(rec);
720 return BSM_NOAUDIT;
721 }
722
723 kau_write(rec, subj_tok);
724 tok = au_to_return32((char)ar->ar_errno, ar->ar_retval);
725 kau_write(rec, tok); /* Every record gets a return token */
726
727 kau_close(rec, &ar->ar_endtime, ar->ar_event);
728
729 *pau = rec;
730 return BSM_SUCCESS;
731}
732
733/*
734 * Verify that a record is a valid BSM record. This verification is
735 * simple now, but may be expanded on sometime in the future.
736 * Return 1 if the record is good, 0 otherwise.
737 *
738 */
739int
740bsm_rec_verify(caddr_t rec)
741{
742 /*
743 * Check the token ID of the first token; it has to be a header
744 * token.
745 */
746 /* XXXAUDIT There needs to be a token structure to map a token.
747 * XXXAUDIT 'Shouldn't be simply looking at the first char.
748 */
749 if ( ((char)*rec != AU_HEADER_32_TOKEN) &&
750 ((char)*rec != AU_HEADER_EX_32_TOKEN) &&
751 ((char)*rec != AU_HEADER_64_TOKEN) &&
752 ((char)*rec != AU_HEADER_EX_64_TOKEN) ) {
753 return (0);
754 }
755 return (1);
756}