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