audit_syscalls.c revision 159318
1155192Srwatson/*
2155192Srwatson * Copyright (c) 1999-2005 Apple Computer, 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.
13155192Srwatson * 3.  Neither the name of Apple Computer, 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 * $FreeBSD: head/sys/security/audit/audit_syscalls.c 159318 2006-06-05 22:36:12Z rwatson $
30155192Srwatson */
31155192Srwatson
32155192Srwatson#include <sys/param.h>
33159318Srwatson#include <sys/mount.h>
34155192Srwatson#include <sys/namei.h>
35155192Srwatson#include <sys/proc.h>
36155192Srwatson#include <sys/sysproto.h>
37155192Srwatson#include <sys/systm.h>
38155192Srwatson#include <sys/vnode.h>
39155192Srwatson
40155192Srwatson#include <bsm/audit.h>
41155192Srwatson#include <bsm/audit_kevents.h>
42155192Srwatson#include <security/audit/audit.h>
43155192Srwatson#include <security/audit/audit_private.h>
44155192Srwatson
45155192Srwatson#ifdef AUDIT
46155192Srwatson
47155192Srwatson/*
48155192Srwatson * MPSAFE
49155192Srwatson *
50156889Srwatson * System call to allow a user space application to submit a BSM audit record
51156889Srwatson * to the kernel for inclusion in the audit log. This function does little
52156889Srwatson * verification on the audit record that is submitted.
53155192Srwatson *
54156889Srwatson * XXXAUDIT: Audit preselection for user records does not currently work,
55156889Srwatson * since we pre-select only based on the AUE_audit event type, not the event
56156889Srwatson * type submitted as part of the user audit data.
57155192Srwatson */
58155192Srwatson/* ARGSUSED */
59155192Srwatsonint
60155192Srwatsonaudit(struct thread *td, struct audit_args *uap)
61155192Srwatson{
62155192Srwatson	int error;
63155192Srwatson	void * rec;
64155192Srwatson	struct kaudit_record *ar;
65155192Srwatson
66155192Srwatson	error = suser(td);
67155192Srwatson	if (error)
68155192Srwatson		return (error);
69155192Srwatson
70155192Srwatson	if ((uap->length <= 0) || (uap->length > audit_qctrl.aq_bufsz))
71155192Srwatson		return (EINVAL);
72155192Srwatson
73155192Srwatson	ar = currecord();
74155192Srwatson
75156889Srwatson	/*
76156889Srwatson	 * If there's no current audit record (audit() itself not audited)
77155192Srwatson	 * commit the user audit record.
78155192Srwatson	 */
79155192Srwatson	if (ar == NULL) {
80155192Srwatson
81156889Srwatson		/*
82156889Srwatson		 * This is not very efficient; we're required to allocate a
83156889Srwatson		 * complete kernel audit record just so the user record can
84156889Srwatson		 * tag along.
85155192Srwatson		 *
86155192Srwatson		 * XXXAUDIT: Maybe AUE_AUDIT in the system call context and
87155192Srwatson		 * special pre-select handling?
88155192Srwatson		 */
89155192Srwatson		td->td_ar = audit_new(AUE_NULL, td);
90155192Srwatson		if (td->td_ar == NULL)
91155192Srwatson			return (ENOTSUP);
92155192Srwatson		ar = td->td_ar;
93155192Srwatson	}
94155192Srwatson
95156889Srwatson	if (uap->length > MAX_AUDIT_RECORD_SIZE)
96155192Srwatson		return (EINVAL);
97155192Srwatson
98155192Srwatson	rec = malloc(uap->length, M_AUDITDATA, M_WAITOK);
99155192Srwatson
100155192Srwatson	error = copyin(uap->record, rec, uap->length);
101155192Srwatson	if (error)
102155192Srwatson		goto free_out;
103155192Srwatson
104156889Srwatson	/* Verify the record. */
105155192Srwatson	if (bsm_rec_verify(rec) == 0) {
106155192Srwatson		error = EINVAL;
107155192Srwatson		goto free_out;
108155192Srwatson	}
109155192Srwatson
110156889Srwatson	/*
111156889Srwatson	 * Attach the user audit record to the kernel audit record. Because
112155192Srwatson	 * this system call is an auditable event, we will write the user
113155192Srwatson	 * record along with the record for this audit event.
114155192Srwatson	 *
115155192Srwatson	 * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen,
116155192Srwatson	 * k_ar_commit & AR_COMMIT_USER?
117155192Srwatson	 */
118155192Srwatson	ar->k_udata = rec;
119155192Srwatson	ar->k_ulen  = uap->length;
120155192Srwatson	ar->k_ar_commit |= AR_COMMIT_USER;
121155192Srwatson	return (0);
122155192Srwatson
123155192Srwatsonfree_out:
124156889Srwatson	/*
125156889Srwatson	 * audit_syscall_exit() will free the audit record on the thread even
126156889Srwatson	 * if we allocated it above.
127155192Srwatson	 */
128155192Srwatson	free(rec, M_AUDITDATA);
129155192Srwatson	return (error);
130155192Srwatson}
131155192Srwatson
132155192Srwatson/*
133155192Srwatson * MPSAFE
134155192Srwatson *
135155192Srwatson *  System call to manipulate auditing.
136155192Srwatson */
137155192Srwatson/* ARGSUSED */
138155192Srwatsonint
139155192Srwatsonauditon(struct thread *td, struct auditon_args *uap)
140155192Srwatson{
141155192Srwatson	int error;
142155192Srwatson	union auditon_udata udata;
143155192Srwatson	struct proc *tp;
144155192Srwatson
145155192Srwatson	AUDIT_ARG(cmd, uap->cmd);
146155192Srwatson	error = suser(td);
147155192Srwatson	if (error)
148155192Srwatson		return (error);
149155192Srwatson
150155192Srwatson	if ((uap->length <= 0) || (uap->length > sizeof(union auditon_udata)))
151155192Srwatson		return (EINVAL);
152155192Srwatson
153155192Srwatson	memset((void *)&udata, 0, sizeof(udata));
154155192Srwatson
155156889Srwatson	/*
156156889Srwatson	 * Some of the GET commands use the arguments too.
157156889Srwatson	 */
158155192Srwatson	switch (uap->cmd) {
159155192Srwatson	case A_SETPOLICY:
160155192Srwatson	case A_SETKMASK:
161155192Srwatson	case A_SETQCTRL:
162155192Srwatson	case A_SETSTAT:
163155192Srwatson	case A_SETUMASK:
164155192Srwatson	case A_SETSMASK:
165155192Srwatson	case A_SETCOND:
166155192Srwatson	case A_SETCLASS:
167155192Srwatson	case A_SETPMASK:
168155192Srwatson	case A_SETFSIZE:
169155192Srwatson	case A_SETKAUDIT:
170155192Srwatson	case A_GETCLASS:
171155192Srwatson	case A_GETPINFO:
172155192Srwatson	case A_GETPINFO_ADDR:
173155192Srwatson	case A_SENDTRIGGER:
174155192Srwatson		error = copyin(uap->data, (void *)&udata, uap->length);
175155192Srwatson		if (error)
176155192Srwatson			return (error);
177155192Srwatson		AUDIT_ARG(auditon, &udata);
178155192Srwatson		break;
179155192Srwatson	}
180155192Srwatson
181156889Srwatson	/*
182156889Srwatson	 * XXX Need to implement these commands by accessing the global
183155192Srwatson	 * values associated with the commands.
184155192Srwatson	 *
185155192Srwatson	 * XXXAUDIT: Locking?
186155192Srwatson	 */
187155192Srwatson	switch (uap->cmd) {
188155192Srwatson	case A_GETPOLICY:
189155192Srwatson		if (!audit_fail_stop)
190155192Srwatson			udata.au_policy |= AUDIT_CNT;
191155192Srwatson		if (audit_panic_on_write_fail)
192155192Srwatson			udata.au_policy |= AUDIT_AHLT;
193155192Srwatson		break;
194155192Srwatson
195155192Srwatson	case A_SETPOLICY:
196155192Srwatson		if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT))
197155192Srwatson			return (EINVAL);
198155192Srwatson		/*
199155192Srwatson		 * XXX - Need to wake up waiters if the policy relaxes?
200155192Srwatson		 */
201155192Srwatson		audit_fail_stop = ((udata.au_policy & AUDIT_CNT) == 0);
202155192Srwatson		audit_panic_on_write_fail = (udata.au_policy & AUDIT_AHLT);
203155192Srwatson		break;
204155192Srwatson
205155192Srwatson	case A_GETKMASK:
206155192Srwatson		udata.au_mask = audit_nae_mask;
207155192Srwatson		break;
208155192Srwatson
209155192Srwatson	case A_SETKMASK:
210155192Srwatson		audit_nae_mask = udata.au_mask;
211155192Srwatson		break;
212155192Srwatson
213155192Srwatson	case A_GETQCTRL:
214155192Srwatson		udata.au_qctrl = audit_qctrl;
215155192Srwatson		break;
216155192Srwatson
217155192Srwatson	case A_SETQCTRL:
218155192Srwatson		if ((udata.au_qctrl.aq_hiwater > AQ_MAXHIGH) ||
219155192Srwatson		    (udata.au_qctrl.aq_lowater >= udata.au_qctrl.aq_hiwater) ||
220155192Srwatson		    (udata.au_qctrl.aq_bufsz > AQ_MAXBUFSZ) ||
221155192Srwatson		    (udata.au_qctrl.aq_minfree < 0) ||
222155192Srwatson		    (udata.au_qctrl.aq_minfree > 100))
223155192Srwatson			return (EINVAL);
224155192Srwatson
225155192Srwatson		audit_qctrl = udata.au_qctrl;
226155192Srwatson		/* XXX The queue delay value isn't used with the kernel. */
227155192Srwatson		audit_qctrl.aq_delay = -1;
228155192Srwatson		break;
229155192Srwatson
230155192Srwatson	case A_GETCWD:
231155192Srwatson		return (ENOSYS);
232155192Srwatson		break;
233155192Srwatson
234155192Srwatson	case A_GETCAR:
235155192Srwatson		return (ENOSYS);
236155192Srwatson		break;
237155192Srwatson
238155192Srwatson	case A_GETSTAT:
239155192Srwatson		return (ENOSYS);
240155192Srwatson		break;
241155192Srwatson
242155192Srwatson	case A_SETSTAT:
243155192Srwatson		return (ENOSYS);
244155192Srwatson		break;
245155192Srwatson
246155192Srwatson	case A_SETUMASK:
247155192Srwatson		return (ENOSYS);
248155192Srwatson		break;
249155192Srwatson
250155192Srwatson	case A_SETSMASK:
251155192Srwatson		return (ENOSYS);
252155192Srwatson		break;
253155192Srwatson
254155192Srwatson	case A_GETCOND:
255155192Srwatson		if (audit_enabled && !audit_suspended)
256155192Srwatson			udata.au_cond = AUC_AUDITING;
257155192Srwatson		else
258155192Srwatson			udata.au_cond = AUC_NOAUDIT;
259155192Srwatson		break;
260155192Srwatson
261155192Srwatson	case A_SETCOND:
262156889Srwatson		if (udata.au_cond == AUC_NOAUDIT)
263155192Srwatson			audit_suspended = 1;
264156889Srwatson		if (udata.au_cond == AUC_AUDITING)
265155192Srwatson			audit_suspended = 0;
266155192Srwatson		if (udata.au_cond == AUC_DISABLED) {
267155192Srwatson			audit_suspended = 1;
268155192Srwatson			audit_shutdown(NULL, 0);
269155192Srwatson		}
270155192Srwatson		break;
271155192Srwatson
272155192Srwatson	case A_GETCLASS:
273156889Srwatson		udata.au_evclass.ec_class = au_event_class(
274156889Srwatson		    udata.au_evclass.ec_number);
275155192Srwatson		break;
276155192Srwatson
277155192Srwatson	case A_SETCLASS:
278155192Srwatson		au_evclassmap_insert(udata.au_evclass.ec_number,
279156889Srwatson		    udata.au_evclass.ec_class);
280155192Srwatson		break;
281155192Srwatson
282155192Srwatson	case A_GETPINFO:
283156889Srwatson		if (udata.au_aupinfo.ap_pid < 1)
284155192Srwatson			return (EINVAL);
285155192Srwatson
286155192Srwatson		/* XXXAUDIT: p_cansee()? */
287155192Srwatson		if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL)
288155192Srwatson			return (EINVAL);
289155192Srwatson
290155192Srwatson		udata.au_aupinfo.ap_auid = tp->p_au->ai_auid;
291156889Srwatson		udata.au_aupinfo.ap_mask.am_success =
292156889Srwatson		    tp->p_au->ai_mask.am_success;
293156889Srwatson		udata.au_aupinfo.ap_mask.am_failure =
294156889Srwatson		    tp->p_au->ai_mask.am_failure;
295156889Srwatson		udata.au_aupinfo.ap_termid.machine =
296156889Srwatson		    tp->p_au->ai_termid.machine;
297156889Srwatson		udata.au_aupinfo.ap_termid.port = tp->p_au->ai_termid.port;
298155192Srwatson		udata.au_aupinfo.ap_asid = tp->p_au->ai_asid;
299155192Srwatson		PROC_UNLOCK(tp);
300155192Srwatson		break;
301155192Srwatson
302155192Srwatson	case A_SETPMASK:
303156889Srwatson		if (udata.au_aupinfo.ap_pid < 1)
304155192Srwatson			return (EINVAL);
305155192Srwatson
306155192Srwatson		/* XXXAUDIT: p_cansee()? */
307155192Srwatson		if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL)
308155192Srwatson			return (EINVAL);
309155192Srwatson
310156889Srwatson		tp->p_au->ai_mask.am_success =
311156889Srwatson		    udata.au_aupinfo.ap_mask.am_success;
312156889Srwatson		tp->p_au->ai_mask.am_failure =
313156889Srwatson		    udata.au_aupinfo.ap_mask.am_failure;
314155192Srwatson		PROC_UNLOCK(tp);
315155192Srwatson		break;
316155192Srwatson
317155192Srwatson	case A_SETFSIZE:
318155192Srwatson		if ((udata.au_fstat.af_filesz != 0) &&
319155192Srwatson		   (udata.au_fstat.af_filesz < MIN_AUDIT_FILE_SIZE))
320155192Srwatson			return (EINVAL);
321155192Srwatson		audit_fstat.af_filesz = udata.au_fstat.af_filesz;
322155192Srwatson		break;
323155192Srwatson
324155192Srwatson	case A_GETFSIZE:
325155192Srwatson		udata.au_fstat.af_filesz = audit_fstat.af_filesz;
326155192Srwatson		udata.au_fstat.af_currsz = audit_fstat.af_currsz;
327155192Srwatson		break;
328155192Srwatson
329155192Srwatson	case A_GETPINFO_ADDR:
330155192Srwatson		return (ENOSYS);
331155192Srwatson		break;
332155192Srwatson
333155192Srwatson	case A_GETKAUDIT:
334155192Srwatson		return (ENOSYS);
335155192Srwatson		break;
336155192Srwatson
337155192Srwatson	case A_SETKAUDIT:
338155192Srwatson		return (ENOSYS);
339155192Srwatson		break;
340155192Srwatson
341155192Srwatson	case A_SENDTRIGGER:
342155192Srwatson		if ((udata.au_trigger < AUDIT_TRIGGER_MIN) ||
343155192Srwatson		    (udata.au_trigger > AUDIT_TRIGGER_MAX))
344155192Srwatson			return (EINVAL);
345156845Srwatson		return (send_trigger(udata.au_trigger));
346155192Srwatson	}
347156889Srwatson
348156889Srwatson	/*
349156889Srwatson	 * Copy data back to userspace for the GET comands.
350156889Srwatson	 */
351155192Srwatson	switch (uap->cmd) {
352155192Srwatson	case A_GETPOLICY:
353155192Srwatson	case A_GETKMASK:
354155192Srwatson	case A_GETQCTRL:
355155192Srwatson	case A_GETCWD:
356155192Srwatson	case A_GETCAR:
357155192Srwatson	case A_GETSTAT:
358155192Srwatson	case A_GETCOND:
359155192Srwatson	case A_GETCLASS:
360155192Srwatson	case A_GETPINFO:
361155192Srwatson	case A_GETFSIZE:
362155192Srwatson	case A_GETPINFO_ADDR:
363155192Srwatson	case A_GETKAUDIT:
364155192Srwatson		error = copyout((void *)&udata, uap->data, uap->length);
365155192Srwatson		if (error)
366155192Srwatson			return (error);
367155192Srwatson		break;
368155192Srwatson	}
369155192Srwatson
370155192Srwatson	return (0);
371155192Srwatson}
372155192Srwatson
373156889Srwatson/*
374155192Srwatson * MPSAFE
375155192Srwatson *
376155192Srwatson * System calls to manage the user audit information.
377155192Srwatson */
378155192Srwatson/* ARGSUSED */
379155192Srwatsonint
380155192Srwatsongetauid(struct thread *td, struct getauid_args *uap)
381155192Srwatson{
382155192Srwatson	int error;
383155192Srwatson	au_id_t id;
384155192Srwatson
385155192Srwatson	error = suser(td);
386155192Srwatson	if (error)
387155192Srwatson		return (error);
388155192Srwatson
389155192Srwatson	/*
390156889Srwatson	 * XXX: Integer read on static pointer dereference: doesn't need
391156889Srwatson	 * locking?
392155192Srwatson	 */
393155192Srwatson	PROC_LOCK(td->td_proc);
394155192Srwatson	id = td->td_proc->p_au->ai_auid;
395155192Srwatson	PROC_UNLOCK(td->td_proc);
396155192Srwatson	return copyout(&id, uap->auid, sizeof(id));
397155192Srwatson}
398155192Srwatson
399155192Srwatson/* MPSAFE */
400155192Srwatson/* ARGSUSED */
401155192Srwatsonint
402155192Srwatsonsetauid(struct thread *td, struct setauid_args *uap)
403155192Srwatson{
404155192Srwatson	int error;
405155192Srwatson	au_id_t id;
406155192Srwatson
407155192Srwatson	error = suser(td);
408155192Srwatson	if (error)
409155192Srwatson		return (error);
410155192Srwatson
411155192Srwatson	error = copyin(uap->auid, &id, sizeof(id));
412155192Srwatson	if (error)
413155192Srwatson		return (error);
414155192Srwatson
415155192Srwatson	audit_arg_auid(id);
416155192Srwatson
417155192Srwatson	/*
418156889Srwatson	 * XXX: Integer write on static pointer dereference: doesn't need
419156889Srwatson	 * locking?
420155192Srwatson	 *
421155192Srwatson	 * XXXAUDIT: Might need locking to serialize audit events in the same
422155192Srwatson	 * order as change events?  Or maybe that's an under-solveable
423155192Srwatson	 * problem.
424155192Srwatson	 *
425155192Srwatson	 * XXXRW: Test privilege while holding the proc lock?
426156889Srwatson	 */
427155192Srwatson	PROC_LOCK(td->td_proc);
428155192Srwatson	td->td_proc->p_au->ai_auid = id;
429155192Srwatson	PROC_UNLOCK(td->td_proc);
430155192Srwatson
431155192Srwatson	return (0);
432155192Srwatson}
433155192Srwatson
434155192Srwatson/*
435155192Srwatson * MPSAFE
436156889Srwatson * System calls to get and set process audit information.
437155192Srwatson */
438155192Srwatson/* ARGSUSED */
439155192Srwatsonint
440155192Srwatsongetaudit(struct thread *td, struct getaudit_args *uap)
441155192Srwatson{
442155192Srwatson	struct auditinfo ai;
443155192Srwatson	int error;
444155192Srwatson
445155192Srwatson	error = suser(td);
446155192Srwatson	if (error)
447155192Srwatson		return (error);
448155192Srwatson
449155192Srwatson	PROC_LOCK(td->td_proc);
450155192Srwatson	ai = *td->td_proc->p_au;
451155192Srwatson	PROC_UNLOCK(td->td_proc);
452155192Srwatson
453155192Srwatson	return (copyout(&ai, uap->auditinfo, sizeof(ai)));
454155192Srwatson}
455155192Srwatson
456155192Srwatson/* MPSAFE */
457155192Srwatson/* ARGSUSED */
458155192Srwatsonint
459155192Srwatsonsetaudit(struct thread *td, struct setaudit_args *uap)
460155192Srwatson{
461155192Srwatson	struct auditinfo ai;
462155192Srwatson	int error;
463155192Srwatson
464155192Srwatson	error = suser(td);
465155192Srwatson	if (error)
466155192Srwatson		return (error);
467155192Srwatson
468155192Srwatson	error = copyin(uap->auditinfo, &ai, sizeof(ai));
469155192Srwatson	if (error)
470155192Srwatson		return (error);
471155192Srwatson
472155192Srwatson	audit_arg_auditinfo(&ai);
473155192Srwatson
474155192Srwatson	/*
475155192Srwatson	 * XXXRW: Test privilege while holding the proc lock?
476155192Srwatson	*/
477155192Srwatson	PROC_LOCK(td->td_proc);
478155192Srwatson	*td->td_proc->p_au = ai;
479155192Srwatson	PROC_UNLOCK(td->td_proc);
480155192Srwatson
481155192Srwatson	return (0);
482155192Srwatson}
483155192Srwatson
484155192Srwatson/* MPSAFE */
485155192Srwatson/* ARGSUSED */
486155192Srwatsonint
487155192Srwatsongetaudit_addr(struct thread *td, struct getaudit_addr_args *uap)
488155192Srwatson{
489155192Srwatson	int error;
490155192Srwatson
491155192Srwatson	error = suser(td);
492155192Srwatson	if (error)
493155192Srwatson		return (error);
494155192Srwatson	return (ENOSYS);
495155192Srwatson}
496155192Srwatson
497155192Srwatson/* MPSAFE */
498155192Srwatson/* ARGSUSED */
499155192Srwatsonint
500155192Srwatsonsetaudit_addr(struct thread *td, struct setaudit_addr_args *uap)
501155192Srwatson{
502155192Srwatson	int error;
503155192Srwatson
504155192Srwatson	error = suser(td);
505155192Srwatson	if (error)
506155192Srwatson		return (error);
507155192Srwatson	return (ENOSYS);
508155192Srwatson}
509155192Srwatson
510155192Srwatson/*
511155192Srwatson * MPSAFE
512155192Srwatson * Syscall to manage audit files.
513155192Srwatson *
514155192Srwatson * XXX: Should generate an audit event.
515155192Srwatson */
516155192Srwatson/* ARGSUSED */
517155192Srwatsonint
518155192Srwatsonauditctl(struct thread *td, struct auditctl_args *uap)
519155192Srwatson{
520155192Srwatson	struct nameidata nd;
521155192Srwatson	struct ucred *cred;
522155192Srwatson	struct vnode *vp;
523155192Srwatson	int error = 0;
524159318Srwatson	int flags, vfslocked;
525155192Srwatson
526155192Srwatson	error = suser(td);
527155192Srwatson	if (error)
528155192Srwatson		return (error);
529155192Srwatson
530155192Srwatson	vp = NULL;
531155192Srwatson	cred = NULL;
532155192Srwatson
533155192Srwatson	/*
534155192Srwatson	 * If a path is specified, open the replacement vnode, perform
535155192Srwatson	 * validity checks, and grab another reference to the current
536155192Srwatson	 * credential.
537155192Srwatson	 *
538155192Srwatson	 * XXXAUDIT: On Darwin, a NULL path is used to disable audit.
539155192Srwatson	 */
540155192Srwatson	if (uap->path == NULL)
541155192Srwatson		return (EINVAL);
542155192Srwatson
543159318Srwatson	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE, UIO_USERSPACE,
544159318Srwatson	    uap->path, td);
545155192Srwatson	flags = AUDIT_OPEN_FLAGS;
546155192Srwatson	error = vn_open(&nd, &flags, 0, -1);
547159318Srwatson	if (error)
548159318Srwatson		return (error);
549159318Srwatson	vfslocked = NDHASGIANT(&nd);
550155192Srwatson	VOP_UNLOCK(nd.ni_vp, 0, td);
551155192Srwatson	vp = nd.ni_vp;
552155192Srwatson	if (vp->v_type != VREG) {
553155192Srwatson		vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td);
554159318Srwatson		VFS_UNLOCK_GIANT(vfslocked);
555159318Srwatson		return (EINVAL);
556155192Srwatson	}
557159318Srwatson	VFS_UNLOCK_GIANT(vfslocked);
558155192Srwatson	cred = td->td_ucred;
559155192Srwatson	crhold(cred);
560155192Srwatson
561155192Srwatson	/*
562155192Srwatson	 * XXXAUDIT: Should audit_suspended actually be cleared by
563155192Srwatson	 * audit_worker?
564155192Srwatson	 */
565155192Srwatson	audit_suspended = 0;
566155192Srwatson
567155192Srwatson	audit_rotate_vnode(cred, vp);
568155192Srwatson
569155192Srwatson	return (error);
570155192Srwatson}
571155192Srwatson
572155192Srwatson#else /* !AUDIT */
573155192Srwatson
574155192Srwatsonint
575155192Srwatsonaudit(struct thread *td, struct audit_args *uap)
576155192Srwatson{
577155192Srwatson
578155192Srwatson	return (ENOSYS);
579155192Srwatson}
580155192Srwatson
581155192Srwatsonint
582155192Srwatsonauditon(struct thread *td, struct auditon_args *uap)
583155192Srwatson{
584155192Srwatson
585155192Srwatson	return (ENOSYS);
586155192Srwatson}
587155192Srwatson
588155192Srwatsonint
589155192Srwatsongetauid(struct thread *td, struct getauid_args *uap)
590155192Srwatson{
591155192Srwatson
592155192Srwatson	return (ENOSYS);
593155192Srwatson}
594155192Srwatson
595155192Srwatsonint
596155192Srwatsonsetauid(struct thread *td, struct setauid_args *uap)
597155192Srwatson{
598155192Srwatson
599155192Srwatson	return (ENOSYS);
600155192Srwatson}
601155192Srwatson
602155192Srwatsonint
603155192Srwatsongetaudit(struct thread *td, struct getaudit_args *uap)
604155192Srwatson{
605155192Srwatson
606155192Srwatson	return (ENOSYS);
607155192Srwatson}
608155192Srwatson
609155192Srwatsonint
610155192Srwatsonsetaudit(struct thread *td, struct setaudit_args *uap)
611155192Srwatson{
612155192Srwatson
613155192Srwatson	return (ENOSYS);
614155192Srwatson}
615155192Srwatson
616155192Srwatsonint
617155192Srwatsongetaudit_addr(struct thread *td, struct getaudit_addr_args *uap)
618155192Srwatson{
619155192Srwatson
620155192Srwatson	return (ENOSYS);
621155192Srwatson}
622155192Srwatson
623155192Srwatsonint
624155192Srwatsonsetaudit_addr(struct thread *td, struct setaudit_addr_args *uap)
625155192Srwatson{
626155192Srwatson
627155192Srwatson	return (ENOSYS);
628155192Srwatson}
629155192Srwatson
630155192Srwatsonint
631155192Srwatsonauditctl(struct thread *td, struct auditctl_args *uap)
632155192Srwatson{
633155192Srwatson
634155192Srwatson	return (ENOSYS);
635155192Srwatson}
636155192Srwatson
637155192Srwatsonvoid
638155192Srwatsonaudit_proc_init(struct proc *p)
639155192Srwatson{
640155192Srwatson
641155192Srwatson}
642155192Srwatson
643155192Srwatsonvoid
644155192Srwatsonaudit_proc_fork(struct proc *parent, struct proc *child)
645155192Srwatson{
646155192Srwatson
647155192Srwatson}
648155192Srwatson
649155192Srwatsonvoid
650155192Srwatsonaudit_proc_free(struct proc *p)
651155192Srwatson{
652155192Srwatson
653155192Srwatson}
654155192Srwatson
655155192Srwatson#endif /* AUDIT */
656