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 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/param.h> 27 #include <sys/types.h> 28 #include <sys/kmem.h> 29 #include <sys/t_lock.h> 30 #include <sys/thread.h> 31 #include <sys/systm.h> 32 #include <c2/audit.h> 33 #include <c2/audit_kernel.h> 34 #include <c2/audit_record.h> 35 36 static kmem_cache_t *au_buf_cache; 37 38 /* 39 * au_buff_t and token_t are equivalent (see audit_record.h). Don't 40 * confuse this token_t with the one that is defined for userspace 41 * in the same header file. 42 */ 43 44 /* 45 * Function: au_get_buff 46 * args: 47 */ 48 struct au_buff * 49 au_get_buff(void) 50 { 51 au_buff_t *buffer; 52 t_audit_data_t *tad = U2A(u); 53 54 ASSERT(tad); 55 56 /* 57 * If asynchronous (interrupt) thread, then we can't sleep 58 * (the tad ERRJMP flag is set at the start of async processing). 59 */ 60 if (tad->tad_ctrl & PAD_ERRJMP) { 61 buffer = kmem_cache_alloc(au_buf_cache, KM_NOSLEEP); 62 if (buffer == NULL) { 63 /* return to top of stack & report an error */ 64 ASSERT(tad->tad_errjmp); 65 longjmp(tad->tad_errjmp); 66 } 67 } else { 68 buffer = kmem_cache_alloc(au_buf_cache, KM_SLEEP); 69 } 70 /* Never gets here when buffer == NULL */ 71 bzero(buffer, sizeof (*buffer)); 72 return (buffer); 73 } 74 75 /* 76 * Function: au_free_rec 77 * args: 78 * au_buff_t *buf; start of the record chain 79 */ 80 void 81 au_free_rec(au_buff_t *buf) 82 { 83 au_buff_t *next; 84 t_audit_data_t *tad = U2A(u); 85 86 ASSERT(tad); 87 88 /* 89 * If asynchronous (interrupt) thread, schedule the release 90 * (the tad ERRJMP flag is set at the start of async processing). 91 */ 92 if (tad->tad_ctrl & PAD_ERRJMP) { 93 /* Discard async events via softcall. */ 94 softcall(audit_async_discard_backend, buf); 95 } 96 97 while (buf != NULL) { 98 next = buf->next_buf; 99 kmem_cache_free(au_buf_cache, buf); 100 buf = next; 101 } 102 } 103 104 /* 105 * Backend routine to discard an async event. Invoked from softcall. 106 * (Note: the freeing of memory for the event can't be done safely in high 107 * interrupt context due to the chance of sleeping on an adaptive mutex. 108 * Hence the softcall.) 109 */ 110 void 111 audit_async_discard_backend(void *addr) 112 { 113 au_toss_token(addr); 114 } 115 116 /* 117 * Function: au_append_rec 118 * args: 119 * au_buff_t *rec; start of the record chain 120 * au_buff_t *buf; buffer to append 121 * int pack; AU_PACK/1 - pack data, AU_LINK/0 - link buffer 122 */ 123 int 124 au_append_rec(au_buff_t *rec, au_buff_t *buf, int pack) 125 { 126 if (!rec) 127 return (-1); 128 129 while (rec->next_buf) 130 rec = rec->next_buf; 131 if (((int)(rec->len + buf->len) <= AU_BUFSIZE) && pack) { 132 bcopy(buf->buf, (char *)(rec->buf + rec->len), 133 (uint_t)buf->len); 134 rec->len += buf->len; 135 rec->next_buf = buf->next_buf; 136 kmem_cache_free(au_buf_cache, buf); 137 } else { 138 rec->next_buf = buf; 139 } 140 return (0); 141 } 142 143 /* 144 * Function: au_append_buf 145 * args: 146 * char *data; data buffer to append 147 * int len; size of data to append 148 * au_buff_t *buf; buffer to append to 149 */ 150 int 151 au_append_buf(const char *data, int len, au_buff_t *buf) 152 { 153 au_buff_t *new_buf; 154 int new_len; 155 156 while (buf->next_buf != NULL) 157 buf = buf->next_buf; 158 159 new_len = (uint_t)(buf->len + len) > AU_BUFSIZE ? 160 AU_BUFSIZE - buf->len : len; 161 bcopy(data, (buf->buf + buf->len), (uint_t)new_len); 162 buf->len += (uchar_t)new_len; 163 len -= new_len; 164 165 while (len > 0) { 166 data += new_len; 167 if ((new_buf = au_get_buff()) == NULL) { 168 return (-1); 169 } 170 buf->next_buf = new_buf; 171 buf = new_buf; 172 new_len = len > AU_BUFSIZE ? AU_BUFSIZE : len; 173 bcopy(data, buf->buf, (uint_t)new_len); 174 buf->len = (uchar_t)new_len; 175 len -= new_len; 176 } 177 return (0); 178 } 179 180 void 181 au_mem_init() 182 { 183 au_buf_cache = kmem_cache_create("audit_buffer", 184 sizeof (au_buff_t), 0, NULL, NULL, NULL, NULL, NULL, 0); 185 } 186