Home | History | Annotate | Download | only in syscall
      1      0    stevel /*
      2      0    stevel  * CDDL HEADER START
      3      0    stevel  *
      4      0    stevel  * The contents of this file are subject to the terms of the
      5   2267        dp  * Common Development and Distribution License (the "License").
      6   2267        dp  * You may not use this file except in compliance with the License.
      7      0    stevel  *
      8      0    stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9      0    stevel  * or http://www.opensolaris.org/os/licensing.
     10      0    stevel  * See the License for the specific language governing permissions
     11      0    stevel  * and limitations under the License.
     12      0    stevel  *
     13      0    stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14      0    stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15      0    stevel  * If applicable, add the following below this CDDL HEADER, with the
     16      0    stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17      0    stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18      0    stevel  *
     19      0    stevel  * CDDL HEADER END
     20      0    stevel  */
     21    390       raf 
     22      0    stevel /*
     23   9160    Sherry  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24      0    stevel  * Use is subject to license terms.
     25      0    stevel  */
     26      0    stevel 
     27      0    stevel #include <sys/param.h>
     28      0    stevel #include <sys/types.h>
     29      0    stevel #include <sys/sysmacros.h>
     30      0    stevel #include <sys/systm.h>
     31      0    stevel #include <sys/errno.h>
     32      0    stevel #include <sys/vfs.h>
     33      0    stevel #include <sys/vnode.h>
     34      0    stevel #include <sys/swap.h>
     35      0    stevel #include <sys/file.h>
     36      0    stevel #include <sys/proc.h>
     37      0    stevel #include <sys/var.h>
     38      0    stevel #include <sys/uadmin.h>
     39      0    stevel #include <sys/signal.h>
     40      0    stevel #include <sys/time.h>
     41      0    stevel #include <vm/seg_kmem.h>
     42      0    stevel #include <sys/modctl.h>
     43      0    stevel #include <sys/callb.h>
     44      0    stevel #include <sys/dumphdr.h>
     45      0    stevel #include <sys/debug.h>
     46      0    stevel #include <sys/ftrace.h>
     47      0    stevel #include <sys/cmn_err.h>
     48      0    stevel #include <sys/panic.h>
     49      0    stevel #include <sys/ddi.h>
     50      0    stevel #include <sys/sunddi.h>
     51      0    stevel #include <sys/policy.h>
     52      0    stevel #include <sys/zone.h>
     53   4579  cg209009 #include <sys/condvar.h>
     54   4579  cg209009 #include <sys/thread.h>
     55   6878   brendan #include <sys/sdt.h>
     56      0    stevel 
     57      0    stevel /*
     58      0    stevel  * Administrivia system call.  We provide this in two flavors: one for calling
     59      0    stevel  * from the system call path (uadmin), and the other for calling from elsewhere
     60      0    stevel  * within the kernel (kadmin).  Callers must beware that certain uadmin cmd
     61      0    stevel  * values (specifically A_SWAPCTL) are only supported by uadmin and not kadmin.
     62      0    stevel  */
     63      0    stevel 
     64      0    stevel extern ksema_t fsflush_sema;
     65      0    stevel kmutex_t ualock;
     66   4579  cg209009 kcondvar_t uacond;
     67   4579  cg209009 kthread_t *ua_shutdown_thread = NULL;
     68      0    stevel 
     69   2621     llai1 int sys_shutdown = 0;
     70   7656    Sherry volatile int fastreboot_dryrun = 0;
     71      0    stevel 
     72      0    stevel /*
     73      0    stevel  * Kill all user processes in said zone.  A special argument of ALL_ZONES is
     74      0    stevel  * passed in when the system as a whole is shutting down.  The lack of per-zone
     75      0    stevel  * process lists is likely to make the following a performance bottleneck on a
     76      0    stevel  * system with many zones.
     77      0    stevel  */
     78      0    stevel void
     79      0    stevel killall(zoneid_t zoneid)
     80      0    stevel {
     81      0    stevel 	proc_t *p;
     82      0    stevel 
     83      0    stevel 	ASSERT(zoneid != GLOBAL_ZONEID);
     84      0    stevel 	/*
     85      0    stevel 	 * Kill all processes except kernel daemons and ourself.
     86      0    stevel 	 * Make a first pass to stop all processes so they won't
     87      0    stevel 	 * be trying to restart children as we kill them.
     88      0    stevel 	 */
     89      0    stevel 	mutex_enter(&pidlock);
     90      0    stevel 	for (p = practive; p != NULL; p = p->p_next) {
     91      0    stevel 		if ((zoneid == ALL_ZONES || p->p_zone->zone_id == zoneid) &&
     92      0    stevel 		    p->p_exec != NULLVP &&	/* kernel daemons */
     93      0    stevel 		    p->p_as != &kas &&
     94      0    stevel 		    p->p_stat != SZOMB) {
     95      0    stevel 			mutex_enter(&p->p_lock);
     96      0    stevel 			p->p_flag |= SNOWAIT;
     97      0    stevel 			sigtoproc(p, NULL, SIGSTOP);
     98      0    stevel 			mutex_exit(&p->p_lock);
     99      0    stevel 		}
    100      0    stevel 	}
    101      0    stevel 	p = practive;
    102      0    stevel 	while (p != NULL) {
    103      0    stevel 		if ((zoneid == ALL_ZONES || p->p_zone->zone_id == zoneid) &&
    104      0    stevel 		    p->p_exec != NULLVP &&	/* kernel daemons */
    105      0    stevel 		    p->p_as != &kas &&
    106      0    stevel 		    p->p_stat != SIDL &&
    107      0    stevel 		    p->p_stat != SZOMB) {
    108      0    stevel 			mutex_enter(&p->p_lock);
    109      0    stevel 			if (sigismember(&p->p_sig, SIGKILL)) {
    110      0    stevel 				mutex_exit(&p->p_lock);
    111      0    stevel 				p = p->p_next;
    112      0    stevel 			} else {
    113      0    stevel 				sigtoproc(p, NULL, SIGKILL);
    114      0    stevel 				mutex_exit(&p->p_lock);
    115  11066    rafael 				(void) cv_reltimedwait(&p->p_srwchan_cv,
    116  11066    rafael 				    &pidlock, hz, TR_CLOCK_TICK);
    117      0    stevel 				p = practive;
    118      0    stevel 			}
    119      0    stevel 		} else {
    120      0    stevel 			p = p->p_next;
    121      0    stevel 		}
    122      0    stevel 	}
    123      0    stevel 	mutex_exit(&pidlock);
    124      0    stevel }
    125      0    stevel 
    126      0    stevel int
    127      0    stevel kadmin(int cmd, int fcn, void *mdep, cred_t *credp)
    128      0    stevel {
    129      0    stevel 	int error = 0;
    130      0    stevel 	char *buf;
    131      0    stevel 	size_t buflen = 0;
    132    136  achartre 	boolean_t invoke_cb = B_FALSE;
    133      0    stevel 
    134      0    stevel 	/*
    135      0    stevel 	 * We might be called directly by the kernel's fault-handling code, so
    136      0    stevel 	 * we can't assert that the caller is in the global zone.
    137      0    stevel 	 */
    138      0    stevel 
    139      0    stevel 	/*
    140      0    stevel 	 * Make sure that cmd is one of the valid <sys/uadmin.h> command codes
    141      0    stevel 	 * and that we have appropriate privileges for this action.
    142      0    stevel 	 */
    143      0    stevel 	switch (cmd) {
    144      0    stevel 	case A_FTRACE:
    145      0    stevel 	case A_SHUTDOWN:
    146      0    stevel 	case A_REBOOT:
    147      0    stevel 	case A_REMOUNT:
    148      0    stevel 	case A_FREEZE:
    149      0    stevel 	case A_DUMP:
    150   6878   brendan 	case A_SDTTEST:
    151   9160    Sherry 	case A_CONFIG:
    152      0    stevel 		if (secpolicy_sys_config(credp, B_FALSE) != 0)
    153      0    stevel 			return (EPERM);
    154      0    stevel 		break;
    155      0    stevel 
    156      0    stevel 	default:
    157      0    stevel 		return (EINVAL);
    158      0    stevel 	}
    159      0    stevel 
    160      0    stevel 	/*
    161   4579  cg209009 	 * Serialize these operations on ualock.  If it is held, the
    162   4579  cg209009 	 * system should shutdown, reboot, or remount shortly, unless there is
    163   4579  cg209009 	 * an error.  We need a cv rather than just a mutex because proper
    164   4579  cg209009 	 * functioning of A_REBOOT relies on being able to interrupt blocked
    165   4579  cg209009 	 * userland callers.
    166   4579  cg209009 	 *
    167   9160    Sherry 	 * We only clear ua_shutdown_thread after A_REMOUNT or A_CONFIG.
    168   9160    Sherry 	 * Other commands should never return.
    169      0    stevel 	 */
    170   9160    Sherry 	if (cmd == A_SHUTDOWN || cmd == A_REBOOT || cmd == A_REMOUNT ||
    171   9160    Sherry 	    cmd == A_CONFIG) {
    172   4579  cg209009 		mutex_enter(&ualock);
    173   4579  cg209009 		while (ua_shutdown_thread != NULL) {
    174   4579  cg209009 			if (cv_wait_sig(&uacond, &ualock) == 0) {
    175   4579  cg209009 				/*
    176   4579  cg209009 				 * If we were interrupted, leave, and handle
    177   4579  cg209009 				 * the signal (or exit, depending on what
    178   4579  cg209009 				 * happened)
    179   4579  cg209009 				 */
    180   4579  cg209009 				mutex_exit(&ualock);
    181   4579  cg209009 				return (EINTR);
    182   4579  cg209009 			}
    183   4579  cg209009 		}
    184   4579  cg209009 		ua_shutdown_thread = curthread;
    185   4579  cg209009 		mutex_exit(&ualock);
    186      0    stevel 	}
    187      0    stevel 
    188      0    stevel 	switch (cmd) {
    189      0    stevel 	case A_SHUTDOWN:
    190      0    stevel 	{
    191      0    stevel 		proc_t *p = ttoproc(curthread);
    192      0    stevel 
    193      0    stevel 		/*
    194      0    stevel 		 * Release (almost) all of our own resources if we are called
    195      0    stevel 		 * from a user context, however if we are calling kadmin() from
    196      0    stevel 		 * a kernel context then we do not release these resources.
    197      0    stevel 		 */
    198    390       raf 		if (p != &p0) {
    199    390       raf 			proc_is_exiting(p);
    200   4434  cg209009 			if ((error = exitlwps(0)) != 0) {
    201   4579  cg209009 				/*
    202   4579  cg209009 				 * Another thread in this process also called
    203   4579  cg209009 				 * exitlwps().
    204   4579  cg209009 				 */
    205   4579  cg209009 				mutex_enter(&ualock);
    206   4579  cg209009 				ua_shutdown_thread = NULL;
    207   4579  cg209009 				cv_signal(&uacond);
    208   4434  cg209009 				mutex_exit(&ualock);
    209      0    stevel 				return (error);
    210   4434  cg209009 			}
    211      0    stevel 			mutex_enter(&p->p_lock);
    212      0    stevel 			p->p_flag |= SNOWAIT;
    213      0    stevel 			sigfillset(&p->p_ignore);
    214      0    stevel 			curthread->t_lwp->lwp_cursig = 0;
    215      0    stevel 			curthread->t_lwp->lwp_extsig = 0;
    216      0    stevel 			if (p->p_exec) {
    217      0    stevel 				vnode_t *exec_vp = p->p_exec;
    218      0    stevel 				p->p_exec = NULLVP;
    219      0    stevel 				mutex_exit(&p->p_lock);
    220      0    stevel 				VN_RELE(exec_vp);
    221      0    stevel 			} else {
    222      0    stevel 				mutex_exit(&p->p_lock);
    223      0    stevel 			}
    224      0    stevel 
    225      0    stevel 			pollcleanup();
    226      0    stevel 			closeall(P_FINFO(curproc));
    227      0    stevel 			relvm();
    228      0    stevel 
    229      0    stevel 		} else {
    230      0    stevel 			/*
    231      0    stevel 			 * Reset t_cred if not set because much of the
    232      0    stevel 			 * filesystem code depends on CRED() being valid.
    233      0    stevel 			 */
    234      0    stevel 			if (curthread->t_cred == NULL)
    235      0    stevel 				curthread->t_cred = kcred;
    236      0    stevel 		}
    237   2621     llai1 
    238   2621     llai1 		/* indicate shutdown in progress */
    239   2621     llai1 		sys_shutdown = 1;
    240      0    stevel 
    241      0    stevel 		/*
    242      0    stevel 		 * Communcate that init shouldn't be restarted.
    243      0    stevel 		 */
    244      0    stevel 		zone_shutdown_global();
    245      0    stevel 
    246      0    stevel 		killall(ALL_ZONES);
    247      0    stevel 		/*
    248      0    stevel 		 * If we are calling kadmin() from a kernel context then we
    249      0    stevel 		 * do not release these resources.
    250      0    stevel 		 */
    251      0    stevel 		if (ttoproc(curthread) != &p0) {
    252   3446       mrj 			VN_RELE(PTOU(curproc)->u_cdir);
    253   3446       mrj 			if (PTOU(curproc)->u_rdir)
    254   3446       mrj 				VN_RELE(PTOU(curproc)->u_rdir);
    255   3446       mrj 			if (PTOU(curproc)->u_cwd)
    256   3446       mrj 				refstr_rele(PTOU(curproc)->u_cwd);
    257      0    stevel 
    258   3446       mrj 			PTOU(curproc)->u_cdir = rootdir;
    259   3446       mrj 			PTOU(curproc)->u_rdir = NULL;
    260   3446       mrj 			PTOU(curproc)->u_cwd = NULL;
    261      0    stevel 		}
    262      0    stevel 
    263      0    stevel 		/*
    264      0    stevel 		 * Allow the reboot/halt/poweroff code a chance to do
    265      0    stevel 		 * anything it needs to whilst we still have filesystems
    266      0    stevel 		 * mounted, like loading any modules necessary for later
    267      0    stevel 		 * performing the actual poweroff.
    268      0    stevel 		 */
    269      0    stevel 		if ((mdep != NULL) && (*(char *)mdep == '/')) {
    270      0    stevel 			buf = i_convert_boot_device_name(mdep, NULL, &buflen);
    271      0    stevel 			mdpreboot(cmd, fcn, buf);
    272      0    stevel 		} else
    273      0    stevel 			mdpreboot(cmd, fcn, mdep);
    274      0    stevel 
    275      0    stevel 		/*
    276      0    stevel 		 * Allow fsflush to finish running and then prevent it
    277      0    stevel 		 * from ever running again so that vfs_unmountall() and
    278      0    stevel 		 * vfs_syncall() can acquire the vfs locks they need.
    279      0    stevel 		 */
    280      0    stevel 		sema_p(&fsflush_sema);
    281      0    stevel 		(void) callb_execute_class(CB_CL_UADMIN_PRE_VFS, NULL);
    282      0    stevel 
    283      0    stevel 		vfs_unmountall();
    284      0    stevel 		(void) VFS_MOUNTROOT(rootvfs, ROOT_UNMOUNT);
    285      0    stevel 		vfs_syncall();
    286      0    stevel 
    287      0    stevel 		dump_ereports();
    288      0    stevel 		dump_messages();
    289    136  achartre 
    290    136  achartre 		invoke_cb = B_TRUE;
    291      0    stevel 
    292      0    stevel 		/* FALLTHROUGH */
    293      0    stevel 	}
    294      0    stevel 
    295      0    stevel 	case A_REBOOT:
    296      0    stevel 		if ((mdep != NULL) && (*(char *)mdep == '/')) {
    297      0    stevel 			buf = i_convert_boot_device_name(mdep, NULL, &buflen);
    298    136  achartre 			mdboot(cmd, fcn, buf, invoke_cb);
    299      0    stevel 		} else
    300    136  achartre 			mdboot(cmd, fcn, mdep, invoke_cb);
    301      0    stevel 		/* no return expected */
    302      0    stevel 		break;
    303      0    stevel 
    304   9160    Sherry 	case A_CONFIG:
    305   9160    Sherry 		switch (fcn) {
    306   9160    Sherry 		case AD_UPDATE_BOOT_CONFIG:
    307   9160    Sherry #ifndef	__sparc
    308   9160    Sherry 		{
    309   9160    Sherry 			extern void fastboot_update_config(const char *);
    310   9160    Sherry 
    311  10559    Sherry 			fastboot_update_config(mdep);
    312   9160    Sherry 		}
    313   9160    Sherry #endif
    314   9160    Sherry 
    315   9160    Sherry 			break;
    316   9160    Sherry 		}
    317   9160    Sherry 		/* Let other threads enter the shutdown path now */
    318   9160    Sherry 		mutex_enter(&ualock);
    319   9160    Sherry 		ua_shutdown_thread = NULL;
    320   9160    Sherry 		cv_signal(&uacond);
    321   9160    Sherry 		mutex_exit(&ualock);
    322   9160    Sherry 		break;
    323   9160    Sherry 
    324      0    stevel 	case A_REMOUNT:
    325      0    stevel 		(void) VFS_MOUNTROOT(rootvfs, ROOT_REMOUNT);
    326   4579  cg209009 		/* Let other threads enter the shutdown path now */
    327   4579  cg209009 		mutex_enter(&ualock);
    328   4579  cg209009 		ua_shutdown_thread = NULL;
    329   4579  cg209009 		cv_signal(&uacond);
    330   4579  cg209009 		mutex_exit(&ualock);
    331      0    stevel 		break;
    332      0    stevel 
    333      0    stevel 	case A_FREEZE:
    334      0    stevel 	{
    335   5295    randyf 		/*
    336   5295    randyf 		 * This is the entrypoint for all suspend/resume actions.
    337   5295    randyf 		 */
    338   5295    randyf 		extern int cpr(int, void *);
    339      0    stevel 
    340      0    stevel 		if (modload("misc", "cpr") == -1)
    341      0    stevel 			return (ENOTSUP);
    342   5295    randyf 		/* Let the CPR module decide what to do with mdep */
    343   5295    randyf 		error = cpr(fcn, mdep);
    344      0    stevel 		break;
    345      0    stevel 	}
    346      0    stevel 
    347      0    stevel 	case A_FTRACE:
    348      0    stevel 	{
    349      0    stevel 		switch (fcn) {
    350      0    stevel 		case AD_FTRACE_START:
    351      0    stevel 			(void) FTRACE_START();
    352      0    stevel 			break;
    353      0    stevel 		case AD_FTRACE_STOP:
    354      0    stevel 			(void) FTRACE_STOP();
    355      0    stevel 			break;
    356      0    stevel 		default:
    357      0    stevel 			error = EINVAL;
    358      0    stevel 		}
    359      0    stevel 		break;
    360      0    stevel 	}
    361      0    stevel 
    362      0    stevel 	case A_DUMP:
    363      0    stevel 	{
    364      0    stevel 		if (fcn == AD_NOSYNC) {
    365      0    stevel 			in_sync = 1;
    366      0    stevel 			break;
    367      0    stevel 		}
    368      0    stevel 
    369      0    stevel 		panic_bootfcn = fcn;
    370      0    stevel 		panic_forced = 1;
    371      0    stevel 
    372      0    stevel 		if ((mdep != NULL) && (*(char *)mdep == '/')) {
    373      0    stevel 			panic_bootstr = i_convert_boot_device_name(mdep,
    374   2267        dp 			    NULL, &buflen);
    375      0    stevel 		} else
    376      0    stevel 			panic_bootstr = mdep;
    377   9160    Sherry 
    378   9160    Sherry #ifndef	__sparc
    379  10559    Sherry 		extern void fastboot_update_and_load(int, char *);
    380   9160    Sherry 
    381  10559    Sherry 		fastboot_update_and_load(fcn, mdep);
    382   9160    Sherry #endif
    383      0    stevel 
    384      0    stevel 		panic("forced crash dump initiated at user request");
    385      0    stevel 		/*NOTREACHED*/
    386      0    stevel 	}
    387      0    stevel 
    388   6878   brendan 	case A_SDTTEST:
    389   6878   brendan 	{
    390   6878   brendan 		DTRACE_PROBE7(test, int, 1, int, 2, int, 3, int, 4, int, 5,
    391   6878   brendan 		    int, 6, int, 7);
    392   6878   brendan 		break;
    393   6878   brendan 	}
    394   6878   brendan 
    395      0    stevel 	default:
    396      0    stevel 		error = EINVAL;
    397      0    stevel 	}
    398      0    stevel 
    399      0    stevel 	return (error);
    400      0    stevel }
    401      0    stevel 
    402      0    stevel int
    403      0    stevel uadmin(int cmd, int fcn, uintptr_t mdep)
    404      0    stevel {
    405      0    stevel 	int error = 0, rv = 0;
    406      0    stevel 	size_t nbytes = 0;
    407      0    stevel 	cred_t *credp = CRED();
    408   2267        dp 	char *bootargs = NULL;
    409   7656    Sherry 	int reset_status = 0;
    410   7656    Sherry 
    411   7656    Sherry 	if (cmd == A_SHUTDOWN && fcn == AD_FASTREBOOT_DRYRUN) {
    412   7656    Sherry 		ddi_walk_devs(ddi_root_node(), check_driver_quiesce,
    413   7656    Sherry 		    &reset_status);
    414   7656    Sherry 		if (reset_status != 0)
    415   7656    Sherry 			return (EIO);
    416   7656    Sherry 		else
    417   7656    Sherry 			return (0);
    418   7656    Sherry 	}
    419      0    stevel 
    420      0    stevel 	/*
    421      0    stevel 	 * The swapctl system call doesn't have its own entry point: it uses
    422      0    stevel 	 * uadmin as a wrapper so we just call it directly from here.
    423      0    stevel 	 */
    424      0    stevel 	if (cmd == A_SWAPCTL) {
    425      0    stevel 		if (get_udatamodel() == DATAMODEL_NATIVE)
    426      0    stevel 			error = swapctl(fcn, (void *)mdep, &rv);
    427      0    stevel #if defined(_SYSCALL32_IMPL)
    428      0    stevel 		else
    429      0    stevel 			error = swapctl32(fcn, (void *)mdep, &rv);
    430      0    stevel #endif /* _SYSCALL32_IMPL */
    431      0    stevel 		return (error ? set_errno(error) : rv);
    432      0    stevel 	}
    433      0    stevel 
    434      0    stevel 	/*
    435   2267        dp 	 * Certain subcommands intepret a non-NULL mdep value as a pointer to
    436   2267        dp 	 * a boot string.  We pull that in as bootargs, if applicable.
    437      0    stevel 	 */
    438   2267        dp 	if (mdep != NULL &&
    439   5295    randyf 	    (cmd == A_SHUTDOWN || cmd == A_REBOOT || cmd == A_DUMP ||
    440   9160    Sherry 	    cmd == A_FREEZE || cmd == A_CONFIG)) {
    441   2267        dp 		bootargs = kmem_zalloc(BOOTARGS_MAX, KM_SLEEP);
    442   2267        dp 		if ((error = copyinstr((const char *)mdep, bootargs,
    443   2267        dp 		    BOOTARGS_MAX, &nbytes)) != 0) {
    444   2267        dp 			kmem_free(bootargs, BOOTARGS_MAX);
    445   2267        dp 			return (set_errno(error));
    446   2267        dp 		}
    447      0    stevel 	}
    448      0    stevel 
    449      0    stevel 	/*
    450   2267        dp 	 * Invoke the appropriate kadmin() routine.
    451      0    stevel 	 */
    452   2267        dp 	if (getzoneid() != GLOBAL_ZONEID)
    453   2267        dp 		error = zone_kadmin(cmd, fcn, bootargs, credp);
    454   2267        dp 	else
    455   2267        dp 		error = kadmin(cmd, fcn, bootargs, credp);
    456      0    stevel 
    457   2267        dp 	if (bootargs != NULL)
    458   2267        dp 		kmem_free(bootargs, BOOTARGS_MAX);
    459   2267        dp 	return (error ? set_errno(error) : 0);
    460      0    stevel }
    461