10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
52334Ssetje * Common Development and Distribution License (the "License").
62334Ssetje * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*12160SMarek.Pospisil@Sun.COM * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
260Sstevel@tonic-gate /* All Rights Reserved */
270Sstevel@tonic-gate
280Sstevel@tonic-gate
290Sstevel@tonic-gate
306425Sgww #include <errno.h>
310Sstevel@tonic-gate #include <fcntl.h>
320Sstevel@tonic-gate #include <stdio.h>
330Sstevel@tonic-gate #include <stdlib.h>
346425Sgww #include <string.h>
356425Sgww #include <strings.h>
360Sstevel@tonic-gate #include <signal.h>
376425Sgww #include <unistd.h>
389160SSherry.Moore@Sun.COM #ifdef __i386
399160SSherry.Moore@Sun.COM #include <libscf_priv.h>
409160SSherry.Moore@Sun.COM #endif /* __i386 */
416425Sgww
425319Stz204579 #include <bsm/adt.h>
435319Stz204579 #include <bsm/adt_event.h>
446425Sgww
456680Sgww #include <sys/types.h>
466425Sgww #include <sys/uadmin.h>
476680Sgww #include <sys/wait.h>
480Sstevel@tonic-gate
495319Stz204579 #define SMF_RST "/etc/svc/volatile/resetting"
506680Sgww #define RETRY_COUNT 15 /* number of 1 sec retries for audit(1M) to complete */
512334Ssetje
520Sstevel@tonic-gate static const char *Usage = "Usage: %s cmd fcn [mdep]\n";
530Sstevel@tonic-gate
546680Sgww static int closeout_audit(int, int);
556680Sgww static int turnoff_auditd(void);
565319Stz204579 static void wait_for_auqueue();
576680Sgww static int change_audit_file(void);
580Sstevel@tonic-gate
590Sstevel@tonic-gate int
main(int argc,char * argv[])600Sstevel@tonic-gate main(int argc, char *argv[])
610Sstevel@tonic-gate {
620Sstevel@tonic-gate int cmd, fcn;
630Sstevel@tonic-gate uintptr_t mdep = NULL;
640Sstevel@tonic-gate sigset_t set;
655319Stz204579 adt_session_data_t *ah; /* audit session handle */
665319Stz204579 adt_event_data_t *event = NULL; /* event to be generated */
675319Stz204579 au_event_t event_id;
685319Stz204579 enum adt_uadmin_fcn fcn_id;
690Sstevel@tonic-gate
700Sstevel@tonic-gate if (argc < 3 || argc > 4) {
710Sstevel@tonic-gate (void) fprintf(stderr, Usage, argv[0]);
720Sstevel@tonic-gate return (1);
730Sstevel@tonic-gate }
740Sstevel@tonic-gate
750Sstevel@tonic-gate (void) sigfillset(&set);
760Sstevel@tonic-gate (void) sigprocmask(SIG_BLOCK, &set, NULL);
770Sstevel@tonic-gate
780Sstevel@tonic-gate cmd = atoi(argv[1]);
790Sstevel@tonic-gate fcn = atoi(argv[2]);
800Sstevel@tonic-gate if (argc == 4) { /* mdep argument given */
815295Srandyf if (cmd != A_REBOOT && cmd != A_SHUTDOWN && cmd != A_DUMP &&
825295Srandyf cmd != A_FREEZE) {
830Sstevel@tonic-gate (void) fprintf(stderr, "%s: mdep argument not "
840Sstevel@tonic-gate "allowed for this cmd value\n", argv[0]);
850Sstevel@tonic-gate (void) fprintf(stderr, Usage, argv[0]);
860Sstevel@tonic-gate return (1);
870Sstevel@tonic-gate } else {
880Sstevel@tonic-gate mdep = (uintptr_t)argv[3];
890Sstevel@tonic-gate }
900Sstevel@tonic-gate }
910Sstevel@tonic-gate
925319Stz204579 /* set up audit session and event */
935319Stz204579 if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) {
945319Stz204579 (void) fprintf(stderr, "%s: can't start audit session\n",
955319Stz204579 argv[0]);
965319Stz204579 }
975319Stz204579 switch (cmd) {
985319Stz204579 case A_SHUTDOWN:
995319Stz204579 event_id = ADT_uadmin_shutdown;
1005319Stz204579 break;
1015319Stz204579 case A_REBOOT:
1025319Stz204579 event_id = ADT_uadmin_reboot;
1035319Stz204579 break;
1045319Stz204579 case A_DUMP:
1055319Stz204579 event_id = ADT_uadmin_dump;
1065319Stz204579 break;
1075319Stz204579 case A_REMOUNT:
1085319Stz204579 event_id = ADT_uadmin_remount;
1095319Stz204579 break;
1105319Stz204579 case A_FREEZE:
1115319Stz204579 event_id = ADT_uadmin_freeze;
1125319Stz204579 break;
1135319Stz204579 case A_FTRACE:
1145319Stz204579 event_id = ADT_uadmin_ftrace;
1155319Stz204579 break;
1169160SSherry.Moore@Sun.COM case A_CONFIG:
1179160SSherry.Moore@Sun.COM event_id = ADT_uadmin_config;
1189160SSherry.Moore@Sun.COM break;
1195319Stz204579 case A_SWAPCTL:
1205319Stz204579 event_id = ADT_uadmin_swapctl;
1215319Stz204579 break;
1225319Stz204579 default:
1235319Stz204579 event_id = 0;
1245319Stz204579 }
1255319Stz204579 if ((event_id != 0) &&
1265319Stz204579 (event = adt_alloc_event(ah, event_id)) == NULL) {
1275319Stz204579 (void) fprintf(stderr, "%s: can't allocate audit event\n",
1285319Stz204579 argv[0]);
1295319Stz204579 }
1305319Stz204579 switch (fcn) {
1315319Stz204579 case AD_HALT:
1325319Stz204579 fcn_id = ADT_UADMIN_FCN_AD_HALT;
1335319Stz204579 break;
1345319Stz204579 case AD_POWEROFF:
1355319Stz204579 fcn_id = ADT_UADMIN_FCN_AD_POWEROFF;
1365319Stz204579 break;
1375319Stz204579 case AD_BOOT:
1385319Stz204579 fcn_id = ADT_UADMIN_FCN_AD_BOOT;
1395319Stz204579 break;
1405319Stz204579 case AD_IBOOT:
1415319Stz204579 fcn_id = ADT_UADMIN_FCN_AD_IBOOT;
1425319Stz204579 break;
1435319Stz204579 case AD_SBOOT:
1445319Stz204579 fcn_id = ADT_UADMIN_FCN_AD_SBOOT;
1455319Stz204579 break;
1465319Stz204579 case AD_SIBOOT:
1475319Stz204579 fcn_id = ADT_UADMIN_FCN_AD_SIBOOT;
1485319Stz204579 break;
1495319Stz204579 case AD_NOSYNC:
1505319Stz204579 fcn_id = ADT_UADMIN_FCN_AD_NOSYNC;
1515319Stz204579 break;
1527656SSherry.Moore@Sun.COM case AD_FASTREBOOT:
1537656SSherry.Moore@Sun.COM #ifdef __i386
1547656SSherry.Moore@Sun.COM fcn_id = ADT_UADMIN_FCN_AD_FASTREBOOT;
1557656SSherry.Moore@Sun.COM mdep = NULL; /* Ignore all arguments */
1569160SSherry.Moore@Sun.COM #else /* __i386 */
1577656SSherry.Moore@Sun.COM fcn = AD_BOOT;
1587656SSherry.Moore@Sun.COM fcn_id = ADT_UADMIN_FCN_AD_BOOT;
1597656SSherry.Moore@Sun.COM #endif /* __i386 */
1607656SSherry.Moore@Sun.COM break;
1617656SSherry.Moore@Sun.COM case AD_FASTREBOOT_DRYRUN:
1627656SSherry.Moore@Sun.COM fcn_id = ADT_UADMIN_FCN_AD_FASTREBOOT_DRYRUN;
1637656SSherry.Moore@Sun.COM mdep = NULL; /* Ignore all arguments */
1647656SSherry.Moore@Sun.COM break;
1655319Stz204579 default:
1665319Stz204579 fcn_id = 0;
1675319Stz204579 }
1685319Stz204579 if (cmd == A_FREEZE) {
1695319Stz204579 switch (fcn) {
1705319Stz204579 case AD_SUSPEND_TO_DISK:
1715319Stz204579 fcn_id = ADT_UADMIN_FCN_AD_SUSPEND_TO_DISK;
1725319Stz204579 break;
1735319Stz204579 case AD_CHECK_SUSPEND_TO_DISK:
1745319Stz204579 fcn_id = ADT_UADMIN_FCN_AD_CHECK_SUSPEND_TO_DISK;
1755319Stz204579 break;
1765319Stz204579 case AD_FORCE:
1775319Stz204579 fcn_id = ADT_UADMIN_FCN_AD_FORCE;
1785319Stz204579 break;
1795319Stz204579 case AD_SUSPEND_TO_RAM:
1805319Stz204579 fcn_id = ADT_UADMIN_FCN_AD_SUSPEND_TO_RAM;
1815319Stz204579 break;
1825319Stz204579 case AD_CHECK_SUSPEND_TO_RAM:
1835319Stz204579 fcn_id = ADT_UADMIN_FCN_AD_CHECK_SUSPEND_TO_RAM;
1845319Stz204579 break;
1855319Stz204579 case AD_REUSEINIT:
1865319Stz204579 fcn_id = ADT_UADMIN_FCN_AD_REUSEINIT;
1875319Stz204579 break;
1885319Stz204579 case AD_REUSABLE:
1895319Stz204579 fcn_id = ADT_UADMIN_FCN_AD_REUSABLE;
1905319Stz204579 break;
1915319Stz204579 case AD_REUSEFINI:
1925319Stz204579 fcn_id = ADT_UADMIN_FCN_AD_REUSEFINI;
1935319Stz204579 break;
1945319Stz204579 }
1955319Stz204579 } else if (cmd == A_FTRACE) {
1965319Stz204579 switch (fcn) {
1975319Stz204579 case AD_FTRACE_START:
1985319Stz204579 fcn_id = ADT_UADMIN_FCN_AD_FTRACE_START;
1995319Stz204579 break;
2005319Stz204579 case AD_FTRACE_STOP:
2015319Stz204579 fcn_id = ADT_UADMIN_FCN_AD_FTRACE_STOP;
2025319Stz204579 break;
2035319Stz204579 }
2049160SSherry.Moore@Sun.COM #ifdef __i386
2059160SSherry.Moore@Sun.COM } else if (cmd == A_CONFIG) {
20610559SSherry.Moore@Sun.COM uint8_t boot_config = 0;
20710559SSherry.Moore@Sun.COM uint8_t boot_config_ovr = 0;
20810559SSherry.Moore@Sun.COM
2099160SSherry.Moore@Sun.COM switch (fcn) {
2109160SSherry.Moore@Sun.COM case AD_UPDATE_BOOT_CONFIG:
2119160SSherry.Moore@Sun.COM fcn_id = ADT_UADMIN_FCN_AD_UPDATE_BOOT_CONFIG;
2129160SSherry.Moore@Sun.COM scf_get_boot_config(&boot_config);
21310559SSherry.Moore@Sun.COM boot_config_ovr = boot_config;
21410559SSherry.Moore@Sun.COM scf_get_boot_config_ovr(&boot_config_ovr);
21510559SSherry.Moore@Sun.COM boot_config &= boot_config_ovr;
2169160SSherry.Moore@Sun.COM mdep = (uintptr_t)(&boot_config);
2179160SSherry.Moore@Sun.COM break;
2189160SSherry.Moore@Sun.COM }
2199160SSherry.Moore@Sun.COM #endif /* __i386 */
2205319Stz204579 }
2215319Stz204579
2220Sstevel@tonic-gate if (geteuid() == 0) {
2235319Stz204579 if (event != NULL) {
2245319Stz204579 switch (cmd) {
2255319Stz204579 case A_SHUTDOWN:
2265319Stz204579 event->adt_uadmin_shutdown.fcn = fcn_id;
2275319Stz204579 event->adt_uadmin_shutdown.mdep = (char *)mdep;
2285319Stz204579 break;
2295319Stz204579 case A_REBOOT:
2305319Stz204579 event->adt_uadmin_reboot.fcn = fcn_id;
2315319Stz204579 event->adt_uadmin_reboot.mdep = (char *)mdep;
2325319Stz204579 break;
2335319Stz204579 case A_DUMP:
2345319Stz204579 event->adt_uadmin_dump.fcn = fcn_id;
2355319Stz204579 event->adt_uadmin_dump.mdep = (char *)mdep;
2365319Stz204579 break;
2375319Stz204579 case A_REMOUNT:
2385319Stz204579 /* no parameters */
2395319Stz204579 break;
2405319Stz204579 case A_FREEZE:
2415319Stz204579 event->adt_uadmin_freeze.fcn = fcn_id;
2425319Stz204579 event->adt_uadmin_freeze.mdep = (char *)mdep;
2435319Stz204579 break;
2445319Stz204579 case A_FTRACE:
2455319Stz204579 event->adt_uadmin_ftrace.fcn = fcn_id;
2469160SSherry.Moore@Sun.COM event->adt_uadmin_ftrace.mdep = (char *)mdep;
2479160SSherry.Moore@Sun.COM break;
2489160SSherry.Moore@Sun.COM case A_CONFIG:
2499160SSherry.Moore@Sun.COM event->adt_uadmin_config.fcn = fcn_id;
2509160SSherry.Moore@Sun.COM event->adt_uadmin_config.mdep = (char *)mdep;
2515319Stz204579 break;
2525319Stz204579 case A_SWAPCTL:
2535319Stz204579 event->adt_uadmin_swapctl.fcn = fcn_id;
2545319Stz204579 break;
2555319Stz204579 }
2565319Stz204579
2575319Stz204579 if (adt_put_event(event, ADT_SUCCESS, 0) != 0) {
2585319Stz204579 (void) fprintf(stderr,
2595319Stz204579 "%s: can't put audit event\n", argv[0]);
2605319Stz204579 }
2615319Stz204579 /*
2625319Stz204579 * allow audit record to be processed in the kernel
2635319Stz204579 * audit queue
2645319Stz204579 */
2655319Stz204579 wait_for_auqueue();
2665319Stz204579 }
2675319Stz204579
2686680Sgww if (closeout_audit(cmd, fcn) == -1)
2690Sstevel@tonic-gate (void) fprintf(stderr, "%s: can't turn off auditd\n",
2700Sstevel@tonic-gate argv[0]);
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate if (cmd == A_SHUTDOWN || cmd == A_REBOOT)
2732334Ssetje (void) creat(SMF_RST, 0777);
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate
2765319Stz204579 (void) adt_free_event(event);
2770Sstevel@tonic-gate if (uadmin(cmd, fcn, mdep) < 0) {
2780Sstevel@tonic-gate perror("uadmin");
2790Sstevel@tonic-gate
2802334Ssetje (void) unlink(SMF_RST);
2812334Ssetje
2820Sstevel@tonic-gate return (1);
2830Sstevel@tonic-gate }
2840Sstevel@tonic-gate
2856680Sgww /* If returning from a suspend, audit thaw */
2866680Sgww if ((cmd == A_FREEZE) &&
2876680Sgww ((fcn == AD_FORCE) ||
2886680Sgww (fcn == AD_REUSABLE) ||
2896680Sgww (fcn == AD_SUSPEND_TO_DISK) ||
2906680Sgww (fcn == AD_SUSPEND_TO_RAM))) {
2916680Sgww if ((event = adt_alloc_event(ah, ADT_uadmin_thaw)) == NULL) {
2926680Sgww (void) fprintf(stderr, "%s: can't allocate thaw audit "
2936680Sgww "event\n", argv[0]);
2946680Sgww }
2956680Sgww event->adt_uadmin_thaw.fcn = fcn_id;
2966680Sgww if (adt_put_event(event, ADT_SUCCESS, 0) != 0) {
2976680Sgww (void) fprintf(stderr, "%s: can't put thaw audit "
2986680Sgww "event\n", argv[0]);
2996680Sgww }
3006680Sgww (void) adt_free_event(event);
3016680Sgww }
3026680Sgww (void) adt_end_session(ah);
3036680Sgww
3040Sstevel@tonic-gate return (0);
3050Sstevel@tonic-gate }
3065319Stz204579
3075319Stz204579 static int
closeout_audit(int cmd,int fcn)3086680Sgww closeout_audit(int cmd, int fcn)
3095319Stz204579 {
3106680Sgww if (!adt_audit_state(AUC_AUDITING)) {
3116680Sgww /* auditd not running, just return */
3126680Sgww return (0);
3136680Sgww }
3146066Sgww switch (cmd) {
3156066Sgww case A_SHUTDOWN:
3167656SSherry.Moore@Sun.COM switch (fcn) {
3177656SSherry.Moore@Sun.COM case AD_FASTREBOOT_DRYRUN:
3187656SSherry.Moore@Sun.COM /* No system discontinuity, don't turn off auditd */
3197656SSherry.Moore@Sun.COM return (0);
3207656SSherry.Moore@Sun.COM default:
3217656SSherry.Moore@Sun.COM break; /* For all the other shutdown functions */
3227656SSherry.Moore@Sun.COM }
3237656SSherry.Moore@Sun.COM /* FALLTHROUGH */
3246066Sgww case A_REBOOT:
3256066Sgww case A_DUMP:
3266066Sgww /* system shutting down, turn off auditd */
3276680Sgww return (turnoff_auditd());
3286066Sgww case A_REMOUNT:
3296066Sgww case A_SWAPCTL:
3306066Sgww case A_FTRACE:
3319160SSherry.Moore@Sun.COM case A_CONFIG:
3326066Sgww /* No system discontinuity, don't turn off auditd */
3336066Sgww return (0);
3346066Sgww case A_FREEZE:
3356066Sgww switch (fcn) {
3366066Sgww case AD_CHECK_SUSPEND_TO_DISK: /* AD_CHECK */
3376066Sgww case AD_CHECK_SUSPEND_TO_RAM:
3386066Sgww case AD_REUSEINIT:
3396066Sgww case AD_REUSEFINI:
3406066Sgww /* No system discontinuity, don't turn off auditd */
3416066Sgww return (0);
3426066Sgww case AD_REUSABLE:
3436066Sgww case AD_SUSPEND_TO_DISK: /* AD_COMPRESS */
3446066Sgww case AD_SUSPEND_TO_RAM:
3456066Sgww case AD_FORCE:
3466066Sgww /* suspend the system, change audit files */
3476680Sgww return (change_audit_file());
3486066Sgww default:
3496680Sgww return (0); /* not an audit error */
3506066Sgww }
3516066Sgww default:
3526680Sgww return (0); /* not an audit error */
3536066Sgww }
3546680Sgww }
3556680Sgww
3566680Sgww static int
turnoff_auditd(void)3576680Sgww turnoff_auditd(void)
3586680Sgww {
3596680Sgww int rc;
3606680Sgww int retries = RETRY_COUNT;
3616066Sgww
3626680Sgww if ((rc = (int)fork()) == 0) {
363*12160SMarek.Pospisil@Sun.COM (void) execl("/usr/sbin/audit", "audit", "-T", NULL);
3646680Sgww (void) fprintf(stderr, "error disabling auditd: %s\n",
3656680Sgww strerror(errno));
3666680Sgww _exit(-1);
3676680Sgww } else if (rc == -1) {
3686680Sgww (void) fprintf(stderr, "error disabling auditd: %s\n",
3696680Sgww strerror(errno));
3706680Sgww return (-1);
3715319Stz204579 }
3725319Stz204579
3736425Sgww /*
3746425Sgww * wait for auditd to finish its work. auditd will change the
3756425Sgww * auditstart from AUC_AUDITING (auditd up and running) to
3766425Sgww * AUC_NOAUDIT. Other states are errors, so we're done as well.
3776425Sgww */
3785319Stz204579 do {
3796425Sgww int auditstate;
3805319Stz204579
3816425Sgww rc = -1;
3826425Sgww if ((auditon(A_GETCOND, (caddr_t)&auditstate,
3836425Sgww sizeof (auditstate)) == 0) &&
3846425Sgww (auditstate == AUC_AUDITING)) {
3855319Stz204579 retries--;
3865319Stz204579 (void) sleep(1);
3875319Stz204579 } else {
3885319Stz204579 rc = 0;
3895319Stz204579 }
3906425Sgww } while ((rc != 0) && (retries != 0));
3915319Stz204579
3925319Stz204579 return (rc);
3935319Stz204579 }
3945319Stz204579
3956680Sgww static int
change_audit_file(void)3966680Sgww change_audit_file(void)
3976680Sgww {
3986680Sgww pid_t pid;
3996680Sgww
4006680Sgww if ((pid = fork()) == 0) {
4016680Sgww (void) execl("/usr/sbin/audit", "audit", "-n", NULL);
4026680Sgww (void) fprintf(stderr, "error changing audit files: %s\n",
4036680Sgww strerror(errno));
4046680Sgww _exit(-1);
4056680Sgww } else if (pid == -1) {
4066680Sgww (void) fprintf(stderr, "error changing audit files: %s\n",
4076680Sgww strerror(errno));
4086680Sgww return (-1);
4096680Sgww } else {
4106680Sgww pid_t rc;
4116680Sgww int retries = RETRY_COUNT;
4126680Sgww
4136680Sgww /*
4146680Sgww * Wait for audit(1M) -n process to complete
4156680Sgww *
4166680Sgww */
4176680Sgww do {
4186680Sgww if ((rc = waitpid(pid, NULL, WNOHANG)) == pid) {
4196680Sgww return (0);
4206680Sgww } else if (rc == -1) {
4216680Sgww return (-1);
4226680Sgww } else {
4236680Sgww (void) sleep(1);
4246680Sgww retries--;
4256680Sgww }
4266680Sgww
4276680Sgww } while (retries != 0);
4286680Sgww }
4296680Sgww return (-1);
4306680Sgww }
4316680Sgww
4325319Stz204579 static void
wait_for_auqueue()4335319Stz204579 wait_for_auqueue()
4345319Stz204579 {
4355319Stz204579 au_stat_t au_stat;
4365319Stz204579 int retries = 10;
4375319Stz204579
4385319Stz204579 while (retries-- && auditon(A_GETSTAT, (caddr_t)&au_stat, NULL) == 0) {
4395319Stz204579 if (au_stat.as_enqueue == au_stat.as_written) {
4405319Stz204579 break;
4415319Stz204579 }
4425319Stz204579 (void) sleep(1);
4435319Stz204579 }
4445319Stz204579 }
445