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 ---