diff options
author | Marek Pospisil <Marek.Pospisil@Sun.COM> | 2010-03-05 13:16:08 -0800 |
---|---|---|
committer | Marek Pospisil <Marek.Pospisil@Sun.COM> | 2010-03-05 13:16:08 -0800 |
commit | 005d3feb53a9a10272d4a24b03991575d6a9bcb3 (patch) | |
tree | 3c239c5ec7be3de4c1719c4539033149da56a799 | |
parent | 83d7a2524bdbf7b1da1c47b52bc20eee0f12c60e (diff) | |
download | illumos-gate-005d3feb53a9a10272d4a24b03991575d6a9bcb3.tar.gz |
PSARC/2009/354 Always on / no reboot Solaris Audit
6192139 Solaris auditing should be able to start collecting audit records without a reboot
63 files changed, 2618 insertions, 2469 deletions
diff --git a/usr/src/cmd/audit/audit.c b/usr/src/cmd/audit/audit.c index 66a4553203..bf31448d13 100644 --- a/usr/src/cmd/audit/audit.c +++ b/usr/src/cmd/audit/audit.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -50,7 +50,6 @@ /* GLOBALS */ static char *progname = "audit"; static char *usage = "audit [-n] | [-s] | [-t] | [-v filepath]"; -static int silent = 0; static void display_smf_error(); @@ -70,9 +69,7 @@ static int sig_auditd(int); /* send signal to auditd */ * audit -n * - signal audit daemon to use next audit_control audit directory. * audit -t - * - signal audit daemon to disable auditing. - * audit -T - * - signal audit daemon to disable auditing report no errors. + * - signal audit daemon to permanently disable auditing. * audit -v filepath * - validate audit_control parameters but use filepath for * the name. Emit errors or "syntax ok" @@ -95,13 +92,13 @@ main(int argc, char *argv[]) (void) textdomain(TEXT_DOMAIN); /* first option required */ - if ((c = getopt(argc, argv, "nstTv:")) == -1) { + if ((c = getopt(argc, argv, "nstv:")) == -1) { (void) fprintf(stderr, gettext("usage: %s\n"), usage); exit(3); } first_option = optarg; /* second or more options not allowed; please pick one */ - if (getopt(argc, argv, "nstTv:") != -1) { + if (getopt(argc, argv, "nstv:") != -1) { (void) fprintf(stderr, gettext("usage: %s\n"), usage); exit(5); } @@ -123,21 +120,11 @@ main(int argc, char *argv[]) case 't': if (!is_valid_zone(0)) /* 0 == no error message display */ exit(10); - /* use bmsunconv to permanently disable, -t for temporary */ - if (smf_disable_instance(AUDITD_FMRI, SMF_TEMPORARY) != 0) { + if (smf_disable_instance(AUDITD_FMRI, 0) != 0) { display_smf_error(); exit(11); } break; - case 'T': - silent = 1; - if (!is_valid_zone(0)) /* 0 == no error message display */ - exit(10); - - if (smf_disable_instance(AUDITD_FMRI, SMF_TEMPORARY) != 0) { - exit(11); - } - break; case 'v': if (is_audit_control_ok(first_option)) { (void) fprintf(stderr, gettext("syntax ok\n")); @@ -302,11 +289,6 @@ is_audit_control_ok(char *filename) { /* * The operations that call this function are only valid in the global * zone unless the perzone audit policy is set. - * - * "!silent" and "show_err" are slightly different; silent is from - * -T for which no error messages should be displayed and show_err - * applies to more options (including -T) - * */ static boolean_t @@ -315,10 +297,9 @@ is_valid_zone(boolean_t show_err) long policy; if (auditon(A_GETPOLICY, (char *)&policy, 0) == -1) { - if (!silent) - (void) fprintf(stderr, gettext( - "%s: Cannot read audit policy: %s\n"), - progname, strerror(errno)); + (void) fprintf(stderr, gettext( + "%s: Cannot read audit policy: %s\n"), + progname, strerror(errno)); return (0); } if (policy & AUDIT_PERZONE) diff --git a/usr/src/cmd/bsmconv/bsmconv.sh b/usr/src/cmd/bsmconv/bsmconv.sh index f562c5390d..5a4c653a4d 100644 --- a/usr/src/cmd/bsmconv/bsmconv.sh +++ b/usr/src/cmd/bsmconv/bsmconv.sh @@ -20,22 +20,28 @@ # # CDDL HEADER END # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # PROG=bsmconv -DEVALLOC=/etc/security/device_allocate -DEVMAPS=/etc/security/device_maps + TEXTDOMAIN="SUNW_OST_OSCMD" export TEXTDOMAIN +DEVALLOC=/etc/security/device_allocate +DEVMAPS=/etc/security/device_maps +DEVFSADM=/usr/sbin/devfsadm +MKDEVALLOC=/usr/sbin/mkdevalloc +MKDEVMAPS=/usr/sbin/mkdevmaps +ZONENAME=/sbin/zonename + # Perform required permission checks, depending on value of LOCAL_ROOT # (whether we are converting the active OS or just alternative boot # environments). permission() { -ZONE=`/sbin/zonename` +ZONE=`${ZONENAME}` if [ ! "$ZONE" = "global" -a "$LOCAL_ROOT" = "true" ] then form=`gettext "%s: ERROR: you must be in the global zone to run this script."` @@ -54,7 +60,7 @@ fi RESP="x" while [ "$RESP" != `gettext "y"` -a "$RESP" != `gettext "n"` ] do -gettext "This script is used to enable Solaris Auditing and device allocation.\n" +gettext "This script is used to enable device allocation.\n" form=`gettext "Shall we continue with the conversion now? [y/n]"` echo "$form \c" read RESP @@ -74,7 +80,6 @@ sanity_check() { for ROOT in $@ do - if [ -d $ROOT -a -w $ROOT -a -f $ROOT/etc/system -a -d $ROOT/usr ] then # There is a root directory to write to, @@ -90,12 +95,11 @@ do done } -# bsmconvert +# dev_allocation_convert # All the real work gets done in this function -bsmconvert() +dev_allocation_convert() { - # Prevent automount of removable and hotpluggable volumes # by forcing volume.ignore HAL property on all such volumes. if [ -d ${ROOT}/etc/hal/fdi ] ; then @@ -116,27 +120,6 @@ if [ -d ${ROOT}/etc/hal/fdi ] ; then FDI fi -# Turn on auditing in the loadable module - -form=`gettext "%s: INFO: turning on audit module."` -printf "${form}\n" $PROG -if [ ! -f ${ROOT}/etc/system ] -then - echo "" > ${ROOT}/etc/system -fi - -grep -v "c2audit:audit_load" ${ROOT}/etc/system > /tmp/etc.system.$$ -echo "set c2audit:audit_load = 1" >> /tmp/etc.system.$$ -mv /tmp/etc.system.$$ ${ROOT}/etc/system -grep "set c2audit:audit_load = 1" ${ROOT}/etc/system > /dev/null 2>&1 -if [ $? -ne 0 ] -then - form=`gettext "%s: ERROR: cannot 'set c2audit:audit_load = 1' in %s/etc/system"` - printf "${form}\n" $PROG $ROOT - form=`gettext "%s: Continuing ..."` - printf "${form}\n" $PROG -fi - # Initialize device allocation form=`gettext "%s: INFO: initializing device allocation."` @@ -155,23 +138,18 @@ if [ $? = 0 ]; then # This is not currently done for alternate boot environments. if [ -z "$ROOT" -o "$ROOT" = "/" ] then - /usr/sbin/devfsadm -e + ${DEVFSADM} -e fi else if [ ! -f ${ROOT}/${DEVALLOC} ] then - mkdevalloc > ${ROOT}/$DEVALLOC + ${MKDEVALLOC} > ${ROOT}/$DEVALLOC fi if [ ! -f ${ROOT}/${DEVMAPS} ] then - mkdevmaps > ${ROOT}/$DEVMAPS + ${MKDEVMAPS} > ${ROOT}/$DEVMAPS fi fi - -# enable auditd at next boot. -cat >> ${ROOT}/var/svc/profile/upgrade <<SVC_UPGRADE -/usr/sbin/svcadm enable system/auditd -SVC_UPGRADE } # main loop @@ -184,15 +162,13 @@ then permission ROOT= - bsmconvert + + dev_allocation_convert echo - gettext "Solaris Auditing and device allocation is ready.\n" - gettext "If there were any errors, please fix them now.\n" - gettext "Configure Solaris Auditing and device allocation by editing " - gettext "files\nlocated in /etc/security.\n" - gettext "Reboot this system now to come up with auditing " - gettext "and device allocation enabled.\n" + gettext "Device allocation is ready. If there were any errors, please\n" + gettext "fix them now. Reboot this system now to come up with device\n" + gettext "allocation enabled." else # determine if local root is being converted ("/" passed on # command line), if so, full permission check required @@ -213,18 +189,15 @@ else do form=`gettext "%s: INFO: converting boot environment %s ..."` printf "${form}\n" $PROG $ROOT - bsmconvert $ROOT + dev_allocation_convert $ROOT form=`gettext "%s: INFO: done with boot environment %s"` printf "${form}\n" $PROG $ROOT done + echo - gettext "Solaris Auditing and device allocation is ready.\n" - gettext "If there were any errors, please fix them now.\n" - gettext "Configure Solaris auditing and device allocation by editing " - gettext "files\nlocated in /etc/security in the root directories " - gettext "of each host converted.\n" - gettext "Reboot each system converted to come up with auditing " - gettext "and device\nallocation enabled.\n" + gettext "Device allocation is ready. If there were any errors,\n" + gettext "please fix them now. Reboot each non-local system\n" + gettext "converted to come up with device allocation enabled.\n" fi exit 0 diff --git a/usr/src/cmd/bsmunconv/bsmunconv.sh b/usr/src/cmd/bsmunconv/bsmunconv.sh index 060662a8b3..f8c1f36e59 100644 --- a/usr/src/cmd/bsmunconv/bsmunconv.sh +++ b/usr/src/cmd/bsmunconv/bsmunconv.sh @@ -21,15 +21,18 @@ # # CDDL HEADER END # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# PROG=bsmunconv +PATH=/usr/sbin:/usr/bin:/sbin + TEXTDOMAIN="SUNW_OST_OSCMD" export TEXTDOMAIN +ZONENAME=/sbin/zonename +DEVFSADM=/usr/sbin/devfsadm + # Perform required permission checks, depending on value of LOCAL_ROOT # (whether we are converting the active OS or just alternative boot @@ -37,7 +40,7 @@ export TEXTDOMAIN permission() { cd /usr/lib -ZONE=`/sbin/zonename` +ZONE=`${ZONENAME}` if [ ! "$ZONE" = "global" -a "$LOCAL_ROOT" = "true" ] then form=`gettext "%s: ERROR: you must be in the global zone to run this script."` @@ -53,24 +56,10 @@ then exit 1 fi -set -- `/usr/bin/who -r` -RUNLEVEL="$3" -if [ "$RUNLEVEL" -ne "S" -a "$LOCAL_ROOT" = "true" ] -then - form=`gettext "%s: ERROR: this script should be run at run level S."` - printf "${form}\n" $PROG - form=`gettext "Are you sure you want to continue? [y/n]"` - echo "$form \c" - read RESP - case $RESP in - `gettext "n"`*|`gettext "N"`* ) exit 1 ;; - esac -fi - RESP="x" while [ "$RESP" != `gettext "y"` -a "$RESP" != `gettext "n"` ] do -gettext "This script is used to disable Solaris Auditing and device allocation.\n" +gettext "This script is used to disable device allocation.\n" form=`gettext "Would you like to continue now? [y/n]"` echo "$form \c" read RESP @@ -84,56 +73,19 @@ then fi } -bsmunconvert() +# disable device allocation + +dev_allocation_unconvert() { # Turn off device allocation. This is not currently done for alternate # boot environments. if [ -z "$ROOT" -o "$ROOT" = "/" ] then - /usr/sbin/devfsadm -d + ${DEVFSADM} -d fi -# disable auditd service on next boot -cat >> ${ROOT}/var/svc/profile/upgrade <<SVC_UPGRADE -/usr/sbin/svcadm disable system/auditd -SVC_UPGRADE - # Restore default policy for removable and hotpluggable volumes rm -f ${ROOT}/etc/hal/fdi/policy/30user/90-solaris-device-allocation.fdi - -# Turn off auditing in the loadable module - -if [ -f ${ROOT}/etc/system ] -then - form=`gettext "%s: INFO: removing c2audit:audit_load from %s/etc/system."` - printf "${form}\n" $PROG $ROOT - grep -v "c2audit:audit_load" ${ROOT}/etc/system > /tmp/etc.system.$$ - mv /tmp/etc.system.$$ ${ROOT}/etc/system -else - form=`gettext "%s: ERROR: can't find %s/etc/system."` - printf "${form}\n" $PROG $ROOT - form=`gettext "%s: ERROR: audit module may not be disabled."` - printf "${form}\n" $PROG -fi - -# If we are currently converting the active host (${ROOT}="/") we will -# need to ensure that cron is not running. cron should not be running -# at run-level S, but it may have been started by hand. - -if [ -z "$ROOT" -o "$ROOT" = "/" ] -then - /usr/bin/pgrep -u root -f /usr/sbin/cron > /dev/null - if [ $? -eq 0 ]; then - form=`gettext "%s: INFO: stopping the cron daemon."` - printf "${form}\n" $PROG - - /usr/sbin/svcadm disable -t system/cron - fi -fi - -rm -f ${ROOT}/var/spool/cron/atjobs/*.au -rm -f ${ROOT}/var/spool/cron/crontabs/*.au - } # main @@ -147,10 +99,12 @@ then # begin conversion ROOT= - bsmunconvert + + dev_allocation_unconvert + echo - gettext "Solaris Auditing and device allocation has been disabled.\n" - gettext "Reboot the system now to come up without these features.\n" + gettext "Device allocation has been disabled. Reboot the system now\n" + gettext "to come up without this feature.\n" else # determine if local root is being converted ("/" passed on @@ -170,12 +124,12 @@ else for ROOT in $@ do - bsmunconvert $ROOT + dev_allocation_unconvert $ROOT done echo - gettext "Solaris Auditing and device allocation has been disabled.\n" - gettext "Reboot each system that was disabled to come up without these features.\n" + gettext "Device allocation has been disabled. Reboot each non-local\n" + gettext "system that was disabled to come up without this feature.\n" fi exit 0 diff --git a/usr/src/cmd/tsol/labeld/svc-labeld b/usr/src/cmd/tsol/labeld/svc-labeld index e924c28c60..028c93fad6 100644 --- a/usr/src/cmd/tsol/labeld/svc-labeld +++ b/usr/src/cmd/tsol/labeld/svc-labeld @@ -90,7 +90,7 @@ __ENABLE_OTHERS do_bsmconv() { - # Run bsmconv so audit and device allocation is enabled by + # Run bsmconv so device allocation is enabled by # default with Trusted Extensions. if [ "$ROOT_PATH" = "/" -o "$ROOT_PATH" = "" ]; then BSMDIR="" @@ -100,6 +100,16 @@ do_bsmconv() echo "Running bsmconv ..." echo `TEXTDOMAIN="SUNW_OST_OSCMD" gettext "y"` | \ $ROOT_PATH/etc/security/bsmconv $ROOT_PATH + # Run auditd so auditing is enabled by default + # with Trusted Extensions. + if [ "$BSMDIR" = "" ]; then + echo "Starting auditd ..." + /usr/sbin/audit -s + else + cat >> $ROOT_PATH/var/svc/profile/upgrade <<\_ENABLE_AUDITD + /usr/sbin/audit -s +_ENABLE_AUDITD + fi } do_nscd() diff --git a/usr/src/lib/brand/solaris10/s10_brand/common/s10_brand.c b/usr/src/lib/brand/solaris10/s10_brand/common/s10_brand.c index a5176e4179..35a0926d7b 100644 --- a/usr/src/lib/brand/solaris10/s10_brand/common/s10_brand.c +++ b/usr/src/lib/brand/solaris10/s10_brand/common/s10_brand.c @@ -1244,6 +1244,7 @@ s10_acctctl(sysret_t *rval, int cmd, void *buf, size_t bufsz) #define S10_AUDIT_HMASK 0xffffffc0 #define S10_AUDIT_LMASK 0x3f +#define S10_AUC_NOSPACE 0x3 int s10_auditsys(sysret_t *rval, int bsmcmd, intptr_t a0, intptr_t a1, intptr_t a2) @@ -1270,6 +1271,22 @@ s10_auditsys(sysret_t *rval, int bsmcmd, intptr_t a0, intptr_t a1, intptr_t a2) m = ((m >> 1) & S10_AUDIT_HMASK) | (m & S10_AUDIT_LMASK); return (__systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0, &m, a2)); + } else if ((int)a0 == A_GETCOND) { + if ((err = __systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0, + &m, a2)) != 0) + return (err); + if (m == AUC_NOSPACE) + m = S10_AUC_NOSPACE; + if (s10_uucopy(&m, (void *)a1, sizeof (m)) != 0) + return (EFAULT); + return (0); + } else if ((int)a0 == A_SETCOND) { + if (s10_uucopy((const void *)a1, &m, sizeof (m)) != 0) + return (EFAULT); + if (m == S10_AUC_NOSPACE) + m = AUC_NOSPACE; + return (__systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0, &m, + a2)); } return (__systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0, a1, a2)); diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files index b751c7e30a..acf8cb24c2 100644 --- a/usr/src/uts/common/Makefile.files +++ b/usr/src/uts/common/Makefile.files @@ -92,6 +92,9 @@ GENUNIX_OBJS += \ alarm.o \ aio_subr.o \ auditsys.o \ + audit_core.o \ + audit_zone.o \ + audit_memory.o \ autoconf.o \ avl.o \ bdev_dsort.o \ @@ -1535,7 +1538,7 @@ KSSL_OBJS += kssl.o ksslioctl.o ksslapi.o ksslrec.o C2AUDIT_OBJS += adr.o audit.o audit_event.o audit_io.o \ audit_path.o audit_start.o audit_syscalls.o audit_token.o \ - audit_mem.o audit_zone.o + audit_mem.o PCIC_OBJS += pcic.o diff --git a/usr/src/uts/common/c2/audit.c b/usr/src/uts/common/c2/audit.c index 7c12cf3406..3641e2b212 100644 --- a/usr/src/uts/common/c2/audit.c +++ b/usr/src/uts/common/c2/audit.c @@ -68,175 +68,6 @@ static void add_return_token(caddr_t *, unsigned int scid, int err, int rval); static void audit_pathbuild(struct pathname *pnp); -/* - * ROUTINE: AUDIT_NEWPROC - * PURPOSE: initialize the child p_audit_data structure - * CALLBY: GETPROC - * NOTE: All threads for the parent process are locked at this point. - * We are essentially running singled threaded for this reason. - * GETPROC is called when system creates a new process. - * By the time AUDIT_NEWPROC is called, the child proc - * structure has already been initialized. What we need - * to do is to allocate the child p_audit_data and - * initialize it with the content of current parent process. - */ - -void -audit_newproc(struct proc *cp) /* initialized child proc structure */ -{ - p_audit_data_t *pad; /* child process audit data */ - p_audit_data_t *opad; /* parent process audit data */ - - pad = kmem_cache_alloc(au_pad_cache, KM_SLEEP); - - P2A(cp) = pad; - - opad = P2A(curproc); - - /* - * copy the audit data. Note that all threads of current - * process have been "held". Thus there is no race condition - * here with mutiple threads trying to alter the cwrd - * structure (such as releasing it). - * - * The audit context in the cred is "duplicated" for the new - * proc by elsewhere crhold'ing the parent's cred which it shares. - * - * We still want to hold things since auditon() [A_SETUMASK, - * A_SETSMASK] could be walking through the processes to - * update things. - */ - mutex_enter(&opad->pad_lock); /* lock opad structure during copy */ - pad->pad_data = opad->pad_data; /* copy parent's process audit data */ - au_pathhold(pad->pad_root); - au_pathhold(pad->pad_cwd); - mutex_exit(&opad->pad_lock); /* current proc will keep cwrd open */ - - /* - * finish auditing of parent here so that it will be done - * before child has a chance to run. We include the child - * pid since the return value in the return token is a dummy - * one and contains no useful information (it is included to - * make the audit record structure consistant). - * - * tad_flag is set if auditing is on - */ - if (((t_audit_data_t *)T2A(curthread))->tad_flag) - au_uwrite(au_to_arg32(0, "child PID", (uint32_t)cp->p_pid)); - - /* - * finish up audit record generation here because child process - * is set to run before parent process. We distinguish here - * between FORK, FORK1, or VFORK by the saved system call ID. - */ - audit_finish(0, ((t_audit_data_t *)T2A(curthread))->tad_scid, 0, 0); -} - -/* - * ROUTINE: AUDIT_PFREE - * PURPOSE: deallocate the per-process udit data structure - * CALLBY: EXIT - * FORK_FAIL - * NOTE: all lwp except current one have stopped in SEXITLWPS - * why we are single threaded? - * . all lwp except current one have stopped in SEXITLWPS. - */ -void -audit_pfree(struct proc *p) /* proc structure to be freed */ - -{ /* AUDIT_PFREE */ - - p_audit_data_t *pad; - - pad = P2A(p); - - /* better be a per process audit data structure */ - ASSERT(pad != (p_audit_data_t *)0); - - if (pad == pad0) { - return; - } - - /* deallocate all auditing resources for this process */ - au_pathrele(pad->pad_root); - au_pathrele(pad->pad_cwd); - - /* - * Since the pad structure is completely overwritten after alloc, - * we don't bother to clear it. - */ - - kmem_cache_free(au_pad_cache, pad); -} - -/* - * ROUTINE: AUDIT_THREAD_CREATE - * PURPOSE: allocate per-process thread audit data structure - * CALLBY: THREAD_CREATE - * NOTE: This is called just after *t was bzero'd. - * We are single threaded in this routine. - * TODO: - * QUESTION: - */ - -void -audit_thread_create(kthread_id_t t) -{ - t_audit_data_t *tad; /* per-thread audit data */ - - tad = kmem_zalloc(sizeof (struct t_audit_data), KM_SLEEP); - - T2A(t) = tad; /* set up thread audit data ptr */ - tad->tad_thread = t; /* back ptr to thread: DEBUG */ -} - -/* - * ROUTINE: AUDIT_THREAD_FREE - * PURPOSE: free the per-thread audit data structure - * CALLBY: THREAD_FREE - * NOTE: most thread data is clear after return - */ -void -audit_thread_free(kthread_t *t) -{ - t_audit_data_t *tad; - au_defer_info_t *attr; - - tad = T2A(t); - - /* thread audit data must still be set */ - - if (tad == tad0) { - return; - } - - if (tad == NULL) { - return; - } - - t->t_audit_data = 0; - - /* must not have any audit record residual */ - ASSERT(tad->tad_ad == NULL); - - /* saved path must be empty */ - ASSERT(tad->tad_aupath == NULL); - - if (tad->tad_atpath) - au_pathrele(tad->tad_atpath); - - attr = tad->tad_defer_head; - while (attr != NULL) { - au_defer_info_t *tmp_attr = attr; - - au_free_rec(attr->audi_ad); - - attr = attr->audi_next; - kmem_free(tmp_attr, sizeof (au_defer_info_t)); - } - - kmem_free(tad, sizeof (*tad)); -} /* * ROUTINE: AUDIT_SAVEPATH @@ -448,12 +279,6 @@ audit_addcomponent(struct pathname *pnp) } /* AUDIT_ADDCOMPONENT */ - - - - - - /* * ROUTINE: AUDIT_ANCHORPATH * PURPOSE: @@ -678,58 +503,6 @@ audit_attributes(struct vnode *vp) /* - * ROUTINE: AUDIT_FALLOC - * PURPOSE: allocating a new file structure - * CALLBY: FALLOC - * NOTE: file structure already initialized - * TODO: - * QUESTION: - */ - -void -audit_falloc(struct file *fp) -{ /* AUDIT_FALLOC */ - - f_audit_data_t *fad; - - /* allocate per file audit structure if there a'int any */ - ASSERT(F2A(fp) == NULL); - - fad = kmem_zalloc(sizeof (struct f_audit_data), KM_SLEEP); - - F2A(fp) = fad; - - fad->fad_thread = curthread; /* file audit data back ptr; DEBUG */ -} - -/* - * ROUTINE: AUDIT_UNFALLOC - * PURPOSE: deallocate file audit data structure - * CALLBY: CLOSEF - * UNFALLOC - * NOTE: - * TODO: - * QUESTION: - */ - -void -audit_unfalloc(struct file *fp) -{ - f_audit_data_t *fad; - - fad = F2A(fp); - - if (!fad) { - return; - } - if (fad->fad_aupath != NULL) { - au_pathrele(fad->fad_aupath); - } - fp->f_audit_data = 0; - kmem_free(fad, sizeof (struct f_audit_data)); -} - -/* * ROUTINE: AUDIT_EXIT * PURPOSE: * CALLBY: EXIT @@ -769,7 +542,7 @@ audit_exit(int code, int what) /* * Generate an audit record for process exit if preselected. */ - (void) audit_start(0, SYS_exit, 0, 0); + (void) audit_start(0, SYS_exit, AUC_UNSET, 0, 0); audit_finish(0, SYS_exit, 0, 0); } @@ -883,7 +656,7 @@ audit_core_finish(int code) } /* Close up everything */ - au_close(kctx, &(u_ad), flag, tad->tad_event, tad->tad_evmod); + au_close(kctx, &(u_ad), flag, tad->tad_event, tad->tad_evmod, NULL); /* free up any space remaining with the path's */ if (tad->tad_aupath != NULL) { @@ -1010,6 +783,7 @@ audit_closef(struct file *fp) int getattr_ret; cred_t *cr; au_kcontext_t *kctx = GET_KCTX_PZ; + uint32_t auditing; fad = F2A(fp); estate = kctx->auk_ets[AUE_CLOSE]; @@ -1024,9 +798,9 @@ audit_closef(struct file *fp) } /* if auditing not enabled, then don't generate an audit record */ - if (!((kctx->auk_auditstate == AUC_AUDITING || - kctx->auk_auditstate == AUC_INIT_AUDIT) || - kctx->auk_auditstate == AUC_NOSPACE)) + auditing = (tad->tad_audit == AUC_UNSET) ? + kctx->auk_auditstate : tad->tad_audit; + if (auditing & ~(AUC_AUDITING | AUC_INIT_AUDIT | AUC_NOSPACE)) return; ainfo = crgetauinfo(cr); @@ -1094,7 +868,7 @@ audit_closef(struct file *fp) * thus we always indicate successful closes. */ au_close(kctx, (caddr_t *)&(ad), AU_OK | AU_DEFER, - AUE_CLOSE, evmod); + AUE_CLOSE, evmod, NULL); } /* @@ -1281,7 +1055,7 @@ audit_reboot(void) /* Close up everything */ au_close(kctx, &(u_ad), flag | AU_DONTBLOCK, - tad->tad_event, tad->tad_evmod); + tad->tad_event, tad->tad_evmod, NULL); } void @@ -1517,7 +1291,7 @@ audit_enterprom(int flg) else au_write((caddr_t *)&(rp), au_to_return32(ECANCELED, 0)); - AUDIT_ASYNC_FINISH(rp, AUE_ENTERPROM, NULL); + AUDIT_ASYNC_FINISH(rp, AUE_ENTERPROM, NULL, NULL); } @@ -1550,7 +1324,7 @@ audit_exitprom(int flg) else au_write((caddr_t *)&(rp), au_to_return32(ECANCELED, 0)); - AUDIT_ASYNC_FINISH(rp, AUE_EXITPROM, NULL); + AUDIT_ASYNC_FINISH(rp, AUE_EXITPROM, NULL, NULL); } struct fcntla { @@ -2218,7 +1992,8 @@ audit_cryptoadm(int cmd, char *module_name, crypto_mech_name_t *mech_names, AS_INC(as_generated, 1, kctx); AS_INC(as_kernel, 1, kctx); - au_close(kctx, (caddr_t *)&ad, AU_OK, AUE_CRYPTOADM, tad->tad_evmod); + au_close(kctx, (caddr_t *)&ad, AU_OK, AUE_CRYPTOADM, tad->tad_evmod, + NULL); } /* @@ -2290,7 +2065,8 @@ audit_kssl(int cmd, void *params, int error) AS_INC(as_generated, 1, kctx); AS_INC(as_kernel, 1, kctx); - au_close(kctx, (caddr_t *)&ad, AU_OK, AUE_CONFIGKSSL, tad->tad_evmod); + au_close(kctx, (caddr_t *)&ad, AU_OK, AUE_CONFIGKSSL, tad->tad_evmod, + NULL); } /* @@ -2422,7 +2198,8 @@ audit_pf_policy(int cmd, cred_t *cred, netstack_t *ns, char *tun, AS_INC(as_kernel, 1, kctx); } - au_close(kctx, (caddr_t *)&ad, flag, tad->tad_event, tad->tad_evmod); + au_close(kctx, (caddr_t *)&ad, flag, tad->tad_event, tad->tad_evmod, + NULL); /* * clear the ctrl flag so that we don't have spurious collection of diff --git a/usr/src/uts/common/c2/audit.h b/usr/src/uts/common/c2/audit.h index 0cc71d6cd6..836a66e0f7 100644 --- a/usr/src/uts/common/c2/audit.h +++ b/usr/src/uts/common/c2/audit.h @@ -51,10 +51,10 @@ extern "C" { #define AUC_UNSET 0 /* on/off hasn't been decided */ #define AUC_ENABLED 1 /* loaded and enabled */ /* local zone state */ -#define AUC_INIT_AUDIT 4 /* c2audit is ready but auditd has not run */ -#define AUC_AUDITING 1 /* auditing is being done */ -#define AUC_NOAUDIT 2 /* auditing is not being done */ -#define AUC_NOSPACE 3 /* audit enabled, no space for audit records */ +#define AUC_INIT_AUDIT 0x4 /* c2audit is ready but auditd has not run */ +#define AUC_AUDITING 0x1 /* auditing is being done */ +#define AUC_NOAUDIT 0x2 /* auditing is not being done */ +#define AUC_NOSPACE 0x8 /* audit enabled, no space for audit records */ /* * The user id -2 is never audited - in fact, a setauid(AU_NOAUDITID) @@ -470,6 +470,7 @@ typedef struct audit_stat au_stat_t; #include <c2/audit_door_infc.h> #include <sys/crypto/ioctladmin.h> #include <sys/netstack.h> +#include <sys/zone.h> #ifdef __cplusplus extern "C" { @@ -491,12 +492,11 @@ struct auditcalls { }; int audit(caddr_t, int); -int _audit(caddr_t, int); int auditsys(struct auditcalls *, union rval *); /* fake stub */ -int _auditsys(struct auditcalls *, union rval *); /* real deal */ void audit_cryptoadm(int, char *, crypto_mech_name_t *, uint_t, uint_t, uint32_t, int); void audit_init(void); +void audit_init_module(void); void audit_newproc(struct proc *); void audit_pfree(struct proc *); void audit_thread_create(kthread_id_t); @@ -534,11 +534,10 @@ void audit_enterprom(int); void audit_exitprom(int); void audit_chdirec(struct vnode *, struct vnode **); void audit_sock(int, struct queue *, struct msgb *, int); -void audit_free(void); -int audit_start(unsigned int, unsigned int, int, klwp_t *); +int audit_start(unsigned int, unsigned int, uint32_t, int, klwp_t *); void audit_finish(unsigned int, unsigned int, int, union rval *); int audit_async_start(label_t *, au_event_t, int); -void audit_async_finish(caddr_t *, au_event_t, au_emod_t); +void audit_async_finish(caddr_t *, au_event_t, au_emod_t, timestruc_t *); void audit_async_discard_backend(void *); void audit_async_done(caddr_t *, int); void audit_async_drop(caddr_t *, int); @@ -548,6 +547,35 @@ void audit_async_drop(caddr_t *, int); typedef struct au_kcontext au_kcontext_t; #endif +/* Zone audit context setup routine */ +void au_zone_setup(void); + +/* + * c2audit module states + */ +#define C2AUDIT_DISABLED 0 /* c2audit module excluded in /etc/system */ +#define C2AUDIT_UNLOADED 1 /* c2audit module not loaded */ +#define C2AUDIT_LOADED 2 /* c2audit module loaded */ + +uint32_t audit_getstate(void); +int au_zone_getstate(const au_kcontext_t *); + +/* The audit mask defining in which case is auditing enabled */ +#define AU_AUDIT_MASK (AUC_AUDITING | AUC_NOSPACE) + +/* + * Get the given zone audit status. zcontext != NULL serves + * as a protection when c2audit module is not loaded. + */ +#define AU_ZONE_AUDITING(zcontext) \ + (audit_active == C2AUDIT_LOADED && \ + ((AU_AUDIT_MASK) & au_zone_getstate((zcontext)))) + +/* + * Get auditing status + */ +#define AU_AUDITING() (audit_getstate()) + int audit_success(au_kcontext_t *, struct t_audit_data *, int, cred_t *); int auditme(au_kcontext_t *, struct t_audit_data *, au_state_t); void audit_fixpath(struct audit_path *, int); diff --git a/usr/src/uts/common/c2/audit_event.c b/usr/src/uts/common/c2/audit_event.c index ed1d8c8f76..3ac61782c2 100644 --- a/usr/src/uts/common/c2/audit_event.c +++ b/usr/src/uts/common/c2/audit_event.c @@ -1824,7 +1824,7 @@ aus_close(struct t_audit_data *tad) tad->tad_flag = 0; tad->tad_evmod = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); releasef(fd); return; } @@ -3956,7 +3956,7 @@ auf_recvmsg( /* don't want to audit every recvmsg attempt */ tad->tad_flag = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); releasef(fd); return; } @@ -4002,7 +4002,7 @@ auf_recvmsg( /* don't want to audit every recvmsg attempt */ tad->tad_flag = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); return; } /* @@ -4158,7 +4158,7 @@ auf_recvfrom( /* don't want to audit every recvfrom attempt */ tad->tad_flag = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); releasef(fd); return; } @@ -4203,7 +4203,7 @@ auf_recvfrom( /* don't want to audit every recvfrom attempt */ tad->tad_flag = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); releasef(fd); return; } @@ -4348,7 +4348,7 @@ auf_sendmsg(struct t_audit_data *tad, int error, rval_t *rval) /* don't want to audit every sendmsg attempt */ tad->tad_flag = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); return; } @@ -4394,7 +4394,7 @@ auf_sendmsg(struct t_audit_data *tad, int error, rval_t *rval) /* don't want to audit every sendmsg attempt */ tad->tad_flag = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); return; } /* @@ -4544,7 +4544,7 @@ auf_sendto(struct t_audit_data *tad, int error, rval_t *rval) /* don't want to audit every sendto attempt */ tad->tad_flag = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); releasef(fd); return; } @@ -4589,7 +4589,7 @@ auf_sendto(struct t_audit_data *tad, int error, rval_t *rval) /* don't want to audit every sendto attempt */ tad->tad_flag = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); releasef(fd); return; } @@ -5243,7 +5243,7 @@ auf_read(tad, error, rval) /* don't really want to audit every read attempt */ tad->tad_flag = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); releasef(fd); return; } @@ -5300,7 +5300,7 @@ auf_write(tad, error, rval) /* don't really want to audit every write attempt */ tad->tad_flag = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); releasef(fd); return; } @@ -5349,7 +5349,7 @@ auf_recv(tad, error, rval) /* Turn off audit record generation here. */ tad->tad_flag = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); return; } @@ -5359,7 +5359,7 @@ auf_recv(tad, error, rval) /* Turn off audit record generation here. */ tad->tad_flag = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); return; } @@ -5375,7 +5375,7 @@ auf_recv(tad, error, rval) /* don't really want to audit every recv call */ tad->tad_flag = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); return; } @@ -5418,7 +5418,7 @@ auf_recv(tad, error, rval) /* don't really want to audit every recv call */ tad->tad_flag = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); return; @@ -5485,7 +5485,7 @@ auf_send(tad, error, rval) /* Turn off audit record generation here. */ tad->tad_flag = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); return; } @@ -5495,7 +5495,7 @@ auf_send(tad, error, rval) /* Turn off audit record generation here. */ tad->tad_flag = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); return; } @@ -5511,7 +5511,7 @@ auf_send(tad, error, rval) /* don't really want to audit every send call */ tad->tad_flag = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); return; } @@ -5553,7 +5553,7 @@ auf_send(tad, error, rval) /* don't really want to audit every send call */ tad->tad_flag = 0; /* free any residual audit data */ - au_close(kctx, &(u_ad), 0, 0, 0); + au_close(kctx, &(u_ad), 0, 0, 0, NULL); return; diff --git a/usr/src/uts/common/c2/audit_io.c b/usr/src/uts/common/c2/audit_io.c index c062ca204e..4d6cc3f7c3 100644 --- a/usr/src/uts/common/c2/audit_io.c +++ b/usr/src/uts/common/c2/audit_io.c @@ -21,7 +21,7 @@ /* * Routines for writing audit records. * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -102,7 +102,7 @@ au_write(caddr_t *d, token_t *m) */ void au_close(au_kcontext_t *kctx, caddr_t *d, int flag, au_event_t e_type, - au_emod_t e_mod) + au_emod_t e_mod, timestruc_t *e_time) { token_t *dchain; /* au_membuf chain which is the tokens */ t_audit_data_t *tad = U2A(u); @@ -122,10 +122,10 @@ au_close(au_kcontext_t *kctx, caddr_t *d, int flag, au_event_t e_type, */ if ((flag & AU_DONTBLOCK) || ((flag & AU_DEFER) && (tad->tad_scid != 0) && (tad->tad_scid != SYS_exit))) { - au_close_defer(dchain, flag, e_type, e_mod); + au_close_defer(dchain, flag, e_type, e_mod, e_time); return; } - au_close_time(kctx, dchain, flag, e_type, e_mod, NULL); + au_close_time(kctx, dchain, flag, e_type, e_mod, e_time); } /* @@ -134,7 +134,8 @@ au_close(au_kcontext_t *kctx, caddr_t *d, int flag, au_event_t e_type, * syscall end time it will be pulled off. */ void -au_close_defer(token_t *dchain, int flag, au_event_t e_type, au_emod_t e_mod) +au_close_defer(token_t *dchain, int flag, au_event_t e_type, au_emod_t e_mod, + timestruc_t *e_time) { au_defer_info_t *attr; t_audit_data_t *tad = U2A(u); @@ -159,7 +160,10 @@ au_close_defer(token_t *dchain, int flag, au_event_t e_type, au_emod_t e_mod) attr->audi_e_type = e_type; attr->audi_e_mod = e_mod; attr->audi_flag = flag; - gethrestime(&attr->audi_atime); + if (e_time != NULL) + attr->audi_atime = *e_time; + else + gethrestime(&attr->audi_atime); /* * All async events must be queued via softcall to avoid possible @@ -233,6 +237,7 @@ au_close_time(au_kcontext_t *kctx, token_t *dchain, int flag, au_event_t e_type, adr_t hadr; /* handle for header token */ adr_t sadr; /* handle for sequence token */ size_t zone_length; /* length of zonename token */ + uint32_t auditing; ASSERT(dchain != NULL); @@ -242,10 +247,14 @@ au_close_time(au_kcontext_t *kctx, token_t *dchain, int flag, au_event_t e_type, return; } /* if auditing not enabled, then don't generate an audit record */ + ASSERT(U2A(u) != NULL); ASSERT(kctx != NULL); - if ((kctx->auk_auditstate != AUC_AUDITING) && - (kctx->auk_auditstate != AUC_INIT_AUDIT)) { + auditing = (U2A(u)->tad_audit == AUC_UNSET) + ? kctx->auk_auditstate + : U2A(u)->tad_audit; + + if (auditing & ~(AUC_AUDITING | AUC_INIT_AUDIT)) { /* * at system boot, neither is set yet we want to generate * an audit record. @@ -460,7 +469,9 @@ audit_sync_block(au_kcontext_t *kctx) * Loop while we are at the high watermark. */ do { - if ((kctx->auk_auditstate != AUC_AUDITING) || + if (((U2A(u)->tad_audit != AUC_UNSET) + ? (U2A(u)->tad_audit != AUC_AUDITING) + : (kctx->auk_auditstate != AUC_AUDITING)) || (kctx->auk_policy & AUDIT_CNT)) { /* just count # of dropped audit records */ @@ -815,13 +826,14 @@ audit_async_start(label_t *jb, au_event_t event, int sorf) * work can be done in a safe context. */ void -audit_async_finish(caddr_t *ad, au_event_t aid, au_emod_t amod) +audit_async_finish(caddr_t *ad, au_event_t aid, au_emod_t amod, + timestruc_t *e_time) { au_kcontext_t *kctx; kctx = GET_KCTX_GZ; - au_close(kctx, ad, AU_DONTBLOCK | AU_OK, aid, PAD_NONATTR|amod); + au_close(kctx, ad, AU_DONTBLOCK | AU_OK, aid, PAD_NONATTR|amod, e_time); } /* diff --git a/usr/src/uts/common/c2/audit_kernel.h b/usr/src/uts/common/c2/audit_kernel.h index df6c2910eb..21d648ae83 100644 --- a/usr/src/uts/common/c2/audit_kernel.h +++ b/usr/src/uts/common/c2/audit_kernel.h @@ -208,6 +208,7 @@ struct t_audit_data { int tad_ctrl; /* audit control/status flags */ void *tad_errjmp; /* error longjmp (audit record aborted) */ int tad_flag; /* to audit or not to audit */ + uint32_t tad_audit; /* auditing enabled/disabled */ struct audit_path *tad_aupath; /* captured at vfs_lookup */ struct audit_path *tad_atpath; /* openat prefix, path of fd */ struct vnode *tad_vn; /* saved inode from vfs_lookup */ @@ -338,8 +339,6 @@ extern zone_key_t au_zone_key; */ extern int audit_policy; extern int audit_active; -extern int audit_load; -extern int au_auditstate; extern struct audit_queue au_queue; extern struct p_audit_data *pad0; @@ -352,6 +351,17 @@ void au_pathhold(struct audit_path *); void au_pathrele(struct audit_path *); struct audit_path *au_pathdup(const struct audit_path *, int, int); +void au_pad_init(void); + +int auditctl(int cmd, caddr_t data, int length); +int auditdoor(int fd); +int getauid(caddr_t); +int setauid(caddr_t); +int getaudit(caddr_t); +int getaudit_addr(caddr_t, int); +int setaudit(caddr_t); +int setaudit_addr(caddr_t, int); + /* * Macros to hide asynchronous, non-blocking audit record start and finish * processing. @@ -373,8 +383,9 @@ struct audit_path *au_pathdup(const struct audit_path *, int, int); } \ } -#define AUDIT_ASYNC_FINISH(rp, audit_event, event_modifier) \ - audit_async_finish((caddr_t *)&(rp), audit_event, event_modifier); +#define AUDIT_ASYNC_FINISH(rp, audit_event, event_modifier, event_time) \ + audit_async_finish((caddr_t *)&(rp), audit_event, event_modifier, \ + event_time); #ifdef _KERNEL diff --git a/usr/src/uts/common/c2/audit_mem.c b/usr/src/uts/common/c2/audit_mem.c index 7e88f2dd5e..9782324d6f 100644 --- a/usr/src/uts/common/c2/audit_mem.c +++ b/usr/src/uts/common/c2/audit_mem.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/param.h> #include <sys/types.h> #include <sys/kmem.h> @@ -36,8 +33,6 @@ #include <c2/audit_kernel.h> #include <c2/audit_record.h> -kmem_cache_t *au_pad_cache; - static kmem_cache_t *au_buf_cache; /* @@ -162,7 +157,7 @@ au_append_buf(const char *data, int len, au_buff_t *buf) buf = buf->next_buf; new_len = (uint_t)(buf->len + len) > AU_BUFSIZE ? - AU_BUFSIZE - buf->len : len; + AU_BUFSIZE - buf->len : len; bcopy(data, (buf->buf + buf->len), (uint_t)new_len); buf->len += (uchar_t)new_len; len -= new_len; @@ -182,33 +177,9 @@ au_append_buf(const char *data, int len, au_buff_t *buf) return (0); } -/*ARGSUSED1*/ -static int -au_pad_const(void *vpad, void *priv, int flags) -{ - p_audit_data_t *pad = vpad; - - mutex_init(&pad->pad_lock, NULL, MUTEX_DEFAULT, NULL); - - return (0); -} - -/*ARGSUSED1*/ -static void -au_pad_destr(void *vpad, void *priv) -{ - p_audit_data_t *pad = vpad; - - mutex_destroy(&pad->pad_lock); -} - void au_mem_init() { au_buf_cache = kmem_cache_create("audit_buffer", - sizeof (au_buff_t), 0, NULL, NULL, NULL, NULL, NULL, 0); - - au_pad_cache = kmem_cache_create("audit_proc", - sizeof (p_audit_data_t), 0, au_pad_const, au_pad_destr, - NULL, NULL, NULL, 0); + sizeof (au_buff_t), 0, NULL, NULL, NULL, NULL, NULL, 0); } diff --git a/usr/src/uts/common/c2/audit_path.c b/usr/src/uts/common/c2/audit_path.c index ec0f3ce5de..cf51d2c3b6 100644 --- a/usr/src/uts/common/c2/audit_path.c +++ b/usr/src/uts/common/c2/audit_path.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 1991-2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * @(#)audit_path.c 2.7 92/02/16 SMI; SunOS CMW * @(#)audit_path.c 4.2.1.2 91/05/08 SMI; BSM Module @@ -56,66 +53,6 @@ #include <sys/sysmacros.h> #include <sys/atomic.h> -/* - * allocate a new auditpath - * newsect = increment sections count, - * charincr = change in strings storage - */ -struct audit_path * -au_pathdup(const struct audit_path *oldapp, int newsect, int charincr) -{ - struct audit_path *newapp; - int i, alloc_size, oldlen; - char *oldcp, *newcp; - - newsect = (newsect != 0); - oldcp = oldapp->audp_sect[0]; - oldlen = (oldapp->audp_sect[oldapp->audp_cnt] - oldcp); - alloc_size = sizeof (struct audit_path) + - (oldapp->audp_cnt + newsect) * sizeof (char *) + - oldlen + charincr; - - newapp = kmem_alloc(alloc_size, KM_SLEEP); - newapp->audp_ref = 1; - newapp->audp_size = alloc_size; - - newapp->audp_cnt = oldapp->audp_cnt + newsect; - newcp = (char *)(&newapp->audp_sect[newapp->audp_cnt + 1]); - for (i = 0; i <= oldapp->audp_cnt; i++) { - newapp->audp_sect[i] = newcp + - (oldapp->audp_sect[i] - oldcp); - } - /* - * if this is a new section, set its end - * if this is an extended section, reset its end - */ - newapp->audp_sect[newapp->audp_cnt] = newcp + oldlen + charincr; - /* copy all of the old strings */ - bcopy(oldcp, newcp, oldlen); - - return (newapp); -} - -/* - * increment audit path reference count - */ -void -au_pathhold(struct audit_path *app) -{ - atomic_add_32(&app->audp_ref, 1); -} - -/* - * decrement audit path reference count - */ -void -au_pathrele(struct audit_path *app) -{ - if (atomic_add_32_nv(&app->audp_ref, -1) > 0) - return; - kmem_free(app, app->audp_size); -} - int au_token_size(m) diff --git a/usr/src/uts/common/c2/audit_record.h b/usr/src/uts/common/c2/audit_record.h index b41ac34a88..f8818c4b63 100644 --- a/usr/src/uts/common/c2/audit_record.h +++ b/usr/src/uts/common/c2/audit_record.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -301,8 +301,9 @@ token_t *au_to_label(bslabel_t *); token_t *au_to_privset(const char *, const priv_set_t *, char, int); void au_uwrite(); -void au_close(au_kcontext_t *, caddr_t *, int, au_event_t, au_emod_t); -void au_close_defer(token_t *, int, au_event_t, au_emod_t); +void au_close(au_kcontext_t *, caddr_t *, int, au_event_t, au_emod_t, + timestruc_t *); +void au_close_defer(token_t *, int, au_event_t, au_emod_t, timestruc_t *); void au_close_time(au_kcontext_t *, token_t *, int, au_event_t, au_emod_t, timestruc_t *); void au_free_rec(au_buff_t *); diff --git a/usr/src/uts/common/c2/audit_start.c b/usr/src/uts/common/c2/audit_start.c index 7f9471c1ff..f0e0adb0c4 100644 --- a/usr/src/uts/common/c2/audit_start.c +++ b/usr/src/uts/common/c2/audit_start.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -50,87 +50,43 @@ extern uint_t num_syscall; /* size of audit_s2e table */ extern kmutex_t pidlock; /* proc table lock */ -int audit_load = 0; /* set from /etc/system */ +/* + * Obsolete and ignored - Historically, the 'set c2audit:audit_load=1' entry + * in /etc/system enabled auditing. The No Reboot Audit project does not + * use this entry. However, to prevent the system from printing warning + * messages, the audit_load entry is being left in /etc/system. It will be + * removed when there is a small chance that the entry is used on currently + * running systems. + */ +int audit_load = 0; -struct p_audit_data *pad0; -struct t_audit_data *tad0; +kmutex_t module_lock; /* audit_module_state lock */ /* * Das Boot. Initialize first process. Also generate an audit record indicating * that the system has been booted. */ void -audit_init() +audit_init_module() { - kthread_t *au_thread; token_t *rp = NULL; label_t jb; - struct audit_path apempty; - auditinfo_addr_t *ainfo; - if (audit_load == 0) { - audit_active = 0; - au_auditstate = AUC_DISABLED; + /* + * Solaris Auditing module is being loaded -> change the state. The lock + * is here to prevent memory leaks caused by multiple initializations. + */ + mutex_enter(&module_lock); + if (audit_active != C2AUDIT_UNLOADED) { + mutex_exit(&module_lock); return; -#ifdef DEBUG - } else if (audit_load == 2) { - debug_enter((char *)NULL); -#endif } - - audit_active = 1; - set_all_proc_sys(); /* set pre- and post-syscall flags */ + audit_active = C2AUDIT_LOADED; + mutex_exit(&module_lock); /* initialize memory allocators */ au_mem_init(); - au_zone_setup(); - - /* inital thread structure */ - tad0 = kmem_zalloc(sizeof (struct t_audit_data), KM_SLEEP); - - /* initial process structure */ - pad0 = kmem_cache_alloc(au_pad_cache, KM_SLEEP); - bzero(&pad0->pad_data, sizeof (pad0->pad_data)); - - T2A(curthread) = tad0; - P2A(curproc) = pad0; - - /* - * The kernel allocates a bunch of threads make sure they have - * a valid tad - */ - - mutex_enter(&pidlock); - - au_thread = curthread; - do { - if (T2A(au_thread) == NULL) { - T2A(au_thread) = tad0; - } - au_thread = au_thread->t_next; - } while (au_thread != curthread); - - tad0->tad_ad = NULL; - mutex_exit(&pidlock); - - /* - * Initialize audit context in our cred (kcred). - * No copy-on-write needed here because it's so early in init. - */ - ainfo = crgetauinfo_modifiable(kcred); - ASSERT(ainfo != NULL); - bzero(ainfo, sizeof (auditinfo_addr_t)); - ainfo->ai_auid = AU_NOAUDITID; - - /* fabricate an empty audit_path to extend */ - apempty.audp_cnt = 0; - apempty.audp_sect[0] = (char *)(&apempty.audp_sect[1]); - pad0->pad_root = au_pathdup(&apempty, 1, 2); - bcopy("/", pad0->pad_root->audp_sect[0], 2); - au_pathhold(pad0->pad_root); - pad0->pad_cwd = pad0->pad_root; - /* * setup environment for asynchronous auditing. We can't use * audit_async_start() here since it assumes the audit system @@ -150,82 +106,8 @@ audit_init() /* generate a system-booted audit record */ au_write((caddr_t *)&rp, au_to_text("booting kernel")); - - audit_async_finish((caddr_t *)&rp, AUE_SYSTEMBOOT, NULL); -} - -void -audit_free() -{ -} - -/* - * Check for any pending changes to the audit context for the given proc. - * p_crlock and pad_lock for the process are acquired here. Caller is - * responsible for assuring the process doesn't go away. If context is - * updated, the specified cralloc'ed cred will be used, otherwise it's freed. - * If no cred is given, it will be cralloc'ed here and caller assures that - * it is safe to allocate memory. - */ -void -audit_update_context(proc_t *p, cred_t *ncr) -{ - struct p_audit_data *pad; - cred_t *newcred = ncr; - - pad = P2A(p); - if (pad == NULL) { - if (newcred != NULL) - crfree(newcred); - return; - } - - /* If a mask update is pending, take care of it. */ - if (pad->pad_flags & PAD_SETMASK) { - auditinfo_addr_t *ainfo; - - if (newcred == NULL) - newcred = cralloc(); - - mutex_enter(&pad->pad_lock); - /* the condition may have been handled by the time we lock */ - if (pad->pad_flags & PAD_SETMASK) { - ainfo = crgetauinfo_modifiable(newcred); - if (ainfo == NULL) { - mutex_enter(&pad->pad_lock); - crfree(newcred); - return; - } - - mutex_enter(&p->p_crlock); - crcopy_to(p->p_cred, newcred); - p->p_cred = newcred; - - ainfo->ai_mask = pad->pad_newmask; - - /* Unlock and cleanup. */ - mutex_exit(&p->p_crlock); - pad->pad_flags &= ~PAD_SETMASK; - - /* - * For curproc, assure that our thread points to right - * cred, so CRED() will be correct. Otherwise, no need - * to broadcast changes (via set_proc_pre_sys), since - * t_pre_sys is ALWAYS on when audit is enabled... due - * to syscall auditing. - */ - if (p == curproc) - crset(p, newcred); - else - crfree(newcred); - } else { - crfree(newcred); - } - mutex_exit(&pad->pad_lock); - } else { - if (newcred != NULL) - crfree(newcred); - } + audit_async_finish((caddr_t *)&rp, AUE_SYSTEMBOOT, NULL, + &(p0.p_user.u_start)); } @@ -241,6 +123,7 @@ int audit_start( unsigned type, unsigned scid, + uint32_t audit_state, int error, klwp_t *lwp) { @@ -250,6 +133,9 @@ audit_start( tad = U2A(u); ASSERT(tad != NULL); + /* Remember the audit state in the cache */ + tad->tad_audit = audit_state; + if (error) { tad->tad_ctrl = 0; tad->tad_flag = 0; @@ -309,8 +195,7 @@ audit_start( * if auditing not enabled, then don't generate an audit record * and don't count it. */ - if ((kctx->auk_auditstate != AUC_AUDITING && - kctx->auk_auditstate != AUC_INIT_AUDIT)) { + if (audit_state & ~(AUC_AUDITING | AUC_INIT_AUDIT)) { /* * we assume that audit_finish will always be called. */ @@ -323,7 +208,7 @@ audit_start( * space left to hold audit records. We decide here if records * should be dropped (but counted). */ - if (kctx->auk_auditstate == AUC_NOSPACE) { + if (audit_state == AUC_NOSPACE) { if ((kctx->auk_policy & AUDIT_CNT) || (kctx->auk_policy & AUDIT_SCNT)) { /* assume that audit_finish will always be called. */ @@ -389,6 +274,7 @@ audit_finish( tad->tad_event = 0; tad->tad_evmod = 0; tad->tad_ctrl = 0; + tad->tad_audit = AUC_UNSET; ASSERT(tad->tad_aupath == NULL); return; } @@ -479,7 +365,8 @@ audit_finish( } /* Close up everything */ - au_close(kctx, &(u_ad), flag, tad->tad_event, tad->tad_evmod); + au_close(kctx, &(u_ad), flag, tad->tad_event, tad->tad_evmod, + NULL); } ASSERT(u_ad == NULL); @@ -505,6 +392,7 @@ audit_finish( tad->tad_event = 0; tad->tad_evmod = 0; tad->tad_ctrl = 0; + tad->tad_audit = AUC_UNSET; } int diff --git a/usr/src/uts/common/c2/audit_syscalls.c b/usr/src/uts/common/c2/audit_syscalls.c index 9cd0e6b403..fc58881e99 100644 --- a/usr/src/uts/common/c2/audit_syscalls.c +++ b/usr/src/uts/common/c2/audit_syscalls.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -28,7 +28,6 @@ * */ - #include <sys/param.h> #include <sys/systm.h> #include <sys/user.h> @@ -60,83 +59,37 @@ #include <c2/audit_kernel.h> #include <c2/audit_record.h> -#define CLEAR_VAL -1 - #define HEADER_SIZE64 1; #define HEADER_SIZE32 0; #define AU_MIN_FILE_SZ 0x80000 /* minumum audit file size */ #define AUDIT_REC_SIZE 0x8000 /* maximum user audit record size */ -extern kmutex_t pidlock; - -extern pri_t minclsyspri; /* priority for taskq */ +extern pri_t minclsyspri; /* priority for taskq */ -extern int audit_load; /* defined in audit_start.c */ - -int au_auditstate = AUC_UNSET; /* global audit state */ -int audit_policy; /* global audit policies in force */ static clock_t au_resid = 15; /* wait .15 sec before droping a rec */ -static int getauid(caddr_t); -static int setauid(caddr_t); -static int getaudit(caddr_t); -static int getaudit_addr(caddr_t, int); -static int setaudit(caddr_t); -static int setaudit_addr(caddr_t, int); -static int auditdoor(int); -static int auditctl(int, caddr_t, int); -static int audit_modsysent(char *, int, int (*)()); static void au_output_thread(); + /* * This is the loadable module wrapper. */ #include <sys/modctl.h> -#include "sys/syscall.h" - -static struct sysent auditsysent = { - 6, - 0, - _auditsys -}; /* * Module linkage information for the kernel. */ -extern struct mod_ops mod_syscallops; - -static struct modlsys modlsys = { - &mod_syscallops, "C2 system call", &auditsysent +static struct modlmisc modlmisc = { + &mod_miscops, "Solaris Auditing (C2)" }; static struct modlinkage modlinkage = { - MODREV_1, (void *)&modlsys, 0 + MODREV_1, (void *)&modlmisc, 0 }; int _init() { - int retval; - - if (audit_load == 0) - return (-1); - - /* - * We are going to do an ugly thing here. - * Because auditsys is already defined as a regular - * syscall we have to change the definition for syscall - * auditsys. Basically or in the SE_LOADABLE flag for - * auditsys. We no have a static loadable syscall. Also - * create an rw_lock. - */ - - if ((audit_modsysent("c2audit", SE_LOADABLE|SE_NOUNLOAD, - _auditsys)) == -1) - return (-1); - - if ((retval = mod_install(&modlinkage)) != 0) - return (retval); - - return (0); + return (mod_install(&modlinkage)); } int @@ -152,358 +105,6 @@ _info(struct modinfo *modinfop) } /* - * when auditing is updated to allow enable/disable without - * reboot (and when the audit stubs are removed) *most* of these - * calls should return an error when auditing is off -- some - * for local zones only. - */ - -int -_auditsys(struct auditcalls *uap, rval_t *rvp) -{ - int result = 0; - - switch (uap->code) { - case BSM_GETAUID: - result = getauid((caddr_t)uap->a1); - break; - case BSM_SETAUID: - result = setauid((caddr_t)uap->a1); - break; - case BSM_GETAUDIT: - result = getaudit((caddr_t)uap->a1); - break; - case BSM_GETAUDIT_ADDR: - - result = getaudit_addr((caddr_t)uap->a1, (int)uap->a2); - break; - case BSM_SETAUDIT: - result = setaudit((caddr_t)uap->a1); - break; - case BSM_SETAUDIT_ADDR: - result = setaudit_addr((caddr_t)uap->a1, (int)uap->a2); - break; - case BSM_AUDIT: - result = audit((caddr_t)uap->a1, (int)uap->a2); - break; - case BSM_AUDITDOOR: - result = auditdoor((int)uap->a1); - break; - case BSM_AUDITCTL: - result = auditctl((int)uap->a1, (caddr_t)uap->a2, (int)uap->a3); - break; - default: - result = EINVAL; - } - rvp->r_vals = result; - return (result); -} - -/* - * Return the audit user ID for the current process. Currently only - * the privileged processes may see the audit id. That may change. - * If copyout is unsucessful return EFAULT. - */ -static int -getauid(caddr_t auid_p) -{ - const auditinfo_addr_t *ainfo; - - if (secpolicy_audit_getattr(CRED()) != 0) - return (EPERM); - - ainfo = crgetauinfo(CRED()); - if (ainfo == NULL) - return (EINVAL); - - if (copyout(&ainfo->ai_auid, auid_p, sizeof (au_id_t))) - return (EFAULT); - - return (0); -} - -/* - * Set the audit userid, for a process. This can only be changed by - * privileged processes. The audit userid is inherited across forks & execs. - * Passed in is a pointer to the au_id_t; if copyin unsuccessful return EFAULT. - */ -static int -setauid(caddr_t auid_p) -{ - proc_t *p; - au_id_t auid; - cred_t *newcred; - auditinfo_addr_t *auinfo; - - if (secpolicy_audit_config(CRED()) != 0) - return (EPERM); - - if (copyin(auid_p, &auid, sizeof (au_id_t))) { - return (EFAULT); - } - - newcred = cralloc(); - if ((auinfo = crgetauinfo_modifiable(newcred)) == NULL) { - crfree(newcred); - return (EINVAL); - } - - /* grab p_crlock and switch to new cred */ - p = curproc; - mutex_enter(&p->p_crlock); - crcopy_to(p->p_cred, newcred); - p->p_cred = newcred; - - auinfo->ai_auid = auid; /* update the auid */ - - /* unlock and broadcast the cred changes */ - mutex_exit(&p->p_crlock); - crset(p, newcred); - - return (0); -} - -/* - * Get the audit state information from the current process. - * Return EFAULT if copyout fails. - */ -static int -getaudit(caddr_t info_p) -{ - STRUCT_DECL(auditinfo, info); - const auditinfo_addr_t *ainfo; - model_t model; - - if (secpolicy_audit_getattr(CRED()) != 0) - return (EPERM); - - model = get_udatamodel(); - STRUCT_INIT(info, model); - - ainfo = crgetauinfo(CRED()); - if (ainfo == NULL) - return (EINVAL); - - /* trying to read a process with an IPv6 address? */ - if (ainfo->ai_termid.at_type == AU_IPv6) - return (EOVERFLOW); - - STRUCT_FSET(info, ai_auid, ainfo->ai_auid); - STRUCT_FSET(info, ai_mask, ainfo->ai_mask); -#ifdef _LP64 - if (model == DATAMODEL_ILP32) { - dev32_t dev; - /* convert internal 64 bit form to 32 bit version */ - if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) { - return (EOVERFLOW); - } - STRUCT_FSET(info, ai_termid.port, dev); - } else - STRUCT_FSET(info, ai_termid.port, ainfo->ai_termid.at_port); -#else - STRUCT_FSET(info, ai_termid.port, ainfo->ai_termid.at_port); -#endif - STRUCT_FSET(info, ai_termid.machine, ainfo->ai_termid.at_addr[0]); - STRUCT_FSET(info, ai_asid, ainfo->ai_asid); - - if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info))) - return (EFAULT); - - return (0); -} - -/* - * Get the audit state information from the current process. - * Return EFAULT if copyout fails. - */ -static int -getaudit_addr(caddr_t info_p, int len) -{ - STRUCT_DECL(auditinfo_addr, info); - const auditinfo_addr_t *ainfo; - model_t model; - - if (secpolicy_audit_getattr(CRED()) != 0) - return (EPERM); - - model = get_udatamodel(); - STRUCT_INIT(info, model); - - if (len < STRUCT_SIZE(info)) - return (EOVERFLOW); - - ainfo = crgetauinfo(CRED()); - - if (ainfo == NULL) - return (EINVAL); - - STRUCT_FSET(info, ai_auid, ainfo->ai_auid); - STRUCT_FSET(info, ai_mask, ainfo->ai_mask); -#ifdef _LP64 - if (model == DATAMODEL_ILP32) { - dev32_t dev; - /* convert internal 64 bit form to 32 bit version */ - if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) { - return (EOVERFLOW); - } - STRUCT_FSET(info, ai_termid.at_port, dev); - } else - STRUCT_FSET(info, ai_termid.at_port, ainfo->ai_termid.at_port); -#else - STRUCT_FSET(info, ai_termid.at_port, ainfo->ai_termid.at_port); -#endif - STRUCT_FSET(info, ai_termid.at_type, ainfo->ai_termid.at_type); - STRUCT_FSET(info, ai_termid.at_addr[0], ainfo->ai_termid.at_addr[0]); - STRUCT_FSET(info, ai_termid.at_addr[1], ainfo->ai_termid.at_addr[1]); - STRUCT_FSET(info, ai_termid.at_addr[2], ainfo->ai_termid.at_addr[2]); - STRUCT_FSET(info, ai_termid.at_addr[3], ainfo->ai_termid.at_addr[3]); - STRUCT_FSET(info, ai_asid, ainfo->ai_asid); - - if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info))) - return (EFAULT); - - return (0); -} - -/* - * Set the audit state information for the current process. - * Return EFAULT if copyout fails. - */ -static int -setaudit(caddr_t info_p) -{ - STRUCT_DECL(auditinfo, info); - proc_t *p; - cred_t *newcred; - model_t model; - auditinfo_addr_t *ainfo; - - if (secpolicy_audit_config(CRED()) != 0) - return (EPERM); - - model = get_udatamodel(); - STRUCT_INIT(info, model); - - if (copyin(info_p, STRUCT_BUF(info), STRUCT_SIZE(info))) - return (EFAULT); - - newcred = cralloc(); - if ((ainfo = crgetauinfo_modifiable(newcred)) == NULL) { - crfree(newcred); - return (EINVAL); - } - - /* grab p_crlock and switch to new cred */ - p = curproc; - mutex_enter(&p->p_crlock); - crcopy_to(p->p_cred, newcred); - p->p_cred = newcred; - - /* Set audit mask, id, termid and session id as specified */ - ainfo->ai_auid = STRUCT_FGET(info, ai_auid); -#ifdef _LP64 - /* only convert to 64 bit if coming from a 32 bit binary */ - if (model == DATAMODEL_ILP32) - ainfo->ai_termid.at_port = - DEVEXPL(STRUCT_FGET(info, ai_termid.port)); - else - ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.port); -#else - ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.port); -#endif - ainfo->ai_termid.at_type = AU_IPv4; - ainfo->ai_termid.at_addr[0] = STRUCT_FGET(info, ai_termid.machine); - ainfo->ai_asid = STRUCT_FGET(info, ai_asid); - ainfo->ai_mask = STRUCT_FGET(info, ai_mask); - - /* unlock and broadcast the cred changes */ - mutex_exit(&p->p_crlock); - crset(p, newcred); - - return (0); -} - -/* - * Set the audit state information for the current process. - * Return EFAULT if copyin fails. - */ -static int -setaudit_addr(caddr_t info_p, int len) -{ - STRUCT_DECL(auditinfo_addr, info); - proc_t *p; - cred_t *newcred; - model_t model; - int i; - int type; - auditinfo_addr_t *ainfo; - - if (secpolicy_audit_config(CRED()) != 0) - return (EPERM); - - model = get_udatamodel(); - STRUCT_INIT(info, model); - - if (len < STRUCT_SIZE(info)) - return (EOVERFLOW); - - if (copyin(info_p, STRUCT_BUF(info), STRUCT_SIZE(info))) - return (EFAULT); - - type = STRUCT_FGET(info, ai_termid.at_type); - if ((type != AU_IPv4) && (type != AU_IPv6)) - return (EINVAL); - - newcred = cralloc(); - if ((ainfo = crgetauinfo_modifiable(newcred)) == NULL) { - crfree(newcred); - return (EINVAL); - } - - /* grab p_crlock and switch to new cred */ - p = curproc; - mutex_enter(&p->p_crlock); - crcopy_to(p->p_cred, newcred); - p->p_cred = newcred; - - /* Set audit mask, id, termid and session id as specified */ - ainfo->ai_auid = STRUCT_FGET(info, ai_auid); - ainfo->ai_mask = STRUCT_FGET(info, ai_mask); -#ifdef _LP64 - /* only convert to 64 bit if coming from a 32 bit binary */ - if (model == DATAMODEL_ILP32) - ainfo->ai_termid.at_port = - DEVEXPL(STRUCT_FGET(info, ai_termid.at_port)); - else - ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.at_port); -#else - ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.at_port); -#endif - ainfo->ai_termid.at_type = type; - bzero(&ainfo->ai_termid.at_addr[0], sizeof (ainfo->ai_termid.at_addr)); - for (i = 0; i < (type/sizeof (int)); i++) - ainfo->ai_termid.at_addr[i] = - STRUCT_FGET(info, ai_termid.at_addr[i]); - - if (ainfo->ai_termid.at_type == AU_IPv6 && - IN6_IS_ADDR_V4MAPPED(((in6_addr_t *)ainfo->ai_termid.at_addr))) { - ainfo->ai_termid.at_type = AU_IPv4; - ainfo->ai_termid.at_addr[0] = ainfo->ai_termid.at_addr[3]; - ainfo->ai_termid.at_addr[1] = 0; - ainfo->ai_termid.at_addr[2] = 0; - ainfo->ai_termid.at_addr[3] = 0; - } - - ainfo->ai_asid = STRUCT_FGET(info, ai_asid); - - /* unlock and broadcast the cred changes */ - mutex_exit(&p->p_crlock); - crset(p, newcred); - - return (0); -} - -/* * The audit system call. Trust what the user has sent down and save it * away in the audit file. User passes a complete audit record and its * length. We will fill in the time stamp, check the header and the length @@ -528,10 +129,12 @@ audit(caddr_t record, int length) int host_len; size_t zlen; au_kcontext_t *kctx = GET_KCTX_PZ; + uint32_t auditing; /* if auditing not enabled, then don't generate an audit record */ - if (kctx->auk_auditstate != AUC_AUDITING && - kctx->auk_auditstate != AUC_INIT_AUDIT) + auditing = (U2A(u)->tad_audit != AUC_UNSET) ? + U2A(u)->tad_audit : kctx->auk_auditstate; + if (auditing & ~(AUC_AUDITING | AUC_INIT_AUDIT)) return (0); /* Only privileged processes can audit */ @@ -713,19 +316,6 @@ audit(caddr_t record, int length) return (0); } -static void -audit_dont_stop(void *kctx) -{ - - if ((((au_kcontext_t *)kctx)->auk_valid != AUK_VALID) || - (((au_kcontext_t *)kctx)->auk_auditstate == AUC_NOAUDIT)) - return; - - mutex_enter(&(((au_kcontext_t *)kctx)->auk_queue.lock)); - cv_broadcast(&(((au_kcontext_t *)kctx)->auk_queue.write_cv)); - mutex_exit(&(((au_kcontext_t *)kctx)->auk_queue.lock)); -} - /* * auditdoor starts a kernel thread to generate output from the audit * queue. The thread terminates when it detects auditing being turned @@ -735,7 +325,7 @@ audit_dont_stop(void *kctx) * for insuring that multiple copies are not running. */ -static int +int auditdoor(int fd) { struct file *fp; @@ -797,6 +387,19 @@ auditdoor(int fd) return (0); } +static void +audit_dont_stop(void *kctx) +{ + + if ((((au_kcontext_t *)kctx)->auk_valid != AUK_VALID) || + (((au_kcontext_t *)kctx)->auk_auditstate == AUC_NOAUDIT)) + return; + + mutex_enter(&(((au_kcontext_t *)kctx)->auk_queue.lock)); + cv_broadcast(&(((au_kcontext_t *)kctx)->auk_queue.write_cv)); + mutex_exit(&(((au_kcontext_t *)kctx)->auk_queue.lock)); +} + /* * au_queue_kick -- wake up the output queue after delay ticks */ @@ -893,1074 +496,3 @@ output_exit: mutex_exit(&(kctx->auk_svc_lock)); } - - -/* - * Get the global policy flag - */ - -static int -getpolicy(caddr_t data) -{ - int policy; - au_kcontext_t *kctx = GET_KCTX_PZ; - - policy = audit_policy | kctx->auk_policy; - - if (copyout(&policy, data, sizeof (int))) - return (EFAULT); - return (0); -} - -/* - * Set the global and local policy flags - * - * The global flags only make sense from the global zone; - * the local flags depend on the AUDIT_PERZONE policy: - * if the perzone policy is set, then policy is set separately - * per zone, else held only in the global zone. - * - * The initial value of a local zone's policy flag is determined - * by the value of the global zone's flags at the time the - * local zone is created. - * - * While auditconfig(1M) allows setting and unsetting policies one bit - * at a time, the mask passed in from auditconfig() is created by a - * syscall to getpolicy and then modified based on the auditconfig() - * cmd line, so the input policy value is used to replace the existing - * policy. - */ - - -static int -setpolicy(caddr_t data) -{ - int policy; - au_kcontext_t *kctx; - - if (copyin(data, &policy, sizeof (int))) - return (EFAULT); - - kctx = GET_KCTX_NGZ; - - if (INGLOBALZONE(curproc)) { - if (policy & ~(AUDIT_GLOBAL | AUDIT_LOCAL)) - return (EINVAL); - - audit_policy = policy & AUDIT_GLOBAL; - } else { - if (!(audit_policy & AUDIT_PERZONE)) - return (EINVAL); - - if (policy & ~AUDIT_LOCAL) /* global bits are a no-no */ - return (EINVAL); - } - kctx->auk_policy = policy & AUDIT_LOCAL; - - /* - * auk_current_vp is NULL before auditd starts (or during early - * auditd starup) or if auditd is halted; in either case, - * notification of a policy change is not needed, since auditd - * reads policy as it comes up. The error return from au_doormsg() - * is ignored to avoid a race condition -- for example if auditd - * segv's, the audit state may be "auditing" but the door may - * be closed. Returning an error if the door is open makes it - * impossible for Greenline to restart auditd. - */ - if (kctx->auk_current_vp != NULL) - (void) au_doormsg(kctx, AU_DBUF_POLICY, &policy); - - /* - * Wake up anyone who might have blocked on full audit - * partitions. audit daemons need to set AUDIT_FULL when no - * space so we can tell if we should start dropping records. - */ - mutex_enter(&(kctx->auk_queue.lock)); - - if ((policy & (AUDIT_CNT | AUDIT_SCNT) && - (kctx->auk_queue.cnt >= kctx->auk_queue.hiwater))) - cv_broadcast(&(kctx->auk_queue.write_cv)); - - mutex_exit(&(kctx->auk_queue.lock)); - - return (0); -} - -static int -getkmask(caddr_t data) -{ - au_kcontext_t *kctx; - - kctx = GET_KCTX_PZ; - - if (copyout(&kctx->auk_info.ai_mask, data, sizeof (au_mask_t))) - return (EFAULT); - return (0); -} - -static int -setkmask(caddr_t data) -{ - au_mask_t mask; - au_kcontext_t *kctx; - - if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc)) - return (EINVAL); - - kctx = GET_KCTX_NGZ; - - if (copyin(data, &mask, sizeof (au_mask_t))) - return (EFAULT); - - kctx->auk_info.ai_mask = mask; - return (0); -} - -static int -getkaudit(caddr_t info_p, int len) -{ - STRUCT_DECL(auditinfo_addr, info); - model_t model; - au_kcontext_t *kctx = GET_KCTX_PZ; - - model = get_udatamodel(); - STRUCT_INIT(info, model); - - if (len < STRUCT_SIZE(info)) - return (EOVERFLOW); - - STRUCT_FSET(info, ai_auid, kctx->auk_info.ai_auid); - STRUCT_FSET(info, ai_mask, kctx->auk_info.ai_mask); -#ifdef _LP64 - if (model == DATAMODEL_ILP32) { - dev32_t dev; - /* convert internal 64 bit form to 32 bit version */ - if (cmpldev(&dev, kctx->auk_info.ai_termid.at_port) == 0) { - return (EOVERFLOW); - } - STRUCT_FSET(info, ai_termid.at_port, dev); - } else { - STRUCT_FSET(info, ai_termid.at_port, - kctx->auk_info.ai_termid.at_port); - } -#else - STRUCT_FSET(info, ai_termid.at_port, - kctx->auk_info.ai_termid.at_port); -#endif - STRUCT_FSET(info, ai_termid.at_type, - kctx->auk_info.ai_termid.at_type); - STRUCT_FSET(info, ai_termid.at_addr[0], - kctx->auk_info.ai_termid.at_addr[0]); - STRUCT_FSET(info, ai_termid.at_addr[1], - kctx->auk_info.ai_termid.at_addr[1]); - STRUCT_FSET(info, ai_termid.at_addr[2], - kctx->auk_info.ai_termid.at_addr[2]); - STRUCT_FSET(info, ai_termid.at_addr[3], - kctx->auk_info.ai_termid.at_addr[3]); - STRUCT_FSET(info, ai_asid, kctx->auk_info.ai_asid); - - if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info))) - return (EFAULT); - - return (0); -} - -/* - * the host address for AUDIT_PERZONE == 0 is that of the global - * zone and for local zones it is of the current zone. - */ - -static int -setkaudit(caddr_t info_p, int len) -{ - STRUCT_DECL(auditinfo_addr, info); - model_t model; - au_kcontext_t *kctx; - - if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc)) - return (EINVAL); - - kctx = GET_KCTX_NGZ; - - model = get_udatamodel(); - STRUCT_INIT(info, model); - - if (len < STRUCT_SIZE(info)) - return (EOVERFLOW); - - if (copyin(info_p, STRUCT_BUF(info), STRUCT_SIZE(info))) - return (EFAULT); - - if ((STRUCT_FGET(info, ai_termid.at_type) != AU_IPv4) && - (STRUCT_FGET(info, ai_termid.at_type) != AU_IPv6)) - return (EINVAL); - - /* Set audit mask, termid and session id as specified */ - kctx->auk_info.ai_auid = STRUCT_FGET(info, ai_auid); - kctx->auk_info.ai_mask = STRUCT_FGET(info, ai_mask); -#ifdef _LP64 - /* only convert to 64 bit if coming from a 32 bit binary */ - if (model == DATAMODEL_ILP32) - kctx->auk_info.ai_termid.at_port = - DEVEXPL(STRUCT_FGET(info, ai_termid.at_port)); - else - kctx->auk_info.ai_termid.at_port = - STRUCT_FGET(info, ai_termid.at_port); -#else - kctx->auk_info.ai_termid.at_port = STRUCT_FGET(info, ai_termid.at_port); -#endif - kctx->auk_info.ai_termid.at_type = STRUCT_FGET(info, ai_termid.at_type); - bzero(&kctx->auk_info.ai_termid.at_addr[0], - sizeof (kctx->auk_info.ai_termid.at_addr)); - kctx->auk_info.ai_termid.at_addr[0] = - STRUCT_FGET(info, ai_termid.at_addr[0]); - kctx->auk_info.ai_termid.at_addr[1] = - STRUCT_FGET(info, ai_termid.at_addr[1]); - kctx->auk_info.ai_termid.at_addr[2] = - STRUCT_FGET(info, ai_termid.at_addr[2]); - kctx->auk_info.ai_termid.at_addr[3] = - STRUCT_FGET(info, ai_termid.at_addr[3]); - kctx->auk_info.ai_asid = STRUCT_FGET(info, ai_asid); - - if (kctx->auk_info.ai_termid.at_type == AU_IPv6 && - IN6_IS_ADDR_V4MAPPED( - ((in6_addr_t *)kctx->auk_info.ai_termid.at_addr))) { - kctx->auk_info.ai_termid.at_type = AU_IPv4; - kctx->auk_info.ai_termid.at_addr[0] = - kctx->auk_info.ai_termid.at_addr[3]; - kctx->auk_info.ai_termid.at_addr[1] = 0; - kctx->auk_info.ai_termid.at_addr[2] = 0; - kctx->auk_info.ai_termid.at_addr[3] = 0; - } - if (kctx->auk_info.ai_termid.at_type == AU_IPv6) - kctx->auk_hostaddr_valid = IN6_IS_ADDR_UNSPECIFIED( - (in6_addr_t *)kctx->auk_info.ai_termid.at_addr) ? 0 : 1; - else - kctx->auk_hostaddr_valid = - (kctx->auk_info.ai_termid.at_addr[0] == - htonl(INADDR_ANY)) ? 0 : 1; - - return (0); -} - -static int -getqctrl(caddr_t data) -{ - au_kcontext_t *kctx = GET_KCTX_PZ; - STRUCT_DECL(au_qctrl, qctrl); - STRUCT_INIT(qctrl, get_udatamodel()); - - mutex_enter(&(kctx->auk_queue.lock)); - STRUCT_FSET(qctrl, aq_hiwater, kctx->auk_queue.hiwater); - STRUCT_FSET(qctrl, aq_lowater, kctx->auk_queue.lowater); - STRUCT_FSET(qctrl, aq_bufsz, kctx->auk_queue.bufsz); - STRUCT_FSET(qctrl, aq_delay, kctx->auk_queue.delay); - mutex_exit(&(kctx->auk_queue.lock)); - - if (copyout(STRUCT_BUF(qctrl), data, STRUCT_SIZE(qctrl))) - return (EFAULT); - - return (0); -} - -static int -setqctrl(caddr_t data) -{ - au_kcontext_t *kctx; - struct au_qctrl qctrl_tmp; - STRUCT_DECL(au_qctrl, qctrl); - STRUCT_INIT(qctrl, get_udatamodel()); - - if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc)) - return (EINVAL); - kctx = GET_KCTX_NGZ; - - if (copyin(data, STRUCT_BUF(qctrl), STRUCT_SIZE(qctrl))) - return (EFAULT); - - qctrl_tmp.aq_hiwater = (size_t)STRUCT_FGET(qctrl, aq_hiwater); - qctrl_tmp.aq_lowater = (size_t)STRUCT_FGET(qctrl, aq_lowater); - qctrl_tmp.aq_bufsz = (size_t)STRUCT_FGET(qctrl, aq_bufsz); - qctrl_tmp.aq_delay = (clock_t)STRUCT_FGET(qctrl, aq_delay); - - /* enforce sane values */ - - if (qctrl_tmp.aq_hiwater <= qctrl_tmp.aq_lowater) - return (EINVAL); - - if (qctrl_tmp.aq_hiwater < AQ_LOWATER) - return (EINVAL); - - if (qctrl_tmp.aq_hiwater > AQ_MAXHIGH) - return (EINVAL); - - if (qctrl_tmp.aq_bufsz < AQ_BUFSZ) - return (EINVAL); - - if (qctrl_tmp.aq_bufsz > AQ_MAXBUFSZ) - return (EINVAL); - - if (qctrl_tmp.aq_delay == 0) - return (EINVAL); - - if (qctrl_tmp.aq_delay > AQ_MAXDELAY) - return (EINVAL); - - /* update everything at once so things are consistant */ - mutex_enter(&(kctx->auk_queue.lock)); - kctx->auk_queue.hiwater = qctrl_tmp.aq_hiwater; - kctx->auk_queue.lowater = qctrl_tmp.aq_lowater; - kctx->auk_queue.bufsz = qctrl_tmp.aq_bufsz; - kctx->auk_queue.delay = qctrl_tmp.aq_delay; - - if (kctx->auk_queue.rd_block && - kctx->auk_queue.cnt > kctx->auk_queue.lowater) - cv_broadcast(&(kctx->auk_queue.read_cv)); - - if (kctx->auk_queue.wt_block && - kctx->auk_queue.cnt < kctx->auk_queue.hiwater) - cv_broadcast(&(kctx->auk_queue.write_cv)); - - mutex_exit(&(kctx->auk_queue.lock)); - - return (0); -} - -static int -getcwd(caddr_t data, int length) -{ - struct p_audit_data *pad; - struct audit_path *app; - int pathlen; - - pad = P2A(curproc); - ASSERT(pad != NULL); - - mutex_enter(&(pad->pad_lock)); - app = pad->pad_cwd; - au_pathhold(app); - mutex_exit(&(pad->pad_lock)); - - pathlen = app->audp_sect[1] - app->audp_sect[0]; - if (pathlen > length) { - au_pathrele(app); - return (E2BIG); - } - - if (copyout(app->audp_sect[0], data, pathlen)) { - au_pathrele(app); - return (EFAULT); - } - - au_pathrele(app); - return (0); -} - -static int -getcar(caddr_t data, int length) -{ - struct p_audit_data *pad; - struct audit_path *app; - int pathlen; - - pad = P2A(curproc); - ASSERT(pad != NULL); - - mutex_enter(&(pad->pad_lock)); - app = pad->pad_root; - au_pathhold(app); - mutex_exit(&(pad->pad_lock)); - - pathlen = app->audp_sect[1] - app->audp_sect[0]; - if (pathlen > length) { - au_pathrele(app); - return (E2BIG); - } - - if (copyout(app->audp_sect[0], data, pathlen)) { - au_pathrele(app); - return (EFAULT); - } - - au_pathrele(app); - return (0); -} - -static int -getstat(caddr_t data) -{ - au_kcontext_t *kctx = GET_KCTX_PZ; - - membar_consumer(); - - if (copyout((caddr_t)&(kctx->auk_statistics), data, sizeof (au_stat_t))) - return (EFAULT); - return (0); -} - - -static int -setstat(caddr_t data) -{ - au_kcontext_t *kctx = GET_KCTX_PZ; - au_stat_t au_stat; - - if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc)) - return (EINVAL); - - if (copyin(data, &au_stat, sizeof (au_stat_t))) - return (EFAULT); - - if (au_stat.as_generated == CLEAR_VAL) - kctx->auk_statistics.as_generated = 0; - if (au_stat.as_nonattrib == CLEAR_VAL) - kctx->auk_statistics.as_nonattrib = 0; - if (au_stat.as_kernel == CLEAR_VAL) - kctx->auk_statistics.as_kernel = 0; - if (au_stat.as_audit == CLEAR_VAL) - kctx->auk_statistics.as_audit = 0; - if (au_stat.as_auditctl == CLEAR_VAL) - kctx->auk_statistics.as_auditctl = 0; - if (au_stat.as_enqueue == CLEAR_VAL) - kctx->auk_statistics.as_enqueue = 0; - if (au_stat.as_written == CLEAR_VAL) - kctx->auk_statistics.as_written = 0; - if (au_stat.as_wblocked == CLEAR_VAL) - kctx->auk_statistics.as_wblocked = 0; - if (au_stat.as_rblocked == CLEAR_VAL) - kctx->auk_statistics.as_rblocked = 0; - if (au_stat.as_dropped == CLEAR_VAL) - kctx->auk_statistics.as_dropped = 0; - if (au_stat.as_totalsize == CLEAR_VAL) - kctx->auk_statistics.as_totalsize = 0; - - membar_producer(); - - return (0); - -} - -static int -setumask(caddr_t data) -{ - STRUCT_DECL(auditinfo, user_info); - struct proc *p; - const auditinfo_addr_t *ainfo; - model_t model; - - /* setumask not applicable in non-global zones without perzone policy */ - if (!(audit_policy & AUDIT_PERZONE) && (!INGLOBALZONE(curproc))) - return (EINVAL); - - model = get_udatamodel(); - STRUCT_INIT(user_info, model); - - if (copyin(data, STRUCT_BUF(user_info), STRUCT_SIZE(user_info))) - return (EFAULT); - - mutex_enter(&pidlock); /* lock the process queue against updates */ - for (p = practive; p != NULL; p = p->p_next) { - cred_t *cr; - - /* if in non-global zone only modify processes in same zone */ - if (!HASZONEACCESS(curproc, p->p_zone->zone_id)) - continue; - - mutex_enter(&p->p_lock); /* so process doesn't go away */ - - /* skip system processes and ones being created or going away */ - if (p->p_stat == SIDL || p->p_stat == SZOMB || - (p->p_flag & (SSYS | SEXITING | SEXITLWPS))) { - mutex_exit(&p->p_lock); - continue; - } - - mutex_enter(&p->p_crlock); - crhold(cr = p->p_cred); - mutex_exit(&p->p_crlock); - ainfo = crgetauinfo(cr); - if (ainfo == NULL) { - mutex_exit(&p->p_lock); - crfree(cr); - continue; - } - - if (ainfo->ai_auid == STRUCT_FGET(user_info, ai_auid)) { - au_mask_t mask; - int err; - - /* - * Here's a process which matches the specified auid. - * If its mask doesn't already match the new mask, - * save the new mask in the pad, to be picked up - * next syscall. - */ - mask = STRUCT_FGET(user_info, ai_mask); - err = bcmp(&mask, &ainfo->ai_mask, sizeof (au_mask_t)); - crfree(cr); - if (err != 0) { - struct p_audit_data *pad = P2A(p); - ASSERT(pad != NULL); - - mutex_enter(&(pad->pad_lock)); - pad->pad_flags |= PAD_SETMASK; - pad->pad_newmask = mask; - mutex_exit(&(pad->pad_lock)); - - /* - * No need to call set_proc_pre_sys(), since - * t_pre_sys is ALWAYS on when audit is - * enabled...due to syscall auditing. - */ - } - } else { - crfree(cr); - } - mutex_exit(&p->p_lock); - } - mutex_exit(&pidlock); - - return (0); -} - -static int -setsmask(caddr_t data) -{ - STRUCT_DECL(auditinfo, user_info); - struct proc *p; - const auditinfo_addr_t *ainfo; - model_t model; - - /* setsmask not applicable in non-global zones without perzone policy */ - if (!(audit_policy & AUDIT_PERZONE) && (!INGLOBALZONE(curproc))) - return (EINVAL); - - model = get_udatamodel(); - STRUCT_INIT(user_info, model); - - if (copyin(data, STRUCT_BUF(user_info), STRUCT_SIZE(user_info))) - return (EFAULT); - - mutex_enter(&pidlock); /* lock the process queue against updates */ - for (p = practive; p != NULL; p = p->p_next) { - cred_t *cr; - - /* if in non-global zone only modify processes in same zone */ - if (!HASZONEACCESS(curproc, p->p_zone->zone_id)) - continue; - - mutex_enter(&p->p_lock); /* so process doesn't go away */ - - /* skip system processes and ones being created or going away */ - if (p->p_stat == SIDL || p->p_stat == SZOMB || - (p->p_flag & (SSYS | SEXITING | SEXITLWPS))) { - mutex_exit(&p->p_lock); - continue; - } - - mutex_enter(&p->p_crlock); - crhold(cr = p->p_cred); - mutex_exit(&p->p_crlock); - ainfo = crgetauinfo(cr); - if (ainfo == NULL) { - mutex_exit(&p->p_lock); - crfree(cr); - continue; - } - - if (ainfo->ai_asid == STRUCT_FGET(user_info, ai_asid)) { - au_mask_t mask; - int err; - - /* - * Here's a process which matches the specified asid. - * If its mask doesn't already match the new mask, - * save the new mask in the pad, to be picked up - * next syscall. - */ - mask = STRUCT_FGET(user_info, ai_mask); - err = bcmp(&mask, &ainfo->ai_mask, sizeof (au_mask_t)); - crfree(cr); - if (err != 0) { - struct p_audit_data *pad = P2A(p); - ASSERT(pad != NULL); - - mutex_enter(&(pad->pad_lock)); - pad->pad_flags |= PAD_SETMASK; - pad->pad_newmask = mask; - mutex_exit(&(pad->pad_lock)); - - /* - * No need to call set_proc_pre_sys(), since - * t_pre_sys is ALWAYS on when audit is - * enabled...due to syscall auditing. - */ - } - } else { - crfree(cr); - } - mutex_exit(&p->p_lock); - } - mutex_exit(&pidlock); - - return (0); -} - -/* - * Get the current audit state of the system - */ -static int -getcond(caddr_t data) -{ - au_kcontext_t *kctx; - - if (au_auditstate == AUC_DISABLED) - if (copyout(&au_auditstate, data, sizeof (int))) - return (EFAULT); - - kctx = GET_KCTX_PZ; - - if (copyout(&(kctx->auk_auditstate), data, sizeof (int))) - return (EFAULT); - - return (0); -} - -/* - * Set the current audit state of the system to on (AUC_AUDITING) or - * off (AUC_NOAUDIT). - */ -/* ARGSUSED */ -static int -setcond(caddr_t data) -{ - int auditstate; - au_kcontext_t *kctx; - - if (!(audit_policy & AUDIT_PERZONE) && (!INGLOBALZONE(curproc))) - return (EINVAL); - - kctx = GET_KCTX_NGZ; - - if (copyin(data, &auditstate, sizeof (int))) - return (EFAULT); - - switch (auditstate) { - case AUC_AUDITING: /* Turn auditing on */ - kctx->auk_auditstate = AUC_AUDITING; - au_auditstate = AUC_ENABLED; - break; - - case AUC_NOAUDIT: /* Turn auditing off */ - if (kctx->auk_auditstate == AUC_NOAUDIT) - break; - kctx->auk_auditstate = AUC_NOAUDIT; - - /* clear out the audit queue */ - - mutex_enter(&(kctx->auk_queue.lock)); - if (kctx->auk_queue.wt_block) - cv_broadcast(&(kctx->auk_queue.write_cv)); - - /* unblock au_output_thread */ - cv_broadcast(&(kctx->auk_queue.read_cv)); - - mutex_exit(&(kctx->auk_queue.lock)); - break; - - default: - return (EINVAL); - } - - return (0); -} - -static int -getclass(caddr_t data) -{ - au_evclass_map_t event; - au_kcontext_t *kctx = GET_KCTX_PZ; - - if (copyin(data, &event, sizeof (au_evclass_map_t))) - return (EFAULT); - - if (event.ec_number > MAX_KEVENTS) - return (EINVAL); - - event.ec_class = kctx->auk_ets[event.ec_number]; - - if (copyout(&event, data, sizeof (au_evclass_map_t))) - return (EFAULT); - - return (0); -} - -static int -setclass(caddr_t data) -{ - au_evclass_map_t event; - au_kcontext_t *kctx; - - if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc)) - return (EINVAL); - - kctx = GET_KCTX_NGZ; - - if (copyin(data, &event, sizeof (au_evclass_map_t))) - return (EFAULT); - - if (event.ec_number > MAX_KEVENTS) - return (EINVAL); - - kctx->auk_ets[event.ec_number] = event.ec_class; - - return (0); -} - -static int -getpinfo(caddr_t data) -{ - STRUCT_DECL(auditpinfo, apinfo); - proc_t *proc; - const auditinfo_addr_t *ainfo; - model_t model; - cred_t *cr, *newcred; - - model = get_udatamodel(); - STRUCT_INIT(apinfo, model); - - if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo))) - return (EFAULT); - - newcred = cralloc(); - - mutex_enter(&pidlock); - if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) { - mutex_exit(&pidlock); - crfree(newcred); - return (ESRCH); /* no such process */ - } - mutex_enter(&proc->p_lock); /* so process doesn't go away */ - mutex_exit(&pidlock); - - audit_update_context(proc, newcred); /* make sure it's up-to-date */ - - mutex_enter(&proc->p_crlock); - crhold(cr = proc->p_cred); - mutex_exit(&proc->p_crlock); - mutex_exit(&proc->p_lock); - - ainfo = crgetauinfo(cr); - if (ainfo == NULL) { - crfree(cr); - return (EINVAL); - } - - /* designated process has an ipv6 address? */ - if (ainfo->ai_termid.at_type == AU_IPv6) { - crfree(cr); - return (EOVERFLOW); - } - - STRUCT_FSET(apinfo, ap_auid, ainfo->ai_auid); - STRUCT_FSET(apinfo, ap_asid, ainfo->ai_asid); -#ifdef _LP64 - if (model == DATAMODEL_ILP32) { - dev32_t dev; - /* convert internal 64 bit form to 32 bit version */ - if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) { - crfree(cr); - return (EOVERFLOW); - } - STRUCT_FSET(apinfo, ap_termid.port, dev); - } else - STRUCT_FSET(apinfo, ap_termid.port, ainfo->ai_termid.at_port); -#else - STRUCT_FSET(apinfo, ap_termid.port, ainfo->ai_termid.at_port); -#endif - STRUCT_FSET(apinfo, ap_termid.machine, ainfo->ai_termid.at_addr[0]); - STRUCT_FSET(apinfo, ap_mask, ainfo->ai_mask); - - crfree(cr); - - if (copyout(STRUCT_BUF(apinfo), data, STRUCT_SIZE(apinfo))) - return (EFAULT); - - return (0); -} - -static int -getpinfo_addr(caddr_t data, int len) -{ - STRUCT_DECL(auditpinfo_addr, apinfo); - proc_t *proc; - const auditinfo_addr_t *ainfo; - model_t model; - cred_t *cr, *newcred; - - model = get_udatamodel(); - STRUCT_INIT(apinfo, model); - - if (len < STRUCT_SIZE(apinfo)) - return (EOVERFLOW); - - if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo))) - return (EFAULT); - - newcred = cralloc(); - - mutex_enter(&pidlock); - if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) { - mutex_exit(&pidlock); - crfree(newcred); - return (ESRCH); - } - mutex_enter(&proc->p_lock); /* so process doesn't go away */ - mutex_exit(&pidlock); - - audit_update_context(proc, newcred); /* make sure it's up-to-date */ - - mutex_enter(&proc->p_crlock); - crhold(cr = proc->p_cred); - mutex_exit(&proc->p_crlock); - mutex_exit(&proc->p_lock); - - ainfo = crgetauinfo(cr); - if (ainfo == NULL) { - crfree(cr); - return (EINVAL); - } - - STRUCT_FSET(apinfo, ap_auid, ainfo->ai_auid); - STRUCT_FSET(apinfo, ap_asid, ainfo->ai_asid); -#ifdef _LP64 - if (model == DATAMODEL_ILP32) { - dev32_t dev; - /* convert internal 64 bit form to 32 bit version */ - if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) { - crfree(cr); - return (EOVERFLOW); - } - STRUCT_FSET(apinfo, ap_termid.at_port, dev); - } else - STRUCT_FSET(apinfo, ap_termid.at_port, - ainfo->ai_termid.at_port); -#else - STRUCT_FSET(apinfo, ap_termid.at_port, ainfo->ai_termid.at_port); -#endif - STRUCT_FSET(apinfo, ap_termid.at_type, ainfo->ai_termid.at_type); - STRUCT_FSET(apinfo, ap_termid.at_addr[0], ainfo->ai_termid.at_addr[0]); - STRUCT_FSET(apinfo, ap_termid.at_addr[1], ainfo->ai_termid.at_addr[1]); - STRUCT_FSET(apinfo, ap_termid.at_addr[2], ainfo->ai_termid.at_addr[2]); - STRUCT_FSET(apinfo, ap_termid.at_addr[3], ainfo->ai_termid.at_addr[3]); - STRUCT_FSET(apinfo, ap_mask, ainfo->ai_mask); - - crfree(cr); - - if (copyout(STRUCT_BUF(apinfo), data, STRUCT_SIZE(apinfo))) - return (EFAULT); - - return (0); -} - -static int -setpmask(caddr_t data) -{ - STRUCT_DECL(auditpinfo, apinfo); - proc_t *proc; - cred_t *newcred; - auditinfo_addr_t *ainfo; - struct p_audit_data *pad; - - model_t model; - - model = get_udatamodel(); - STRUCT_INIT(apinfo, model); - - if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo))) - return (EFAULT); - - mutex_enter(&pidlock); - if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) { - mutex_exit(&pidlock); - return (ESRCH); - } - mutex_enter(&proc->p_lock); /* so process doesn't go away */ - mutex_exit(&pidlock); - - newcred = cralloc(); - if ((ainfo = crgetauinfo_modifiable(newcred)) == NULL) { - mutex_exit(&proc->p_lock); - crfree(newcred); - return (EINVAL); - } - - mutex_enter(&proc->p_crlock); - crcopy_to(proc->p_cred, newcred); - proc->p_cred = newcred; - - ainfo->ai_mask = STRUCT_FGET(apinfo, ap_mask); - - /* - * Unlock. No need to broadcast changes via set_proc_pre_sys(), - * since t_pre_sys is ALWAYS on when audit is enabled... due to - * syscall auditing. - */ - crfree(newcred); - mutex_exit(&proc->p_crlock); - - /* Reset flag for any previous pending mask change; this supercedes */ - pad = P2A(proc); - ASSERT(pad != NULL); - mutex_enter(&(pad->pad_lock)); - pad->pad_flags &= ~PAD_SETMASK; - mutex_exit(&(pad->pad_lock)); - - mutex_exit(&proc->p_lock); - - return (0); -} - -/* - * The out of control system call - * This is audit kitchen sink aka auditadm, aka auditon - */ -static int -auditctl( - int cmd, - caddr_t data, - int length) -{ - int result; - - if (!audit_active) - return (EINVAL); - - switch (cmd) { - case A_GETCOND: - case A_GETCAR: - case A_GETCLASS: - case A_GETCWD: - case A_GETKAUDIT: - case A_GETKMASK: - case A_GETPINFO: - case A_GETPINFO_ADDR: - case A_GETPOLICY: - case A_GETQCTRL: - case A_GETSTAT: - if (secpolicy_audit_getattr(CRED()) != 0) - return (EPERM); - break; - default: - if (secpolicy_audit_config(CRED()) != 0) - return (EPERM); - break; - } - - switch (cmd) { - case A_GETPOLICY: - result = getpolicy(data); - break; - case A_SETPOLICY: - result = setpolicy(data); - break; - case A_GETKMASK: - result = getkmask(data); - break; - case A_SETKMASK: - result = setkmask(data); - break; - case A_GETKAUDIT: - result = getkaudit(data, length); - break; - case A_SETKAUDIT: - result = setkaudit(data, length); - break; - case A_GETQCTRL: - result = getqctrl(data); - break; - case A_SETQCTRL: - result = setqctrl(data); - break; - case A_GETCWD: - result = getcwd(data, length); - break; - case A_GETCAR: - result = getcar(data, length); - break; - case A_GETSTAT: - result = getstat(data); - break; - case A_SETSTAT: - result = setstat(data); - break; - case A_SETUMASK: - result = setumask(data); - break; - case A_SETSMASK: - result = setsmask(data); - break; - case A_GETCOND: - result = getcond(data); - break; - case A_SETCOND: - result = setcond(data); - break; - case A_GETCLASS: - result = getclass(data); - break; - case A_SETCLASS: - result = setclass(data); - break; - case A_GETPINFO: - result = getpinfo(data); - break; - case A_GETPINFO_ADDR: - result = getpinfo_addr(data, length); - break; - case A_SETPMASK: - result = setpmask(data); - break; - default: - result = EINVAL; - break; - } - return (result); -} - -static int -audit_modsysent(char *modname, int flags, int (*func)()) -{ - struct sysent *sysp; - int sysnum; - krwlock_t *kl; - - if ((sysnum = mod_getsysnum(modname)) == -1) { - cmn_err(CE_WARN, "system call missing from bind file"); - return (-1); - } - - kl = (krwlock_t *)kobj_zalloc(sizeof (krwlock_t), KM_SLEEP); - - sysp = &sysent[sysnum]; - sysp->sy_narg = auditsysent.sy_narg; -#ifdef _LP64 - sysp->sy_flags = (unsigned short)flags; -#else - sysp->sy_flags = (unsigned char)flags; -#endif - sysp->sy_call = func; - sysp->sy_lock = kl; - -#ifdef _SYSCALL32_IMPL - sysp = &sysent32[sysnum]; - sysp->sy_narg = auditsysent.sy_narg; - sysp->sy_flags = (unsigned short)flags; - sysp->sy_call = func; - sysp->sy_lock = kl; -#endif - - rw_init(sysp->sy_lock, NULL, RW_DEFAULT, NULL); - - return (0); -} diff --git a/usr/src/uts/common/crypto/io/cryptoadm.c b/usr/src/uts/common/crypto/io/cryptoadm.c index 9f7a839f77..bddc6d4778 100644 --- a/usr/src/uts/common/crypto/io/cryptoadm.c +++ b/usr/src/uts/common/crypto/io/cryptoadm.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -558,7 +558,7 @@ out: error = EFAULT; } out2: - if (audit_active) + if (AU_AUDITING()) audit_cryptoadm(CRYPTO_LOAD_DEV_DISABLED, dev_name, entries, count, instance, rv, error); return (error); @@ -636,7 +636,7 @@ out: error = EFAULT; } out2: - if (audit_active) + if (AU_AUDITING()) audit_cryptoadm(CRYPTO_LOAD_SOFT_DISABLED, name, entries, count, 0, rv, error); return (error); @@ -718,7 +718,7 @@ out: error = EFAULT; } out2: - if (audit_active) + if (AU_AUDITING()) audit_cryptoadm(CRYPTO_LOAD_SOFT_CONFIG, name, entries, count, 0, rv, error); return (error); @@ -763,7 +763,7 @@ out: error = EFAULT; } out2: - if (audit_active) + if (AU_AUDITING()) audit_cryptoadm(CRYPTO_UNLOAD_SOFT_MODULE, name, NULL, 0, 0, rv, error); @@ -799,7 +799,7 @@ out: error = EFAULT; out2: - if (audit_active) + if (AU_AUDITING()) audit_cryptoadm(CRYPTO_LOAD_DOOR, NULL, NULL, 0, 0, rv, error); return (error); @@ -882,6 +882,7 @@ static int cryptoadm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c, int *rval) { + uint32_t auditing = AU_AUDITING(); int error; #define ARG ((caddr_t)arg) @@ -932,7 +933,7 @@ cryptoadm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c, * So, this is a no op. We are keeping this ioctl around * to be used for any future threadpool related work. */ - if (audit_active) + if (auditing) audit_cryptoadm(CRYPTO_POOL_CREATE, NULL, NULL, 0, 0, 0, 0); return (0); @@ -945,7 +946,7 @@ cryptoadm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c, == -1) err = EFAULT; } - if (audit_active) + if (auditing) audit_cryptoadm(CRYPTO_POOL_WAIT, NULL, NULL, 0, 0, 0, err); return (err); @@ -955,7 +956,7 @@ cryptoadm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c, int err; err = kcf_svc_do_run(); - if (audit_active) + if (auditing) audit_cryptoadm(CRYPTO_POOL_RUN, NULL, NULL, 0, 0, 0, err); return (err); @@ -969,7 +970,7 @@ cryptoadm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c, int err; err = fips140_actions(dev, ARG, mode, rval, cmd); - if (audit_active) + if (auditing) audit_cryptoadm(CRYPTO_FIPS140_SET, NULL, NULL, 0, 0, 0, err); return (err); diff --git a/usr/src/uts/common/fs/lookup.c b/usr/src/uts/common/fs/lookup.c index 076887fdbc..940b2f17d1 100644 --- a/usr/src/uts/common/fs/lookup.c +++ b/usr/src/uts/common/fs/lookup.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -92,7 +92,7 @@ lookupnameatcred( error = pn_get_buf(fnamep, seg, &lookpn, namebuf, sizeof (namebuf)); if (error == 0) { - if (audit_active) + if (AU_AUDITING()) audit_lookupname(); error = lookuppnatcred(&lookpn, NULL, followlink, dirvpp, compvpp, startvp, cr); @@ -230,6 +230,7 @@ lookuppnvp( vnode_t *zonevp = curproc->p_zone->zone_rootvp; /* zone root */ int must_be_directory = 0; boolean_t retry_with_kcred; + uint32_t auditing = AU_AUDITING(); CPU_STATS_ADDQ(CPU, sys, namei, 1); nlink = 0; @@ -244,7 +245,7 @@ lookuppnvp( pp = &presrvd; } - if (audit_active) + if (auditing) audit_anchorpath(pnp, vp == rootvp); /* @@ -276,7 +277,7 @@ next: * Process the next component of the pathname. */ if (error = pn_getcomponent(pnp, component)) { - if (audit_active) + if (auditing) audit_addcomponent(pnp); goto bad; } @@ -408,7 +409,7 @@ checkforroot: */ if (pn_pathleft(pnp) || dirvpp == NULL || error != ENOENT) goto bad; - if (audit_active) { /* directory access */ + if (auditing) { /* directory access */ if (error = audit_savepath(pnp, vp, error, cr)) goto bad_noaudit; } @@ -466,7 +467,7 @@ checkforroot: */ if (cvp->v_type == VLNK && ((flags & FOLLOW) || pn_pathleft(pnp))) { struct pathname linkpath; - if (audit_active) { + if (auditing) { if (error = audit_pathcomp(pnp, cvp, cr)) goto bad; } @@ -481,7 +482,7 @@ checkforroot: goto bad; } - if (audit_active) + if (auditing) audit_symlink(pnp, &linkpath); if (pn_pathleft(&linkpath) == 0) @@ -505,7 +506,7 @@ checkforroot: vp = rootvp; VN_HOLD(vp); } - if (audit_active) + if (auditing) audit_anchorpath(pnp, vp == rootvp); if (pn_fixslash(pnp)) { flags |= FOLLOW; @@ -578,7 +579,7 @@ checkforroot: * an alias of the last component. */ if (vn_compare(vp, cvp)) { - if (audit_active) + if (auditing) (void) audit_savepath(pnp, cvp, EINVAL, cr); pn_setlast(pnp); @@ -590,14 +591,14 @@ checkforroot: pn_free(pp); return (EINVAL); } - if (audit_active) { + if (auditing) { if (error = audit_pathcomp(pnp, vp, cr)) goto bad; } *dirvpp = vp; } else VN_RELE(vp); - if (audit_active) + if (auditing) (void) audit_savepath(pnp, cvp, 0, cr); if (pnp->pn_path == pnp->pn_buf) (void) pn_set(pnp, "."); @@ -621,7 +622,7 @@ checkforroot: return (0); } - if (audit_active) { + if (auditing) { if (error = audit_pathcomp(pnp, cvp, cr)) goto bad; } @@ -645,7 +646,7 @@ checkforroot: goto next; bad: - if (audit_active) /* reached end of path */ + if (auditing) /* reached end of path */ (void) audit_savepath(pnp, cvp, error, cr); bad_noaudit: /* diff --git a/usr/src/uts/common/fs/sockfs/sockstr.c b/usr/src/uts/common/fs/sockfs/sockstr.c index dc2af07a93..4b08e4aac3 100644 --- a/usr/src/uts/common/fs/sockfs/sockstr.c +++ b/usr/src/uts/common/fs/sockfs/sockstr.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1679,6 +1679,7 @@ strsock_proto(vnode_t *vp, mblk_t *mp, union T_primitives *tpr; struct sonode *so; sotpi_info_t *sti; + uint32_t auditing = AU_AUDITING(); so = VTOSO(vp); sti = SOTOTPI(so); @@ -1788,7 +1789,7 @@ strsock_proto(vnode_t *vp, mblk_t *mp, *allmsgsigs = S_INPUT | S_RDNORM; *pollwakeups = POLLIN | POLLRDNORM; *wakeups = RSLEEP; - if (audit_active) + if (auditing) audit_sock(T_UNITDATA_IND, strvp2wq(vp), mp, 0); return (mp); @@ -2279,7 +2280,7 @@ strsock_proto(vnode_t *vp, mblk_t *mp, return (NULL); } - if (audit_active) + if (auditing) audit_sock(T_CONN_IND, strvp2wq(vp), mp, 0); if (!(so->so_state & SS_ACCEPTCONN)) { zcmn_err(getzoneid(), CE_WARN, diff --git a/usr/src/uts/common/fs/sockfs/socksubr.c b/usr/src/uts/common/fs/sockfs/socksubr.c index 526fdd4937..2a329da653 100644 --- a/usr/src/uts/common/fs/sockfs/socksubr.c +++ b/usr/src/uts/common/fs/sockfs/socksubr.c @@ -62,7 +62,6 @@ #include <sys/socketvar.h> #include <netinet/in.h> #include <sys/un.h> - #include <sys/ucred.h> #include <sys/tiuser.h> @@ -756,7 +755,7 @@ fdbuf_extract(struct fdbuf *fdbuf, void *rights, int rightslen) mutex_exit(&fp->f_tlock); setf(fd, fp); *rp++ = fd; - if (audit_active) + if (AU_AUDITING()) audit_fdrecv(fd, fp); dprint(1, ("fdbuf_extract: [%d] = %d, %p refcnt %d\n", i, fd, (void *)fp, fp->f_count)); @@ -830,7 +829,7 @@ fdbuf_create(void *rights, int rightslen, struct fdbuf **fdbufp) fdbuf->fd_fds[i] = fp; fdbuf->fd_numfd++; releasef(fds[i]); - if (audit_active) + if (AU_AUDITING()) audit_fdsend(fds[i], fp, 0); } *fdbufp = fdbuf; diff --git a/usr/src/uts/common/fs/sockfs/socktpi.c b/usr/src/uts/common/fs/sockfs/socktpi.c index bfbd67ad81..de0293e710 100644 --- a/usr/src/uts/common/fs/sockfs/socktpi.c +++ b/usr/src/uts/common/fs/sockfs/socktpi.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -2591,7 +2591,7 @@ sotpi_connect(struct sonode *so, soisconnecting(so); mutex_exit(&so->so_lock); - if (audit_active) + if (AU_AUDITING()) audit_sock(T_CONN_REQ, strvp2wq(SOTOV(so)), mp, 0); error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0, @@ -3857,7 +3857,7 @@ sosend_dgramcmsg(struct sonode *so, struct sockaddr *name, socklen_t namelen, ASSERT(MBLKL(mp) <= (ssize_t)size); ASSERT(mp->b_wptr <= mp->b_datap->db_lim); - if (audit_active) + if (AU_AUDITING()) audit_sock(T_UNITDATA_REQ, strvp2wq(SOTOV(so)), mp, 0); error = kstrputmsg(SOTOV(so), mp, uiop, len, 0, MSG_BAND, 0); @@ -4135,7 +4135,7 @@ sosend_dgram(struct sonode *so, struct sockaddr *name, socklen_t namelen, ASSERT(mp->b_wptr <= mp->b_datap->db_lim); } - if (audit_active) + if (AU_AUDITING()) audit_sock(T_UNITDATA_REQ, strvp2wq(SOTOV(so)), mp, 0); error = kstrputmsg(SOTOV(so), mp, uiop, len, 0, MSG_BAND, 0); @@ -4657,6 +4657,7 @@ sodgram_direct(struct sonode *so, struct sockaddr *name, boolean_t connected; mblk_t *mpdata = NULL; sotpi_info_t *sti = SOTOTPI(so); + uint32_t auditing = AU_AUDITING(); ASSERT(name != NULL && namelen != 0); ASSERT(!(so->so_mode & SM_CONNREQUIRED)); @@ -4721,7 +4722,7 @@ sodgram_direct(struct sonode *so, struct sockaddr *name, linkb(mp, mpdata); else mp = mpdata; - if (audit_active) + if (auditing) audit_sock(T_UNITDATA_REQ, strvp2wq(SOTOV(so)), mp, 0); udp_wput(udp_wq, mp); @@ -4741,7 +4742,7 @@ sodgram_direct(struct sonode *so, struct sockaddr *name, if (connected) return (strwrite(SOTOV(so), uiop, CRED())); - if (audit_active) + if (auditing) audit_sock(T_UNITDATA_REQ, strvp2wq(SOTOV(so)), mp, 0); error = kstrputmsg(SOTOV(so), mp, uiop, len, 0, MSG_BAND, 0); diff --git a/usr/src/uts/common/fs/vnode.c b/usr/src/uts/common/fs/vnode.c index acdfdb36a1..f1a69479b8 100644 --- a/usr/src/uts/common/fs/vnode.c +++ b/usr/src/uts/common/fs/vnode.c @@ -1295,6 +1295,7 @@ vn_createat( struct vattr vattr; enum symfollow follow; int estale_retry = 0; + uint32_t auditing = AU_AUDITING(); ASSERT((vap->va_mask & (AT_TYPE|AT_MODE)) == (AT_TYPE|AT_MODE)); @@ -1318,7 +1319,7 @@ top: */ if (error = pn_get(pnamep, seg, &pn)) return (error); - if (audit_active) + if (auditing) audit_vncreate_start(); dvp = NULL; *vpp = NULL; @@ -1526,7 +1527,7 @@ top: out: - if (audit_active) + if (auditing) audit_vncreate_finish(*vpp, error); if (in_crit) { nbl_end_crit(vp); @@ -1628,6 +1629,7 @@ vn_renameat(vnode_t *fdvp, char *fname, vnode_t *tdvp, vnode_t *fromvp, *fvp; vnode_t *tovp, *targvp; int estale_retry = 0; + uint32_t auditing = AU_AUDITING(); top: fvp = fromvp = tovp = targvp = NULL; @@ -1651,7 +1653,7 @@ top: * use the lib directory for the rename. */ - if (audit_active) + if (auditing) audit_setfsat_path(1); /* * Lookup to and from directories. @@ -1668,7 +1670,7 @@ top: goto out; } - if (audit_active) + if (auditing) audit_setfsat_path(3); if (error = lookuppnat(&tpn, NULL, NO_FOLLOW, &tovp, &targvp, tdvp)) { goto out; diff --git a/usr/src/uts/common/inet/ip/spdsock.c b/usr/src/uts/common/inet/ip/spdsock.c index 1ff0cff31d..4a9053cddf 100644 --- a/usr/src/uts/common/inet/ip/spdsock.c +++ b/usr/src/uts/common/inet/ip/spdsock.c @@ -590,10 +590,11 @@ spdsock_flush(queue_t *q, ipsec_policy_head_t *iph, ipsec_tun_pol_t *itp, boolean_t active; spdsock_t *ss = (spdsock_t *)q->q_ptr; netstack_t *ns = ss->spdsock_spds->spds_netstack; + uint32_t auditing = AU_AUDITING(); if (iph != ALL_ACTIVE_POLHEADS && iph != ALL_INACTIVE_POLHEADS) { spdsock_flush_one(iph, ns); - if (audit_active) { + if (auditing) { spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr; cred_t *cr; pid_t cpid; @@ -609,7 +610,7 @@ spdsock_flush(queue_t *q, ipsec_policy_head_t *iph, ipsec_tun_pol_t *itp, /* First flush the global policy. */ spdsock_flush_one(active ? ipsec_system_policy(ns) : ipsec_inactive_policy(ns), ns); - if (audit_active) { + if (auditing) { cred_t *cr; pid_t cpid; @@ -619,7 +620,7 @@ spdsock_flush(queue_t *q, ipsec_policy_head_t *iph, ipsec_tun_pol_t *itp, } /* Then flush every tunnel's appropriate one. */ itp_walk(spdsock_flush_node, (void *)active, ns); - if (audit_active) { + if (auditing) { cred_t *cr; pid_t cpid; @@ -1024,11 +1025,12 @@ spdsock_addrule(queue_t *q, ipsec_policy_head_t *iph, mblk_t *mp, boolean_t tunnel_mode, empty_itp, active; uint64_t *index = (itp == NULL) ? NULL : &itp->itp_next_policy_index; spdsock_t *ss = (spdsock_t *)q->q_ptr; - spd_stack_t *spds = ss->spdsock_spds; + spd_stack_t *spds = ss->spdsock_spds; + uint32_t auditing = AU_AUDITING(); if (rule == NULL) { spdsock_diag(q, mp, SPD_DIAGNOSTIC_NO_RULE_EXT); - if (audit_active) { + if (auditing) { spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr; cred_t *cr; pid_t cpid; @@ -1138,7 +1140,7 @@ spdsock_addrule(queue_t *q, ipsec_policy_head_t *iph, mblk_t *mp, ipsec_actvec_free(actp, nact); spd_echo(q, mp); - if (audit_active) { + if (auditing) { spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr; cred_t *cr; pid_t cpid; @@ -1162,7 +1164,7 @@ fail2: mutex_exit(&itp->itp_lock); } spdsock_error(q, mp, error, diag); - if (audit_active) { + if (auditing) { spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr; cred_t *cr; pid_t cpid; @@ -1183,10 +1185,11 @@ spdsock_deleterule(queue_t *q, ipsec_policy_head_t *iph, mblk_t *mp, int err, diag = 0; spdsock_t *ss = (spdsock_t *)q->q_ptr; netstack_t *ns = ss->spdsock_spds->spds_netstack; + uint32_t auditing = AU_AUDITING(); if (rule == NULL) { spdsock_diag(q, mp, SPD_DIAGNOSTIC_NO_RULE_EXT); - if (audit_active) { + if (auditing) { boolean_t active; spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr; cred_t *cr; @@ -1247,7 +1250,7 @@ spdsock_deleterule(queue_t *q, ipsec_policy_head_t *iph, mblk_t *mp, mutex_exit(&itp->itp_lock); } spd_echo(q, mp); - if (audit_active) { + if (auditing) { boolean_t active; spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr; cred_t *cr; @@ -1263,7 +1266,7 @@ fail: if (itp != NULL) mutex_exit(&itp->itp_lock); spdsock_error(q, mp, err, diag); - if (audit_active) { + if (auditing) { boolean_t active; spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr; cred_t *cr; @@ -1296,13 +1299,14 @@ spdsock_flip(queue_t *q, mblk_t *mp, spd_if_t *tunname) ipsec_tun_pol_t *itp; spdsock_t *ss = (spdsock_t *)q->q_ptr; netstack_t *ns = ss->spdsock_spds->spds_netstack; + uint32_t auditing = AU_AUDITING(); if (tunname != NULL) { tname = (char *)tunname->spd_if_name; if (*tname == '\0') { /* can't fail */ ipsec_swap_global_policy(ns); - if (audit_active) { + if (auditing) { boolean_t active; spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr; cred_t *cr; @@ -1314,7 +1318,7 @@ spdsock_flip(queue_t *q, mblk_t *mp, spd_if_t *tunname) NULL, active, 0, cpid); } itp_walk(spdsock_flip_node, NULL, ns); - if (audit_active) { + if (auditing) { boolean_t active; spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr; cred_t *cr; @@ -1330,7 +1334,7 @@ spdsock_flip(queue_t *q, mblk_t *mp, spd_if_t *tunname) if (itp == NULL) { /* Better idea for "tunnel not found"? */ spdsock_error(q, mp, ESRCH, 0); - if (audit_active) { + if (auditing) { boolean_t active; spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr; @@ -1347,7 +1351,7 @@ spdsock_flip(queue_t *q, mblk_t *mp, spd_if_t *tunname) return; } spdsock_flip_node(itp, NULL, ns); - if (audit_active) { + if (auditing) { boolean_t active; spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr; cred_t *cr; @@ -1362,7 +1366,7 @@ spdsock_flip(queue_t *q, mblk_t *mp, spd_if_t *tunname) } } else { ipsec_swap_global_policy(ns); /* can't fail */ - if (audit_active) { + if (auditing) { boolean_t active; spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr; cred_t *cr; @@ -2106,12 +2110,13 @@ spdsock_clone(queue_t *q, mblk_t *mp, spd_if_t *tunname) ipsec_tun_pol_t *itp; spdsock_t *ss = (spdsock_t *)q->q_ptr; netstack_t *ns = ss->spdsock_spds->spds_netstack; + uint32_t auditing = AU_AUDITING(); if (tunname != NULL) { tname = (char *)tunname->spd_if_name; if (*tname == '\0') { error = ipsec_clone_system_policy(ns); - if (audit_active) { + if (auditing) { boolean_t active; spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr; cred_t *cr; @@ -2124,7 +2129,7 @@ spdsock_clone(queue_t *q, mblk_t *mp, spd_if_t *tunname) } if (error == 0) { itp_walk(spdsock_clone_node, &error, ns); - if (audit_active) { + if (auditing) { boolean_t active; spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr; @@ -2143,7 +2148,7 @@ spdsock_clone(queue_t *q, mblk_t *mp, spd_if_t *tunname) itp = get_tunnel_policy(tname, ns); if (itp == NULL) { spdsock_error(q, mp, ENOENT, 0); - if (audit_active) { + if (auditing) { boolean_t active; spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr; @@ -2159,7 +2164,7 @@ spdsock_clone(queue_t *q, mblk_t *mp, spd_if_t *tunname) return; } spdsock_clone_node(itp, &error, NULL); - if (audit_active) { + if (auditing) { boolean_t active; spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr; cred_t *cr; @@ -2174,7 +2179,7 @@ spdsock_clone(queue_t *q, mblk_t *mp, spd_if_t *tunname) } } else { error = ipsec_clone_system_policy(ns); - if (audit_active) { + if (auditing) { boolean_t active; spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr; cred_t *cr; @@ -2769,6 +2774,7 @@ spdsock_updatealg(queue_t *q, mblk_t *mp, spd_ext_t *extv[]) spdsock_t *ss = (spdsock_t *)q->q_ptr; spd_stack_t *spds = ss->spdsock_spds; ipsec_stack_t *ipss = spds->spds_netstack->netstack_ipsec; + uint32_t auditing = AU_AUDITING(); if (!ipsec_loaded(ipss)) { /* @@ -2790,7 +2796,7 @@ spdsock_updatealg(queue_t *q, mblk_t *mp, spd_ext_t *extv[]) spds->spds_mp_algs = mp; spds->spds_algs_pending = B_TRUE; mutex_exit(&spds->spds_alg_lock); - if (audit_active) { + if (auditing) { cred_t *cr; pid_t cpid; @@ -2814,7 +2820,7 @@ spdsock_updatealg(queue_t *q, mblk_t *mp, spd_ext_t *extv[]) spds->spds_netstack); mutex_exit(&spds->spds_alg_lock); spd_echo(q, mp); - if (audit_active) { + if (auditing) { cred_t *cr; pid_t cpid; @@ -2826,7 +2832,7 @@ spdsock_updatealg(queue_t *q, mblk_t *mp, spd_ext_t *extv[]) } else { mutex_exit(&spds->spds_alg_lock); spdsock_diag(q, mp, diag); - if (audit_active) { + if (auditing) { cred_t *cr; pid_t cpid; diff --git a/usr/src/uts/common/inet/kssl/kssl.c b/usr/src/uts/common/inet/kssl/kssl.c index 19699a3990..0b6890fadb 100644 --- a/usr/src/uts/common/inet/kssl/kssl.c +++ b/usr/src/uts/common/inet/kssl/kssl.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -278,6 +278,7 @@ kssl_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c, int *rval) { int error = EINVAL; + uint32_t auditing = AU_AUDITING(); #define ARG ((caddr_t)arg) @@ -310,7 +311,7 @@ kssl_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c, return (EFAULT); } error = kssl_add_entry(kssl_params); - if (audit_active) + if (auditing) audit_kssl(KSSL_ADD_ENTRY, kssl_params, error); off = offsetof(kssl_params_t, kssl_token) + offsetof(kssl_tokinfo_t, ck_rv); @@ -331,7 +332,7 @@ kssl_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c, } error = kssl_delete_entry(&server_addr); - if (audit_active) + if (auditing) audit_kssl(KSSL_DELETE_ENTRY, &server_addr, error); break; } diff --git a/usr/src/uts/common/io/timod.c b/usr/src/uts/common/io/timod.c index 4d9e4eaa6e..41bf9ce7dc 100644 --- a/usr/src/uts/common/io/timod.c +++ b/usr/src/uts/common/io/timod.c @@ -20,7 +20,7 @@ */ /* ONC_PLUS EXTRACT START */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -695,6 +695,7 @@ timodprocessinfo(queue_t *q, struct tim_tim *tp, struct T_info_ack *tia) static int timodrproc(queue_t *q, mblk_t *mp) { + uint32_t auditing = AU_AUDITING(); union T_primitives *pptr; struct tim_tim *tp; struct iocblk *iocbp; @@ -787,7 +788,7 @@ timodrproc(queue_t *q, mblk_t *mp) default: /* ONC_PLUS EXTRACT END */ - if (audit_active) + if (auditing) audit_sock(T_UNITDATA_IND, q, mp, TIMOD_ID); /* ONC_PLUS EXTRACT START */ putnext(q, mp); @@ -969,23 +970,24 @@ timodrproc(queue_t *q, mblk_t *mp) /* ONC_PLUS EXTRACT END */ case T_OPTMGMT_ACK: - tilog("timodrproc: Got T_OPTMGMT_ACK\n", 0); + tilog("timodrproc: Got T_OPTMGMT_ACK\n", 0); - /* Restore db_type - recover() might have change it */ - mp->b_datap->db_type = M_PCPROTO; + /* Restore db_type - recover() might have change it */ + mp->b_datap->db_type = M_PCPROTO; - if (((tp->tim_flags & WAITIOCACK) == 0) || - ((tp->tim_saved_prim != T_SVR4_OPTMGMT_REQ) && - (tp->tim_saved_prim != T_OPTMGMT_REQ))) { - putnext(q, mp); - } else { - ASSERT(tp->tim_iocsave != NULL); - tim_ioctl_send_reply(q, tp->tim_iocsave, mp); - tp->tim_iocsave = NULL; - tp->tim_saved_prim = -1; - tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | - TI_CAP_RECVD | CAP_WANTS_INFO); - } + if (((tp->tim_flags & WAITIOCACK) == 0) || + ((tp->tim_saved_prim != T_SVR4_OPTMGMT_REQ) && + (tp->tim_saved_prim != T_OPTMGMT_REQ))) { + putnext(q, mp); + } else { + ASSERT(tp->tim_iocsave != NULL); + tim_ioctl_send_reply(q, tp->tim_iocsave, mp); + tp->tim_iocsave = NULL; + tp->tim_saved_prim = -1; + tp->tim_flags &= ~(WAITIOCACK | + WAIT_IOCINFOACK | TI_CAP_RECVD | + CAP_WANTS_INFO); + } break; case T_INFO_ACK: { @@ -1109,31 +1111,31 @@ timodrproc(queue_t *q, mblk_t *mp) deficit) { mblk_t *tmp = allocb(expected_ack_size, BPRI_HI); - if (tmp == NULL) { - ASSERT(MBLKSIZE(mp) >= - sizeof (struct T_error_ack)); - - tilog("timodrproc: allocb failed no " - "recovery attempt\n", 0); - - mp->b_rptr = mp->b_datap->db_base; - pptr = (union T_primitives *) - mp->b_rptr; - pptr->error_ack.ERROR_prim = T_INFO_REQ; - pptr->error_ack.TLI_error = TSYSERR; - pptr->error_ack.UNIX_error = EAGAIN; - pptr->error_ack.PRIM_type = T_ERROR_ACK; - mp->b_datap->db_type = M_PCPROTO; - tim_send_ioc_error_ack(q, tp, mp); - break; - } else { - bcopy(mp->b_rptr, tmp->b_rptr, blen); - tmp->b_wptr += blen; - pptr = (union T_primitives *) - tmp->b_rptr; - freemsg(mp); - mp = tmp; - } + if (tmp == NULL) { + ASSERT(MBLKSIZE(mp) >= + sizeof (struct T_error_ack)); + + tilog("timodrproc: allocb failed no " + "recovery attempt\n", 0); + + mp->b_rptr = mp->b_datap->db_base; + pptr = (union T_primitives *) + mp->b_rptr; + pptr->error_ack.ERROR_prim = T_INFO_REQ; + pptr->error_ack.TLI_error = TSYSERR; + pptr->error_ack.UNIX_error = EAGAIN; + pptr->error_ack.PRIM_type = T_ERROR_ACK; + mp->b_datap->db_type = M_PCPROTO; + tim_send_ioc_error_ack(q, tp, mp); + break; + } else { + bcopy(mp->b_rptr, tmp->b_rptr, blen); + tmp->b_wptr += blen; + pptr = (union T_primitives *) + tmp->b_rptr; + freemsg(mp); + mp = tmp; + } } } /* @@ -1218,7 +1220,7 @@ timodrproc(queue_t *q, mblk_t *mp) } } /* ONC_PLUS EXTRACT END */ - if (audit_active) + if (auditing) audit_sock(T_CONN_IND, q, mp, TIMOD_ID); /* ONC_PLUS EXTRACT START */ putnext(q, mp); @@ -1281,16 +1283,16 @@ timodrproc(queue_t *q, mblk_t *mp) case T_ORDREL_IND: - tilog("timodrproc: Got T_ORDREL_IND\n", 0); + tilog("timodrproc: Got T_ORDREL_IND\n", 0); - if (tp->tim_flags & LOCORDREL) { - tp->tim_flags &= ~(LOCORDREL|REMORDREL); - tim_clear_peer(tp); - } else { - tp->tim_flags |= REMORDREL; - } - putnext(q, mp); - break; + if (tp->tim_flags & LOCORDREL) { + tp->tim_flags &= ~(LOCORDREL|REMORDREL); + tim_clear_peer(tp); + } else { + tp->tim_flags |= REMORDREL; + } + putnext(q, mp); + break; case T_EXDATA_IND: case T_DATA_IND: @@ -1430,36 +1432,36 @@ timodrproc(queue_t *q, mblk_t *mp) /* ONC_PLUS EXTRACT START */ case M_IOCNAK: - tilog("timodrproc: Got M_IOCNAK\n", 0); + tilog("timodrproc: Got M_IOCNAK\n", 0); - iocbp = (struct iocblk *)mp->b_rptr; - if (((iocbp->ioc_cmd == TI_GETMYNAME) || - (iocbp->ioc_cmd == TI_GETPEERNAME)) && - ((iocbp->ioc_error == EINVAL) || (iocbp->ioc_error == 0))) { - PI_PROVLOCK(tp->tim_provinfo); - if (iocbp->ioc_cmd == TI_GETMYNAME) { - if (tp->tim_provinfo->tpi_myname == PI_DONTKNOW) - tp->tim_provinfo->tpi_myname = PI_NO; - } else if (iocbp->ioc_cmd == TI_GETPEERNAME) { - if (tp->tim_provinfo->tpi_peername == PI_DONTKNOW) - tp->tim_provinfo->tpi_peername = PI_NO; - } - PI_PROVUNLOCK(tp->tim_provinfo); - /* tim_iocsave may already be overwritten. */ - if ((tp->tim_iocsave != NULL) && - (tp->tim_saved_prim == -1)) { - freemsg(mp); - mp = tp->tim_iocsave; - tp->tim_iocsave = NULL; - tp->tim_flags |= NAMEPROC; - if (ti_doname(WR(q), mp) != DONAME_CONT) { - tp->tim_flags &= ~NAMEPROC; - } - break; - } - } - putnext(q, mp); - break; + iocbp = (struct iocblk *)mp->b_rptr; + if (((iocbp->ioc_cmd == TI_GETMYNAME) || + (iocbp->ioc_cmd == TI_GETPEERNAME)) && + ((iocbp->ioc_error == EINVAL) || (iocbp->ioc_error == 0))) { + PI_PROVLOCK(tp->tim_provinfo); + if (iocbp->ioc_cmd == TI_GETMYNAME) { + if (tp->tim_provinfo->tpi_myname == PI_DONTKNOW) + tp->tim_provinfo->tpi_myname = PI_NO; + } else if (iocbp->ioc_cmd == TI_GETPEERNAME) { + if (tp->tim_provinfo->tpi_peername == PI_DONTKNOW) + tp->tim_provinfo->tpi_peername = PI_NO; + } + PI_PROVUNLOCK(tp->tim_provinfo); + /* tim_iocsave may already be overwritten. */ + if ((tp->tim_iocsave != NULL) && + (tp->tim_saved_prim == -1)) { + freemsg(mp); + mp = tp->tim_iocsave; + tp->tim_iocsave = NULL; + tp->tim_flags |= NAMEPROC; + if (ti_doname(WR(q), mp) != DONAME_CONT) { + tp->tim_flags &= ~NAMEPROC; + } + break; + } + } + putnext(q, mp); + break; /* ONC_PLUS EXTRACT END */ } @@ -1614,6 +1616,7 @@ timodwproc(queue_t *q, mblk_t *mp) { union T_primitives *pptr; struct tim_tim *tp; + uint32_t auditing = AU_AUDITING(); mblk_t *tmp; struct iocblk *iocbp; int error; @@ -1997,7 +2000,7 @@ getname: mp = tmp; } } - if (audit_active) + if (auditing) audit_sock(T_UNITDATA_REQ, q, mp, TIMOD_ID); if (!bcanputnext(q, mp->b_band)) { (void) putbq(q, mp); @@ -2053,12 +2056,12 @@ getname: if (tp->tim_flags & COTS) tp->tim_flags |= CONNWAIT; /* ONC_PLUS EXTRACT END */ - if (audit_active) + if (auditing) audit_sock(T_CONN_REQ, q, mp, TIMOD_ID); /* ONC_PLUS EXTRACT START */ putnext(q, mp); break; - } + } case O_T_CONN_RES: case T_CONN_RES: { diff --git a/usr/src/uts/common/os/audit_core.c b/usr/src/uts/common/os/audit_core.c new file mode 100644 index 0000000000..74fcf3b937 --- /dev/null +++ b/usr/src/uts/common/os/audit_core.c @@ -0,0 +1,439 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/kmem.h> +#include <sys/proc.h> +#include <sys/vnode.h> +#include <sys/file.h> +#include <sys/user.h> +#include <sys/stropts.h> +#include <sys/systm.h> +#include <sys/pathname.h> +#include <sys/debug.h> +#include <sys/cred_impl.h> +#include <sys/zone.h> +#include <sys/modctl.h> +#include <sys/sysconf.h> +#include <c2/audit.h> +#include <c2/audit_kernel.h> +#include <c2/audit_kevents.h> +#include <c2/audit_record.h> + + +struct p_audit_data *pad0; +struct t_audit_data *tad0; + +extern uint_t num_syscall; /* size of audit_s2e table */ +extern kmutex_t pidlock; /* proc table lock */ + + +void +audit_init() +{ + kthread_t *au_thread; + auditinfo_addr_t *ainfo; + struct audit_path apempty; + + /* + * If the c2audit module is explicitely excluded in /etc/system, + * it cannot be loaded later (e.g. using modload). Make a notice + * that the module won't be present and do nothing. + */ + + if (mod_sysctl(SYS_CHECK_EXCLUDE, "c2audit") != 0) { + audit_active = C2AUDIT_DISABLED; + return; + } + + /* c2audit module can be loaded anytime */ + audit_active = C2AUDIT_UNLOADED; + + /* initialize the process audit data (pad) memory allocator */ + au_pad_init(); + + /* initialize the zone audit context */ + au_zone_setup(); + + /* inital thread structure */ + tad0 = kmem_zalloc(sizeof (struct t_audit_data), KM_SLEEP); + + /* initial process structure */ + pad0 = kmem_cache_alloc(au_pad_cache, KM_SLEEP); + bzero(&pad0->pad_data, sizeof (pad0->pad_data)); + + curthread->t_audit_data = tad0; + curproc->p_audit_data = pad0; + + /* + * The kernel allocates a bunch of threads make sure they have + * a valid tad + */ + + mutex_enter(&pidlock); + + au_thread = curthread; + do { + if (T2A(au_thread) == NULL) { + T2A(au_thread) = tad0; + } + au_thread = au_thread->t_next; + } while (au_thread != curthread); + + tad0->tad_ad = NULL; + mutex_exit(&pidlock); + + /* + * Initialize audit context in our cred (kcred). + * No copy-on-write needed here because it's so early in init. + */ + + ainfo = crgetauinfo_modifiable(kcred); + ASSERT(ainfo != NULL); + bzero(ainfo, sizeof (auditinfo_addr_t)); + ainfo->ai_auid = AU_NOAUDITID; + + /* fabricate an empty audit_path to extend */ + apempty.audp_cnt = 0; + apempty.audp_sect[0] = (char *)(&apempty.audp_sect[1]); + pad0->pad_root = au_pathdup(&apempty, 1, 2); + bcopy("/", pad0->pad_root->audp_sect[0], 2); + au_pathhold(pad0->pad_root); + pad0->pad_cwd = pad0->pad_root; +} + +/* + * Check for any pending changes to the audit context for the given proc. + * p_crlock and pad_lock for the process are acquired here. Caller is + * responsible for assuring the process doesn't go away. If context is + * updated, the specified cralloc'ed cred will be used, otherwise it's freed. + * If no cred is given, it will be cralloc'ed here and caller assures that + * it is safe to allocate memory. + */ + +void +audit_update_context(proc_t *p, cred_t *ncr) +{ + struct p_audit_data *pad; + cred_t *newcred = ncr; + + pad = P2A(p); + if (pad == NULL) { + if (newcred != NULL) + crfree(newcred); + return; + } + + /* If a mask update is pending, take care of it. */ + if (pad->pad_flags & PAD_SETMASK) { + auditinfo_addr_t *ainfo; + + if (newcred == NULL) + newcred = cralloc(); + + mutex_enter(&pad->pad_lock); + /* the condition may have been handled by the time we lock */ + if (pad->pad_flags & PAD_SETMASK) { + ainfo = crgetauinfo_modifiable(newcred); + if (ainfo == NULL) { + mutex_enter(&pad->pad_lock); + crfree(newcred); + return; + } + + mutex_enter(&p->p_crlock); + crcopy_to(p->p_cred, newcred); + p->p_cred = newcred; + + ainfo->ai_mask = pad->pad_newmask; + + /* Unlock and cleanup. */ + mutex_exit(&p->p_crlock); + pad->pad_flags &= ~PAD_SETMASK; + + /* + * For curproc, assure that our thread points to right + * cred, so CRED() will be correct. Otherwise, no need + * to broadcast changes (via set_proc_pre_sys), since + * t_pre_sys is ALWAYS on when audit is enabled... due + * to syscall auditing. + */ + if (p == curproc) + crset(p, newcred); + else + crfree(newcred); + } else { + crfree(newcred); + } + mutex_exit(&pad->pad_lock); + } else { + if (newcred != NULL) + crfree(newcred); + } +} + +/* + * ROUTINE: AUDIT_NEWPROC + * PURPOSE: initialize the child p_audit_data structure + * CALLBY: GETPROC + * NOTE: All threads for the parent process are locked at this point. + * We are essentially running singled threaded for this reason. + * GETPROC is called when system creates a new process. + * By the time AUDIT_NEWPROC is called, the child proc + * structure has already been initialized. What we need + * to do is to allocate the child p_audit_data and + * initialize it with the content of current parent process. + */ + +void +audit_newproc(struct proc *cp) /* initialized child proc structure */ +{ + p_audit_data_t *pad; /* child process audit data */ + p_audit_data_t *opad; /* parent process audit data */ + + pad = kmem_cache_alloc(au_pad_cache, KM_SLEEP); + + P2A(cp) = pad; + + opad = P2A(curproc); + + /* + * copy the audit data. Note that all threads of current + * process have been "held". Thus there is no race condition + * here with mutiple threads trying to alter the cwrd + * structure (such as releasing it). + * + * The audit context in the cred is "duplicated" for the new + * proc by elsewhere crhold'ing the parent's cred which it shares. + * + * We still want to hold things since auditon() [A_SETUMASK, + * A_SETSMASK] could be walking through the processes to + * update things. + */ + mutex_enter(&opad->pad_lock); /* lock opad structure during copy */ + pad->pad_data = opad->pad_data; /* copy parent's process audit data */ + au_pathhold(pad->pad_root); + au_pathhold(pad->pad_cwd); + mutex_exit(&opad->pad_lock); /* current proc will keep cwrd open */ + + /* + * If we are in the limited mode, there is nothing to audit and + * there could not have been anything to audit, since it is not + * possible to switch from the full mode into the limited mode + * once the full mode is set. + */ + if (audit_active != C2AUDIT_LOADED) + return; + + /* + * finish auditing of parent here so that it will be done + * before child has a chance to run. We include the child + * pid since the return value in the return token is a dummy + * one and contains no useful information (it is included to + * make the audit record structure consistant). + * + * tad_flag is set if auditing is on + */ + if (((t_audit_data_t *)T2A(curthread))->tad_flag) + au_uwrite(au_to_arg32(0, "child PID", (uint32_t)cp->p_pid)); + + /* + * finish up audit record generation here because child process + * is set to run before parent process. We distinguish here + * between FORK, FORK1, or VFORK by the saved system call ID. + */ + audit_finish(0, ((t_audit_data_t *)T2A(curthread))->tad_scid, 0, 0); +} + +/* + * ROUTINE: AUDIT_PFREE + * PURPOSE: deallocate the per-process udit data structure + * CALLBY: EXIT + * FORK_FAIL + * NOTE: all lwp except current one have stopped in SEXITLWPS + * why we are single threaded? + * . all lwp except current one have stopped in SEXITLWPS. + */ + +void +audit_pfree(struct proc *p) /* proc structure to be freed */ + +{ /* AUDIT_PFREE */ + + p_audit_data_t *pad; + + pad = P2A(p); + + /* better be a per process audit data structure */ + ASSERT(pad != (p_audit_data_t *)0); + + if (pad == pad0) { + return; + } + + /* deallocate all auditing resources for this process */ + au_pathrele(pad->pad_root); + au_pathrele(pad->pad_cwd); + + /* + * Since the pad structure is completely overwritten after alloc, + * we don't bother to clear it. + */ + + kmem_cache_free(au_pad_cache, pad); +} + +/* + * ROUTINE: AUDIT_THREAD_CREATE + * PURPOSE: allocate per-process thread audit data structure + * CALLBY: THREAD_CREATE + * NOTE: This is called just after *t was bzero'd. + * We are single threaded in this routine. + * TODO: + * QUESTION: + */ + +void +audit_thread_create(kthread_id_t t) +{ + t_audit_data_t *tad; /* per-thread audit data */ + + tad = kmem_zalloc(sizeof (struct t_audit_data), KM_SLEEP); + + T2A(t) = tad; /* set up thread audit data ptr */ + tad->tad_thread = t; /* back ptr to thread: DEBUG */ +} + +/* + * ROUTINE: AUDIT_THREAD_FREE + * PURPOSE: free the per-thread audit data structure + * CALLBY: THREAD_FREE + * NOTE: most thread data is clear after return + */ + +void +audit_thread_free(kthread_t *t) +{ + t_audit_data_t *tad; + au_defer_info_t *attr; + + tad = T2A(t); + + /* thread audit data must still be set */ + + if (tad == tad0) { + return; + } + + if (tad == NULL) { + return; + } + + t->t_audit_data = 0; + + /* must not have any audit record residual */ + ASSERT(tad->tad_ad == NULL); + + /* saved path must be empty */ + ASSERT(tad->tad_aupath == NULL); + + if (tad->tad_atpath) + au_pathrele(tad->tad_atpath); + + if (audit_active == C2AUDIT_LOADED) { + attr = tad->tad_defer_head; + while (attr != NULL) { + au_defer_info_t *tmp_attr = attr; + + au_free_rec(attr->audi_ad); + + attr = attr->audi_next; + kmem_free(tmp_attr, sizeof (au_defer_info_t)); + } + } + + kmem_free(tad, sizeof (*tad)); +} + +/* + * ROUTINE: AUDIT_FALLOC + * PURPOSE: allocating a new file structure + * CALLBY: FALLOC + * NOTE: file structure already initialized + * TODO: + * QUESTION: + */ + +void +audit_falloc(struct file *fp) +{ /* AUDIT_FALLOC */ + + f_audit_data_t *fad; + + /* allocate per file audit structure if there a'int any */ + ASSERT(F2A(fp) == NULL); + + fad = kmem_zalloc(sizeof (struct f_audit_data), KM_SLEEP); + + F2A(fp) = fad; + + fad->fad_thread = curthread; /* file audit data back ptr; DEBUG */ +} + +/* + * ROUTINE: AUDIT_UNFALLOC + * PURPOSE: deallocate file audit data structure + * CALLBY: CLOSEF + * UNFALLOC + * NOTE: + * TODO: + * QUESTION: + */ + +void +audit_unfalloc(struct file *fp) +{ + f_audit_data_t *fad; + + fad = F2A(fp); + + if (!fad) { + return; + } + if (fad->fad_aupath != NULL) { + au_pathrele(fad->fad_aupath); + } + fp->f_audit_data = 0; + kmem_free(fad, sizeof (struct f_audit_data)); +} + +uint32_t +audit_getstate() +{ + return (audit_active == C2AUDIT_LOADED && + ((AU_AUDIT_MASK) & U2A(u)->tad_audit)); +} diff --git a/usr/src/uts/common/os/audit_memory.c b/usr/src/uts/common/os/audit_memory.c new file mode 100644 index 0000000000..a3b61e13e2 --- /dev/null +++ b/usr/src/uts/common/os/audit_memory.c @@ -0,0 +1,123 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/kmem.h> +#include <c2/audit.h> +#include <c2/audit_kernel.h> + + +/* process audit data (pad) cache */ +kmem_cache_t *au_pad_cache; + +/* + * increment audit path reference count + */ +void +au_pathhold(struct audit_path *app) +{ + atomic_add_32(&app->audp_ref, 1); +} + +/* + * decrement audit path reference count + */ +void +au_pathrele(struct audit_path *app) +{ + if (atomic_add_32_nv(&app->audp_ref, -1) > 0) + return; + kmem_free(app, app->audp_size); +} + +/* + * allocate a new auditpath + * newsect = increment sections count, + * charincr = change in strings storage + */ + +struct audit_path * +au_pathdup(const struct audit_path *oldapp, int newsect, int charincr) +{ + struct audit_path *newapp; + int i, alloc_size, oldlen; + char *oldcp, *newcp; + + newsect = (newsect != 0); + oldcp = oldapp->audp_sect[0]; + oldlen = (oldapp->audp_sect[oldapp->audp_cnt] - oldcp); + alloc_size = sizeof (struct audit_path) + + (oldapp->audp_cnt + newsect) * sizeof (char *) + + oldlen + charincr; + + newapp = kmem_alloc(alloc_size, KM_SLEEP); + newapp->audp_ref = 1; + newapp->audp_size = alloc_size; + + newapp->audp_cnt = oldapp->audp_cnt + newsect; + newcp = (char *)(&newapp->audp_sect[newapp->audp_cnt + 1]); + for (i = 0; i <= oldapp->audp_cnt; i++) { + newapp->audp_sect[i] = newcp + + (oldapp->audp_sect[i] - oldcp); + } + /* + * if this is a new section, set its end + * if this is an extended section, reset its end + */ + newapp->audp_sect[newapp->audp_cnt] = newcp + oldlen + charincr; + /* copy all of the old strings */ + bcopy(oldcp, newcp, oldlen); + + return (newapp); +} + +/*ARGSUSED1*/ +static int +au_pad_const(void *vpad, void *priv, int flags) +{ + p_audit_data_t *pad = vpad; + + mutex_init(&pad->pad_lock, NULL, MUTEX_DEFAULT, NULL); + + return (0); +} + +/*ARGSUSED1*/ +static void +au_pad_destr(void *vpad, void *priv) +{ + p_audit_data_t *pad = vpad; + + mutex_destroy(&pad->pad_lock); +} + +void +au_pad_init() +{ + au_pad_cache = kmem_cache_create("audit_proc", + sizeof (p_audit_data_t), 0, au_pad_const, au_pad_destr, + NULL, NULL, NULL, 0); +} diff --git a/usr/src/uts/common/c2/audit_zone.c b/usr/src/uts/common/os/audit_zone.c index dedc943f23..a42f4e6ee2 100644 --- a/usr/src/uts/common/c2/audit_zone.c +++ b/usr/src/uts/common/os/audit_zone.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -99,9 +99,8 @@ au_zone_shutdown(zoneid_t zone, void *arg) { au_kcontext_t *kctx = arg; - if ((kctx->auk_zid == GLOBAL_ZONEID || - (audit_policy | AUDIT_PERZONE)) && - (kctx->auk_current_vp != NULL)) + if (audit_active == C2AUDIT_LOADED && (kctx->auk_zid == GLOBAL_ZONEID || + (audit_policy | AUDIT_PERZONE)) && (kctx->auk_current_vp != NULL)) (void) au_doormsg(kctx, AU_DBUF_SHUTDOWN, NULL); kctx->auk_valid = AUK_INVALID; @@ -154,3 +153,14 @@ au_zone_setup() au_zone_destroy); } + +int +au_zone_getstate(const au_kcontext_t *context) +{ + au_kcontext_t *tcontext; + + if (context != NULL) + return (context->auk_auditstate); + tcontext = GET_KCTX_PZ; + return (tcontext->auk_auditstate); +} diff --git a/usr/src/uts/common/os/cred.c b/usr/src/uts/common/os/cred.c index 7a208b331e..01dc69774d 100644 --- a/usr/src/uts/common/os/cred.c +++ b/usr/src/uts/common/os/cred.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -62,6 +62,7 @@ #include <sys/idmap.h> #include <sys/klpd.h> #include <sys/varargs.h> +#include <sys/sysconf.h> #include <util/qsort.h> @@ -1063,14 +1064,14 @@ get_c2audit_load(void) { static int gotit = 0; static int c2audit_load; - u_longlong_t audit_load_val; if (gotit) return (c2audit_load); - audit_load_val = 0; /* set default value once */ - (void) mod_sysvar("c2audit", "audit_load", &audit_load_val); - c2audit_load = (int)audit_load_val; + c2audit_load = 1; /* set default value once */ + if (mod_sysctl(SYS_CHECK_EXCLUDE, "c2audit") != 0) + c2audit_load = 0; gotit++; + return (c2audit_load); } diff --git a/usr/src/uts/common/os/devpolicy.c b/usr/src/uts/common/os/devpolicy.c index beb573a357..441b1d7c17 100644 --- a/usr/src/uts/common/os/devpolicy.c +++ b/usr/src/uts/common/os/devpolicy.c @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Device policy implementation. * @@ -483,7 +481,7 @@ devpolicy_load(int nitems, size_t sz, devplcysys_t *uitmp) lastwild = wild; } - if (audit_active) + if (AU_AUDITING()) audit_devpolicy(nitems, items); /* diff --git a/usr/src/uts/common/os/exec.c b/usr/src/uts/common/os/exec.c index fc299421fa..f6d31f8e8b 100644 --- a/usr/src/uts/common/os/exec.c +++ b/usr/src/uts/common/os/exec.c @@ -1829,7 +1829,7 @@ exec_args(execa_t *uap, uarg_t *args, intpdata_t *intp, void **auxvpp) */ delete_itimer_realprof(); - if (audit_active) + if (AU_AUDITING()) audit_exec(args->stk_base, args->stk_base + args->arglen, args->na - args->ne, args->ne); diff --git a/usr/src/uts/common/os/exit.c b/usr/src/uts/common/os/exit.c index d2f5fd5767..f86c422fd8 100644 --- a/usr/src/uts/common/os/exit.c +++ b/usr/src/uts/common/os/exit.c @@ -561,7 +561,7 @@ proc_exit(int why, int what) /* * Release any resources associated with C2 auditing */ - if (audit_active) { + if (AU_AUDITING()) { /* * audit exit system call */ diff --git a/usr/src/uts/common/os/fio.c b/usr/src/uts/common/os/fio.c index c3641dd331..57bdc54c85 100644 --- a/usr/src/uts/common/os/fio.c +++ b/usr/src/uts/common/os/fio.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -610,7 +610,7 @@ getf(int fd) /* * archive per file audit data */ - if (audit_active) + if (AU_AUDITING()) (void) audit_getf(fd); set_active_fd(fd); /* record the active file descriptor */ @@ -688,7 +688,7 @@ closeandsetf(int fd, file_t *newfp) /* * archive per file audit data */ - if (audit_active) + if (AU_AUDITING()) (void) audit_getf(fd); ASSERT(ufp->uf_busy); ufp->uf_file = NULL; @@ -942,7 +942,7 @@ closef(file_t *fp) /* * audit close of file (may be exit) */ - if (audit_active) + if (AU_AUDITING()) audit_closef(fp); ASSERT(MUTEX_NOT_HELD(&P_FINFO(curproc)->fi_lock)); @@ -1167,7 +1167,7 @@ setf(int fd, file_t *fp) uf_info_t *fip = P_FINFO(curproc); uf_entry_t *ufp; - if (audit_active) + if (AU_AUDITING()) audit_setf(fp, fd); if (fp == NULL) { diff --git a/usr/src/uts/common/os/ipc.c b/usr/src/uts/common/os/ipc.c index 06324b140a..8f47821566 100644 --- a/usr/src/uts/common/os/ipc.c +++ b/usr/src/uts/common/os/ipc.c @@ -19,16 +19,14 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ -/* All Rights Reserved */ +/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Common Inter-Process Communication routines. * @@ -538,7 +536,7 @@ ipcperm_set(ipc_service_t *service, struct cred *cr, kperm->ipc_gid = gid; kperm->ipc_mode = (mode & 0777) | (kperm->ipc_mode & ~0777); - if (audit_active) + if (AU_AUDITING()) audit_ipcget(service->ipcs_atype, kperm); return (0); @@ -580,7 +578,7 @@ ipcperm_set64(ipc_service_t *service, struct cred *cr, kperm->ipc_mode = (perm64->ipcx_mode & 0777) | (kperm->ipc_mode & ~0777); - if (audit_active) + if (AU_AUDITING()) audit_ipcget(service->ipcs_atype, kperm); return (0); @@ -806,7 +804,7 @@ ipc_lookup(ipc_service_t *service, int id, kipc_perm_t **perm) ASSERT(IPC_SEQ(id) == service->ipcs_table[index].ipct_seq); *perm = result; - if (audit_active) + if (AU_AUDITING()) audit_ipc(service->ipcs_atype, id, result); return (&service->ipcs_table[index].ipct_lock); @@ -928,7 +926,7 @@ ipc_keylookup(ipc_service_t *service, key_t key, int flag, kipc_perm_t **permp) if ((flag & (IPC_CREAT | IPC_EXCL)) == (IPC_CREAT | IPC_EXCL)) return (EEXIST); if ((flag & 0777) & ~perm->ipc_mode) { - if (audit_active) + if (AU_AUDITING()) audit_ipcget(NULL, (void *)perm); return (EACCES); } diff --git a/usr/src/uts/common/os/main.c b/usr/src/uts/common/os/main.c index 5845c9efd3..0e11b8b30f 100644 --- a/usr/src/uts/common/os/main.c +++ b/usr/src/uts/common/os/main.c @@ -87,12 +87,20 @@ proc_t *proc_fsflush; /* fsflush daemon */ pgcnt_t maxmem; /* Maximum available memory in pages. */ pgcnt_t freemem; /* Current available memory in pages. */ -int audit_active; int interrupts_unleashed; /* set when we do the first spl0() */ kmem_cache_t *process_cache; /* kmem cache for proc structures */ /* + * Indicates whether the auditing module (c2audit) is loaded. Possible + * values are: + * 0 - c2audit module is excluded in /etc/system and cannot be loaded + * 1 - c2audit module is not loaded but can be anytime + * 2 - c2audit module is loaded + */ +int audit_active = C2AUDIT_DISABLED; + +/* * Process 0's lwp directory and lwpid hash table. */ lwpdir_t p0_lwpdir[2]; diff --git a/usr/src/uts/common/os/msg.c b/usr/src/uts/common/os/msg.c index 4d547c9df6..5b763e187b 100644 --- a/usr/src/uts/common/os/msg.c +++ b/usr/src/uts/common/os/msg.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -653,8 +653,10 @@ top: pp->p_rctls, pp); lock = ipc_commit_end(msq_svc, &qp->msg_perm); } - if (audit_active) + + if (AU_AUDITING()) audit_ipcget(AT_IPC_MSG, (void *)qp); + id = qp->msg_perm.ipc_id; mutex_exit(lock); return (id); diff --git a/usr/src/uts/common/os/policy.c b/usr/src/uts/common/os/policy.c index aaddff4756..d6444e7fc3 100644 --- a/usr/src/uts/common/os/policy.c +++ b/usr/src/uts/common/os/policy.c @@ -356,7 +356,7 @@ static void priv_policy_err(const cred_t *cr, int priv, boolean_t allzone, const char *msg) { - if (audit_active) + if (AU_AUDITING()) audit_priv(priv, allzone ? ZONEPRIVS(cr) : NULL, 0); DTRACE_PROBE2(priv__err, int, priv, boolean_t, allzone); @@ -387,7 +387,7 @@ priv_policy_ap(const cred_t *cr, int priv, boolean_t allzone, int err, !PRIV_ISASSERT(priv_basic, priv)) && !servicing_interrupt()) { PTOU(curproc)->u_acflag |= ASU; /* Needed for SVVS */ - if (audit_active) + if (AU_AUDITING()) audit_priv(priv, allzone ? ZONEPRIVS(cr) : NULL, 1); } @@ -431,7 +431,7 @@ priv_policy_choice(const cred_t *cr, int priv, boolean_t allzone) (!allzone || HAS_ALLZONEPRIVS(cr)); /* Audit success only */ - if (res && audit_active && + if (res && AU_AUDITING() && (allzone || priv == PRIV_ALL || !PRIV_ISASSERT(priv_basic, priv)) && !servicing_interrupt()) { audit_priv(priv, allzone ? ZONEPRIVS(cr) : NULL, 1); @@ -488,7 +488,7 @@ secpolicy_require_set(const cred_t *cr, const priv_set_t *req, const char *msg) priv_inverse(&pset); /* all non present privileges */ priv_intersect(req, &pset); /* the actual missing privs */ - if (audit_active) + if (AU_AUDITING()) audit_priv(PRIV_NONE, &pset, 0); /* * Privilege debugging; special case "one privilege in set". diff --git a/usr/src/uts/common/os/shm.c b/usr/src/uts/common/os/shm.c index 869bbd5a38..bf18627c34 100644 --- a/usr/src/uts/common/os/shm.c +++ b/usr/src/uts/common/os/shm.c @@ -935,7 +935,7 @@ top: lock = ipc_commit_end(shm_svc, &sp->shm_perm); } - if (audit_active) + if (AU_AUDITING()) audit_ipcget(AT_IPC_SHM, (void *)sp); *rvp = (uintptr_t)(sp->shm_perm.ipc_id); diff --git a/usr/src/uts/common/os/sig.c b/usr/src/uts/common/os/sig.c index 0988b6a486..f22f10063e 100644 --- a/usr/src/uts/common/os/sig.c +++ b/usr/src/uts/common/os/sig.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1267,6 +1267,7 @@ psig(void) id_t ctid = 0; zoneid_t zoneid = -1; sigqueue_t *sqp = NULL; + uint32_t auditing = AU_AUDITING(); mutex_enter(&p->p_lock); schedctl_finish_sigblock(t); @@ -1447,11 +1448,11 @@ psig(void) sig = SIGKILL; ext = (p->p_flag & SEXTKILLED) != 0; } else { - if (audit_active) /* audit core dump */ + if (auditing) /* audit core dump */ audit_core_start(sig); if (core(sig, ext) == 0) code = CLD_DUMPED; - if (audit_active) /* audit core dump */ + if (auditing) /* audit core dump */ audit_core_finish(code); } } @@ -2649,11 +2650,11 @@ realsigprof_fast(int sysnum, int nsysarg, int error) mutex_enter(&p->p_lock); lwp_exit(); } - if (audit_active) + if (audit_active == C2AUDIT_LOADED) audit_core_start(SIGSEGV); if (core(SIGSEGV, 0) == 0) code = CLD_DUMPED; - if (audit_active) + if (audit_active == C2AUDIT_LOADED) audit_core_finish(code); exit(code, SIGSEGV); } diff --git a/usr/src/uts/common/os/streamio.c b/usr/src/uts/common/os/streamio.c index 0cf8d66056..2ac660e419 100644 --- a/usr/src/uts/common/os/streamio.c +++ b/usr/src/uts/common/os/streamio.c @@ -23,7 +23,7 @@ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -77,6 +77,7 @@ #include <sys/policy.h> #include <sys/dld.h> #include <sys/zone.h> +#include <c2/audit.h> /* * This define helps improve the readability of streams code while @@ -250,7 +251,7 @@ stropen(vnode_t *vp, dev_t *devp, int flag, cred_t *crp) zoneid_t zoneid; uint_t anchor; - if (audit_active) + if (AU_AUDITING()) audit_stropen(vp, devp, flag, crp); /* @@ -619,7 +620,7 @@ strclose(struct vnode *vp, int flag, cred_t *crp) int freestp = 1; queue_t *rmq; - if (audit_active) + if (AU_AUDITING()) audit_strclose(vp, flag, crp); TRACE_1(TR_FAC_STREAMS_FR, @@ -3210,6 +3211,7 @@ strioctl(struct vnode *vp, int cmd, intptr_t arg, int flag, int copyflag, queue_t *wrq; queue_t *rdq; boolean_t kioctl = B_FALSE; + uint32_t auditing = AU_AUDITING(); if (flag & FKIOCTL) { copyflag = K_TO_K; @@ -3222,7 +3224,7 @@ strioctl(struct vnode *vp, int cmd, intptr_t arg, int flag, int copyflag, TRACE_3(TR_FAC_STREAMS_FR, TR_IOCTL_ENTER, "strioctl:stp %p cmd %X arg %lX", stp, cmd, arg); - if (audit_active) + if (auditing) audit_strioctl(vp, cmd, arg, flag, copyflag, crp, rvalp); /* @@ -5296,7 +5298,7 @@ strioctl(struct vnode *vp, int cmd, intptr_t arg, int flag, int copyflag, if ((fp = getf((int)arg)) == NULL) return (EBADF); error = do_sendfp(stp, fp, crp); - if (audit_active) { + if (auditing) { audit_fdsend((int)arg, fp, error); } releasef((int)arg); @@ -5385,7 +5387,7 @@ strioctl(struct vnode *vp, int cmd, intptr_t arg, int flag, int copyflag, mutex_exit(&stp->sd_lock); return (error); } - if (audit_active) { + if (auditing) { audit_fdrecv(fd, srf->fp); } @@ -7756,7 +7758,7 @@ strputmsg( xpg4 = (flag & MSG_XPG4) ? 1 : 0; flag &= ~MSG_XPG4; - if (audit_active) + if (AU_AUDITING()) audit_strputmsg(vp, mctl, mdata, pri, flag, fmode); mutex_enter(&stp->sd_lock); @@ -7945,7 +7947,7 @@ kstrputmsg( ASSERT(vp->v_stream); stp = vp->v_stream; wqp = stp->sd_wrq; - if (audit_active) + if (AU_AUDITING()) audit_strputmsg(vp, NULL, NULL, pri, flag, fmode); if (mctl == NULL) return (EINVAL); diff --git a/usr/src/uts/common/os/sysent.c b/usr/src/uts/common/os/sysent.c index 07c8fe03f6..44dd747a0b 100644 --- a/usr/src/uts/common/os/sysent.c +++ b/usr/src/uts/common/os/sysent.c @@ -637,7 +637,7 @@ struct sysent sysent[NSYSCALL] = /* 183 */ SYSENT_CI("pollsys", pollsys, 4), /* 184 */ SYSENT_CI("labelsys", labelsys, 5), /* 185 */ SYSENT_CI("acl", acl, 4), - /* 186 */ SYSENT_AP("auditsys", auditsys, 2), + /* 186 */ SYSENT_AP("auditsys", auditsys, 6), /* 187 */ SYSENT_CI("processor_bind", processor_bind, 4), /* 188 */ SYSENT_CI("processor_info", processor_info, 2), /* 189 */ SYSENT_CI("p_online", p_online, 2), @@ -993,7 +993,7 @@ struct sysent sysent32[NSYSCALL] = /* 183 */ SYSENT_CI("pollsys", pollsys, 4), /* 184 */ SYSENT_CI("labelsys", labelsys, 5), /* 185 */ SYSENT_CI("acl", acl, 4), - /* 186 */ SYSENT_AP("auditsys", auditsys, 2), + /* 186 */ SYSENT_AP("auditsys", auditsys, 6), /* 187 */ SYSENT_CI("processor_bind", processor_bind, 4), /* 188 */ SYSENT_CI("processor_info", processor_info, 2), /* 189 */ SYSENT_CI("p_online", p_online, 2), diff --git a/usr/src/uts/common/os/zone.c b/usr/src/uts/common/os/zone.c index ed1286bf97..4f08e77f59 100644 --- a/usr/src/uts/common/os/zone.c +++ b/usr/src/uts/common/os/zone.c @@ -3072,7 +3072,8 @@ zone_chdir(vnode_t *vp, vnode_t **vpp, proc_t *pp) /* we're going to hold a reference here to the directory */ VN_HOLD(vp); - if (audit_active) /* update abs cwd/root path see c2audit.c */ + /* update abs cwd/root path see c2/audit.c */ + if (AU_AUDITING()) audit_chdirec(vp, vpp); mutex_enter(&pp->p_lock); diff --git a/usr/src/uts/common/sys/proc.h b/usr/src/uts/common/sys/proc.h index 6ecd15093a..b419f8235f 100644 --- a/usr/src/uts/common/sys/proc.h +++ b/usr/src/uts/common/sys/proc.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -671,6 +671,7 @@ extern void set_proc_post_sys(proc_t *p); extern void set_proc_sys(proc_t *p); extern void set_proc_ast(proc_t *p); extern void set_all_proc_sys(void); +extern void set_all_zone_usr_proc_sys(zoneid_t); /* thread function prototypes */ diff --git a/usr/src/uts/common/sys/systm.h b/usr/src/uts/common/sys/systm.h index ca477d3746..e5ee80c404 100644 --- a/usr/src/uts/common/sys/systm.h +++ b/usr/src/uts/common/sys/systm.h @@ -98,7 +98,7 @@ extern int klustsize; extern int abort_enable; /* Platform input-device abort policy */ -extern int audit_active; /* Solaris Auditing active 1, absent 0. */ +extern int audit_active; /* Solaris Auditing module state */ extern int avenrun[]; /* array of load averages */ diff --git a/usr/src/uts/common/syscall/access.c b/usr/src/uts/common/syscall/access.c index bf71b77b8c..16b7ff7534 100644 --- a/usr/src/uts/common/syscall/access.c +++ b/usr/src/uts/common/syscall/access.c @@ -152,7 +152,7 @@ faccessat(int fd, char *fname, int fmode, int flag) } } - if (audit_active) + if (AU_AUDITING()) audit_setfsat_path(1); /* Do not allow E_OK unless AT_EACCESS flag is set */ diff --git a/usr/src/uts/common/syscall/auditsys.c b/usr/src/uts/common/syscall/auditsys.c index a940bd7d18..538709e2d2 100644 --- a/usr/src/uts/common/syscall/auditsys.c +++ b/usr/src/uts/common/syscall/auditsys.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -28,35 +28,63 @@ #include <sys/policy.h> #include <c2/audit.h> +#include <c2/audit_kernel.h> +#include <c2/audit_record.h> + +#define CLEAR_VAL -1 + +extern kmutex_t pidlock; + +int audit_policy; /* global audit policies in force */ + /*ARGSUSED1*/ int auditsys(struct auditcalls *uap, rval_t *rvp) { int err; + int result = 0; - /* - * this ugly hack is because auditsys returns - * 0 for all cases except audit_active == 0 - * and uap->code == BSM_AUDITCTL || default) - */ - - if (!audit_active) + if (audit_active == C2AUDIT_DISABLED) return (ENOTSUP); switch (uap->code) { case BSM_GETAUID: + result = getauid((caddr_t)uap->a1); + break; case BSM_SETAUID: + result = setauid((caddr_t)uap->a1); + break; case BSM_GETAUDIT: + result = getaudit((caddr_t)uap->a1); + break; + case BSM_GETAUDIT_ADDR: + result = getaudit_addr((caddr_t)uap->a1, (int)uap->a2); + break; case BSM_SETAUDIT: - case BSM_AUDIT: - return (0); + result = setaudit((caddr_t)uap->a1); + break; + case BSM_SETAUDIT_ADDR: + result = setaudit_addr((caddr_t)uap->a1, (int)uap->a2); + break; case BSM_AUDITCTL: - if ((int)uap->a1 == A_GETCOND) - err = secpolicy_audit_getattr(CRED()); - else - /* FALLTHROUGH */ + result = auditctl((int)uap->a1, (caddr_t)uap->a2, (int)uap->a3); + break; + case BSM_AUDIT: + if (audit_active == C2AUDIT_UNLOADED) + return (0); + result = audit((caddr_t)uap->a1, (int)uap->a2); + break; + case BSM_AUDITDOOR: + if (audit_active == C2AUDIT_LOADED) { + result = auditdoor((int)uap->a1); + break; + } default: + if (audit_active == C2AUDIT_LOADED) { + result = EINVAL; + break; + } /* Return a different error when not privileged */ err = secpolicy_audit_config(CRED()); if (err == 0) @@ -64,4 +92,1334 @@ auditsys(struct auditcalls *uap, rval_t *rvp) else return (err); } + rvp->r_vals = result; + return (result); +} + +/* + * Return the audit user ID for the current process. Currently only + * the privileged processes may see the audit id. That may change. + * If copyout is unsucessful return EFAULT. + */ +int +getauid(caddr_t auid_p) +{ + const auditinfo_addr_t *ainfo; + + if (secpolicy_audit_getattr(CRED()) != 0) + return (EPERM); + + ainfo = crgetauinfo(CRED()); + if (ainfo == NULL) + return (EINVAL); + + if (copyout(&ainfo->ai_auid, auid_p, sizeof (au_id_t))) + return (EFAULT); + + return (0); +} + +/* + * Set the audit userid, for a process. This can only be changed by + * privileged processes. The audit userid is inherited across forks & execs. + * Passed in is a pointer to the au_id_t; if copyin unsuccessful return EFAULT. + */ +int +setauid(caddr_t auid_p) +{ + proc_t *p; + au_id_t auid; + cred_t *newcred; + auditinfo_addr_t *auinfo; + + if (secpolicy_audit_config(CRED()) != 0) + return (EPERM); + + if (copyin(auid_p, &auid, sizeof (au_id_t))) { + return (EFAULT); + } + + newcred = cralloc(); + if ((auinfo = crgetauinfo_modifiable(newcred)) == NULL) { + crfree(newcred); + return (EINVAL); + } + + /* grab p_crlock and switch to new cred */ + p = curproc; + mutex_enter(&p->p_crlock); + crcopy_to(p->p_cred, newcred); + p->p_cred = newcred; + + auinfo->ai_auid = auid; /* update the auid */ + + /* unlock and broadcast the cred changes */ + mutex_exit(&p->p_crlock); + crset(p, newcred); + + return (0); +} + +/* + * Get the audit state information from the current process. + * Return EFAULT if copyout fails. + */ +int +getaudit(caddr_t info_p) +{ + STRUCT_DECL(auditinfo, info); + const auditinfo_addr_t *ainfo; + model_t model; + + if (secpolicy_audit_getattr(CRED()) != 0) + return (EPERM); + + model = get_udatamodel(); + STRUCT_INIT(info, model); + + ainfo = crgetauinfo(CRED()); + if (ainfo == NULL) + return (EINVAL); + + /* trying to read a process with an IPv6 address? */ + if (ainfo->ai_termid.at_type == AU_IPv6) + return (EOVERFLOW); + + STRUCT_FSET(info, ai_auid, ainfo->ai_auid); + STRUCT_FSET(info, ai_mask, ainfo->ai_mask); +#ifdef _LP64 + if (model == DATAMODEL_ILP32) { + dev32_t dev; + /* convert internal 64 bit form to 32 bit version */ + if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) { + return (EOVERFLOW); + } + STRUCT_FSET(info, ai_termid.port, dev); + } else + STRUCT_FSET(info, ai_termid.port, ainfo->ai_termid.at_port); +#else + STRUCT_FSET(info, ai_termid.port, ainfo->ai_termid.at_port); +#endif + STRUCT_FSET(info, ai_termid.machine, ainfo->ai_termid.at_addr[0]); + STRUCT_FSET(info, ai_asid, ainfo->ai_asid); + + if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info))) + return (EFAULT); + + return (0); +} + +/* + * Get the audit state information from the current process. + * Return EFAULT if copyout fails. + */ +int +getaudit_addr(caddr_t info_p, int len) +{ + STRUCT_DECL(auditinfo_addr, info); + const auditinfo_addr_t *ainfo; + model_t model; + + if (secpolicy_audit_getattr(CRED()) != 0) + return (EPERM); + + model = get_udatamodel(); + STRUCT_INIT(info, model); + + if (len < STRUCT_SIZE(info)) + return (EOVERFLOW); + + ainfo = crgetauinfo(CRED()); + + if (ainfo == NULL) + return (EINVAL); + + STRUCT_FSET(info, ai_auid, ainfo->ai_auid); + STRUCT_FSET(info, ai_mask, ainfo->ai_mask); +#ifdef _LP64 + if (model == DATAMODEL_ILP32) { + dev32_t dev; + /* convert internal 64 bit form to 32 bit version */ + if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) { + return (EOVERFLOW); + } + STRUCT_FSET(info, ai_termid.at_port, dev); + } else + STRUCT_FSET(info, ai_termid.at_port, ainfo->ai_termid.at_port); +#else + STRUCT_FSET(info, ai_termid.at_port, ainfo->ai_termid.at_port); +#endif + STRUCT_FSET(info, ai_termid.at_type, ainfo->ai_termid.at_type); + STRUCT_FSET(info, ai_termid.at_addr[0], ainfo->ai_termid.at_addr[0]); + STRUCT_FSET(info, ai_termid.at_addr[1], ainfo->ai_termid.at_addr[1]); + STRUCT_FSET(info, ai_termid.at_addr[2], ainfo->ai_termid.at_addr[2]); + STRUCT_FSET(info, ai_termid.at_addr[3], ainfo->ai_termid.at_addr[3]); + STRUCT_FSET(info, ai_asid, ainfo->ai_asid); + + if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info))) + return (EFAULT); + + return (0); +} + +/* + * Set the audit state information for the current process. + * Return EFAULT if copyout fails. + */ +int +setaudit(caddr_t info_p) +{ + STRUCT_DECL(auditinfo, info); + proc_t *p; + cred_t *newcred; + model_t model; + auditinfo_addr_t *ainfo; + + if (secpolicy_audit_config(CRED()) != 0) + return (EPERM); + + model = get_udatamodel(); + STRUCT_INIT(info, model); + + if (copyin(info_p, STRUCT_BUF(info), STRUCT_SIZE(info))) + return (EFAULT); + + newcred = cralloc(); + if ((ainfo = crgetauinfo_modifiable(newcred)) == NULL) { + crfree(newcred); + return (EINVAL); + } + + /* grab p_crlock and switch to new cred */ + p = curproc; + mutex_enter(&p->p_crlock); + crcopy_to(p->p_cred, newcred); + p->p_cred = newcred; + + /* Set audit mask, id, termid and session id as specified */ + ainfo->ai_auid = STRUCT_FGET(info, ai_auid); +#ifdef _LP64 + /* only convert to 64 bit if coming from a 32 bit binary */ + if (model == DATAMODEL_ILP32) + ainfo->ai_termid.at_port = + DEVEXPL(STRUCT_FGET(info, ai_termid.port)); + else + ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.port); +#else + ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.port); +#endif + ainfo->ai_termid.at_type = AU_IPv4; + ainfo->ai_termid.at_addr[0] = STRUCT_FGET(info, ai_termid.machine); + ainfo->ai_asid = STRUCT_FGET(info, ai_asid); + ainfo->ai_mask = STRUCT_FGET(info, ai_mask); + + /* unlock and broadcast the cred changes */ + mutex_exit(&p->p_crlock); + crset(p, newcred); + + return (0); +} + +/* + * Set the audit state information for the current process. + * Return EFAULT if copyin fails. + */ +int +setaudit_addr(caddr_t info_p, int len) +{ + STRUCT_DECL(auditinfo_addr, info); + proc_t *p; + cred_t *newcred; + model_t model; + int i; + int type; + auditinfo_addr_t *ainfo; + + if (secpolicy_audit_config(CRED()) != 0) + return (EPERM); + + model = get_udatamodel(); + STRUCT_INIT(info, model); + + if (len < STRUCT_SIZE(info)) + return (EOVERFLOW); + + if (copyin(info_p, STRUCT_BUF(info), STRUCT_SIZE(info))) + return (EFAULT); + + type = STRUCT_FGET(info, ai_termid.at_type); + if ((type != AU_IPv4) && (type != AU_IPv6)) + return (EINVAL); + + newcred = cralloc(); + if ((ainfo = crgetauinfo_modifiable(newcred)) == NULL) { + crfree(newcred); + return (EINVAL); + } + + /* grab p_crlock and switch to new cred */ + p = curproc; + mutex_enter(&p->p_crlock); + crcopy_to(p->p_cred, newcred); + p->p_cred = newcred; + + /* Set audit mask, id, termid and session id as specified */ + ainfo->ai_auid = STRUCT_FGET(info, ai_auid); + ainfo->ai_mask = STRUCT_FGET(info, ai_mask); +#ifdef _LP64 + /* only convert to 64 bit if coming from a 32 bit binary */ + if (model == DATAMODEL_ILP32) + ainfo->ai_termid.at_port = + DEVEXPL(STRUCT_FGET(info, ai_termid.at_port)); + else + ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.at_port); +#else + ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.at_port); +#endif + ainfo->ai_termid.at_type = type; + bzero(&ainfo->ai_termid.at_addr[0], sizeof (ainfo->ai_termid.at_addr)); + for (i = 0; i < (type/sizeof (int)); i++) + ainfo->ai_termid.at_addr[i] = + STRUCT_FGET(info, ai_termid.at_addr[i]); + + if (ainfo->ai_termid.at_type == AU_IPv6 && + IN6_IS_ADDR_V4MAPPED(((in6_addr_t *)ainfo->ai_termid.at_addr))) { + ainfo->ai_termid.at_type = AU_IPv4; + ainfo->ai_termid.at_addr[0] = ainfo->ai_termid.at_addr[3]; + ainfo->ai_termid.at_addr[1] = 0; + ainfo->ai_termid.at_addr[2] = 0; + ainfo->ai_termid.at_addr[3] = 0; + } + + ainfo->ai_asid = STRUCT_FGET(info, ai_asid); + + /* unlock and broadcast the cred changes */ + mutex_exit(&p->p_crlock); + crset(p, newcred); + + return (0); +} + +/* + * Get the global policy flag + */ +static int +getpolicy(caddr_t data) +{ + int policy; + au_kcontext_t *kctx = GET_KCTX_PZ; + + policy = audit_policy | kctx->auk_policy; + + if (copyout(&policy, data, sizeof (int))) + return (EFAULT); + return (0); +} + +/* + * Set the global and local policy flags + * + * The global flags only make sense from the global zone; + * the local flags depend on the AUDIT_PERZONE policy: + * if the perzone policy is set, then policy is set separately + * per zone, else held only in the global zone. + * + * The initial value of a local zone's policy flag is determined + * by the value of the global zone's flags at the time the + * local zone is created. + * + * While auditconfig(1M) allows setting and unsetting policies one bit + * at a time, the mask passed in from auditconfig() is created by a + * syscall to getpolicy and then modified based on the auditconfig() + * cmd line, so the input policy value is used to replace the existing + * policy. + */ +static int +setpolicy(caddr_t data) +{ + int policy; + au_kcontext_t *kctx; + + if (copyin(data, &policy, sizeof (int))) + return (EFAULT); + + kctx = GET_KCTX_NGZ; + + if (INGLOBALZONE(curproc)) { + if (policy & ~(AUDIT_GLOBAL | AUDIT_LOCAL)) + return (EINVAL); + + audit_policy = policy & AUDIT_GLOBAL; + } else { + if (!(audit_policy & AUDIT_PERZONE)) + return (EINVAL); + + if (policy & ~AUDIT_LOCAL) /* global bits are a no-no */ + return (EINVAL); + } + kctx->auk_policy = policy & AUDIT_LOCAL; + + /* + * auk_current_vp is NULL before auditd starts (or during early + * auditd starup) or if auditd is halted; in either case, + * notification of a policy change is not needed, since auditd + * reads policy as it comes up. The error return from au_doormsg() + * is ignored to avoid a race condition -- for example if auditd + * segv's, the audit state may be "auditing" but the door may + * be closed. Returning an error if the door is open makes it + * impossible for Greenline to restart auditd. + */ + if (kctx->auk_current_vp != NULL) + (void) au_doormsg(kctx, AU_DBUF_POLICY, &policy); + + /* + * Wake up anyone who might have blocked on full audit + * partitions. audit daemons need to set AUDIT_FULL when no + * space so we can tell if we should start dropping records. + */ + mutex_enter(&(kctx->auk_queue.lock)); + + if ((policy & (AUDIT_CNT | AUDIT_SCNT) && + (kctx->auk_queue.cnt >= kctx->auk_queue.hiwater))) + cv_broadcast(&(kctx->auk_queue.write_cv)); + + mutex_exit(&(kctx->auk_queue.lock)); + + return (0); +} + +static int +getkmask(caddr_t data) +{ + au_kcontext_t *kctx; + + kctx = GET_KCTX_PZ; + + if (copyout(&kctx->auk_info.ai_mask, data, sizeof (au_mask_t))) + return (EFAULT); + return (0); +} + +static int +setkmask(caddr_t data) +{ + au_mask_t mask; + au_kcontext_t *kctx; + + if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc)) + return (EINVAL); + + kctx = GET_KCTX_NGZ; + + if (copyin(data, &mask, sizeof (au_mask_t))) + return (EFAULT); + + kctx->auk_info.ai_mask = mask; + return (0); +} + +static int +getkaudit(caddr_t info_p, int len) +{ + STRUCT_DECL(auditinfo_addr, info); + model_t model; + au_kcontext_t *kctx = GET_KCTX_PZ; + + model = get_udatamodel(); + STRUCT_INIT(info, model); + + if (len < STRUCT_SIZE(info)) + return (EOVERFLOW); + + STRUCT_FSET(info, ai_auid, kctx->auk_info.ai_auid); + STRUCT_FSET(info, ai_mask, kctx->auk_info.ai_mask); +#ifdef _LP64 + if (model == DATAMODEL_ILP32) { + dev32_t dev; + /* convert internal 64 bit form to 32 bit version */ + if (cmpldev(&dev, kctx->auk_info.ai_termid.at_port) == 0) { + return (EOVERFLOW); + } + STRUCT_FSET(info, ai_termid.at_port, dev); + } else { + STRUCT_FSET(info, ai_termid.at_port, + kctx->auk_info.ai_termid.at_port); + } +#else + STRUCT_FSET(info, ai_termid.at_port, + kctx->auk_info.ai_termid.at_port); +#endif + STRUCT_FSET(info, ai_termid.at_type, + kctx->auk_info.ai_termid.at_type); + STRUCT_FSET(info, ai_termid.at_addr[0], + kctx->auk_info.ai_termid.at_addr[0]); + STRUCT_FSET(info, ai_termid.at_addr[1], + kctx->auk_info.ai_termid.at_addr[1]); + STRUCT_FSET(info, ai_termid.at_addr[2], + kctx->auk_info.ai_termid.at_addr[2]); + STRUCT_FSET(info, ai_termid.at_addr[3], + kctx->auk_info.ai_termid.at_addr[3]); + STRUCT_FSET(info, ai_asid, kctx->auk_info.ai_asid); + + if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info))) + return (EFAULT); + + return (0); +} + +/* + * the host address for AUDIT_PERZONE == 0 is that of the global + * zone and for local zones it is of the current zone. + */ +static int +setkaudit(caddr_t info_p, int len) +{ + STRUCT_DECL(auditinfo_addr, info); + model_t model; + au_kcontext_t *kctx; + + if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc)) + return (EINVAL); + + kctx = GET_KCTX_NGZ; + + model = get_udatamodel(); + STRUCT_INIT(info, model); + + if (len < STRUCT_SIZE(info)) + return (EOVERFLOW); + + if (copyin(info_p, STRUCT_BUF(info), STRUCT_SIZE(info))) + return (EFAULT); + + if ((STRUCT_FGET(info, ai_termid.at_type) != AU_IPv4) && + (STRUCT_FGET(info, ai_termid.at_type) != AU_IPv6)) + return (EINVAL); + + /* Set audit mask, termid and session id as specified */ + kctx->auk_info.ai_auid = STRUCT_FGET(info, ai_auid); + kctx->auk_info.ai_mask = STRUCT_FGET(info, ai_mask); +#ifdef _LP64 + /* only convert to 64 bit if coming from a 32 bit binary */ + if (model == DATAMODEL_ILP32) + kctx->auk_info.ai_termid.at_port = + DEVEXPL(STRUCT_FGET(info, ai_termid.at_port)); + else + kctx->auk_info.ai_termid.at_port = + STRUCT_FGET(info, ai_termid.at_port); +#else + kctx->auk_info.ai_termid.at_port = STRUCT_FGET(info, ai_termid.at_port); +#endif + kctx->auk_info.ai_termid.at_type = STRUCT_FGET(info, ai_termid.at_type); + bzero(&kctx->auk_info.ai_termid.at_addr[0], + sizeof (kctx->auk_info.ai_termid.at_addr)); + kctx->auk_info.ai_termid.at_addr[0] = + STRUCT_FGET(info, ai_termid.at_addr[0]); + kctx->auk_info.ai_termid.at_addr[1] = + STRUCT_FGET(info, ai_termid.at_addr[1]); + kctx->auk_info.ai_termid.at_addr[2] = + STRUCT_FGET(info, ai_termid.at_addr[2]); + kctx->auk_info.ai_termid.at_addr[3] = + STRUCT_FGET(info, ai_termid.at_addr[3]); + kctx->auk_info.ai_asid = STRUCT_FGET(info, ai_asid); + + if (kctx->auk_info.ai_termid.at_type == AU_IPv6 && + IN6_IS_ADDR_V4MAPPED( + ((in6_addr_t *)kctx->auk_info.ai_termid.at_addr))) { + kctx->auk_info.ai_termid.at_type = AU_IPv4; + kctx->auk_info.ai_termid.at_addr[0] = + kctx->auk_info.ai_termid.at_addr[3]; + kctx->auk_info.ai_termid.at_addr[1] = 0; + kctx->auk_info.ai_termid.at_addr[2] = 0; + kctx->auk_info.ai_termid.at_addr[3] = 0; + } + if (kctx->auk_info.ai_termid.at_type == AU_IPv6) + kctx->auk_hostaddr_valid = IN6_IS_ADDR_UNSPECIFIED( + (in6_addr_t *)kctx->auk_info.ai_termid.at_addr) ? 0 : 1; + else + kctx->auk_hostaddr_valid = + (kctx->auk_info.ai_termid.at_addr[0] == + htonl(INADDR_ANY)) ? 0 : 1; + + return (0); +} + +static int +getqctrl(caddr_t data) +{ + au_kcontext_t *kctx = GET_KCTX_PZ; + STRUCT_DECL(au_qctrl, qctrl); + STRUCT_INIT(qctrl, get_udatamodel()); + + mutex_enter(&(kctx->auk_queue.lock)); + STRUCT_FSET(qctrl, aq_hiwater, kctx->auk_queue.hiwater); + STRUCT_FSET(qctrl, aq_lowater, kctx->auk_queue.lowater); + STRUCT_FSET(qctrl, aq_bufsz, kctx->auk_queue.bufsz); + STRUCT_FSET(qctrl, aq_delay, kctx->auk_queue.delay); + mutex_exit(&(kctx->auk_queue.lock)); + + if (copyout(STRUCT_BUF(qctrl), data, STRUCT_SIZE(qctrl))) + return (EFAULT); + + return (0); +} + +static int +setqctrl(caddr_t data) +{ + au_kcontext_t *kctx; + struct au_qctrl qctrl_tmp; + STRUCT_DECL(au_qctrl, qctrl); + STRUCT_INIT(qctrl, get_udatamodel()); + + if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc)) + return (EINVAL); + kctx = GET_KCTX_NGZ; + + if (copyin(data, STRUCT_BUF(qctrl), STRUCT_SIZE(qctrl))) + return (EFAULT); + + qctrl_tmp.aq_hiwater = (size_t)STRUCT_FGET(qctrl, aq_hiwater); + qctrl_tmp.aq_lowater = (size_t)STRUCT_FGET(qctrl, aq_lowater); + qctrl_tmp.aq_bufsz = (size_t)STRUCT_FGET(qctrl, aq_bufsz); + qctrl_tmp.aq_delay = (clock_t)STRUCT_FGET(qctrl, aq_delay); + + /* enforce sane values */ + + if (qctrl_tmp.aq_hiwater <= qctrl_tmp.aq_lowater) + return (EINVAL); + + if (qctrl_tmp.aq_hiwater < AQ_LOWATER) + return (EINVAL); + + if (qctrl_tmp.aq_hiwater > AQ_MAXHIGH) + return (EINVAL); + + if (qctrl_tmp.aq_bufsz < AQ_BUFSZ) + return (EINVAL); + + if (qctrl_tmp.aq_bufsz > AQ_MAXBUFSZ) + return (EINVAL); + + if (qctrl_tmp.aq_delay == 0) + return (EINVAL); + + if (qctrl_tmp.aq_delay > AQ_MAXDELAY) + return (EINVAL); + + /* update everything at once so things are consistant */ + mutex_enter(&(kctx->auk_queue.lock)); + kctx->auk_queue.hiwater = qctrl_tmp.aq_hiwater; + kctx->auk_queue.lowater = qctrl_tmp.aq_lowater; + kctx->auk_queue.bufsz = qctrl_tmp.aq_bufsz; + kctx->auk_queue.delay = qctrl_tmp.aq_delay; + + if (kctx->auk_queue.rd_block && + kctx->auk_queue.cnt > kctx->auk_queue.lowater) + cv_broadcast(&(kctx->auk_queue.read_cv)); + + if (kctx->auk_queue.wt_block && + kctx->auk_queue.cnt < kctx->auk_queue.hiwater) + cv_broadcast(&(kctx->auk_queue.write_cv)); + + mutex_exit(&(kctx->auk_queue.lock)); + + return (0); +} + +static int +getcwd(caddr_t data, int length) +{ + struct p_audit_data *pad; + struct audit_path *app; + int pathlen; + + pad = P2A(curproc); + ASSERT(pad != NULL); + + mutex_enter(&(pad->pad_lock)); + app = pad->pad_cwd; + au_pathhold(app); + mutex_exit(&(pad->pad_lock)); + + pathlen = app->audp_sect[1] - app->audp_sect[0]; + if (pathlen > length) { + au_pathrele(app); + return (E2BIG); + } + + if (copyout(app->audp_sect[0], data, pathlen)) { + au_pathrele(app); + return (EFAULT); + } + + au_pathrele(app); + return (0); +} + +static int +getcar(caddr_t data, int length) +{ + struct p_audit_data *pad; + struct audit_path *app; + int pathlen; + + pad = P2A(curproc); + ASSERT(pad != NULL); + + mutex_enter(&(pad->pad_lock)); + app = pad->pad_root; + au_pathhold(app); + mutex_exit(&(pad->pad_lock)); + + pathlen = app->audp_sect[1] - app->audp_sect[0]; + if (pathlen > length) { + au_pathrele(app); + return (E2BIG); + } + + if (copyout(app->audp_sect[0], data, pathlen)) { + au_pathrele(app); + return (EFAULT); + } + + au_pathrele(app); + return (0); +} + +static int +getstat(caddr_t data) +{ + au_kcontext_t *kctx = GET_KCTX_PZ; + + membar_consumer(); + + if (copyout((caddr_t)&(kctx->auk_statistics), data, sizeof (au_stat_t))) + return (EFAULT); + return (0); +} + +static int +setstat(caddr_t data) +{ + au_kcontext_t *kctx = GET_KCTX_PZ; + au_stat_t au_stat; + + if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc)) + return (EINVAL); + + if (copyin(data, &au_stat, sizeof (au_stat_t))) + return (EFAULT); + + if (au_stat.as_generated == CLEAR_VAL) + kctx->auk_statistics.as_generated = 0; + if (au_stat.as_nonattrib == CLEAR_VAL) + kctx->auk_statistics.as_nonattrib = 0; + if (au_stat.as_kernel == CLEAR_VAL) + kctx->auk_statistics.as_kernel = 0; + if (au_stat.as_audit == CLEAR_VAL) + kctx->auk_statistics.as_audit = 0; + if (au_stat.as_auditctl == CLEAR_VAL) + kctx->auk_statistics.as_auditctl = 0; + if (au_stat.as_enqueue == CLEAR_VAL) + kctx->auk_statistics.as_enqueue = 0; + if (au_stat.as_written == CLEAR_VAL) + kctx->auk_statistics.as_written = 0; + if (au_stat.as_wblocked == CLEAR_VAL) + kctx->auk_statistics.as_wblocked = 0; + if (au_stat.as_rblocked == CLEAR_VAL) + kctx->auk_statistics.as_rblocked = 0; + if (au_stat.as_dropped == CLEAR_VAL) + kctx->auk_statistics.as_dropped = 0; + if (au_stat.as_totalsize == CLEAR_VAL) + kctx->auk_statistics.as_totalsize = 0; + + membar_producer(); + + return (0); + +} + +static int +setumask(caddr_t data) +{ + STRUCT_DECL(auditinfo, user_info); + struct proc *p; + const auditinfo_addr_t *ainfo; + model_t model; + + /* setumask not applicable in non-global zones without perzone policy */ + if (!(audit_policy & AUDIT_PERZONE) && (!INGLOBALZONE(curproc))) + return (EINVAL); + + model = get_udatamodel(); + STRUCT_INIT(user_info, model); + + if (copyin(data, STRUCT_BUF(user_info), STRUCT_SIZE(user_info))) + return (EFAULT); + + mutex_enter(&pidlock); /* lock the process queue against updates */ + for (p = practive; p != NULL; p = p->p_next) { + cred_t *cr; + + /* if in non-global zone only modify processes in same zone */ + if (!HASZONEACCESS(curproc, p->p_zone->zone_id)) + continue; + + mutex_enter(&p->p_lock); /* so process doesn't go away */ + + /* skip system processes and ones being created or going away */ + if (p->p_stat == SIDL || p->p_stat == SZOMB || + (p->p_flag & (SSYS | SEXITING | SEXITLWPS))) { + mutex_exit(&p->p_lock); + continue; + } + + mutex_enter(&p->p_crlock); + crhold(cr = p->p_cred); + mutex_exit(&p->p_crlock); + ainfo = crgetauinfo(cr); + if (ainfo == NULL) { + mutex_exit(&p->p_lock); + crfree(cr); + continue; + } + + if (ainfo->ai_auid == STRUCT_FGET(user_info, ai_auid)) { + au_mask_t mask; + int err; + + /* + * Here's a process which matches the specified auid. + * If its mask doesn't already match the new mask, + * save the new mask in the pad, to be picked up + * next syscall. + */ + mask = STRUCT_FGET(user_info, ai_mask); + err = bcmp(&mask, &ainfo->ai_mask, sizeof (au_mask_t)); + crfree(cr); + if (err != 0) { + struct p_audit_data *pad = P2A(p); + ASSERT(pad != NULL); + + mutex_enter(&(pad->pad_lock)); + pad->pad_flags |= PAD_SETMASK; + pad->pad_newmask = mask; + mutex_exit(&(pad->pad_lock)); + + /* + * No need to call set_proc_pre_sys(), since + * t_pre_sys is ALWAYS on when audit is + * enabled...due to syscall auditing. + */ + } + } else { + crfree(cr); + } + mutex_exit(&p->p_lock); + } + mutex_exit(&pidlock); + + return (0); +} + +static int +setsmask(caddr_t data) +{ + STRUCT_DECL(auditinfo, user_info); + struct proc *p; + const auditinfo_addr_t *ainfo; + model_t model; + + /* setsmask not applicable in non-global zones without perzone policy */ + if (!(audit_policy & AUDIT_PERZONE) && (!INGLOBALZONE(curproc))) + return (EINVAL); + + model = get_udatamodel(); + STRUCT_INIT(user_info, model); + + if (copyin(data, STRUCT_BUF(user_info), STRUCT_SIZE(user_info))) + return (EFAULT); + + mutex_enter(&pidlock); /* lock the process queue against updates */ + for (p = practive; p != NULL; p = p->p_next) { + cred_t *cr; + + /* if in non-global zone only modify processes in same zone */ + if (!HASZONEACCESS(curproc, p->p_zone->zone_id)) + continue; + + mutex_enter(&p->p_lock); /* so process doesn't go away */ + + /* skip system processes and ones being created or going away */ + if (p->p_stat == SIDL || p->p_stat == SZOMB || + (p->p_flag & (SSYS | SEXITING | SEXITLWPS))) { + mutex_exit(&p->p_lock); + continue; + } + + mutex_enter(&p->p_crlock); + crhold(cr = p->p_cred); + mutex_exit(&p->p_crlock); + ainfo = crgetauinfo(cr); + if (ainfo == NULL) { + mutex_exit(&p->p_lock); + crfree(cr); + continue; + } + + if (ainfo->ai_asid == STRUCT_FGET(user_info, ai_asid)) { + au_mask_t mask; + int err; + + /* + * Here's a process which matches the specified asid. + * If its mask doesn't already match the new mask, + * save the new mask in the pad, to be picked up + * next syscall. + */ + mask = STRUCT_FGET(user_info, ai_mask); + err = bcmp(&mask, &ainfo->ai_mask, sizeof (au_mask_t)); + crfree(cr); + if (err != 0) { + struct p_audit_data *pad = P2A(p); + ASSERT(pad != NULL); + + mutex_enter(&(pad->pad_lock)); + pad->pad_flags |= PAD_SETMASK; + pad->pad_newmask = mask; + mutex_exit(&(pad->pad_lock)); + + /* + * No need to call set_proc_pre_sys(), since + * t_pre_sys is ALWAYS on when audit is + * enabled...due to syscall auditing. + */ + } + } else { + crfree(cr); + } + mutex_exit(&p->p_lock); + } + mutex_exit(&pidlock); + + return (0); +} + +/* + * Get the current audit state of the system + */ +static int +getcond(caddr_t data) +{ + au_kcontext_t *kctx = GET_KCTX_PZ; + + if (copyout(&(kctx->auk_auditstate), data, sizeof (int))) + return (EFAULT); + + return (0); +} + +/* + * Set the current audit state of the system to on (AUC_AUDITING) or + * off (AUC_NOAUDIT). + */ +/* ARGSUSED */ +static int +setcond(caddr_t data) +{ + int auditstate; + au_kcontext_t *kctx; + + if (!(audit_policy & AUDIT_PERZONE) && (!INGLOBALZONE(curproc))) + return (EINVAL); + + kctx = GET_KCTX_NGZ; + + if (copyin(data, &auditstate, sizeof (int))) + return (EFAULT); + + switch (auditstate) { + case AUC_AUDITING: /* Turn auditing on */ + if (audit_active == C2AUDIT_UNLOADED) + audit_init_module(); + kctx->auk_auditstate = AUC_AUDITING; + if (!(audit_policy & AUDIT_PERZONE) && INGLOBALZONE(curproc)) + set_all_zone_usr_proc_sys(ALL_ZONES); + else + set_all_zone_usr_proc_sys(curproc->p_zone->zone_id); + break; + + case AUC_NOAUDIT: /* Turn auditing off */ + if (kctx->auk_auditstate == AUC_NOAUDIT) + break; + kctx->auk_auditstate = AUC_NOAUDIT; + + /* clear out the audit queue */ + + mutex_enter(&(kctx->auk_queue.lock)); + if (kctx->auk_queue.wt_block) + cv_broadcast(&(kctx->auk_queue.write_cv)); + + /* unblock au_output_thread */ + cv_broadcast(&(kctx->auk_queue.read_cv)); + + mutex_exit(&(kctx->auk_queue.lock)); + break; + + default: + return (EINVAL); + } + + return (0); +} + +static int +getclass(caddr_t data) +{ + au_evclass_map_t event; + au_kcontext_t *kctx = GET_KCTX_PZ; + + if (copyin(data, &event, sizeof (au_evclass_map_t))) + return (EFAULT); + + if (event.ec_number > MAX_KEVENTS) + return (EINVAL); + + event.ec_class = kctx->auk_ets[event.ec_number]; + + if (copyout(&event, data, sizeof (au_evclass_map_t))) + return (EFAULT); + + return (0); +} + +static int +setclass(caddr_t data) +{ + au_evclass_map_t event; + au_kcontext_t *kctx; + + if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc)) + return (EINVAL); + + kctx = GET_KCTX_NGZ; + + if (copyin(data, &event, sizeof (au_evclass_map_t))) + return (EFAULT); + + if (event.ec_number > MAX_KEVENTS) + return (EINVAL); + + kctx->auk_ets[event.ec_number] = event.ec_class; + + return (0); +} + +static int +getpinfo(caddr_t data) +{ + STRUCT_DECL(auditpinfo, apinfo); + proc_t *proc; + const auditinfo_addr_t *ainfo; + model_t model; + cred_t *cr, *newcred; + + model = get_udatamodel(); + STRUCT_INIT(apinfo, model); + + if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo))) + return (EFAULT); + + newcred = cralloc(); + + mutex_enter(&pidlock); + if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) { + mutex_exit(&pidlock); + crfree(newcred); + return (ESRCH); /* no such process */ + } + mutex_enter(&proc->p_lock); /* so process doesn't go away */ + mutex_exit(&pidlock); + + audit_update_context(proc, newcred); /* make sure it's up-to-date */ + + mutex_enter(&proc->p_crlock); + crhold(cr = proc->p_cred); + mutex_exit(&proc->p_crlock); + mutex_exit(&proc->p_lock); + + ainfo = crgetauinfo(cr); + if (ainfo == NULL) { + crfree(cr); + return (EINVAL); + } + + /* designated process has an ipv6 address? */ + if (ainfo->ai_termid.at_type == AU_IPv6) { + crfree(cr); + return (EOVERFLOW); + } + + STRUCT_FSET(apinfo, ap_auid, ainfo->ai_auid); + STRUCT_FSET(apinfo, ap_asid, ainfo->ai_asid); +#ifdef _LP64 + if (model == DATAMODEL_ILP32) { + dev32_t dev; + /* convert internal 64 bit form to 32 bit version */ + if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) { + crfree(cr); + return (EOVERFLOW); + } + STRUCT_FSET(apinfo, ap_termid.port, dev); + } else + STRUCT_FSET(apinfo, ap_termid.port, ainfo->ai_termid.at_port); +#else + STRUCT_FSET(apinfo, ap_termid.port, ainfo->ai_termid.at_port); +#endif + STRUCT_FSET(apinfo, ap_termid.machine, ainfo->ai_termid.at_addr[0]); + STRUCT_FSET(apinfo, ap_mask, ainfo->ai_mask); + + crfree(cr); + + if (copyout(STRUCT_BUF(apinfo), data, STRUCT_SIZE(apinfo))) + return (EFAULT); + + return (0); +} + +static int +getpinfo_addr(caddr_t data, int len) +{ + STRUCT_DECL(auditpinfo_addr, apinfo); + proc_t *proc; + const auditinfo_addr_t *ainfo; + model_t model; + cred_t *cr, *newcred; + + model = get_udatamodel(); + STRUCT_INIT(apinfo, model); + + if (len < STRUCT_SIZE(apinfo)) + return (EOVERFLOW); + + if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo))) + return (EFAULT); + + newcred = cralloc(); + + mutex_enter(&pidlock); + if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) { + mutex_exit(&pidlock); + crfree(newcred); + return (ESRCH); + } + mutex_enter(&proc->p_lock); /* so process doesn't go away */ + mutex_exit(&pidlock); + + audit_update_context(proc, newcred); /* make sure it's up-to-date */ + + mutex_enter(&proc->p_crlock); + crhold(cr = proc->p_cred); + mutex_exit(&proc->p_crlock); + mutex_exit(&proc->p_lock); + + ainfo = crgetauinfo(cr); + if (ainfo == NULL) { + crfree(cr); + return (EINVAL); + } + + STRUCT_FSET(apinfo, ap_auid, ainfo->ai_auid); + STRUCT_FSET(apinfo, ap_asid, ainfo->ai_asid); +#ifdef _LP64 + if (model == DATAMODEL_ILP32) { + dev32_t dev; + /* convert internal 64 bit form to 32 bit version */ + if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) { + crfree(cr); + return (EOVERFLOW); + } + STRUCT_FSET(apinfo, ap_termid.at_port, dev); + } else + STRUCT_FSET(apinfo, ap_termid.at_port, + ainfo->ai_termid.at_port); +#else + STRUCT_FSET(apinfo, ap_termid.at_port, ainfo->ai_termid.at_port); +#endif + STRUCT_FSET(apinfo, ap_termid.at_type, ainfo->ai_termid.at_type); + STRUCT_FSET(apinfo, ap_termid.at_addr[0], ainfo->ai_termid.at_addr[0]); + STRUCT_FSET(apinfo, ap_termid.at_addr[1], ainfo->ai_termid.at_addr[1]); + STRUCT_FSET(apinfo, ap_termid.at_addr[2], ainfo->ai_termid.at_addr[2]); + STRUCT_FSET(apinfo, ap_termid.at_addr[3], ainfo->ai_termid.at_addr[3]); + STRUCT_FSET(apinfo, ap_mask, ainfo->ai_mask); + + crfree(cr); + + if (copyout(STRUCT_BUF(apinfo), data, STRUCT_SIZE(apinfo))) + return (EFAULT); + + return (0); +} + +static int +setpmask(caddr_t data) +{ + STRUCT_DECL(auditpinfo, apinfo); + proc_t *proc; + cred_t *newcred; + auditinfo_addr_t *ainfo; + struct p_audit_data *pad; + + model_t model; + + model = get_udatamodel(); + STRUCT_INIT(apinfo, model); + + if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo))) + return (EFAULT); + + mutex_enter(&pidlock); + if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) { + mutex_exit(&pidlock); + return (ESRCH); + } + mutex_enter(&proc->p_lock); /* so process doesn't go away */ + mutex_exit(&pidlock); + + newcred = cralloc(); + if ((ainfo = crgetauinfo_modifiable(newcred)) == NULL) { + mutex_exit(&proc->p_lock); + crfree(newcred); + return (EINVAL); + } + + mutex_enter(&proc->p_crlock); + crcopy_to(proc->p_cred, newcred); + proc->p_cred = newcred; + + ainfo->ai_mask = STRUCT_FGET(apinfo, ap_mask); + + /* + * Unlock. No need to broadcast changes via set_proc_pre_sys(), + * since t_pre_sys is ALWAYS on when audit is enabled... due to + * syscall auditing. + */ + crfree(newcred); + mutex_exit(&proc->p_crlock); + + /* Reset flag for any previous pending mask change; this supercedes */ + pad = P2A(proc); + ASSERT(pad != NULL); + mutex_enter(&(pad->pad_lock)); + pad->pad_flags &= ~PAD_SETMASK; + mutex_exit(&(pad->pad_lock)); + + mutex_exit(&proc->p_lock); + + return (0); +} + +/* + * The out of control system call + * This is audit kitchen sink aka auditadm, aka auditon + */ +int +auditctl( + int cmd, + caddr_t data, + int length) +{ + int result; + + switch (cmd) { + case A_GETCOND: + case A_GETCAR: + case A_GETCLASS: + case A_GETCWD: + case A_GETKAUDIT: + case A_GETKMASK: + case A_GETPINFO: + case A_GETPINFO_ADDR: + case A_GETPOLICY: + case A_GETQCTRL: + case A_GETSTAT: + if (secpolicy_audit_getattr(CRED()) != 0) + return (EPERM); + break; + default: + if (secpolicy_audit_config(CRED()) != 0) + return (EPERM); + break; + } + + switch (cmd) { + case A_GETPOLICY: + result = getpolicy(data); + break; + case A_SETPOLICY: + result = setpolicy(data); + break; + case A_GETKMASK: + result = getkmask(data); + break; + case A_SETKMASK: + result = setkmask(data); + break; + case A_GETKAUDIT: + result = getkaudit(data, length); + break; + case A_SETKAUDIT: + result = setkaudit(data, length); + break; + case A_GETQCTRL: + result = getqctrl(data); + break; + case A_SETQCTRL: + result = setqctrl(data); + break; + case A_GETCWD: + result = getcwd(data, length); + break; + case A_GETCAR: + result = getcar(data, length); + break; + case A_GETSTAT: + result = getstat(data); + break; + case A_SETSTAT: + result = setstat(data); + break; + case A_SETUMASK: + result = setumask(data); + break; + case A_SETSMASK: + result = setsmask(data); + break; + case A_GETCOND: + result = getcond(data); + break; + case A_SETCOND: + result = setcond(data); + break; + case A_GETCLASS: + result = getclass(data); + break; + case A_SETCLASS: + result = setclass(data); + break; + case A_GETPINFO: + result = getpinfo(data); + break; + case A_GETPINFO_ADDR: + result = getpinfo_addr(data, length); + break; + case A_SETPMASK: + result = setpmask(data); + break; + default: + result = EINVAL; + break; + } + return (result); } diff --git a/usr/src/uts/common/syscall/chdir.c b/usr/src/uts/common/syscall/chdir.c index 66459ef689..84c924f570 100644 --- a/usr/src/uts/common/syscall/chdir.c +++ b/usr/src/uts/common/syscall/chdir.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,8 +31,6 @@ * under license from the Regents of the University of California. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/param.h> #include <sys/isa_defs.h> #include <sys/types.h> @@ -216,7 +214,8 @@ chdirec(vnode_t *vp, int ischroot, int do_traverse) vpp = &PTOU(pp)->u_cdir; } - if (audit_active) /* update abs cwd/root path see c2audit.c */ + /* update abs cwd/root path see c2/audit.c */ + if (AU_AUDITING()) audit_chdirec(vp, vpp); mutex_enter(&pp->p_lock); diff --git a/usr/src/uts/common/syscall/chown.c b/usr/src/uts/common/syscall/chown.c index 04250e1e35..a0a5821374 100644 --- a/usr/src/uts/common/syscall/chown.c +++ b/usr/src/uts/common/syscall/chown.c @@ -106,7 +106,7 @@ fchownat(int fd, char *name, uid_t uid, gid_t gid, int flags) } } - if (audit_active) + if (AU_AUDITING()) audit_setfsat_path(1); /* diff --git a/usr/src/uts/common/syscall/open.c b/usr/src/uts/common/syscall/open.c index e4fc89f3ec..3f5f484f6d 100644 --- a/usr/src/uts/common/syscall/open.c +++ b/usr/src/uts/common/syscall/open.c @@ -48,7 +48,6 @@ #include <sys/uio.h> #include <sys/debug.h> #include <c2/audit.h> -#include <sys/cmn_err.h> /* * Common code for openat(). Check permissions, allocate an open @@ -68,6 +67,7 @@ copen(int startfd, char *fname, int filemode, int createmode) proc_t *p = curproc; uio_seg_t seg = UIO_USERSPACE; char *open_filename = fname; + uint32_t auditing = AU_AUDITING(); if (startfd == AT_FDCWD) { /* @@ -101,7 +101,7 @@ copen(int startfd, char *fname, int filemode, int createmode) * Handle openattrdirat request */ if (filemode & FXATTRDIROPEN) { - if (audit_active) + if (auditing) audit_setfsat_path(1); if (error = lookupnameat(fname, seg, FOLLOW, @@ -185,7 +185,7 @@ copen(int startfd, char *fname, int filemode, int createmode) filemode &= ~FNDELAY; error = falloc((vnode_t *)NULL, filemode, &fp, &fd); if (error == 0) { - if (audit_active) + if (auditing) audit_setfsat_path(1); /* * Last arg is a don't-care term if @@ -200,7 +200,7 @@ copen(int startfd, char *fname, int filemode, int createmode) if (startvp != NULL) VN_RELE(startvp); if (error == 0) { - if (audit_active) + if (auditing) audit_copen(fd, fp, vp); if ((vp->v_flag & VDUP) == 0) { fp->f_vnode = vp; diff --git a/usr/src/uts/common/syscall/ppriv.c b/usr/src/uts/common/syscall/ppriv.c index dfce48662b..14858710d9 100644 --- a/usr/src/uts/common/syscall/ppriv.c +++ b/usr/src/uts/common/syscall/ppriv.c @@ -73,7 +73,7 @@ setppriv(priv_op_t op, priv_ptype_t type, priv_set_t *in_pset) retry: pcr = p->p_cred; - if (audit_active) + if (AU_AUDITING()) audit_setppriv(op, type, &pset, pcr); /* diff --git a/usr/src/uts/common/syscall/sem.c b/usr/src/uts/common/syscall/sem.c index 7029b95c02..316f806c4d 100644 --- a/usr/src/uts/common/syscall/sem.c +++ b/usr/src/uts/common/syscall/sem.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -725,8 +725,10 @@ top: } lock = ipc_commit_end(sem_svc, &sp->sem_perm); } - if (audit_active) + + if (AU_AUDITING()) audit_ipcget(AT_IPC_SEM, (void *)sp); + id = sp->sem_perm.ipc_id; mutex_exit(lock); return (id); diff --git a/usr/src/uts/common/syscall/stat.c b/usr/src/uts/common/syscall/stat.c index 87ede7fe62..90d191bd9e 100644 --- a/usr/src/uts/common/syscall/stat.c +++ b/usr/src/uts/common/syscall/stat.c @@ -103,7 +103,7 @@ cstatat_getvp(int fd, char *name, int follow, vnode_t **vp, cred_t **cred) } *cred = cr; - if (audit_active) + if (AU_AUDITING()) audit_setfsat_path(1); lookup: @@ -144,7 +144,7 @@ static int cstat(vnode_t *vp, struct stat *, int, cred_t *); return (set_errno(EFAULT)); \ if ((fp = getf(fd)) == NULL) \ return (set_errno(EBADF)); \ - if (audit_active) \ + if (AU_AUDITING()) \ audit_setfsat_path(1); \ error = statfn(fp->f_vnode, sb, 0, fp->f_cred); \ releasef(fd); \ diff --git a/usr/src/uts/common/syscall/symlink.c b/usr/src/uts/common/syscall/symlink.c index 700029cf73..99dcdf01a4 100644 --- a/usr/src/uts/common/syscall/symlink.c +++ b/usr/src/uts/common/syscall/symlink.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,8 +31,6 @@ * under license from the Regents of the University of California. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/param.h> #include <sys/isa_defs.h> #include <sys/types.h> @@ -84,7 +82,7 @@ top: vattr.va_mask = AT_TYPE|AT_MODE; error = VOP_SYMLINK(dvp, lpn.pn_path, &vattr, tbuf, CRED(), NULL, 0); - if (audit_active) + if (AU_AUDITING()) audit_symlink_create(dvp, lpn.pn_path, tbuf, error); } diff --git a/usr/src/uts/common/syscall/ucredsys.c b/usr/src/uts/common/syscall/ucredsys.c index 0f5c0e6303..3a9447a147 100644 --- a/usr/src/uts/common/syscall/ucredsys.c +++ b/usr/src/uts/common/syscall/ucredsys.c @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/param.h> #include <sys/types.h> #include <sys/ucred.h> @@ -133,6 +131,7 @@ ucred_get(pid_t pid, void *ubuf) cred_t *pcr; int err; struct ucred_s *uc; + uint32_t auditing = AU_AUDITING(); if (pid == P_MYID || pid == curproc->p_pid) { pcr = CRED(); @@ -144,7 +143,7 @@ ucred_get(pid_t pid, void *ubuf) if (pid < 0) return (set_errno(EINVAL)); - if (audit_active) + if (auditing) updcred = cralloc(); mutex_enter(&pidlock); @@ -161,7 +160,7 @@ ucred_get(pid_t pid, void *ubuf) * Assure that audit data in cred is up-to-date. * updcred will be used or freed. */ - if (audit_active) + if (auditing) audit_update_context(p, updcred); err = priv_proc_cred_perm(CRED(), p, &pcr, VREAD); diff --git a/usr/src/uts/common/syscall/unlink.c b/usr/src/uts/common/syscall/unlink.c index 27546c959a..d8ba91ac9b 100644 --- a/usr/src/uts/common/syscall/unlink.c +++ b/usr/src/uts/common/syscall/unlink.c @@ -80,7 +80,7 @@ unlinkat(int fd, char *name, int flags) } } - if (audit_active) + if (AU_AUDITING()) audit_setfsat_path(1); error = vn_removeat(dirvp, name, diff --git a/usr/src/uts/common/syscall/utime.c b/usr/src/uts/common/syscall/utime.c index 43cdf1d62b..d0ccd869e3 100644 --- a/usr/src/uts/common/syscall/utime.c +++ b/usr/src/uts/common/syscall/utime.c @@ -84,7 +84,7 @@ cfutimesat(int fd, char *fname, int nmflag, vattr_t *vap, int flags, int follow) } } - if (audit_active) + if (AU_AUDITING()) audit_setfsat_path(1); if ((nmflag == 1) || ((nmflag == 2) && (fname != NULL))) { diff --git a/usr/src/uts/i86pc/os/machdep.c b/usr/src/uts/i86pc/os/machdep.c index 9563b061e4..c9f97fc046 100644 --- a/usr/src/uts/i86pc/os/machdep.c +++ b/usr/src/uts/i86pc/os/machdep.c @@ -130,6 +130,7 @@ #include <sys/traptrace.h> #endif /* TRAPTRACE */ +#include <c2/audit.h> #include <sys/clock_impl.h> extern void audit_enterprom(int); @@ -392,14 +393,14 @@ void abort_sequence_enter(char *msg) { if (abort_enable == 0) { - if (audit_active) + if (AU_ZONE_AUDITING(GET_KCTX_GZ)) audit_enterprom(0); return; } - if (audit_active) + if (AU_ZONE_AUDITING(GET_KCTX_GZ)) audit_enterprom(1); debug_enter(msg); - if (audit_active) + if (AU_ZONE_AUDITING(GET_KCTX_GZ)) audit_exitprom(1); } diff --git a/usr/src/uts/i86pc/os/trap.c b/usr/src/uts/i86pc/os/trap.c index ab873d569e..c679eb2626 100644 --- a/usr/src/uts/i86pc/os/trap.c +++ b/usr/src/uts/i86pc/os/trap.c @@ -1850,6 +1850,7 @@ kern_gpfault(struct regs *rp) struct regs tmpregs, *trp = NULL; caddr_t pc = (caddr_t)rp->r_pc; int v; + uint32_t auditing = AU_AUDITING(); /* * if we're not an lwp, or in the case of running native the @@ -1962,10 +1963,10 @@ kern_gpfault(struct regs *rp) lwp_exit(); } - if (audit_active) /* audit core dump */ + if (auditing) /* audit core dump */ audit_core_start(SIGSEGV); v = core(SIGSEGV, B_FALSE); - if (audit_active) /* audit core dump */ + if (auditing) /* audit core dump */ audit_core_finish(v ? CLD_KILLED : CLD_DUMPED); exit(v ? CLD_KILLED : CLD_DUMPED, SIGSEGV); return (0); diff --git a/usr/src/uts/intel/ia32/ml/modstubs.s b/usr/src/uts/intel/ia32/ml/modstubs.s index 5c83b2ff0d..87e1323772 100644 --- a/usr/src/uts/intel/ia32/ml/modstubs.s +++ b/usr/src/uts/intel/ia32/ml/modstubs.s @@ -951,17 +951,11 @@ fcnname/**/_info: \ */ #ifndef C2AUDIT_MODULE MODULE(c2audit,sys); - STUB(c2audit, audit_init, nomod_zero); - STUB(c2audit, _auditsys, nomod_zero); - NO_UNLOAD_STUB(c2audit, audit_free, nomod_zero); + NO_UNLOAD_STUB(c2audit, audit_init_module, nomod_zero); NO_UNLOAD_STUB(c2audit, audit_start, nomod_zero); NO_UNLOAD_STUB(c2audit, audit_finish, nomod_zero); - NO_UNLOAD_STUB(c2audit, audit_newproc, nomod_zero); - NO_UNLOAD_STUB(c2audit, audit_pfree, nomod_zero); - NO_UNLOAD_STUB(c2audit, audit_thread_free, nomod_zero); - NO_UNLOAD_STUB(c2audit, audit_thread_create, nomod_zero); - NO_UNLOAD_STUB(c2audit, audit_falloc, nomod_zero); - NO_UNLOAD_STUB(c2audit, audit_unfalloc, nomod_zero); + NO_UNLOAD_STUB(c2audit, audit, nomod_zero); + NO_UNLOAD_STUB(c2audit, auditdoor, nomod_zero); NO_UNLOAD_STUB(c2audit, audit_closef, nomod_zero); NO_UNLOAD_STUB(c2audit, audit_copen, nomod_zero); NO_UNLOAD_STUB(c2audit, audit_core_start, nomod_zero); @@ -998,9 +992,12 @@ fcnname/**/_info: \ NO_UNLOAD_STUB(c2audit, audit_devpolicy, nomod_zero); NO_UNLOAD_STUB(c2audit, audit_setfsat_path, nomod_zero); NO_UNLOAD_STUB(c2audit, audit_cryptoadm, nomod_zero); - NO_UNLOAD_STUB(c2audit, audit_update_context, nomod_zero); NO_UNLOAD_STUB(c2audit, audit_kssl, nomod_zero); NO_UNLOAD_STUB(c2audit, audit_pf_policy, nomod_zero); + NO_UNLOAD_STUB(c2audit, au_doormsg, nomod_zero); + NO_UNLOAD_STUB(c2audit, au_uwrite, nomod_zero); + NO_UNLOAD_STUB(c2audit, au_to_arg32, nomod_zero); + NO_UNLOAD_STUB(c2audit, au_free_rec, nomod_zero); END_MODULE(c2audit); #endif diff --git a/usr/src/uts/intel/ia32/os/syscall.c b/usr/src/uts/intel/ia32/os/syscall.c index 0f670853a1..e2b6fd0a88 100644 --- a/usr/src/uts/intel/ia32/os/syscall.c +++ b/usr/src/uts/intel/ia32/os/syscall.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -349,14 +349,23 @@ pre_syscall() return (1); /* don't do system call, return EINTR */ } - if (audit_active) { /* begin auditing for this syscall */ - int error; - if (error = audit_start(T_SYSCALL, code, 0, lwp)) { - t->t_pre_sys = 1; /* repost anyway */ - (void) set_errno(error); - return (1); + /* + * begin auditing for this syscall if the c2audit module is loaded + * and auditing is enabled + */ + if (audit_active == C2AUDIT_LOADED) { + uint32_t auditing = au_zone_getstate(NULL); + + if (auditing & AU_AUDIT_MASK) { + int error; + if (error = audit_start(T_SYSCALL, code, auditing, \ + 0, lwp)) { + t->t_pre_sys = 1; /* repost anyway */ + (void) set_errno(error); + return (1); + } + repost = 1; } - repost = 1; } #ifndef NPROBE @@ -458,7 +467,9 @@ post_syscall(long rval1, long rval2) rp->r_ps &= ~PS_T; aston(curthread); } - if (audit_active) { /* put out audit record for this syscall */ + + /* put out audit record for this syscall */ + if (AU_AUDITING()) { rval_t rval; /* XX64 -- truncation of 64-bit return values? */ @@ -1321,6 +1332,48 @@ set_all_proc_sys() } /* + * set_all_zone_usr_proc_sys - set pre- and post-syscall processing flags for + * all user processes running in the zone of the current process + * + * This is needed when auditing, tracing, or other facilities which affect + * all processes are turned on. + */ +void +set_all_zone_usr_proc_sys(zoneid_t zoneid) +{ + proc_t *p; + kthread_t *t; + + mutex_enter(&pidlock); + for (p = practive; p != NULL; p = p->p_next) { + /* skip kernel and incomplete processes */ + if (p->p_exec == NULLVP || p->p_as == &kas || + p->p_stat == SIDL || p->p_stat == SZOMB || + (p->p_flag & (SSYS | SEXITING | SEXITLWPS))) + continue; + /* + * Only processes in the given zone (eventually in + * all zones) are taken into account + */ + if (zoneid == ALL_ZONES || p->p_zone->zone_id == zoneid) { + mutex_enter(&p->p_lock); + if ((t = p->p_tlist) == NULL) + continue; + /* + * Set pre- and post-syscall processing flags + * for all threads of the process + */ + do { + t->t_pre_sys = 1; + t->t_post_sys = 1; + } while (p->p_tlist != (t = t->t_forw)); + mutex_exit(&p->p_lock); + } + } + mutex_exit(&pidlock); +} + +/* * set_proc_ast - Set asynchronous service trap (AST) flag for all * threads in process. */ diff --git a/usr/src/uts/sparc/ml/modstubs.s b/usr/src/uts/sparc/ml/modstubs.s index e3720f8d34..c04ceea2c9 100644 --- a/usr/src/uts/sparc/ml/modstubs.s +++ b/usr/src/uts/sparc/ml/modstubs.s @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -871,17 +871,11 @@ stubs_base: */ #ifndef C2AUDIT_MODULE MODULE(c2audit,sys); - STUB(c2audit, audit_init, nomod_zero); - STUB(c2audit, _auditsys, nomod_zero); - NO_UNLOAD_STUB(c2audit, audit_free, nomod_zero); + NO_UNLOAD_STUB(c2audit, audit_init_module, nomod_zero); NO_UNLOAD_STUB(c2audit, audit_start, nomod_zero); NO_UNLOAD_STUB(c2audit, audit_finish, nomod_zero); - NO_UNLOAD_STUB(c2audit, audit_newproc, nomod_zero); - NO_UNLOAD_STUB(c2audit, audit_pfree, nomod_zero); - NO_UNLOAD_STUB(c2audit, audit_thread_free, nomod_zero); - NO_UNLOAD_STUB(c2audit, audit_thread_create, nomod_zero); - NO_UNLOAD_STUB(c2audit, audit_falloc, nomod_zero); - NO_UNLOAD_STUB(c2audit, audit_unfalloc, nomod_zero); + NO_UNLOAD_STUB(c2audit, audit, nomod_zero); + NO_UNLOAD_STUB(c2audit, auditdoor, nomod_zero); NO_UNLOAD_STUB(c2audit, audit_closef, nomod_zero); NO_UNLOAD_STUB(c2audit, audit_copen, nomod_zero); NO_UNLOAD_STUB(c2audit, audit_core_start, nomod_zero); @@ -918,9 +912,12 @@ stubs_base: NO_UNLOAD_STUB(c2audit, audit_devpolicy, nomod_zero); NO_UNLOAD_STUB(c2audit, audit_setfsat_path, nomod_zero); NO_UNLOAD_STUB(c2audit, audit_cryptoadm, nomod_zero); - NO_UNLOAD_STUB(c2audit, audit_update_context, nomod_zero); NO_UNLOAD_STUB(c2audit, audit_kssl, nomod_zero); NO_UNLOAD_STUB(c2audit, audit_pf_policy, nomod_zero); + NO_UNLOAD_STUB(c2audit, au_doormsg, nomod_zero); + NO_UNLOAD_STUB(c2audit, au_uwrite, nomod_zero); + NO_UNLOAD_STUB(c2audit, au_to_arg32, nomod_zero); + NO_UNLOAD_STUB(c2audit, au_free_rec, nomod_zero); END_MODULE(c2audit); #endif diff --git a/usr/src/uts/sparc/os/syscall.c b/usr/src/uts/sparc/os/syscall.c index 4bb8851d9e..6157f6addd 100644 --- a/usr/src/uts/sparc/os/syscall.c +++ b/usr/src/uts/sparc/os/syscall.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -452,14 +452,20 @@ pre_syscall(int arg0) return (1); /* don't do system call, return EINTR */ } - if (audit_active) { /* begin auditing for this syscall */ - int error; - if (error = audit_start(T_SYSCALL, code, 0, lwp)) { - t->t_pre_sys = 1; /* repost anyway */ - lwp->lwp_error = 0; /* for old drivers */ - return (error); + /* begin auditing for this syscall */ + if (audit_active == C2AUDIT_LOADED) { + uint32_t auditing = au_zone_getstate(NULL); + + if (auditing & AU_AUDIT_MASK) { + int error; + if (error = audit_start(T_SYSCALL, code, auditing, \ + 0, lwp)) { + t->t_pre_sys = 1; /* repost anyway */ + lwp->lwp_error = 0; /* for old drivers */ + return (error); + } + repost = 1; } - repost = 1; } #ifndef NPROBE @@ -550,7 +556,8 @@ post_syscall(long rval1, long rval2) if (code == 0) goto sig_check; - if (audit_active) { /* put out audit record for this syscall */ + /* put out audit record for this syscall */ + if (AU_AUDITING()) { rval_t rval; /* fix audit_finish() someday */ /* XX64 -- truncation of 64-bit return values? */ @@ -1166,6 +1173,47 @@ set_all_proc_sys() } /* + * set_all_zone_usr_proc_sys - set pre- and post-syscall processing flags for + * all user processes running in the zone of the current process + * + * This is needed when auditing is turned on. + */ +void +set_all_zone_usr_proc_sys(zoneid_t zoneid) +{ + proc_t *p; + kthread_t *t; + + mutex_enter(&pidlock); + for (p = practive; p != NULL; p = p->p_next) { + /* skip kernel processes */ + if (p->p_exec == NULLVP || p->p_as == &kas || + p->p_stat == SIDL || p->p_stat == SZOMB || + (p->p_flag & (SSYS | SEXITING | SEXITLWPS))) + continue; + /* + * Only processes in the given zone (eventually in + * all zones) are taken into account + */ + if (zoneid == ALL_ZONES || p->p_zone->zone_id == zoneid) { + mutex_enter(&p->p_lock); + if ((t = p->p_tlist) == NULL) + continue; + /* + * Set pre- and post-syscall processing flags + * for all threads of the process + */ + do { + t->t_pre_sys = 1; + t->t_post_sys = 1; + } while (p->p_tlist != (t = t->t_forw)); + mutex_exit(&p->p_lock); + } + } + mutex_exit(&pidlock); +} + +/* * set_proc_ast - Set asynchronous service trap (AST) flag for all * threads in process. */ diff --git a/usr/src/uts/sun4/os/cpu_states.c b/usr/src/uts/sun4/os/cpu_states.c index 34298bbb06..5c53df1182 100644 --- a/usr/src/uts/sun4/os/cpu_states.c +++ b/usr/src/uts/sun4/os/cpu_states.c @@ -19,11 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" #include <sys/reboot.h> #include <sys/systm.h> @@ -38,6 +37,7 @@ #include <sys/kdi_machimpl.h> #include <sys/callb.h> #include <sys/wdt.h> +#include <c2/audit.h> #ifdef TRAPTRACE #include <sys/traptrace.h> @@ -97,8 +97,9 @@ static char abort_seq_msgbuf[ABORT_SEQ_MSGBUFSZ]; static uint_t abort_seq_softintr(caddr_t arg) { - char *msg; - char msgbuf[ABORT_SEQ_MSGBUFSZ]; + char *msg; + char msgbuf[ABORT_SEQ_MSGBUFSZ]; + uint32_t auditing = AU_ZONE_AUDITING(GET_KCTX_GZ); mutex_enter(&abort_seq_lock); if (abort_enable != 0 && abort_seq_tstamp != 0LL) { @@ -109,14 +110,14 @@ abort_seq_softintr(caddr_t arg) msg = NULL; abort_seq_tstamp = 0LL; mutex_exit(&abort_seq_lock); - if (audit_active) + if (auditing) audit_enterprom(1); (*abort_seq_handler)(msg); - if (audit_active) + if (auditing) audit_exitprom(1); } else { mutex_exit(&abort_seq_lock); - if (audit_active) + if (auditing) audit_enterprom(0); } return (1); @@ -141,6 +142,7 @@ abort_sequence_enter(char *msg) int s, on_intr; size_t msglen; hrtime_t tstamp; + int auditing = AU_ZONE_AUDITING(GET_KCTX_GZ); if (abort_enable != 0) { s = splhi(); @@ -183,14 +185,14 @@ abort_sequence_enter(char *msg) */ abort_seq_tstamp = 0LL; mutex_exit(&abort_seq_lock); - if (!on_intr && audit_active) + if (!on_intr && auditing) audit_enterprom(1); (*abort_seq_handler)(msg); - if (!on_intr && audit_active) + if (!on_intr && auditing) audit_exitprom(1); } } else { - if (audit_active) + if (auditing) audit_enterprom(0); } } |