943N/A * Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved. 919N/A * Permission is hereby granted, free of charge, to any person obtaining a 919N/A * copy of this software and associated documentation files (the "Software"), 919N/A * to deal in the Software without restriction, including without limitation 919N/A * the rights to use, copy, modify, merge, publish, distribute, sublicense, 919N/A * and/or sell copies of the Software, and to permit persons to whom the 919N/A * Software is furnished to do so, subject to the following conditions: 919N/A * The above copyright notice and this permission notice (including the next 919N/A * paragraph) shall be included in all copies or substantial portions of the 919N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 919N/A * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 919N/A * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 919N/A * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 919N/A * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 919N/A * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 919N/A * DEALINGS IN THE SOFTWARE. 196N/A * auditwrite() - Construct and write user level records to the audit trail. 196N/A/* Include common system files first */ 196N/A /* needs to be restored */ 196N/A * required attribute flags 196N/A * if these attributes are not included in the record, they are added 196N/A * AW_NOUSERDCMD - these cmds may not be used with AW_USERD on auditwrite call. 196N/A * Where control commands end and attribute commands begin. 196N/A * Currently, AW_MAX_REC_SIZE applies to both audit(2). This 196N/A * will need to be changed as the limits associated w/audit(2) and 196N/A * auditctl(2) change. It's defined here because the kernel imposed maximum 196N/A * record size is not program visible. 196N/A * Number of record pointers to initially allocate 196N/A * A record descriptor that is not allocated. 196N/A * This is a fakeout for auditwrite. We don't have a 196N/A * auditctl(A_AUDIT), so we'll emulate this with existing 196N/A/* Data structures used to account for and queue audit record buffers */ 196N/A int len;
/* number of bytes in buffer */ 196N/A * Command table. Contains the command and the number of args that follow 196N/A * If you add to the list, be aware that this is an array, and 196N/A * in indexed accordingly. I don't know why the cmd_number field 196N/A * Control commands. These control the behavior of auditwrite. 196N/A * Attribute commands. These tell audiwrite how many attributes 196N/A/* externally accessible data */ 196N/A "Memory allocation failure",
196N/A "Command not in effect",
196N/A "More than one control command specified",
196N/A "getaudit(2) or getaudit_addr(2) failed",
196N/A "Record descriptor invalid",
196N/A/* Data used by parsing routines and auditwrite */ 196N/A /* used if invoker doesn't specify one */ 196N/A /* every audit record */ 196N/A * a w _ g e t _ a r g s ( ) 196N/A * Gets arguments off the stack; 196N/A * a w _ s k i p _ a r g ( ) 196N/A * Skip args on the invocation line. 196N/A * a u d i t w r i t e ( ) 196N/A * Construct and write user level audit records to the audit trail. 196N/A register int i;
/* counter */ 196N/A /* Is auditing even enabled? If not, just exit */ 196N/A * first time initialization stuff. 196N/A * get the preselection mask and the audit policy. 196N/A * allocate a default record buffer. 196N/A * set context, parse the invocation line and get the command. 196N/A /* need to rewind the command line first... */ 196N/A * Preselect the record here. 196N/A * If we're not going to write it, no sense in constructing it. 196N/A * deallocate all records 196N/A * special case - reallocate the default rd 196N/A * if user blows it away. 196N/A * if user blows away the current rd, set it back 196N/A /* Get the info from the proc */ 196N/A /* Stuff the real values in */ 196N/A * SAVERD can be used by long-running processes 196N/A * (servers) to set-up context for a new "subject". 196N/A * Take the opportunity here to force a check of 196N/A * the event file on disk for any changes. 196N/A /* XXXX refreshauevcache(); */ 196N/A * Called when an an error occurs. Write any incomplete or buffered records. 196N/A /* Write queued or partial records */ 196N/A "aborted: aw_errno = %d = %s, errno = %d = %s",
196N/A * Several programs, most noticably init(1M), have their own local 196N/A * copies of bcopy(3C), which take precedence over lib C's 196N/A * bcopy(3C) that we previously used here. memmove(3C) does the same 196N/A * a w _ b u f _ a p p e n d ( ) 196N/A * Append some data from one buffer to another 196N/A * a w _ b u f _ p r e p e n d ( ) 196N/A * Prepend the contents of one buffer to another 196N/A * a w _ c h k _ a d d r ( ) 196N/A * Make sure address is within allowable boundaries. This is done to minimize 196N/A * core dumps (mostly SIGSEGV and SIGBUS) that can occur when a bad 196N/A * invocation line is passed. 196N/A * if pointer is null, it's bogus 196N/A * a w _ c h k _ e v e n t _ i d ( ) 196N/A * Make sure event id is set. 196N/A * a w _ c h k _ p r i n t ( ) 196N/A * Indicate validity of arbitrary data print arg. 196N/A * a w _ c h k _ t y p e ( ) 196N/A * Indicate validity of arbitrary data type arg. 196N/A * a w _ c h k _ r d ( ) 196N/A * Make sure record descriptor is valid 196N/A * a w _ c l e a n u p ( ) 196N/A * Free all buffer space. Reset all static flags. 196N/A /* Deallocate all audit records and record pointer array */ 196N/A /* Deallocate audit record queue */ 196N/A * a w _ c v r t _ p a t h ( ) 196N/A * Get path ready for the audit trail by prepending the absolute root. 196N/A * a w _ c v r t _ t y p e ( ) 196N/A * Convert arbitrary data print suggestions to token print suggestions. 196N/A * a w _ c v r t _ t y p e ( ) 196N/A * Convert arbitrary data type to token data type. 196N/A * a w _ d o _ s u b j e c t ( ) 196N/A * Check the audit policy and add any necessary attribs. 196N/A * The remaining policies such as seq and trailers are done by audit(2). 196N/A * if the record does not contain a subject attribute 196N/A * Add the subject token using the values we have. 196N/A * Append them to the record under construction 196N/A /* Go grab the sensitivity label for this process */ 196N/A /* Now output the SL */ 196N/A /* Now add the groups */ 196N/A * The sequence token is no longer required to be added by 196N/A * auditwrite(), it's added by BSM. 196N/A * a w _ d o _ w r i t e ( ) 196N/A * Write an audit record. 196N/A * an attempt to write an audit record without an event id 196N/A * set is a serious error 196N/A * if we are a server, we don't need to add subject and return 196N/A * Must add a return attribute in all cases if one 196N/A * has not already been added. this attribute denotes 196N/A /* Now finish up by writing the header attribute */ 196N/A * if queueing is on write to the queue 196N/A * if we are a server, we need to use auditctl(2) 196N/A * default case. we are not a server and we are not queueing. 196N/A * If we are in context for a descriptor, now that the 196N/A * descriptor is gone we must clean up its save rd if any. 196N/A * Only free good addrs. 196N/A * a w _ f r e e _ t o k ( ) 196N/A * a w _ g e n _ r e c ( ) 196N/A * Traverse the invocation line again. This time grab all the record attributes, 196N/A * convert them to ADR format and append them to the current record buffer. 196N/A void *
ad[
8];
/* attribute data */ 196N/A int a;
/* invocation line argument */ 196N/A * This is a bit of a hack. Rather than 196N/A * write a new au_to_attr() routine, we 196N/A * simply allocate a new vattr and stuff 196N/A * Add a header to an audit record. 196N/A * Note that we no longer need to add a trailer in Solaris 2.x, as this 196N/A * is handled by the audit(2) system call. 196N/A char id;
/* tmp variable to hold value */ 196N/A * Need to fix up the size correctly. 196N/A * Parse the invocation line looking for invalid commands and invalid data 196N/A * Returns AW_ERR_RTN when: 196N/A * more than one control command has been specified. 196N/A * AW_APPEND is specified w/out any attribute commands. 196N/A * Returns AW_SUCCESS_RTN upon success. 196N/A * During the port from TS 2, we had to slightly reorg code, thus 196N/A * I'm simply going to continue to use the "a" variable. 196N/A * EVENT attribute and RETURN attribute have preselection 196N/A * info. Need to gobble up that info here so that we can 196N/A * preselect without the overhead of record construction. 196N/A /* Reload with next value of "a" */ 196N/A /* AW_ABORT is not documented. It is used for debugging */ 196N/A * A specified rd of -1 here means that the 196N/A * default rd should be discarded. 196N/A * Already handled a valid one in aw_set_context(). 196N/A /* Reload with the next value of "a" */ 196N/A /* Must have a control command */ 196N/A /* Must be an attribute command with AW_APPEND control command */ 196N/A * If there was an attribute command, need a control command to that 196N/A * tells what to do with the attributes. 196N/A * a w _ p r e s e l e c t ( ) 196N/A * Do user level audit preselection 196N/A * 1 - audit event is preselected 196N/A * 0 - audit event is not preselected 196N/A * a w _ q u e u e _ d e a l l o c ( ) 196N/A * Deallocate audit record queue. 196N/A * a w _ q u e u e _ f l u s h ( ) 196N/A * Flush audit record queue. 196N/A /* write all records on queue to trail */ 196N/A * a w _ q u e u e _ w r i t e ( ) 196N/A * "Queue" an audit record. Actually, each record passed is appended to a 196N/A * buffer. This buffer eventually gets written with auditctl(2). Auditctl(2) 196N/A * will process the records in the order in which it receives them. This 196N/A * creates a "queueing" effect. 196N/A /* no queue? allocate it now. */ 196N/A /* did we reach the hi-water mark? */ 196N/A * a w _ r e c _ i n i t ( ) 196N/A * a w _ r e c _ a l l o c ( ) 196N/A * Allocate a buffer to store an audit record. 196N/A /* allocate the audit record buffer pointers */ 196N/A /* allocate the record */ 196N/A /* linear search to find the next open slot */ 196N/A /* allocate the record */ 196N/A /* no open slots, allocate for another */ 196N/A /* allocate the record */ 196N/A * a w _ r e c _ a p p e n d ( ) 196N/A * Concatentate two previously allocated records. 196N/A * a w _ r e c _ d e a l l o c ( ) 196N/A * Deallocate a previously allocated audit record buffer. 196N/A /* free the audit record buffer */ 196N/A * a w _ r e c _ p r e p e n d ( ) 196N/A * Prepend a record buffer with the contents of another record buffer. 196N/A * append a return token indicating a success event 196N/A * a w _ s e t _ e r r ( ) 196N/A * This routine sets aw_errno. It insures aw_errno is set 196N/A * a w _ s e t _ e v e n t ( ) 196N/A * Set event id and class. 196N/A * if this is the first invocation of auditwrite(3), do some setup 196N/A * allocate a default audit record buf if we don't have one. 196N/A * current record buf was recently deallocated 196N/A * set it back to the default 196N/A * Cache the preselection mask and the audit policies in order 196N/A * to reduce system call overhead. If they change, we will be 196N/A * auditing with stale values. 196N/A /* Stuff the real values in */ 196N/A * a w _ s e t _ c o n t e x t ( ) 196N/A * set context as needed. 196N/A * If the input params start with USERD and after this there's 196N/A * anything besides AW_END, then we need to switch to the context 196N/A * for that record descriptor. 196N/A * USERD is used with another command. 196N/A * Save context first, then load context for the 196N/A * Now load up our values. 196N/A /* initialize as needed... */ 196N/A * Finish basic USERD processing here. 196N/A * a w _ r e s t o r e ( ) 196N/A * restore context if needed. 196N/A * Save context for our rd first... If our rd is gone 196N/A * by now, we can't and won't need to do this part. 196N/A * Now restore the old values. 196N/A * a w _ a u d i t _ w r i t e ( ) 196N/A * Write an audit record to the audit trail using the audit(2) system call. 196N/A * a w _ a u d i t c t l _ w r i t e ( ) 196N/A * Write an audit record to the audit trail using the auditctl(2) system call. 196N/A * aw_debuglog: dump auditwrite parameters and current state 196N/A * General format of such an entry: 196N/A * xxx e pid= nnn stat-flags= xxxxxx aw_errno= n cur_rd= n 196N/A * dflt_rd= n save_rd= n arg1 arg2 ... arg11 196N/A * xxx = text, generally either "in" (auditwrite begin) or "out" (exit) 196N/A * e = auditwrite return value (significant only with "out") 196N/A * arg1, = auditwrite arguments (1st 11 only, whether used or not) 196N/A * Now dump in the arguments auditwrite was called with... Since 196N/A * the number of args is variable, just dump the first 10 or so 196N/A * (some of which may not actually have been passed). 196N/A for (i =
1; i <=
10; i++) {
196N/A * aw_strerror: return the error string 196N/A * aw_geterrno: return the aw_errno for the given descriptor. 196N/A * aw_perror_c: common internal routine to return the error string 196N/A * aw_perror: return the error string 196N/A * aw_perror_r: return the error string 196N/A * Currently we are using Solaris 2.x BSM's audit mechanism, 196N/A * which doesn't have the large queue buffer mechanism. Rather 196N/A * than rewrite the system call, we'll simply emulate the large 196N/A * buffer write. If this gets to be problem in performance, 196N/A * we can readd the system call. 196N/A char id;
/* check for proper audit record */ 196N/A /* The only remaining option to auditctl is be A_AUDIT */ 196N/A /* Where to start parsing */ 196N/A /* Make sure we have a header and output the record */ 196N/A /* Use the audit(2) errno */ 196N/A /* Last minute check to make sure we wrote out the exact number */