xref: /onnv-gate/usr/src/uts/common/syscall/corectl.c (revision 2267:c5d9a656170f)
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
5*2267Sdp  * Common Development and Distribution License (the "License").
6*2267Sdp  * 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*2267Sdp  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <sys/proc.h>
290Sstevel@tonic-gate #include <sys/systm.h>
300Sstevel@tonic-gate #include <sys/param.h>
310Sstevel@tonic-gate #include <sys/atomic.h>
320Sstevel@tonic-gate #include <sys/kmem.h>
330Sstevel@tonic-gate #include <sys/sysmacros.h>
340Sstevel@tonic-gate #include <sys/procset.h>
350Sstevel@tonic-gate #include <sys/corectl.h>
360Sstevel@tonic-gate #include <sys/zone.h>
370Sstevel@tonic-gate #include <sys/cmn_err.h>
380Sstevel@tonic-gate #include <sys/policy.h>
390Sstevel@tonic-gate 
400Sstevel@tonic-gate /*
410Sstevel@tonic-gate  * Core File Settings
420Sstevel@tonic-gate  * ------------------
430Sstevel@tonic-gate  *
440Sstevel@tonic-gate  * A process's core file path and content live in separate reference-counted
450Sstevel@tonic-gate  * structures. The corectl_content_t structure is fairly straightforward --
460Sstevel@tonic-gate  * the only subtlety is that we only really _need_ the mutex on architectures
470Sstevel@tonic-gate  * on which 64-bit memory operations are not atomic. The corectl_path_t
480Sstevel@tonic-gate  * structure is slightly trickier in that it contains a refstr_t rather than
490Sstevel@tonic-gate  * just a char * string. This is to allow consumers of the data in that
500Sstevel@tonic-gate  * structure (the core dumping sub-system for example) to safely use the
510Sstevel@tonic-gate  * string without holding any locks on it in light of updates.
520Sstevel@tonic-gate  *
53*2267Sdp  * At system and zone boot, init_core() sets init(1M)'s core file path and
54*2267Sdp  * content to the same value as the fields core_default_path and
55*2267Sdp  * core_default_content respectively (for the global zone). All subsequent
56*2267Sdp  * children of init(1M) reference those same settings. During boot coreadm(1M)
57*2267Sdp  * is invoked with the -u option to update the system settings from
58*2267Sdp  * /etc/coreadm.conf. This has the effect of also changing the values in
59*2267Sdp  * core_default_path and core_default_content which updates the core file
60*2267Sdp  * settings for all processes in the zone.  Each zone has different default
61*2267Sdp  * settings; when processes enter a non-global zone, their core file path and
62*2267Sdp  * content are set to the zone's default path and content.
630Sstevel@tonic-gate  *
640Sstevel@tonic-gate  * Processes that have their core file settings explicitly overridden using
650Sstevel@tonic-gate  * coreadm(1M) no longer reference core_default_path or core_default_content
660Sstevel@tonic-gate  * so subsequent changes to the default will not affect them.
670Sstevel@tonic-gate  */
680Sstevel@tonic-gate 
690Sstevel@tonic-gate zone_key_t	core_zone_key;
700Sstevel@tonic-gate 
710Sstevel@tonic-gate static int set_proc_info(pid_t pid, const char *path, core_content_t content);
720Sstevel@tonic-gate 
730Sstevel@tonic-gate static corectl_content_t *
corectl_content_alloc(core_content_t cc)740Sstevel@tonic-gate corectl_content_alloc(core_content_t cc)
750Sstevel@tonic-gate {
760Sstevel@tonic-gate 	corectl_content_t *ccp;
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	ccp = kmem_zalloc(sizeof (corectl_content_t), KM_SLEEP);
790Sstevel@tonic-gate 	ccp->ccc_content = cc;
800Sstevel@tonic-gate 	ccp->ccc_refcnt = 1;
810Sstevel@tonic-gate 
820Sstevel@tonic-gate 	return (ccp);
830Sstevel@tonic-gate }
840Sstevel@tonic-gate 
850Sstevel@tonic-gate core_content_t
corectl_content_value(corectl_content_t * ccp)860Sstevel@tonic-gate corectl_content_value(corectl_content_t *ccp)
870Sstevel@tonic-gate {
880Sstevel@tonic-gate 	core_content_t content;
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 	mutex_enter(&ccp->ccc_mtx);
910Sstevel@tonic-gate 	content = ccp->ccc_content;
920Sstevel@tonic-gate 	mutex_exit(&ccp->ccc_mtx);
930Sstevel@tonic-gate 
940Sstevel@tonic-gate 	return (content);
950Sstevel@tonic-gate }
960Sstevel@tonic-gate 
970Sstevel@tonic-gate static void
corectl_content_set(corectl_content_t * ccp,core_content_t content)980Sstevel@tonic-gate corectl_content_set(corectl_content_t *ccp, core_content_t content)
990Sstevel@tonic-gate {
1000Sstevel@tonic-gate 	mutex_enter(&ccp->ccc_mtx);
1010Sstevel@tonic-gate 	ccp->ccc_content = content;
1020Sstevel@tonic-gate 	mutex_exit(&ccp->ccc_mtx);
1030Sstevel@tonic-gate }
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate void
corectl_content_hold(corectl_content_t * ccp)1060Sstevel@tonic-gate corectl_content_hold(corectl_content_t *ccp)
1070Sstevel@tonic-gate {
1080Sstevel@tonic-gate 	atomic_add_32(&ccp->ccc_refcnt, 1);
1090Sstevel@tonic-gate }
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate void
corectl_content_rele(corectl_content_t * ccp)1120Sstevel@tonic-gate corectl_content_rele(corectl_content_t *ccp)
1130Sstevel@tonic-gate {
1140Sstevel@tonic-gate 	if (atomic_add_32_nv(&ccp->ccc_refcnt, -1) == 0)
1150Sstevel@tonic-gate 		kmem_free(ccp, sizeof (corectl_content_t));
1160Sstevel@tonic-gate }
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate static corectl_path_t *
corectl_path_alloc(const char * path)1200Sstevel@tonic-gate corectl_path_alloc(const char *path)
1210Sstevel@tonic-gate {
1220Sstevel@tonic-gate 	corectl_path_t *ccp;
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate 	ccp = kmem_zalloc(sizeof (corectl_path_t), KM_SLEEP);
1250Sstevel@tonic-gate 	ccp->ccp_path = refstr_alloc(path);
1260Sstevel@tonic-gate 	ccp->ccp_refcnt = 1;
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate 	return (ccp);
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate refstr_t *
corectl_path_value(corectl_path_t * ccp)1320Sstevel@tonic-gate corectl_path_value(corectl_path_t *ccp)
1330Sstevel@tonic-gate {
1340Sstevel@tonic-gate 	refstr_t *path;
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	mutex_enter(&ccp->ccp_mtx);
1370Sstevel@tonic-gate 	refstr_hold(path = ccp->ccp_path);
1380Sstevel@tonic-gate 	mutex_exit(&ccp->ccp_mtx);
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate 	return (path);
1410Sstevel@tonic-gate }
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate static void
corectl_path_set(corectl_path_t * ccp,const char * path)1440Sstevel@tonic-gate corectl_path_set(corectl_path_t *ccp, const char *path)
1450Sstevel@tonic-gate {
1460Sstevel@tonic-gate 	refstr_t *npath = refstr_alloc(path);
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 	mutex_enter(&ccp->ccp_mtx);
1490Sstevel@tonic-gate 	refstr_rele(ccp->ccp_path);
1500Sstevel@tonic-gate 	ccp->ccp_path = npath;
1510Sstevel@tonic-gate 	mutex_exit(&ccp->ccp_mtx);
1520Sstevel@tonic-gate }
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate void
corectl_path_hold(corectl_path_t * ccp)1550Sstevel@tonic-gate corectl_path_hold(corectl_path_t *ccp)
1560Sstevel@tonic-gate {
1570Sstevel@tonic-gate 	atomic_add_32(&ccp->ccp_refcnt, 1);
1580Sstevel@tonic-gate }
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate void
corectl_path_rele(corectl_path_t * ccp)1610Sstevel@tonic-gate corectl_path_rele(corectl_path_t *ccp)
1620Sstevel@tonic-gate {
1630Sstevel@tonic-gate 	if (atomic_add_32_nv(&ccp->ccp_refcnt, -1) == 0) {
1640Sstevel@tonic-gate 		refstr_rele(ccp->ccp_path);
1650Sstevel@tonic-gate 		kmem_free(ccp, sizeof (corectl_path_t));
1660Sstevel@tonic-gate 	}
1670Sstevel@tonic-gate }
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate /*
1700Sstevel@tonic-gate  * Constructor routine to be called when a zone is created.
1710Sstevel@tonic-gate  */
1720Sstevel@tonic-gate /*ARGSUSED*/
1730Sstevel@tonic-gate static void *
core_init_zone(zoneid_t zoneid)1740Sstevel@tonic-gate core_init_zone(zoneid_t zoneid)
1750Sstevel@tonic-gate {
1760Sstevel@tonic-gate 	struct core_globals *cg;
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 	cg = kmem_alloc(sizeof (*cg), KM_SLEEP);
1790Sstevel@tonic-gate 	mutex_init(&cg->core_lock, NULL, MUTEX_DEFAULT, NULL);
1800Sstevel@tonic-gate 	cg->core_file = NULL;
1810Sstevel@tonic-gate 	cg->core_options = CC_PROCESS_PATH;
1820Sstevel@tonic-gate 	cg->core_content = CC_CONTENT_DEFAULT;
1830Sstevel@tonic-gate 	cg->core_rlimit = RLIM64_INFINITY;
1840Sstevel@tonic-gate 	cg->core_default_path = corectl_path_alloc("core");
1850Sstevel@tonic-gate 	cg->core_default_content = corectl_content_alloc(CC_CONTENT_DEFAULT);
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 	return (cg);
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate /*
1910Sstevel@tonic-gate  * Destructor routine to be called when a zone is destroyed.
1920Sstevel@tonic-gate  */
1930Sstevel@tonic-gate /*ARGSUSED*/
1940Sstevel@tonic-gate static void
core_free_zone(zoneid_t zoneid,void * arg)1950Sstevel@tonic-gate core_free_zone(zoneid_t zoneid, void *arg)
1960Sstevel@tonic-gate {
1970Sstevel@tonic-gate 	struct core_globals *cg = arg;
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate 	if (cg == NULL)
2000Sstevel@tonic-gate 		return;
2010Sstevel@tonic-gate 	if (cg->core_file != NULL)
2020Sstevel@tonic-gate 		refstr_rele(cg->core_file);
2030Sstevel@tonic-gate 	corectl_path_rele(cg->core_default_path);
2040Sstevel@tonic-gate 	corectl_content_rele(cg->core_default_content);
2050Sstevel@tonic-gate 	kmem_free(cg, sizeof (*cg));
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate /*
209*2267Sdp  * Called from start_init_common(), to set init's core file path and content.
2100Sstevel@tonic-gate  */
2110Sstevel@tonic-gate void
init_core(void)2120Sstevel@tonic-gate init_core(void)
2130Sstevel@tonic-gate {
2140Sstevel@tonic-gate 	struct core_globals *cg;
2150Sstevel@tonic-gate 
216*2267Sdp 	/*
217*2267Sdp 	 * The first time we hit this, in the global zone, we have to
218*2267Sdp 	 * initialize the zsd key.
219*2267Sdp 	 */
220*2267Sdp 	if (INGLOBALZONE(curproc)) {
221*2267Sdp 		zone_key_create(&core_zone_key, core_init_zone, NULL,
222*2267Sdp 		    core_free_zone);
223*2267Sdp 	}
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 	/*
2260Sstevel@tonic-gate 	 * zone_key_create will have called core_init_zone for the
2270Sstevel@tonic-gate 	 * global zone, which sets up the default path and content
2280Sstevel@tonic-gate 	 * variables.
2290Sstevel@tonic-gate 	 */
230*2267Sdp 	VERIFY((cg = zone_getspecific(core_zone_key, curproc->p_zone)) != NULL);
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 	corectl_path_hold(cg->core_default_path);
2330Sstevel@tonic-gate 	corectl_content_hold(cg->core_default_content);
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 	curproc->p_corefile = cg->core_default_path;
2360Sstevel@tonic-gate 	curproc->p_content = cg->core_default_content;
2370Sstevel@tonic-gate }
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate int
corectl(int subcode,uintptr_t arg1,uintptr_t arg2,uintptr_t arg3)2400Sstevel@tonic-gate corectl(int subcode, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
2410Sstevel@tonic-gate {
2420Sstevel@tonic-gate 	int error = 0;
2430Sstevel@tonic-gate 	proc_t *p;
2440Sstevel@tonic-gate 	refstr_t *rp;
2450Sstevel@tonic-gate 	size_t size;
2460Sstevel@tonic-gate 	char *path;
2470Sstevel@tonic-gate 	core_content_t content = CC_CONTENT_INVALID;
2480Sstevel@tonic-gate 	struct core_globals *cg;
2490Sstevel@tonic-gate 	zone_t *zone = curproc->p_zone;
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 	cg = zone_getspecific(core_zone_key, zone);
2520Sstevel@tonic-gate 	ASSERT(cg != NULL);
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 	switch (subcode) {
2550Sstevel@tonic-gate 	case CC_SET_OPTIONS:
2560Sstevel@tonic-gate 		if ((error = secpolicy_coreadm(CRED())) == 0) {
2570Sstevel@tonic-gate 			if (arg1 & ~CC_OPTIONS)
2580Sstevel@tonic-gate 				error = EINVAL;
2590Sstevel@tonic-gate 			else
2600Sstevel@tonic-gate 				cg->core_options = (uint32_t)arg1;
2610Sstevel@tonic-gate 		}
2620Sstevel@tonic-gate 		break;
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 	case CC_GET_OPTIONS:
2650Sstevel@tonic-gate 		return (cg->core_options);
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	case CC_GET_GLOBAL_PATH:
2680Sstevel@tonic-gate 	case CC_GET_DEFAULT_PATH:
2690Sstevel@tonic-gate 	case CC_GET_PROCESS_PATH:
2700Sstevel@tonic-gate 		if (subcode == CC_GET_GLOBAL_PATH) {
2710Sstevel@tonic-gate 			mutex_enter(&cg->core_lock);
2720Sstevel@tonic-gate 			if ((rp = cg->core_file) != NULL)
2730Sstevel@tonic-gate 				refstr_hold(rp);
2740Sstevel@tonic-gate 			mutex_exit(&cg->core_lock);
2750Sstevel@tonic-gate 		} else if (subcode == CC_GET_DEFAULT_PATH) {
2760Sstevel@tonic-gate 			rp = corectl_path_value(cg->core_default_path);
2770Sstevel@tonic-gate 		} else {
2780Sstevel@tonic-gate 			rp = NULL;
2790Sstevel@tonic-gate 			mutex_enter(&pidlock);
2800Sstevel@tonic-gate 			if ((p = prfind((pid_t)arg3)) == NULL ||
2810Sstevel@tonic-gate 			    p->p_stat == SIDL) {
2820Sstevel@tonic-gate 				mutex_exit(&pidlock);
2830Sstevel@tonic-gate 				error = ESRCH;
2840Sstevel@tonic-gate 			} else {
2850Sstevel@tonic-gate 				mutex_enter(&p->p_lock);
2860Sstevel@tonic-gate 				mutex_exit(&pidlock);
2870Sstevel@tonic-gate 				mutex_enter(&p->p_crlock);
2880Sstevel@tonic-gate 				if (!hasprocperm(p->p_cred, CRED()))
2890Sstevel@tonic-gate 					error = EPERM;
2900Sstevel@tonic-gate 				else if (p->p_corefile != NULL)
2910Sstevel@tonic-gate 					rp = corectl_path_value(p->p_corefile);
2920Sstevel@tonic-gate 				mutex_exit(&p->p_crlock);
2930Sstevel@tonic-gate 				mutex_exit(&p->p_lock);
2940Sstevel@tonic-gate 			}
2950Sstevel@tonic-gate 		}
2960Sstevel@tonic-gate 		if (rp == NULL) {
2970Sstevel@tonic-gate 			if (error == 0 && suword8((void *)arg1, 0))
2980Sstevel@tonic-gate 				error = EFAULT;
2990Sstevel@tonic-gate 		} else {
3000Sstevel@tonic-gate 			error = copyoutstr(refstr_value(rp), (char *)arg1,
301*2267Sdp 			    (size_t)arg2, NULL);
3020Sstevel@tonic-gate 			refstr_rele(rp);
3030Sstevel@tonic-gate 		}
3040Sstevel@tonic-gate 		break;
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 	case CC_SET_GLOBAL_PATH:
3070Sstevel@tonic-gate 	case CC_SET_DEFAULT_PATH:
3080Sstevel@tonic-gate 		if ((error = secpolicy_coreadm(CRED())) != 0)
3090Sstevel@tonic-gate 			break;
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate 		/* FALLTHROUGH */
3120Sstevel@tonic-gate 	case CC_SET_PROCESS_PATH:
3130Sstevel@tonic-gate 		if ((size = MIN((size_t)arg2, MAXPATHLEN)) == 0) {
3140Sstevel@tonic-gate 			error = EINVAL;
3150Sstevel@tonic-gate 			break;
3160Sstevel@tonic-gate 		}
3170Sstevel@tonic-gate 		path = kmem_alloc(size, KM_SLEEP);
3180Sstevel@tonic-gate 		error = copyinstr((char *)arg1, path, size, NULL);
3190Sstevel@tonic-gate 		if (error == 0) {
3200Sstevel@tonic-gate 			if (subcode == CC_SET_PROCESS_PATH) {
3210Sstevel@tonic-gate 				error = set_proc_info((pid_t)arg3, path, 0);
3220Sstevel@tonic-gate 			} else if (subcode == CC_SET_DEFAULT_PATH) {
3230Sstevel@tonic-gate 				corectl_path_set(cg->core_default_path, path);
3240Sstevel@tonic-gate 			} else if (*path != '\0' && *path != '/') {
3250Sstevel@tonic-gate 				error = EINVAL;
3260Sstevel@tonic-gate 			} else {
3270Sstevel@tonic-gate 				refstr_t *nrp = refstr_alloc(path);
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 				mutex_enter(&cg->core_lock);
3300Sstevel@tonic-gate 				rp = cg->core_file;
3310Sstevel@tonic-gate 				if (*path == '\0')
3320Sstevel@tonic-gate 					cg->core_file = NULL;
3330Sstevel@tonic-gate 				else
3340Sstevel@tonic-gate 					refstr_hold(cg->core_file = nrp);
3350Sstevel@tonic-gate 				mutex_exit(&cg->core_lock);
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 				if (rp != NULL)
3380Sstevel@tonic-gate 					refstr_rele(rp);
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 				refstr_rele(nrp);
3410Sstevel@tonic-gate 			}
3420Sstevel@tonic-gate 		}
3430Sstevel@tonic-gate 		kmem_free(path, size);
3440Sstevel@tonic-gate 		break;
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 	case CC_SET_GLOBAL_CONTENT:
3470Sstevel@tonic-gate 	case CC_SET_DEFAULT_CONTENT:
3480Sstevel@tonic-gate 		if ((error = secpolicy_coreadm(CRED())) != 0)
3490Sstevel@tonic-gate 			break;
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate 		/* FALLTHROUGH */
3520Sstevel@tonic-gate 	case CC_SET_PROCESS_CONTENT:
3530Sstevel@tonic-gate 		error = copyin((void *)arg1, &content, sizeof (content));
3540Sstevel@tonic-gate 		if (error != 0)
3550Sstevel@tonic-gate 			break;
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 		/*
3580Sstevel@tonic-gate 		 * If any unknown bits are set, don't let this charade
3590Sstevel@tonic-gate 		 * continue.
3600Sstevel@tonic-gate 		 */
3610Sstevel@tonic-gate 		if (content & ~CC_CONTENT_ALL) {
3620Sstevel@tonic-gate 			error = EINVAL;
3630Sstevel@tonic-gate 			break;
3640Sstevel@tonic-gate 		}
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate 		if (subcode == CC_SET_PROCESS_CONTENT) {
3670Sstevel@tonic-gate 			error = set_proc_info((pid_t)arg2, NULL, content);
3680Sstevel@tonic-gate 		} else if (subcode == CC_SET_DEFAULT_CONTENT) {
3690Sstevel@tonic-gate 			corectl_content_set(cg->core_default_content, content);
3700Sstevel@tonic-gate 		} else {
3710Sstevel@tonic-gate 			mutex_enter(&cg->core_lock);
3720Sstevel@tonic-gate 			cg->core_content = content;
3730Sstevel@tonic-gate 			mutex_exit(&cg->core_lock);
3740Sstevel@tonic-gate 		}
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 		break;
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	case CC_GET_GLOBAL_CONTENT:
3790Sstevel@tonic-gate 		content = cg->core_content;
3800Sstevel@tonic-gate 		error = copyout(&content, (void *)arg1, sizeof (content));
3810Sstevel@tonic-gate 		break;
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate 	case CC_GET_DEFAULT_CONTENT:
3840Sstevel@tonic-gate 		content = corectl_content_value(cg->core_default_content);
3850Sstevel@tonic-gate 		error = copyout(&content, (void *)arg1, sizeof (content));
3860Sstevel@tonic-gate 		break;
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate 	case CC_GET_PROCESS_CONTENT:
3890Sstevel@tonic-gate 		mutex_enter(&pidlock);
3900Sstevel@tonic-gate 		if ((p = prfind((pid_t)arg2)) == NULL || p->p_stat == SIDL) {
3910Sstevel@tonic-gate 			mutex_exit(&pidlock);
3920Sstevel@tonic-gate 			error = ESRCH;
3930Sstevel@tonic-gate 			break;
3940Sstevel@tonic-gate 		}
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 		mutex_enter(&p->p_lock);
3970Sstevel@tonic-gate 		mutex_exit(&pidlock);
3980Sstevel@tonic-gate 		mutex_enter(&p->p_crlock);
3990Sstevel@tonic-gate 		if (!hasprocperm(p->p_cred, CRED()))
4000Sstevel@tonic-gate 			error = EPERM;
4010Sstevel@tonic-gate 		else if (p->p_content == NULL)
4020Sstevel@tonic-gate 			content = CC_CONTENT_NONE;
4030Sstevel@tonic-gate 		else
4040Sstevel@tonic-gate 			content = corectl_content_value(p->p_content);
4050Sstevel@tonic-gate 		mutex_exit(&p->p_crlock);
4060Sstevel@tonic-gate 		mutex_exit(&p->p_lock);
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 		if (error == 0)
4090Sstevel@tonic-gate 			error = copyout(&content, (void *)arg1,
4100Sstevel@tonic-gate 			    sizeof (content));
4110Sstevel@tonic-gate 		break;
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate 	default:
4140Sstevel@tonic-gate 		error = EINVAL;
4150Sstevel@tonic-gate 		break;
4160Sstevel@tonic-gate 	}
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate 	if (error)
4190Sstevel@tonic-gate 		return (set_errno(error));
4200Sstevel@tonic-gate 	return (0);
4210Sstevel@tonic-gate }
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate typedef struct {
4240Sstevel@tonic-gate 	int			cc_count;
4250Sstevel@tonic-gate 	corectl_path_t		*cc_path;
4260Sstevel@tonic-gate 	corectl_content_t	*cc_content;
4270Sstevel@tonic-gate } counter_t;
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate static int
set_one_proc_info(proc_t * p,counter_t * counterp)4300Sstevel@tonic-gate set_one_proc_info(proc_t *p, counter_t *counterp)
4310Sstevel@tonic-gate {
4320Sstevel@tonic-gate 	corectl_path_t *corefile;
4330Sstevel@tonic-gate 	corectl_content_t *content;
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate 	mutex_enter(&p->p_crlock);
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate 	if (!(p->p_flag & SSYS) && hasprocperm(p->p_cred, CRED())) {
4380Sstevel@tonic-gate 		mutex_exit(&p->p_crlock);
4390Sstevel@tonic-gate 		counterp->cc_count++;
4400Sstevel@tonic-gate 		if (counterp->cc_path != NULL) {
4410Sstevel@tonic-gate 			corectl_path_hold(counterp->cc_path);
4420Sstevel@tonic-gate 			mutex_enter(&p->p_lock);
4430Sstevel@tonic-gate 			corefile = p->p_corefile;
4440Sstevel@tonic-gate 			p->p_corefile = counterp->cc_path;
4450Sstevel@tonic-gate 			mutex_exit(&p->p_lock);
4460Sstevel@tonic-gate 			if (corefile != NULL)
4470Sstevel@tonic-gate 				corectl_path_rele(corefile);
4480Sstevel@tonic-gate 		} else {
4490Sstevel@tonic-gate 			corectl_content_hold(counterp->cc_content);
4500Sstevel@tonic-gate 			mutex_enter(&p->p_lock);
4510Sstevel@tonic-gate 			content = p->p_content;
4520Sstevel@tonic-gate 			p->p_content = counterp->cc_content;
4530Sstevel@tonic-gate 			mutex_exit(&p->p_lock);
4540Sstevel@tonic-gate 			if (content != NULL)
4550Sstevel@tonic-gate 				corectl_content_rele(content);
4560Sstevel@tonic-gate 		}
4570Sstevel@tonic-gate 	} else {
4580Sstevel@tonic-gate 		mutex_exit(&p->p_crlock);
4590Sstevel@tonic-gate 	}
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate 	return (0);
4620Sstevel@tonic-gate }
4630Sstevel@tonic-gate 
4640Sstevel@tonic-gate static int
set_proc_info(pid_t pid,const char * path,core_content_t content)4650Sstevel@tonic-gate set_proc_info(pid_t pid, const char *path, core_content_t content)
4660Sstevel@tonic-gate {
4670Sstevel@tonic-gate 	proc_t *p;
4680Sstevel@tonic-gate 	counter_t counter;
4690Sstevel@tonic-gate 	int error = 0;
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate 	counter.cc_count = 0;
4720Sstevel@tonic-gate 	/*
4730Sstevel@tonic-gate 	 * Only one of the core file path or content can be set at a time.
4740Sstevel@tonic-gate 	 */
4750Sstevel@tonic-gate 	if (path != NULL) {
4760Sstevel@tonic-gate 		counter.cc_path = corectl_path_alloc(path);
4770Sstevel@tonic-gate 		counter.cc_content = NULL;
4780Sstevel@tonic-gate 	} else {
4790Sstevel@tonic-gate 		counter.cc_path = NULL;
4800Sstevel@tonic-gate 		counter.cc_content = corectl_content_alloc(content);
4810Sstevel@tonic-gate 	}
4820Sstevel@tonic-gate 
4830Sstevel@tonic-gate 	if (pid == -1) {
4840Sstevel@tonic-gate 		procset_t set;
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 		setprocset(&set, POP_AND, P_ALL, P_MYID, P_ALL, P_MYID);
4870Sstevel@tonic-gate 		error = dotoprocs(&set, set_one_proc_info, (char *)&counter);
4880Sstevel@tonic-gate 		if (error == 0 && counter.cc_count == 0)
4890Sstevel@tonic-gate 			error = EPERM;
4900Sstevel@tonic-gate 	} else if (pid > 0) {
4910Sstevel@tonic-gate 		mutex_enter(&pidlock);
4920Sstevel@tonic-gate 		if ((p = prfind(pid)) == NULL || p->p_stat == SIDL) {
4930Sstevel@tonic-gate 			error = ESRCH;
4940Sstevel@tonic-gate 		} else {
4950Sstevel@tonic-gate 			(void) set_one_proc_info(p, &counter);
4960Sstevel@tonic-gate 			if (counter.cc_count == 0)
4970Sstevel@tonic-gate 				error = EPERM;
4980Sstevel@tonic-gate 		}
4990Sstevel@tonic-gate 		mutex_exit(&pidlock);
5000Sstevel@tonic-gate 	} else {
5010Sstevel@tonic-gate 		int nfound = 0;
5020Sstevel@tonic-gate 		pid_t pgid;
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 		if (pid == 0)
5050Sstevel@tonic-gate 			pgid = curproc->p_pgrp;
5060Sstevel@tonic-gate 		else
5070Sstevel@tonic-gate 			pgid = -pid;
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate 		mutex_enter(&pidlock);
5100Sstevel@tonic-gate 		for (p = pgfind(pgid); p != NULL; p = p->p_pglink) {
5110Sstevel@tonic-gate 			if (p->p_stat != SIDL) {
5120Sstevel@tonic-gate 				nfound++;
5130Sstevel@tonic-gate 				(void) set_one_proc_info(p, &counter);
5140Sstevel@tonic-gate 			}
5150Sstevel@tonic-gate 		}
5160Sstevel@tonic-gate 		mutex_exit(&pidlock);
5170Sstevel@tonic-gate 		if (nfound == 0)
5180Sstevel@tonic-gate 			error = ESRCH;
5190Sstevel@tonic-gate 		else if (counter.cc_count == 0)
5200Sstevel@tonic-gate 			error = EPERM;
5210Sstevel@tonic-gate 	}
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate 	if (path != NULL)
5240Sstevel@tonic-gate 		corectl_path_rele(counter.cc_path);
5250Sstevel@tonic-gate 	else
5260Sstevel@tonic-gate 		corectl_content_rele(counter.cc_content);
5270Sstevel@tonic-gate 
5280Sstevel@tonic-gate 	if (error)
5290Sstevel@tonic-gate 		return (set_errno(error));
5300Sstevel@tonic-gate 	return (0);
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate /*
5340Sstevel@tonic-gate  * Give current process the default core settings for its current zone;
5350Sstevel@tonic-gate  * used for processes entering a zone via zone_enter.
5360Sstevel@tonic-gate  */
5370Sstevel@tonic-gate void
set_core_defaults(void)5380Sstevel@tonic-gate set_core_defaults(void)
5390Sstevel@tonic-gate {
5400Sstevel@tonic-gate 	proc_t *p = curproc;
5410Sstevel@tonic-gate 	struct core_globals *cg;
5420Sstevel@tonic-gate 	corectl_path_t *oldpath, *newpath;
5430Sstevel@tonic-gate 	corectl_content_t *oldcontent, *newcontent;
5440Sstevel@tonic-gate 
5450Sstevel@tonic-gate 	cg = zone_getspecific(core_zone_key, p->p_zone);
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 	/* make local copies of default values to protect against change */
5480Sstevel@tonic-gate 	newpath = cg->core_default_path;
5490Sstevel@tonic-gate 	newcontent = cg->core_default_content;
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 	corectl_path_hold(newpath);
5520Sstevel@tonic-gate 	corectl_content_hold(newcontent);
5530Sstevel@tonic-gate 	mutex_enter(&p->p_lock);
5540Sstevel@tonic-gate 	oldpath = p->p_corefile;
5550Sstevel@tonic-gate 	p->p_corefile = newpath;
5560Sstevel@tonic-gate 	oldcontent = p->p_content;
5570Sstevel@tonic-gate 	p->p_content = newcontent;
5580Sstevel@tonic-gate 	mutex_exit(&p->p_lock);
5590Sstevel@tonic-gate 	if (oldpath != NULL)
5600Sstevel@tonic-gate 		corectl_path_rele(oldpath);
5610Sstevel@tonic-gate 	if (oldcontent != NULL)
5620Sstevel@tonic-gate 		corectl_content_rele(oldcontent);
5630Sstevel@tonic-gate }
564