17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53f2f09c1Sdp * Common Development and Distribution License (the "License").
63f2f09c1Sdp * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
223f2f09c1Sdp * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <sys/proc.h>
277c478bd9Sstevel@tonic-gate #include <sys/systm.h>
287c478bd9Sstevel@tonic-gate #include <sys/param.h>
297c478bd9Sstevel@tonic-gate #include <sys/atomic.h>
307c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
317c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
327c478bd9Sstevel@tonic-gate #include <sys/procset.h>
337c478bd9Sstevel@tonic-gate #include <sys/corectl.h>
347c478bd9Sstevel@tonic-gate #include <sys/zone.h>
357c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
367c478bd9Sstevel@tonic-gate #include <sys/policy.h>
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate /*
397c478bd9Sstevel@tonic-gate * Core File Settings
407c478bd9Sstevel@tonic-gate * ------------------
417c478bd9Sstevel@tonic-gate *
427c478bd9Sstevel@tonic-gate * A process's core file path and content live in separate reference-counted
437c478bd9Sstevel@tonic-gate * structures. The corectl_content_t structure is fairly straightforward --
447c478bd9Sstevel@tonic-gate * the only subtlety is that we only really _need_ the mutex on architectures
457c478bd9Sstevel@tonic-gate * on which 64-bit memory operations are not atomic. The corectl_path_t
467c478bd9Sstevel@tonic-gate * structure is slightly trickier in that it contains a refstr_t rather than
477c478bd9Sstevel@tonic-gate * just a char * string. This is to allow consumers of the data in that
487c478bd9Sstevel@tonic-gate * structure (the core dumping sub-system for example) to safely use the
497c478bd9Sstevel@tonic-gate * string without holding any locks on it in light of updates.
507c478bd9Sstevel@tonic-gate *
51*bbf21555SRichard Lowe * At system and zone boot, init_core() sets init(8)'s core file path and
523f2f09c1Sdp * content to the same value as the fields core_default_path and
533f2f09c1Sdp * core_default_content respectively (for the global zone). All subsequent
54*bbf21555SRichard Lowe * children of init(8) reference those same settings. During boot coreadm(8)
553f2f09c1Sdp * is invoked with the -u option to update the system settings from
563f2f09c1Sdp * /etc/coreadm.conf. This has the effect of also changing the values in
573f2f09c1Sdp * core_default_path and core_default_content which updates the core file
583f2f09c1Sdp * settings for all processes in the zone. Each zone has different default
593f2f09c1Sdp * settings; when processes enter a non-global zone, their core file path and
603f2f09c1Sdp * content are set to the zone's default path and content.
617c478bd9Sstevel@tonic-gate *
627c478bd9Sstevel@tonic-gate * Processes that have their core file settings explicitly overridden using
63*bbf21555SRichard Lowe * coreadm(8) no longer reference core_default_path or core_default_content
647c478bd9Sstevel@tonic-gate * so subsequent changes to the default will not affect them.
657c478bd9Sstevel@tonic-gate */
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate zone_key_t core_zone_key;
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate static int set_proc_info(pid_t pid, const char *path, core_content_t content);
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate static corectl_content_t *
corectl_content_alloc(core_content_t cc)727c478bd9Sstevel@tonic-gate corectl_content_alloc(core_content_t cc)
737c478bd9Sstevel@tonic-gate {
747c478bd9Sstevel@tonic-gate corectl_content_t *ccp;
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate ccp = kmem_zalloc(sizeof (corectl_content_t), KM_SLEEP);
777c478bd9Sstevel@tonic-gate ccp->ccc_content = cc;
787c478bd9Sstevel@tonic-gate ccp->ccc_refcnt = 1;
797c478bd9Sstevel@tonic-gate
807c478bd9Sstevel@tonic-gate return (ccp);
817c478bd9Sstevel@tonic-gate }
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate core_content_t
corectl_content_value(corectl_content_t * ccp)847c478bd9Sstevel@tonic-gate corectl_content_value(corectl_content_t *ccp)
857c478bd9Sstevel@tonic-gate {
867c478bd9Sstevel@tonic-gate core_content_t content;
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate mutex_enter(&ccp->ccc_mtx);
897c478bd9Sstevel@tonic-gate content = ccp->ccc_content;
907c478bd9Sstevel@tonic-gate mutex_exit(&ccp->ccc_mtx);
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate return (content);
937c478bd9Sstevel@tonic-gate }
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate static void
corectl_content_set(corectl_content_t * ccp,core_content_t content)967c478bd9Sstevel@tonic-gate corectl_content_set(corectl_content_t *ccp, core_content_t content)
977c478bd9Sstevel@tonic-gate {
987c478bd9Sstevel@tonic-gate mutex_enter(&ccp->ccc_mtx);
997c478bd9Sstevel@tonic-gate ccp->ccc_content = content;
1007c478bd9Sstevel@tonic-gate mutex_exit(&ccp->ccc_mtx);
1017c478bd9Sstevel@tonic-gate }
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate void
corectl_content_hold(corectl_content_t * ccp)1047c478bd9Sstevel@tonic-gate corectl_content_hold(corectl_content_t *ccp)
1057c478bd9Sstevel@tonic-gate {
1061a5e258fSJosef 'Jeff' Sipek atomic_inc_32(&ccp->ccc_refcnt);
1077c478bd9Sstevel@tonic-gate }
1087c478bd9Sstevel@tonic-gate
1097c478bd9Sstevel@tonic-gate void
corectl_content_rele(corectl_content_t * ccp)1107c478bd9Sstevel@tonic-gate corectl_content_rele(corectl_content_t *ccp)
1117c478bd9Sstevel@tonic-gate {
1121a5e258fSJosef 'Jeff' Sipek if (atomic_dec_32_nv(&ccp->ccc_refcnt) == 0)
1137c478bd9Sstevel@tonic-gate kmem_free(ccp, sizeof (corectl_content_t));
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate static corectl_path_t *
corectl_path_alloc(const char * path)1187c478bd9Sstevel@tonic-gate corectl_path_alloc(const char *path)
1197c478bd9Sstevel@tonic-gate {
1207c478bd9Sstevel@tonic-gate corectl_path_t *ccp;
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gate ccp = kmem_zalloc(sizeof (corectl_path_t), KM_SLEEP);
1237c478bd9Sstevel@tonic-gate ccp->ccp_path = refstr_alloc(path);
1247c478bd9Sstevel@tonic-gate ccp->ccp_refcnt = 1;
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate return (ccp);
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate refstr_t *
corectl_path_value(corectl_path_t * ccp)1307c478bd9Sstevel@tonic-gate corectl_path_value(corectl_path_t *ccp)
1317c478bd9Sstevel@tonic-gate {
1327c478bd9Sstevel@tonic-gate refstr_t *path;
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate mutex_enter(&ccp->ccp_mtx);
1357c478bd9Sstevel@tonic-gate refstr_hold(path = ccp->ccp_path);
1367c478bd9Sstevel@tonic-gate mutex_exit(&ccp->ccp_mtx);
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate return (path);
1397c478bd9Sstevel@tonic-gate }
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate static void
corectl_path_set(corectl_path_t * ccp,const char * path)1427c478bd9Sstevel@tonic-gate corectl_path_set(corectl_path_t *ccp, const char *path)
1437c478bd9Sstevel@tonic-gate {
1447c478bd9Sstevel@tonic-gate refstr_t *npath = refstr_alloc(path);
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate mutex_enter(&ccp->ccp_mtx);
1477c478bd9Sstevel@tonic-gate refstr_rele(ccp->ccp_path);
1487c478bd9Sstevel@tonic-gate ccp->ccp_path = npath;
1497c478bd9Sstevel@tonic-gate mutex_exit(&ccp->ccp_mtx);
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate void
corectl_path_hold(corectl_path_t * ccp)1537c478bd9Sstevel@tonic-gate corectl_path_hold(corectl_path_t *ccp)
1547c478bd9Sstevel@tonic-gate {
1551a5e258fSJosef 'Jeff' Sipek atomic_inc_32(&ccp->ccp_refcnt);
1567c478bd9Sstevel@tonic-gate }
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate void
corectl_path_rele(corectl_path_t * ccp)1597c478bd9Sstevel@tonic-gate corectl_path_rele(corectl_path_t *ccp)
1607c478bd9Sstevel@tonic-gate {
1611a5e258fSJosef 'Jeff' Sipek if (atomic_dec_32_nv(&ccp->ccp_refcnt) == 0) {
1627c478bd9Sstevel@tonic-gate refstr_rele(ccp->ccp_path);
1637c478bd9Sstevel@tonic-gate kmem_free(ccp, sizeof (corectl_path_t));
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate /*
1687c478bd9Sstevel@tonic-gate * Constructor routine to be called when a zone is created.
1697c478bd9Sstevel@tonic-gate */
1707c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1717c478bd9Sstevel@tonic-gate static void *
core_init_zone(zoneid_t zoneid)1727c478bd9Sstevel@tonic-gate core_init_zone(zoneid_t zoneid)
1737c478bd9Sstevel@tonic-gate {
1747c478bd9Sstevel@tonic-gate struct core_globals *cg;
1757c478bd9Sstevel@tonic-gate
1767c478bd9Sstevel@tonic-gate cg = kmem_alloc(sizeof (*cg), KM_SLEEP);
1777c478bd9Sstevel@tonic-gate mutex_init(&cg->core_lock, NULL, MUTEX_DEFAULT, NULL);
1787c478bd9Sstevel@tonic-gate cg->core_file = NULL;
1797c478bd9Sstevel@tonic-gate cg->core_options = CC_PROCESS_PATH;
1807c478bd9Sstevel@tonic-gate cg->core_content = CC_CONTENT_DEFAULT;
1817c478bd9Sstevel@tonic-gate cg->core_rlimit = RLIM64_INFINITY;
1827c478bd9Sstevel@tonic-gate cg->core_default_path = corectl_path_alloc("core");
1837c478bd9Sstevel@tonic-gate cg->core_default_content = corectl_content_alloc(CC_CONTENT_DEFAULT);
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate return (cg);
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate
1887c478bd9Sstevel@tonic-gate /*
1897c478bd9Sstevel@tonic-gate * Destructor routine to be called when a zone is destroyed.
1907c478bd9Sstevel@tonic-gate */
1917c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1927c478bd9Sstevel@tonic-gate static void
core_free_zone(zoneid_t zoneid,void * arg)1937c478bd9Sstevel@tonic-gate core_free_zone(zoneid_t zoneid, void *arg)
1947c478bd9Sstevel@tonic-gate {
1957c478bd9Sstevel@tonic-gate struct core_globals *cg = arg;
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate if (cg == NULL)
1987c478bd9Sstevel@tonic-gate return;
1997c478bd9Sstevel@tonic-gate if (cg->core_file != NULL)
2007c478bd9Sstevel@tonic-gate refstr_rele(cg->core_file);
2017c478bd9Sstevel@tonic-gate corectl_path_rele(cg->core_default_path);
2027c478bd9Sstevel@tonic-gate corectl_content_rele(cg->core_default_content);
2037c478bd9Sstevel@tonic-gate kmem_free(cg, sizeof (*cg));
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate /*
2073f2f09c1Sdp * Called from start_init_common(), to set init's core file path and content.
2087c478bd9Sstevel@tonic-gate */
2097c478bd9Sstevel@tonic-gate void
init_core(void)2107c478bd9Sstevel@tonic-gate init_core(void)
2117c478bd9Sstevel@tonic-gate {
2127c478bd9Sstevel@tonic-gate struct core_globals *cg;
2137c478bd9Sstevel@tonic-gate
2143f2f09c1Sdp /*
2153f2f09c1Sdp * The first time we hit this, in the global zone, we have to
2163f2f09c1Sdp * initialize the zsd key.
2173f2f09c1Sdp */
2183f2f09c1Sdp if (INGLOBALZONE(curproc)) {
2193f2f09c1Sdp zone_key_create(&core_zone_key, core_init_zone, NULL,
2203f2f09c1Sdp core_free_zone);
2213f2f09c1Sdp }
2227c478bd9Sstevel@tonic-gate
2237c478bd9Sstevel@tonic-gate /*
2247c478bd9Sstevel@tonic-gate * zone_key_create will have called core_init_zone for the
2257c478bd9Sstevel@tonic-gate * global zone, which sets up the default path and content
2267c478bd9Sstevel@tonic-gate * variables.
2277c478bd9Sstevel@tonic-gate */
2283f2f09c1Sdp VERIFY((cg = zone_getspecific(core_zone_key, curproc->p_zone)) != NULL);
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate corectl_path_hold(cg->core_default_path);
2317c478bd9Sstevel@tonic-gate corectl_content_hold(cg->core_default_content);
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate curproc->p_corefile = cg->core_default_path;
2347c478bd9Sstevel@tonic-gate curproc->p_content = cg->core_default_content;
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate int
corectl(int subcode,uintptr_t arg1,uintptr_t arg2,uintptr_t arg3)2387c478bd9Sstevel@tonic-gate corectl(int subcode, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
2397c478bd9Sstevel@tonic-gate {
2407c478bd9Sstevel@tonic-gate int error = 0;
2417c478bd9Sstevel@tonic-gate proc_t *p;
2427c478bd9Sstevel@tonic-gate refstr_t *rp;
2437c478bd9Sstevel@tonic-gate size_t size;
2447c478bd9Sstevel@tonic-gate char *path;
2457c478bd9Sstevel@tonic-gate core_content_t content = CC_CONTENT_INVALID;
2467c478bd9Sstevel@tonic-gate struct core_globals *cg;
2477c478bd9Sstevel@tonic-gate zone_t *zone = curproc->p_zone;
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate cg = zone_getspecific(core_zone_key, zone);
2507c478bd9Sstevel@tonic-gate ASSERT(cg != NULL);
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate switch (subcode) {
2537c478bd9Sstevel@tonic-gate case CC_SET_OPTIONS:
2547c478bd9Sstevel@tonic-gate if ((error = secpolicy_coreadm(CRED())) == 0) {
2557c478bd9Sstevel@tonic-gate if (arg1 & ~CC_OPTIONS)
2567c478bd9Sstevel@tonic-gate error = EINVAL;
2577c478bd9Sstevel@tonic-gate else
2587c478bd9Sstevel@tonic-gate cg->core_options = (uint32_t)arg1;
2597c478bd9Sstevel@tonic-gate }
2607c478bd9Sstevel@tonic-gate break;
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate case CC_GET_OPTIONS:
2637c478bd9Sstevel@tonic-gate return (cg->core_options);
2647c478bd9Sstevel@tonic-gate
2657c478bd9Sstevel@tonic-gate case CC_GET_GLOBAL_PATH:
2667c478bd9Sstevel@tonic-gate case CC_GET_DEFAULT_PATH:
2677c478bd9Sstevel@tonic-gate case CC_GET_PROCESS_PATH:
2687c478bd9Sstevel@tonic-gate if (subcode == CC_GET_GLOBAL_PATH) {
2697c478bd9Sstevel@tonic-gate mutex_enter(&cg->core_lock);
2707c478bd9Sstevel@tonic-gate if ((rp = cg->core_file) != NULL)
2717c478bd9Sstevel@tonic-gate refstr_hold(rp);
2727c478bd9Sstevel@tonic-gate mutex_exit(&cg->core_lock);
2737c478bd9Sstevel@tonic-gate } else if (subcode == CC_GET_DEFAULT_PATH) {
2747c478bd9Sstevel@tonic-gate rp = corectl_path_value(cg->core_default_path);
2757c478bd9Sstevel@tonic-gate } else {
2767c478bd9Sstevel@tonic-gate rp = NULL;
2777c478bd9Sstevel@tonic-gate mutex_enter(&pidlock);
2787c478bd9Sstevel@tonic-gate if ((p = prfind((pid_t)arg3)) == NULL ||
2797c478bd9Sstevel@tonic-gate p->p_stat == SIDL) {
2807c478bd9Sstevel@tonic-gate mutex_exit(&pidlock);
2817c478bd9Sstevel@tonic-gate error = ESRCH;
2827c478bd9Sstevel@tonic-gate } else {
2837c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
2847c478bd9Sstevel@tonic-gate mutex_exit(&pidlock);
2857c478bd9Sstevel@tonic-gate mutex_enter(&p->p_crlock);
2867c478bd9Sstevel@tonic-gate if (!hasprocperm(p->p_cred, CRED()))
2877c478bd9Sstevel@tonic-gate error = EPERM;
2887c478bd9Sstevel@tonic-gate else if (p->p_corefile != NULL)
2897c478bd9Sstevel@tonic-gate rp = corectl_path_value(p->p_corefile);
2907c478bd9Sstevel@tonic-gate mutex_exit(&p->p_crlock);
2917c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate if (rp == NULL) {
2957c478bd9Sstevel@tonic-gate if (error == 0 && suword8((void *)arg1, 0))
2967c478bd9Sstevel@tonic-gate error = EFAULT;
2977c478bd9Sstevel@tonic-gate } else {
2987c478bd9Sstevel@tonic-gate error = copyoutstr(refstr_value(rp), (char *)arg1,
2993f2f09c1Sdp (size_t)arg2, NULL);
3007c478bd9Sstevel@tonic-gate refstr_rele(rp);
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate break;
3037c478bd9Sstevel@tonic-gate
3047c478bd9Sstevel@tonic-gate case CC_SET_GLOBAL_PATH:
3057c478bd9Sstevel@tonic-gate case CC_SET_DEFAULT_PATH:
3067c478bd9Sstevel@tonic-gate if ((error = secpolicy_coreadm(CRED())) != 0)
3077c478bd9Sstevel@tonic-gate break;
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
3107c478bd9Sstevel@tonic-gate case CC_SET_PROCESS_PATH:
3117c478bd9Sstevel@tonic-gate if ((size = MIN((size_t)arg2, MAXPATHLEN)) == 0) {
3127c478bd9Sstevel@tonic-gate error = EINVAL;
3137c478bd9Sstevel@tonic-gate break;
3147c478bd9Sstevel@tonic-gate }
3157c478bd9Sstevel@tonic-gate path = kmem_alloc(size, KM_SLEEP);
3167c478bd9Sstevel@tonic-gate error = copyinstr((char *)arg1, path, size, NULL);
3177c478bd9Sstevel@tonic-gate if (error == 0) {
3187c478bd9Sstevel@tonic-gate if (subcode == CC_SET_PROCESS_PATH) {
3197c478bd9Sstevel@tonic-gate error = set_proc_info((pid_t)arg3, path, 0);
3207c478bd9Sstevel@tonic-gate } else if (subcode == CC_SET_DEFAULT_PATH) {
3217c478bd9Sstevel@tonic-gate corectl_path_set(cg->core_default_path, path);
3227c478bd9Sstevel@tonic-gate } else if (*path != '\0' && *path != '/') {
3237c478bd9Sstevel@tonic-gate error = EINVAL;
3247c478bd9Sstevel@tonic-gate } else {
3257c478bd9Sstevel@tonic-gate refstr_t *nrp = refstr_alloc(path);
3267c478bd9Sstevel@tonic-gate
3277c478bd9Sstevel@tonic-gate mutex_enter(&cg->core_lock);
3287c478bd9Sstevel@tonic-gate rp = cg->core_file;
3297c478bd9Sstevel@tonic-gate if (*path == '\0')
3307c478bd9Sstevel@tonic-gate cg->core_file = NULL;
3317c478bd9Sstevel@tonic-gate else
3327c478bd9Sstevel@tonic-gate refstr_hold(cg->core_file = nrp);
3337c478bd9Sstevel@tonic-gate mutex_exit(&cg->core_lock);
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate if (rp != NULL)
3367c478bd9Sstevel@tonic-gate refstr_rele(rp);
3377c478bd9Sstevel@tonic-gate
3387c478bd9Sstevel@tonic-gate refstr_rele(nrp);
3397c478bd9Sstevel@tonic-gate }
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate kmem_free(path, size);
3427c478bd9Sstevel@tonic-gate break;
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate case CC_SET_GLOBAL_CONTENT:
3457c478bd9Sstevel@tonic-gate case CC_SET_DEFAULT_CONTENT:
3467c478bd9Sstevel@tonic-gate if ((error = secpolicy_coreadm(CRED())) != 0)
3477c478bd9Sstevel@tonic-gate break;
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
3507c478bd9Sstevel@tonic-gate case CC_SET_PROCESS_CONTENT:
3517c478bd9Sstevel@tonic-gate error = copyin((void *)arg1, &content, sizeof (content));
3527c478bd9Sstevel@tonic-gate if (error != 0)
3537c478bd9Sstevel@tonic-gate break;
3547c478bd9Sstevel@tonic-gate
3557c478bd9Sstevel@tonic-gate /*
3567c478bd9Sstevel@tonic-gate * If any unknown bits are set, don't let this charade
3577c478bd9Sstevel@tonic-gate * continue.
3587c478bd9Sstevel@tonic-gate */
3597c478bd9Sstevel@tonic-gate if (content & ~CC_CONTENT_ALL) {
3607c478bd9Sstevel@tonic-gate error = EINVAL;
3617c478bd9Sstevel@tonic-gate break;
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate
3647c478bd9Sstevel@tonic-gate if (subcode == CC_SET_PROCESS_CONTENT) {
3657c478bd9Sstevel@tonic-gate error = set_proc_info((pid_t)arg2, NULL, content);
3667c478bd9Sstevel@tonic-gate } else if (subcode == CC_SET_DEFAULT_CONTENT) {
3677c478bd9Sstevel@tonic-gate corectl_content_set(cg->core_default_content, content);
3687c478bd9Sstevel@tonic-gate } else {
3697c478bd9Sstevel@tonic-gate mutex_enter(&cg->core_lock);
3707c478bd9Sstevel@tonic-gate cg->core_content = content;
3717c478bd9Sstevel@tonic-gate mutex_exit(&cg->core_lock);
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate
3747c478bd9Sstevel@tonic-gate break;
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate case CC_GET_GLOBAL_CONTENT:
3777c478bd9Sstevel@tonic-gate content = cg->core_content;
3787c478bd9Sstevel@tonic-gate error = copyout(&content, (void *)arg1, sizeof (content));
3797c478bd9Sstevel@tonic-gate break;
3807c478bd9Sstevel@tonic-gate
3817c478bd9Sstevel@tonic-gate case CC_GET_DEFAULT_CONTENT:
3827c478bd9Sstevel@tonic-gate content = corectl_content_value(cg->core_default_content);
3837c478bd9Sstevel@tonic-gate error = copyout(&content, (void *)arg1, sizeof (content));
3847c478bd9Sstevel@tonic-gate break;
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate case CC_GET_PROCESS_CONTENT:
3877c478bd9Sstevel@tonic-gate mutex_enter(&pidlock);
3887c478bd9Sstevel@tonic-gate if ((p = prfind((pid_t)arg2)) == NULL || p->p_stat == SIDL) {
3897c478bd9Sstevel@tonic-gate mutex_exit(&pidlock);
3907c478bd9Sstevel@tonic-gate error = ESRCH;
3917c478bd9Sstevel@tonic-gate break;
3927c478bd9Sstevel@tonic-gate }
3937c478bd9Sstevel@tonic-gate
3947c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
3957c478bd9Sstevel@tonic-gate mutex_exit(&pidlock);
3967c478bd9Sstevel@tonic-gate mutex_enter(&p->p_crlock);
3977c478bd9Sstevel@tonic-gate if (!hasprocperm(p->p_cred, CRED()))
3987c478bd9Sstevel@tonic-gate error = EPERM;
3997c478bd9Sstevel@tonic-gate else if (p->p_content == NULL)
4007c478bd9Sstevel@tonic-gate content = CC_CONTENT_NONE;
4017c478bd9Sstevel@tonic-gate else
4027c478bd9Sstevel@tonic-gate content = corectl_content_value(p->p_content);
4037c478bd9Sstevel@tonic-gate mutex_exit(&p->p_crlock);
4047c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate if (error == 0)
4077c478bd9Sstevel@tonic-gate error = copyout(&content, (void *)arg1,
4087c478bd9Sstevel@tonic-gate sizeof (content));
4097c478bd9Sstevel@tonic-gate break;
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate default:
4127c478bd9Sstevel@tonic-gate error = EINVAL;
4137c478bd9Sstevel@tonic-gate break;
4147c478bd9Sstevel@tonic-gate }
4157c478bd9Sstevel@tonic-gate
4167c478bd9Sstevel@tonic-gate if (error)
4177c478bd9Sstevel@tonic-gate return (set_errno(error));
4187c478bd9Sstevel@tonic-gate return (0);
4197c478bd9Sstevel@tonic-gate }
4207c478bd9Sstevel@tonic-gate
4217c478bd9Sstevel@tonic-gate typedef struct {
4227c478bd9Sstevel@tonic-gate int cc_count;
4237c478bd9Sstevel@tonic-gate corectl_path_t *cc_path;
4247c478bd9Sstevel@tonic-gate corectl_content_t *cc_content;
4257c478bd9Sstevel@tonic-gate } counter_t;
4267c478bd9Sstevel@tonic-gate
4277c478bd9Sstevel@tonic-gate static int
set_one_proc_info(proc_t * p,counter_t * counterp)4287c478bd9Sstevel@tonic-gate set_one_proc_info(proc_t *p, counter_t *counterp)
4297c478bd9Sstevel@tonic-gate {
4307c478bd9Sstevel@tonic-gate corectl_path_t *corefile;
4317c478bd9Sstevel@tonic-gate corectl_content_t *content;
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate mutex_enter(&p->p_crlock);
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate if (!(p->p_flag & SSYS) && hasprocperm(p->p_cred, CRED())) {
4367c478bd9Sstevel@tonic-gate mutex_exit(&p->p_crlock);
4377c478bd9Sstevel@tonic-gate counterp->cc_count++;
4387c478bd9Sstevel@tonic-gate if (counterp->cc_path != NULL) {
4397c478bd9Sstevel@tonic-gate corectl_path_hold(counterp->cc_path);
4407c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
4417c478bd9Sstevel@tonic-gate corefile = p->p_corefile;
4427c478bd9Sstevel@tonic-gate p->p_corefile = counterp->cc_path;
4437c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
4447c478bd9Sstevel@tonic-gate if (corefile != NULL)
4457c478bd9Sstevel@tonic-gate corectl_path_rele(corefile);
4467c478bd9Sstevel@tonic-gate } else {
4477c478bd9Sstevel@tonic-gate corectl_content_hold(counterp->cc_content);
4487c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
4497c478bd9Sstevel@tonic-gate content = p->p_content;
4507c478bd9Sstevel@tonic-gate p->p_content = counterp->cc_content;
4517c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
4527c478bd9Sstevel@tonic-gate if (content != NULL)
4537c478bd9Sstevel@tonic-gate corectl_content_rele(content);
4547c478bd9Sstevel@tonic-gate }
4557c478bd9Sstevel@tonic-gate } else {
4567c478bd9Sstevel@tonic-gate mutex_exit(&p->p_crlock);
4577c478bd9Sstevel@tonic-gate }
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate return (0);
4607c478bd9Sstevel@tonic-gate }
4617c478bd9Sstevel@tonic-gate
4627c478bd9Sstevel@tonic-gate static int
set_proc_info(pid_t pid,const char * path,core_content_t content)4637c478bd9Sstevel@tonic-gate set_proc_info(pid_t pid, const char *path, core_content_t content)
4647c478bd9Sstevel@tonic-gate {
4657c478bd9Sstevel@tonic-gate proc_t *p;
4667c478bd9Sstevel@tonic-gate counter_t counter;
4677c478bd9Sstevel@tonic-gate int error = 0;
4687c478bd9Sstevel@tonic-gate
4697c478bd9Sstevel@tonic-gate counter.cc_count = 0;
4707c478bd9Sstevel@tonic-gate /*
4717c478bd9Sstevel@tonic-gate * Only one of the core file path or content can be set at a time.
4727c478bd9Sstevel@tonic-gate */
4737c478bd9Sstevel@tonic-gate if (path != NULL) {
4747c478bd9Sstevel@tonic-gate counter.cc_path = corectl_path_alloc(path);
4757c478bd9Sstevel@tonic-gate counter.cc_content = NULL;
4767c478bd9Sstevel@tonic-gate } else {
4777c478bd9Sstevel@tonic-gate counter.cc_path = NULL;
4787c478bd9Sstevel@tonic-gate counter.cc_content = corectl_content_alloc(content);
4797c478bd9Sstevel@tonic-gate }
4807c478bd9Sstevel@tonic-gate
4817c478bd9Sstevel@tonic-gate if (pid == -1) {
4827c478bd9Sstevel@tonic-gate procset_t set;
4837c478bd9Sstevel@tonic-gate
4847c478bd9Sstevel@tonic-gate setprocset(&set, POP_AND, P_ALL, P_MYID, P_ALL, P_MYID);
4857c478bd9Sstevel@tonic-gate error = dotoprocs(&set, set_one_proc_info, (char *)&counter);
4867c478bd9Sstevel@tonic-gate if (error == 0 && counter.cc_count == 0)
4877c478bd9Sstevel@tonic-gate error = EPERM;
4887c478bd9Sstevel@tonic-gate } else if (pid > 0) {
4897c478bd9Sstevel@tonic-gate mutex_enter(&pidlock);
4907c478bd9Sstevel@tonic-gate if ((p = prfind(pid)) == NULL || p->p_stat == SIDL) {
4917c478bd9Sstevel@tonic-gate error = ESRCH;
4927c478bd9Sstevel@tonic-gate } else {
4937c478bd9Sstevel@tonic-gate (void) set_one_proc_info(p, &counter);
4947c478bd9Sstevel@tonic-gate if (counter.cc_count == 0)
4957c478bd9Sstevel@tonic-gate error = EPERM;
4967c478bd9Sstevel@tonic-gate }
4977c478bd9Sstevel@tonic-gate mutex_exit(&pidlock);
4987c478bd9Sstevel@tonic-gate } else {
4997c478bd9Sstevel@tonic-gate int nfound = 0;
5007c478bd9Sstevel@tonic-gate pid_t pgid;
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate if (pid == 0)
5037c478bd9Sstevel@tonic-gate pgid = curproc->p_pgrp;
5047c478bd9Sstevel@tonic-gate else
5057c478bd9Sstevel@tonic-gate pgid = -pid;
5067c478bd9Sstevel@tonic-gate
5077c478bd9Sstevel@tonic-gate mutex_enter(&pidlock);
5087c478bd9Sstevel@tonic-gate for (p = pgfind(pgid); p != NULL; p = p->p_pglink) {
5097c478bd9Sstevel@tonic-gate if (p->p_stat != SIDL) {
5107c478bd9Sstevel@tonic-gate nfound++;
5117c478bd9Sstevel@tonic-gate (void) set_one_proc_info(p, &counter);
5127c478bd9Sstevel@tonic-gate }
5137c478bd9Sstevel@tonic-gate }
5147c478bd9Sstevel@tonic-gate mutex_exit(&pidlock);
5157c478bd9Sstevel@tonic-gate if (nfound == 0)
5167c478bd9Sstevel@tonic-gate error = ESRCH;
5177c478bd9Sstevel@tonic-gate else if (counter.cc_count == 0)
5187c478bd9Sstevel@tonic-gate error = EPERM;
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate
5217c478bd9Sstevel@tonic-gate if (path != NULL)
5227c478bd9Sstevel@tonic-gate corectl_path_rele(counter.cc_path);
5237c478bd9Sstevel@tonic-gate else
5247c478bd9Sstevel@tonic-gate corectl_content_rele(counter.cc_content);
5257c478bd9Sstevel@tonic-gate
5267c478bd9Sstevel@tonic-gate if (error)
5277c478bd9Sstevel@tonic-gate return (set_errno(error));
5287c478bd9Sstevel@tonic-gate return (0);
5297c478bd9Sstevel@tonic-gate }
5307c478bd9Sstevel@tonic-gate
5317c478bd9Sstevel@tonic-gate /*
5327c478bd9Sstevel@tonic-gate * Give current process the default core settings for its current zone;
5337c478bd9Sstevel@tonic-gate * used for processes entering a zone via zone_enter.
5347c478bd9Sstevel@tonic-gate */
5357c478bd9Sstevel@tonic-gate void
set_core_defaults(void)5367c478bd9Sstevel@tonic-gate set_core_defaults(void)
5377c478bd9Sstevel@tonic-gate {
5387c478bd9Sstevel@tonic-gate proc_t *p = curproc;
5397c478bd9Sstevel@tonic-gate struct core_globals *cg;
5407c478bd9Sstevel@tonic-gate corectl_path_t *oldpath, *newpath;
5417c478bd9Sstevel@tonic-gate corectl_content_t *oldcontent, *newcontent;
5427c478bd9Sstevel@tonic-gate
5437c478bd9Sstevel@tonic-gate cg = zone_getspecific(core_zone_key, p->p_zone);
5447c478bd9Sstevel@tonic-gate
5457c478bd9Sstevel@tonic-gate /* make local copies of default values to protect against change */
5467c478bd9Sstevel@tonic-gate newpath = cg->core_default_path;
5477c478bd9Sstevel@tonic-gate newcontent = cg->core_default_content;
5487c478bd9Sstevel@tonic-gate
5497c478bd9Sstevel@tonic-gate corectl_path_hold(newpath);
5507c478bd9Sstevel@tonic-gate corectl_content_hold(newcontent);
5517c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
5527c478bd9Sstevel@tonic-gate oldpath = p->p_corefile;
5537c478bd9Sstevel@tonic-gate p->p_corefile = newpath;
5547c478bd9Sstevel@tonic-gate oldcontent = p->p_content;
5557c478bd9Sstevel@tonic-gate p->p_content = newcontent;
5567c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
5577c478bd9Sstevel@tonic-gate if (oldpath != NULL)
5587c478bd9Sstevel@tonic-gate corectl_path_rele(oldpath);
5597c478bd9Sstevel@tonic-gate if (oldcontent != NULL)
5607c478bd9Sstevel@tonic-gate corectl_content_rele(oldcontent);
5617c478bd9Sstevel@tonic-gate }
562