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