]>
Commit | Line | Data |
---|---|---|
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. */ | |
46 | static 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 | */ | |
54 | LIST_HEAD(, au_record) bsm_free_q; | |
55 | ||
56 | /* | |
57 | * Lock for serializing access to the list of audit records. | |
58 | */ | |
59 | static mutex_t *bsm_audit_mutex; | |
60 | ||
61 | /* | |
62 | * Initialize the BSM auditing subsystem. | |
63 | */ | |
64 | void | |
65 | kau_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 | */ | |
80 | struct au_record * | |
81 | kau_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 | */ | |
134 | int 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 | */ | |
156 | int 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 | */ | |
192 | void 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 | */ | |
301 | int | |
302 | kaudit_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 | */ | |
739 | int | |
740 | bsm_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 | } |