Exemplo n.º 1
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);
}
Exemplo n.º 2
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);
}