示例#1
0
/* Start a new audit session if this has been enabled.  */
static gpg_error_t
start_audit_session (ctrl_t ctrl)
{
  audit_release (ctrl->audit);
  ctrl->audit = NULL;
  if (ctrl->server_local->enable_audit_log && !(ctrl->audit = audit_new ()) )
    return gpg_error_from_syserror ();

  return 0;
}
示例#2
0
/* ARGSUSED */
int
audit(struct thread *td, struct audit_args *uap)
{
	int error;
	void * rec;
	struct kaudit_record *ar;

	if (jailed(td->td_ucred))
		return (ENOSYS);
	error = priv_check(td, PRIV_AUDIT_SUBMIT);
	if (error)
		return (error);

	if ((uap->length <= 0) || (uap->length > audit_qctrl.aq_bufsz))
		return (EINVAL);

	ar = currecord();

	/*
	 * If there's no current audit record (audit() itself not audited)
	 * commit the user audit record.
	 */
	if (ar == NULL) {

		/*
		 * This is not very efficient; we're required to allocate a
		 * complete kernel audit record just so the user record can
		 * tag along.
		 *
		 * XXXAUDIT: Maybe AUE_AUDIT in the system call context and
		 * special pre-select handling?
		 */
		td->td_ar = audit_new(AUE_NULL, td);
		if (td->td_ar == NULL)
			return (ENOTSUP);
		td->td_pflags |= TDP_AUDITREC;
		ar = td->td_ar;
	}

	if (uap->length > MAX_AUDIT_RECORD_SIZE)
		return (EINVAL);

	rec = malloc(uap->length, M_AUDITDATA, M_WAITOK);

	error = copyin(uap->record, rec, uap->length);
	if (error)
		goto free_out;

	/* Verify the record. */
	if (bsm_rec_verify(rec) == 0) {
		error = EINVAL;
		goto free_out;
	}

#ifdef MAC
	error = mac_system_check_audit(td->td_ucred, rec, uap->length);
	if (error)
		goto free_out;
#endif

	/*
	 * Attach the user audit record to the kernel audit record.  Because
	 * this system call is an auditable event, we will write the user
	 * record along with the record for this audit event.
	 *
	 * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen,
	 * k_ar_commit & AR_COMMIT_USER?
	 */
	ar->k_udata = rec;
	ar->k_ulen  = uap->length;
	ar->k_ar_commit |= AR_COMMIT_USER;

	/*
	 * Currently we assume that all preselection has been performed in
	 * userspace.  We unconditionally set these masks so that the records
	 * get committed both to the trail and pipe.  In the future we will
	 * want to setup kernel based preselection.
	 */
	ar->k_ar_commit |= (AR_PRESELECT_USER_TRAIL | AR_PRESELECT_USER_PIPE);
	return (0);

free_out:
	/*
	 * audit_syscall_exit() will free the audit record on the thread even
	 * if we allocated it above.
	 */
	free(rec, M_AUDITDATA);
	return (error);
}
示例#3
0
文件: audit.c 项目: coyizumi/cs111
/*
 * audit_syscall_enter() is called on entry to each system call.  It is
 * responsible for deciding whether or not to audit the call (preselection),
 * and if so, allocating a per-thread audit record.  audit_new() will fill in
 * basic thread/credential properties.
 */
