/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. */ #include #include #include #include #include #include #include #include #include static kmem_cache_t *au_buf_cache; /* * au_buff_t and token_t are equivalent (see audit_record.h). Don't * confuse this token_t with the one that is defined for userspace * in the same header file. */ /* * Function: au_get_buff * args: */ struct au_buff * au_get_buff(void) { au_buff_t *buffer; t_audit_data_t *tad = U2A(u); ASSERT(tad); /* * If asynchronous (interrupt) thread, then we can't sleep * (the tad ERRJMP flag is set at the start of async processing). */ if (tad->tad_ctrl & TAD_ERRJMP) { buffer = kmem_cache_alloc(au_buf_cache, KM_NOSLEEP); if (buffer == NULL) { /* return to top of stack & report an error */ ASSERT(tad->tad_errjmp); longjmp(tad->tad_errjmp); } } else { buffer = kmem_cache_alloc(au_buf_cache, KM_SLEEP); } /* Never gets here when buffer == NULL */ bzero(buffer, sizeof (*buffer)); return (buffer); } /* * Function: au_free_rec * args: * au_buff_t *buf; start of the record chain */ void au_free_rec(au_buff_t *buf) { au_buff_t *next; t_audit_data_t *tad = U2A(u); ASSERT(tad); /* * If asynchronous (interrupt) thread, schedule the release * (the tad ERRJMP flag is set at the start of async processing). */ if (tad->tad_ctrl & TAD_ERRJMP) { /* Discard async events via softcall. */ softcall(audit_async_discard_backend, buf); } while (buf != NULL) { next = buf->next_buf; kmem_cache_free(au_buf_cache, buf); buf = next; } } /* * Backend routine to discard an async event. Invoked from softcall. * (Note: the freeing of memory for the event can't be done safely in high * interrupt context due to the chance of sleeping on an adaptive mutex. * Hence the softcall.) */ void audit_async_discard_backend(void *addr) { au_toss_token(addr); } /* * Function: au_append_rec * args: * au_buff_t *rec; start of the record chain * au_buff_t *buf; buffer to append * int pack; AU_PACK/1 - pack data, AU_LINK/0 - link buffer */ int au_append_rec(au_buff_t *rec, au_buff_t *buf, int pack) { if (!rec) return (-1); while (rec->next_buf) rec = rec->next_buf; if (((int)(rec->len + buf->len) <= AU_BUFSIZE) && pack) { bcopy(buf->buf, (char *)(rec->buf + rec->len), (uint_t)buf->len); rec->len += buf->len; rec->next_buf = buf->next_buf; kmem_cache_free(au_buf_cache, buf); } else { rec->next_buf = buf; } return (0); } /* * Function: au_append_buf * args: * char *data; data buffer to append * int len; size of data to append * au_buff_t *buf; buffer to append to */ int au_append_buf(const char *data, int len, au_buff_t *buf) { au_buff_t *new_buf; int new_len; while (buf->next_buf != NULL) buf = buf->next_buf; new_len = (uint_t)(buf->len + len) > AU_BUFSIZE ? AU_BUFSIZE - buf->len : len; bcopy(data, (buf->buf + buf->len), (uint_t)new_len); buf->len += (uchar_t)new_len; len -= new_len; while (len > 0) { data += new_len; if ((new_buf = au_get_buff()) == NULL) { return (-1); } buf->next_buf = new_buf; buf = new_buf; new_len = len > AU_BUFSIZE ? AU_BUFSIZE : len; bcopy(data, buf->buf, (uint_t)new_len); buf->len = (uchar_t)new_len; len -= new_len; } return (0); } void au_mem_init() { au_buf_cache = kmem_cache_create("audit_buffer", sizeof (au_buff_t), 0, NULL, NULL, NULL, NULL, NULL, 0); }