1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <sys/param.h> 26 #include <sys/types.h> 27 #include <sys/kmem.h> 28 #include <sys/t_lock.h> 29 #include <sys/thread.h> 30 #include <sys/systm.h> 31 #include <c2/audit.h> 32 #include <c2/audit_kernel.h> 33 #include <c2/audit_record.h> 34 35 static kmem_cache_t *au_buf_cache; 36 37 /* 38 * au_buff_t and token_t are equivalent (see audit_record.h). Don't 39 * confuse this token_t with the one that is defined for userspace 40 * in the same header file. 41 */ 42 43 /* 44 * Function: au_get_buff 45 * args: 46 */ 47 struct au_buff * 48 au_get_buff(void) 49 { 50 au_buff_t *buffer; 51 t_audit_data_t *tad = U2A(u); 52 53 ASSERT(tad); 54 55 /* 56 * If asynchronous (interrupt) thread, then we can't sleep 57 * (the tad ERRJMP flag is set at the start of async processing). 58 */ 59 if (tad->tad_ctrl & TAD_ERRJMP) { 60 buffer = kmem_cache_alloc(au_buf_cache, KM_NOSLEEP); 61 if (buffer == NULL) { 62 /* return to top of stack & report an error */ 63 ASSERT(tad->tad_errjmp); 64 longjmp(tad->tad_errjmp); 65 } 66 } else { 67 buffer = kmem_cache_alloc(au_buf_cache, KM_SLEEP); 68 } 69 /* Never gets here when buffer == NULL */ 70 bzero(buffer, sizeof (*buffer)); 71 return (buffer); 72 } 73 74 /* 75 * Function: au_free_rec 76 * args: 77 * au_buff_t *buf; start of the record chain 78 */ 79 void 80 au_free_rec(au_buff_t *buf) 81 { 82 au_buff_t *next; 83 t_audit_data_t *tad = U2A(u); 84 85 ASSERT(tad); 86 87 /* 88 * If asynchronous (interrupt) thread, schedule the release 89 * (the tad ERRJMP flag is set at the start of async processing). 90 */ 91 if (tad->tad_ctrl & TAD_ERRJMP) { 92 /* Discard async events via softcall. */ 93 softcall(audit_async_discard_backend, buf); 94 } 95 96 while (buf != NULL) { 97 next = buf->next_buf; 98 kmem_cache_free(au_buf_cache, buf); 99 buf = next; 100 } 101 } 102 103 /* 104 * Backend routine to discard an async event. Invoked from softcall. 105 * (Note: the freeing of memory for the event can't be done safely in high 106 * interrupt context due to the chance of sleeping on an adaptive mutex. 107 * Hence the softcall.) 108 */ 109 void 110 audit_async_discard_backend(void *addr) 111 { 112 au_toss_token(addr); 113 } 114 115 /* 116 * Function: au_append_rec 117 * args: 118 * au_buff_t *rec; start of the record chain 119 * au_buff_t *buf; buffer to append 120 * int pack; AU_PACK/1 - pack data, AU_LINK/0 - link buffer 121 */ 122 int 123 au_append_rec(au_buff_t *rec, au_buff_t *buf, int pack) 124 { 125 if (!rec) 126 return (-1); 127 128 while (rec->next_buf) 129 rec = rec->next_buf; 130 if (((int)(rec->len + buf->len) <= AU_BUFSIZE) && pack) { 131 bcopy(buf->buf, (char *)(rec->buf + rec->len), 132 (uint_t)buf->len); 133 rec->len += buf->len; 134 rec->next_buf = buf->next_buf; 135 kmem_cache_free(au_buf_cache, buf); 136 } else { 137 rec->next_buf = buf; 138 } 139 return (0); 140 } 141 142 /* 143 * Function: au_append_buf 144 * args: 145 * char *data; data buffer to append 146 * int len; size of data to append 147 * au_buff_t *buf; buffer to append to 148 */ 149 int 150 au_append_buf(const char *data, int len, au_buff_t *buf) 151 { 152 au_buff_t *new_buf; 153 int new_len; 154 155 while (buf->next_buf != NULL) 156 buf = buf->next_buf; 157 158 new_len = (uint_t)(buf->len + len) > AU_BUFSIZE ? 159 AU_BUFSIZE - buf->len : len; 160 bcopy(data, (buf->buf + buf->len), (uint_t)new_len); 161 buf->len += (uchar_t)new_len; 162 len -= new_len; 163 164 while (len > 0) { 165 data += new_len; 166 if ((new_buf = au_get_buff()) == NULL) { 167 return (-1); 168 } 169 buf->next_buf = new_buf; 170 buf = new_buf; 171 new_len = len > AU_BUFSIZE ? AU_BUFSIZE : len; 172 bcopy(data, buf->buf, (uint_t)new_len); 173 buf->len = (uchar_t)new_len; 174 len -= new_len; 175 } 176 return (0); 177 } 178 179 void 180 au_mem_init() 181 { 182 au_buf_cache = kmem_cache_create("audit_buffer", 183 sizeof (au_buff_t), 0, NULL, NULL, NULL, NULL, NULL, 0); 184 } 185