void
audit_syscall_enter(unsigned short code, struct thread *td)
{
	struct au_mask *aumask;
	au_class_t class;
	au_event_t event;
	au_id_t auid;

	KASSERT(td->td_ar == NULL, ("audit_syscall_enter: td->td_ar != NULL"));
	KASSERT((td->td_pflags & TDP_AUDITREC) == 0,
	    ("audit_syscall_enter: TDP_AUDITREC set"));

	/*
	 * In FreeBSD, each ABI has its own system call table, and hence
	 * mapping of system call codes to audit events.  Convert the code to
	 * an audit event identifier using the process system call table
	 * reference.  In Darwin, there's only one, so we use the global
	 * symbol for the system call table.  No audit record is generated
	 * for bad system calls, as no operation has been performed.
	 */
	if (code >= td->td_proc->p_sysent->sv_size)
		return;

	event = td->td_proc->p_sysent->sv_table[code].sy_auevent;
	if (event == AUE_NULL)
		return;

	/*
	 * Check which audit mask to use; either the kernel non-attributable
	 * event mask or the process audit mask.
	 */
	auid = td->td_ucred->cr_audit.ai_auid;
	if (auid == AU_DEFAUDITID)
		aumask = &audit_nae_mask;
	else
		aumask = &td->td_ucred->cr_audit.ai_mask;

	/*
	 * Allocate an audit record, if preselection allows it, and store in
	 * the thread for later use.
	 */
	class = au_event_class(event);
	if (au_preselect(event, class, aumask, AU_PRS_BOTH)) {
		/*
		 * If we're out of space and need to suspend unprivileged
		 * processes, do that here rather than trying to allocate
		 * another audit record.
		 *
		 * Note: we might wish to be able to continue here in the
		 * future, if the system recovers.  That should be possible
		 * by means of checking the condition in a loop around
		 * cv_wait().  It might be desirable to reevaluate whether an
		 * audit record is still required for this event by
		 * re-calling au_preselect().
		 */
		if (audit_in_failure &&
		    priv_check(td, PRIV_AUDIT_FAILSTOP) != 0) {
			cv_wait(&audit_fail_cv, &audit_mtx);
			panic("audit_failing_stop: thread continued");
		}
		td->td_ar = audit_new(event, td);
		if (td->td_ar != NULL)
			td->td_pflags |= TDP_AUDITREC;
	} else if (audit_pipe_preselect(auid, event, class, AU_PRS_BOTH, 0)) {
示例#4
0
文件: audit.c 项目: JackieXie168/xnu
/*
 * audit_syscall_enter() is called on entry to each system call.  It is
 * responsible for deciding whether or not to audit the call (preselection),
 * and if so, allocating a per-thread audit record.  audit_new() will fill in
 * basic thread/credential properties.
 */
void
audit_syscall_enter(unsigned int code, proc_t proc, struct uthread *uthread)
{
	struct au_mask *aumask;
	au_class_t class;
	au_event_t event;
	au_id_t auid;
	kauth_cred_t cred;

	/*
	 * In FreeBSD, each ABI has its own system call table, and hence
	 * mapping of system call codes to audit events.  Convert the code to
	 * an audit event identifier using the process system call table
	 * reference.  In Darwin, there's only one, so we use the global
	 * symbol for the system call table.  No audit record is generated
	 * for bad system calls, as no operation has been performed.
	 *
	 * In Mac OS X, the audit events are stored in a table seperate from
	 * the syscall table(s).  This table is generated by makesyscalls.sh
	 * from syscalls.master and stored in audit_kevents.c.
	 */
	if (code > NUM_SYSENT)
		return;
	event = sys_au_event[code];
	if (event == AUE_NULL)
		return;

	KASSERT(uthread->uu_ar == NULL,
	    ("audit_syscall_enter: uthread->uu_ar != NULL"));

	/*
	 * Check which audit mask to use; either the kernel non-attributable
	 * event mask or the process audit mask.
	 */
	cred = kauth_cred_proc_ref(proc);
	auid = cred->cr_audit.as_aia_p->ai_auid;
	if (auid == AU_DEFAUDITID) 
		aumask = &audit_nae_mask;
	else
		aumask = &cred->cr_audit.as_mask;

	/*
	 * Allocate an audit record, if preselection allows it, and store in
	 * the thread for later use.
	 */
	class = au_event_class(event);
#if CONFIG_MACF
	/*
	 * Note: audit_mac_syscall_enter() may call audit_new() and allocate
	 * memory for the audit record (uu_ar).
	 */
	if (audit_mac_syscall_enter(code, proc, uthread, cred, event) == 0)
		goto out;
#endif
	if (au_preselect(event, class, aumask, AU_PRS_BOTH)) {
		/*
		 * If we're out of space and need to suspend unprivileged
		 * processes, do that here rather than trying to allocate
		 * another audit record.
		 *
		 * Note: we might wish to be able to continue here in the
		 * future, if the system recovers.  That should be possible
		 * by means of checking the condition in a loop around
		 * cv_wait().  It might be desirable to reevaluate whether an
		 * audit record is still required for this event by
		 * re-calling au_preselect().
		 */
		if (audit_in_failure &&
		    suser(cred, &proc->p_acflag) != 0) {
			cv_wait(&audit_fail_cv, &audit_mtx);
			panic("audit_failing_stop: thread continued");
		}
		if (uthread->uu_ar == NULL)
			uthread->uu_ar = audit_new(event, proc, uthread);
	} else if (audit_pipe_preselect(auid, event, class, AU_PRS_BOTH, 0)) {
示例#5
0
文件: audit.c 项目: JackieXie168/xnu
		 * future, if the system recovers.  That should be possible
		 * by means of checking the condition in a loop around
		 * cv_wait().  It might be desirable to reevaluate whether an
		 * audit record is still required for this event by
		 * re-calling au_preselect().
		 */
		if (audit_in_failure &&
		    suser(cred, &proc->p_acflag) != 0) {
			cv_wait(&audit_fail_cv, &audit_mtx);
			panic("audit_failing_stop: thread continued");
		}
		if (uthread->uu_ar == NULL)
			uthread->uu_ar = audit_new(event, proc, uthread);
	} else if (audit_pipe_preselect(auid, event, class, AU_PRS_BOTH, 0)) {
		if (uthread->uu_ar == NULL)
			uthread->uu_ar = audit_new(event, proc, uthread);
	} 

out:
	kauth_cred_unref(&cred);
}

/*
 * audit_syscall_exit() is called from the return of every system call, or in
 * the event of exit1(), during the execution of exit1().  It is responsible
 * for committing the audit record, if any, along with return condition.
 *
 * Note: The audit_syscall_exit() parameter list was modified to support
 * mac_audit_check_postselect(), which requires the syscall number.
 */
#if CONFIG_MACF
示例#6
0
/* ARGSUSED */
int
audit(proc_t p, struct audit_args *uap, __unused int32_t *retval)
{
	int error;
	void * rec;
	struct kaudit_record *ar;
	struct uthread *uthr;

	error = suser(kauth_cred_get(), &p->p_acflag);
	if (error)
		return (error);

	mtx_lock(&audit_mtx);
	if ((uap->length <= 0) || (uap->length > (int)audit_qctrl.aq_bufsz)) {
		mtx_unlock(&audit_mtx);
		return (EINVAL);
	}
	mtx_unlock(&audit_mtx);

	ar = currecord();

	/*
	 * If there's no current audit record (audit() itself not audited)
	 * commit the user audit record.
	 */
	if (ar == NULL) {
		uthr = curthread();
		if (uthr == NULL)	/* can this happen? */
			return (ENOTSUP);

		/*
		 * This is not very efficient; we're required to allocate a
		 * complete kernel audit record just so the user record can
		 * tag along.
		 */
		uthr->uu_ar = audit_new(AUE_NULL, p, uthr);
		if (uthr->uu_ar == NULL)
			return (ENOTSUP);
		ar = uthr->uu_ar;
	}

	if (uap->length > MAX_AUDIT_RECORD_SIZE)
		return (EINVAL);

	rec = malloc(uap->length, M_AUDITDATA, M_WAITOK);

	error = copyin(uap->record, rec, uap->length);
	if (error)
		goto free_out;

#if CONFIG_MACF
	error = mac_system_check_audit(kauth_cred_get(), rec, uap->length);
	if (error)
		goto free_out;
#endif

	/* Verify the record. */
	if (bsm_rec_verify(rec) == 0) {
		error = EINVAL;
		goto free_out;
	}

	/*
	 * Attach the user audit record to the kernel audit record.  Because
	 * this system call is an auditable event, we will write the user
	 * record along with the record for this audit event.
	 *
	 * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen,
	 * k_ar_commit & AR_COMMIT_USER?
	 */
	ar->k_udata = rec;
	ar->k_ulen  = uap->length;
	ar->k_ar_commit |= AR_COMMIT_USER;

	/*
	 * Currently we assume that all preselection has been performed in
	 * userspace.  We unconditionally set these masks so that the records
	 * get committed both to the trail and pipe.  In the future we will
	 * want to setup kernel based preselection.
	 */
	ar->k_ar_commit |= (AR_PRESELECT_USER_TRAIL | AR_PRESELECT_USER_PIPE);
	return (0);

free_out:
	/*
	 * audit_syscall_exit() will free the audit record on the thread even
	 * if we allocated it above.
	 */
	free(rec, M_AUDITDATA);
	return (error);
}