xref: /illumos-gate/usr/src/uts/common/c2/audit_mem.c (revision 861a91627796c35220e75654dac61e5707536dcd)
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