17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5005d3febSMarek Pospisil * Common Development and Distribution License (the "License"). 6005d3febSMarek Pospisil * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*4a0fa546SMarek Pospisil * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate #include <sys/param.h> 267c478bd9Sstevel@tonic-gate #include <sys/types.h> 277c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 287c478bd9Sstevel@tonic-gate #include <sys/t_lock.h> 297c478bd9Sstevel@tonic-gate #include <sys/thread.h> 307c478bd9Sstevel@tonic-gate #include <sys/systm.h> 317c478bd9Sstevel@tonic-gate #include <c2/audit.h> 327c478bd9Sstevel@tonic-gate #include <c2/audit_kernel.h> 337c478bd9Sstevel@tonic-gate #include <c2/audit_record.h> 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate static kmem_cache_t *au_buf_cache; 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate /* 387c478bd9Sstevel@tonic-gate * au_buff_t and token_t are equivalent (see audit_record.h). Don't 397c478bd9Sstevel@tonic-gate * confuse this token_t with the one that is defined for userspace 407c478bd9Sstevel@tonic-gate * in the same header file. 417c478bd9Sstevel@tonic-gate */ 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate /* 447c478bd9Sstevel@tonic-gate * Function: au_get_buff 457c478bd9Sstevel@tonic-gate * args: 467c478bd9Sstevel@tonic-gate */ 477c478bd9Sstevel@tonic-gate struct au_buff * 487c478bd9Sstevel@tonic-gate au_get_buff(void) 497c478bd9Sstevel@tonic-gate { 507c478bd9Sstevel@tonic-gate au_buff_t *buffer; 517c478bd9Sstevel@tonic-gate t_audit_data_t *tad = U2A(u); 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate ASSERT(tad); 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate /* 567c478bd9Sstevel@tonic-gate * If asynchronous (interrupt) thread, then we can't sleep 577c478bd9Sstevel@tonic-gate * (the tad ERRJMP flag is set at the start of async processing). 587c478bd9Sstevel@tonic-gate */ 59*4a0fa546SMarek Pospisil if (tad->tad_ctrl & TAD_ERRJMP) { 607c478bd9Sstevel@tonic-gate buffer = kmem_cache_alloc(au_buf_cache, KM_NOSLEEP); 617c478bd9Sstevel@tonic-gate if (buffer == NULL) { 627c478bd9Sstevel@tonic-gate /* return to top of stack & report an error */ 637c478bd9Sstevel@tonic-gate ASSERT(tad->tad_errjmp); 647c478bd9Sstevel@tonic-gate longjmp(tad->tad_errjmp); 657c478bd9Sstevel@tonic-gate } 667c478bd9Sstevel@tonic-gate } else { 677c478bd9Sstevel@tonic-gate buffer = kmem_cache_alloc(au_buf_cache, KM_SLEEP); 687c478bd9Sstevel@tonic-gate } 697c478bd9Sstevel@tonic-gate /* Never gets here when buffer == NULL */ 707c478bd9Sstevel@tonic-gate bzero(buffer, sizeof (*buffer)); 717c478bd9Sstevel@tonic-gate return (buffer); 727c478bd9Sstevel@tonic-gate } 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate /* 757c478bd9Sstevel@tonic-gate * Function: au_free_rec 767c478bd9Sstevel@tonic-gate * args: 777c478bd9Sstevel@tonic-gate * au_buff_t *buf; start of the record chain 787c478bd9Sstevel@tonic-gate */ 797c478bd9Sstevel@tonic-gate void 807c478bd9Sstevel@tonic-gate au_free_rec(au_buff_t *buf) 817c478bd9Sstevel@tonic-gate { 827c478bd9Sstevel@tonic-gate au_buff_t *next; 837c478bd9Sstevel@tonic-gate t_audit_data_t *tad = U2A(u); 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate ASSERT(tad); 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate /* 887c478bd9Sstevel@tonic-gate * If asynchronous (interrupt) thread, schedule the release 897c478bd9Sstevel@tonic-gate * (the tad ERRJMP flag is set at the start of async processing). 907c478bd9Sstevel@tonic-gate */ 91*4a0fa546SMarek Pospisil if (tad->tad_ctrl & TAD_ERRJMP) { 927c478bd9Sstevel@tonic-gate /* Discard async events via softcall. */ 937c478bd9Sstevel@tonic-gate softcall(audit_async_discard_backend, buf); 947c478bd9Sstevel@tonic-gate } 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate while (buf != NULL) { 977c478bd9Sstevel@tonic-gate next = buf->next_buf; 987c478bd9Sstevel@tonic-gate kmem_cache_free(au_buf_cache, buf); 997c478bd9Sstevel@tonic-gate buf = next; 1007c478bd9Sstevel@tonic-gate } 1017c478bd9Sstevel@tonic-gate } 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate /* 1047c478bd9Sstevel@tonic-gate * Backend routine to discard an async event. Invoked from softcall. 1057c478bd9Sstevel@tonic-gate * (Note: the freeing of memory for the event can't be done safely in high 1067c478bd9Sstevel@tonic-gate * interrupt context due to the chance of sleeping on an adaptive mutex. 1077c478bd9Sstevel@tonic-gate * Hence the softcall.) 1087c478bd9Sstevel@tonic-gate */ 1097c478bd9Sstevel@tonic-gate void 1107c478bd9Sstevel@tonic-gate audit_async_discard_backend(void *addr) 1117c478bd9Sstevel@tonic-gate { 1127c478bd9Sstevel@tonic-gate au_toss_token(addr); 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* 1167c478bd9Sstevel@tonic-gate * Function: au_append_rec 1177c478bd9Sstevel@tonic-gate * args: 1187c478bd9Sstevel@tonic-gate * au_buff_t *rec; start of the record chain 1197c478bd9Sstevel@tonic-gate * au_buff_t *buf; buffer to append 1207c478bd9Sstevel@tonic-gate * int pack; AU_PACK/1 - pack data, AU_LINK/0 - link buffer 1217c478bd9Sstevel@tonic-gate */ 1227c478bd9Sstevel@tonic-gate int 1237c478bd9Sstevel@tonic-gate au_append_rec(au_buff_t *rec, au_buff_t *buf, int pack) 1247c478bd9Sstevel@tonic-gate { 1257c478bd9Sstevel@tonic-gate if (!rec) 1267c478bd9Sstevel@tonic-gate return (-1); 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate while (rec->next_buf) 1297c478bd9Sstevel@tonic-gate rec = rec->next_buf; 1307c478bd9Sstevel@tonic-gate if (((int)(rec->len + buf->len) <= AU_BUFSIZE) && pack) { 1317c478bd9Sstevel@tonic-gate bcopy(buf->buf, (char *)(rec->buf + rec->len), 1327c478bd9Sstevel@tonic-gate (uint_t)buf->len); 1337c478bd9Sstevel@tonic-gate rec->len += buf->len; 1347c478bd9Sstevel@tonic-gate rec->next_buf = buf->next_buf; 1357c478bd9Sstevel@tonic-gate kmem_cache_free(au_buf_cache, buf); 1367c478bd9Sstevel@tonic-gate } else { 1377c478bd9Sstevel@tonic-gate rec->next_buf = buf; 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate return (0); 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate /* 1437c478bd9Sstevel@tonic-gate * Function: au_append_buf 1447c478bd9Sstevel@tonic-gate * args: 1457c478bd9Sstevel@tonic-gate * char *data; data buffer to append 1467c478bd9Sstevel@tonic-gate * int len; size of data to append 1477c478bd9Sstevel@tonic-gate * au_buff_t *buf; buffer to append to 1487c478bd9Sstevel@tonic-gate */ 1497c478bd9Sstevel@tonic-gate int 1507c478bd9Sstevel@tonic-gate au_append_buf(const char *data, int len, au_buff_t *buf) 1517c478bd9Sstevel@tonic-gate { 1527c478bd9Sstevel@tonic-gate au_buff_t *new_buf; 1537c478bd9Sstevel@tonic-gate int new_len; 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate while (buf->next_buf != NULL) 1567c478bd9Sstevel@tonic-gate buf = buf->next_buf; 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate new_len = (uint_t)(buf->len + len) > AU_BUFSIZE ? 1597c478bd9Sstevel@tonic-gate AU_BUFSIZE - buf->len : len; 1607c478bd9Sstevel@tonic-gate bcopy(data, (buf->buf + buf->len), (uint_t)new_len); 1617c478bd9Sstevel@tonic-gate buf->len += (uchar_t)new_len; 1627c478bd9Sstevel@tonic-gate len -= new_len; 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate while (len > 0) { 1657c478bd9Sstevel@tonic-gate data += new_len; 1667c478bd9Sstevel@tonic-gate if ((new_buf = au_get_buff()) == NULL) { 1677c478bd9Sstevel@tonic-gate return (-1); 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate buf->next_buf = new_buf; 1707c478bd9Sstevel@tonic-gate buf = new_buf; 1717c478bd9Sstevel@tonic-gate new_len = len > AU_BUFSIZE ? AU_BUFSIZE : len; 1727c478bd9Sstevel@tonic-gate bcopy(data, buf->buf, (uint_t)new_len); 1737c478bd9Sstevel@tonic-gate buf->len = (uchar_t)new_len; 1747c478bd9Sstevel@tonic-gate len -= new_len; 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate return (0); 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate void 1807c478bd9Sstevel@tonic-gate au_mem_init() 1817c478bd9Sstevel@tonic-gate { 1827c478bd9Sstevel@tonic-gate au_buf_cache = kmem_cache_create("audit_buffer", 1837c478bd9Sstevel@tonic-gate sizeof (au_buff_t), 0, NULL, NULL, NULL, NULL, NULL, 0); 1847c478bd9Sstevel@tonic-gate } 185