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 53ad28c1eSrm88369 * Common Development and Distribution License (the "License"). 63ad28c1eSrm88369 * 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 /* 22*2a3221a4Svp157776 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <librestart.h> 297c478bd9Sstevel@tonic-gate #include <librestart_priv.h> 307c478bd9Sstevel@tonic-gate #include <libscf.h> 317c478bd9Sstevel@tonic-gate #include <libscf_priv.h> 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include <assert.h> 347c478bd9Sstevel@tonic-gate #include <ctype.h> 357c478bd9Sstevel@tonic-gate #include <dlfcn.h> 367c478bd9Sstevel@tonic-gate #include <errno.h> 377c478bd9Sstevel@tonic-gate #include <exec_attr.h> 387c478bd9Sstevel@tonic-gate #include <grp.h> 397c478bd9Sstevel@tonic-gate #include <libsysevent.h> 407c478bd9Sstevel@tonic-gate #include <libuutil.h> 417c478bd9Sstevel@tonic-gate #include <limits.h> 427c478bd9Sstevel@tonic-gate #include <link.h> 437c478bd9Sstevel@tonic-gate #include <malloc.h> 447c478bd9Sstevel@tonic-gate #include <pool.h> 457c478bd9Sstevel@tonic-gate #include <priv.h> 467c478bd9Sstevel@tonic-gate #include <project.h> 477c478bd9Sstevel@tonic-gate #include <pthread.h> 487c478bd9Sstevel@tonic-gate #include <pwd.h> 497c478bd9Sstevel@tonic-gate #include <secdb.h> 507c478bd9Sstevel@tonic-gate #include <signal.h> 517c478bd9Sstevel@tonic-gate #include <stdlib.h> 527c478bd9Sstevel@tonic-gate #include <string.h> 537c478bd9Sstevel@tonic-gate #include <syslog.h> 547c478bd9Sstevel@tonic-gate #include <sys/corectl.h> 557c478bd9Sstevel@tonic-gate #include <sys/machelf.h> 567c478bd9Sstevel@tonic-gate #include <sys/task.h> 577c478bd9Sstevel@tonic-gate #include <sys/types.h> 587c478bd9Sstevel@tonic-gate #include <time.h> 597c478bd9Sstevel@tonic-gate #include <unistd.h> 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate #define walkcontext _walkcontext 627c478bd9Sstevel@tonic-gate #include <ucontext.h> 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate #define min(a, b) ((a) > (b) ? (b) : (a)) 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate #define MKW_TRUE ":true" 677c478bd9Sstevel@tonic-gate #define MKW_KILL ":kill" 687c478bd9Sstevel@tonic-gate #define MKW_KILL_PROC ":kill_process" 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate #define ALLOCFAIL ((char *)"Allocation failure.") 717c478bd9Sstevel@tonic-gate #define RCBROKEN ((char *)"Repository connection broken.") 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate #define MAX_COMMIT_RETRIES 20 747c478bd9Sstevel@tonic-gate #define MAX_COMMIT_RETRY_INT (5 * 1000000) /* 5 seconds */ 757c478bd9Sstevel@tonic-gate #define INITIAL_COMMIT_RETRY_INT (10000) /* 1/100th second */ 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate /* 787c478bd9Sstevel@tonic-gate * bad_fail() catches bugs in this and lower layers by reporting supposedly 797c478bd9Sstevel@tonic-gate * impossible function failures. The NDEBUG case keeps the strings out of the 807c478bd9Sstevel@tonic-gate * library but still calls abort() so we can root-cause from the coredump. 817c478bd9Sstevel@tonic-gate */ 827c478bd9Sstevel@tonic-gate #ifndef NDEBUG 837c478bd9Sstevel@tonic-gate #define bad_fail(func, err) { \ 847c478bd9Sstevel@tonic-gate (void) fprintf(stderr, \ 857c478bd9Sstevel@tonic-gate "At %s:%d, %s() failed with unexpected error %d. Aborting.\n", \ 867c478bd9Sstevel@tonic-gate __FILE__, __LINE__, (func), (err)); \ 877c478bd9Sstevel@tonic-gate abort(); \ 887c478bd9Sstevel@tonic-gate } 897c478bd9Sstevel@tonic-gate #else 907c478bd9Sstevel@tonic-gate #define bad_fail(func, err) abort() 917c478bd9Sstevel@tonic-gate #endif 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate struct restarter_event_handle { 947c478bd9Sstevel@tonic-gate char *reh_restarter_name; 957c478bd9Sstevel@tonic-gate char *reh_delegate_channel_name; 967c478bd9Sstevel@tonic-gate evchan_t *reh_delegate_channel; 977c478bd9Sstevel@tonic-gate char *reh_delegate_subscriber_id; 987c478bd9Sstevel@tonic-gate char *reh_master_channel_name; 997c478bd9Sstevel@tonic-gate evchan_t *reh_master_channel; 1007c478bd9Sstevel@tonic-gate char *reh_master_subscriber_id; 1017c478bd9Sstevel@tonic-gate int (*reh_handler)(restarter_event_t *); 1027c478bd9Sstevel@tonic-gate }; 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate struct restarter_event { 1057c478bd9Sstevel@tonic-gate sysevent_t *re_sysevent; 1067c478bd9Sstevel@tonic-gate restarter_event_type_t re_type; 1077c478bd9Sstevel@tonic-gate char *re_instance_name; 1087c478bd9Sstevel@tonic-gate restarter_event_handle_t *re_event_handle; 1097c478bd9Sstevel@tonic-gate restarter_instance_state_t re_state; 1107c478bd9Sstevel@tonic-gate restarter_instance_state_t re_next_state; 1117c478bd9Sstevel@tonic-gate }; 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate static const char * const allocfail = "Allocation failure.\n"; 1147c478bd9Sstevel@tonic-gate static const char * const rcbroken = "Repository connection broken.\n"; 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate static int method_context_safety = 0; /* Can safely call pools/projects. */ 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate int ndebug = 1; 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate static void 1217c478bd9Sstevel@tonic-gate free_restarter_event_handle(struct restarter_event_handle *h) 1227c478bd9Sstevel@tonic-gate { 1237c478bd9Sstevel@tonic-gate if (h == NULL) 1247c478bd9Sstevel@tonic-gate return; 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate /* 1277c478bd9Sstevel@tonic-gate * Just free the memory -- don't unbind the sysevent handle, 1287c478bd9Sstevel@tonic-gate * as otherwise events may be lost if this is just a restarter 1297c478bd9Sstevel@tonic-gate * restart. 1307c478bd9Sstevel@tonic-gate */ 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate if (h->reh_restarter_name != NULL) 1337c478bd9Sstevel@tonic-gate free(h->reh_restarter_name); 1347c478bd9Sstevel@tonic-gate if (h->reh_delegate_channel_name != NULL) 1357c478bd9Sstevel@tonic-gate free(h->reh_delegate_channel_name); 1367c478bd9Sstevel@tonic-gate if (h->reh_delegate_subscriber_id != NULL) 1377c478bd9Sstevel@tonic-gate free(h->reh_delegate_subscriber_id); 1387c478bd9Sstevel@tonic-gate if (h->reh_master_channel_name != NULL) 1397c478bd9Sstevel@tonic-gate free(h->reh_master_channel_name); 1407c478bd9Sstevel@tonic-gate if (h->reh_master_subscriber_id != NULL) 1417c478bd9Sstevel@tonic-gate free(h->reh_master_subscriber_id); 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate free(h); 1447c478bd9Sstevel@tonic-gate } 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate static const char * 1477c478bd9Sstevel@tonic-gate last_part(const char *fmri) 1487c478bd9Sstevel@tonic-gate { 1497c478bd9Sstevel@tonic-gate char *last_part; 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate last_part = strrchr(fmri, '/'); 1527c478bd9Sstevel@tonic-gate last_part++; 1537c478bd9Sstevel@tonic-gate assert(last_part != NULL); 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate return (last_part); 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate char * 1597c478bd9Sstevel@tonic-gate _restarter_get_channel_name(const char *fmri, int type) 1607c478bd9Sstevel@tonic-gate { 1617c478bd9Sstevel@tonic-gate const char *name; 1627c478bd9Sstevel@tonic-gate char *chan_name = malloc(MAX_CHNAME_LEN); 1637c478bd9Sstevel@tonic-gate char prefix_name[3]; 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate if (chan_name == NULL) 1667c478bd9Sstevel@tonic-gate return (NULL); 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate if (type == RESTARTER_CHANNEL_DELEGATE) 1697c478bd9Sstevel@tonic-gate (void) strcpy(prefix_name, "d_"); 1707c478bd9Sstevel@tonic-gate else if (type == RESTARTER_CHANNEL_MASTER) 1717c478bd9Sstevel@tonic-gate (void) strcpy(prefix_name, "m_"); 1727c478bd9Sstevel@tonic-gate else { 1737c478bd9Sstevel@tonic-gate free(chan_name); 1747c478bd9Sstevel@tonic-gate return (NULL); 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate name = last_part(fmri); 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate /* 1807c478bd9Sstevel@tonic-gate * Should check for [a-z],[A-Z],[0-9],.,_,-,: 1817c478bd9Sstevel@tonic-gate */ 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate if (snprintf(chan_name, MAX_CHNAME_LEN, "com.sun:scf:%s%s", 1847c478bd9Sstevel@tonic-gate prefix_name, name) > MAX_CHNAME_LEN) { 1857c478bd9Sstevel@tonic-gate free(chan_name); 1867c478bd9Sstevel@tonic-gate return (NULL); 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate return (chan_name); 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate int 1937c478bd9Sstevel@tonic-gate cb(sysevent_t *syse, void *cookie) 1947c478bd9Sstevel@tonic-gate { 1957c478bd9Sstevel@tonic-gate restarter_event_handle_t *h = (restarter_event_handle_t *)cookie; 1967c478bd9Sstevel@tonic-gate restarter_event_t *e; 1977c478bd9Sstevel@tonic-gate nvlist_t *attr_list = NULL; 1987c478bd9Sstevel@tonic-gate int ret = 0; 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate e = uu_zalloc(sizeof (restarter_event_t)); 2017c478bd9Sstevel@tonic-gate if (e == NULL) 2027c478bd9Sstevel@tonic-gate uu_die(allocfail); 2037c478bd9Sstevel@tonic-gate e->re_event_handle = h; 2047c478bd9Sstevel@tonic-gate e->re_sysevent = syse; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate if (sysevent_get_attr_list(syse, &attr_list) != 0) 2077c478bd9Sstevel@tonic-gate uu_die(allocfail); 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate if ((nvlist_lookup_uint32(attr_list, RESTARTER_NAME_TYPE, 2107c478bd9Sstevel@tonic-gate &(e->re_type)) != 0) || 2117c478bd9Sstevel@tonic-gate (nvlist_lookup_string(attr_list, 2127c478bd9Sstevel@tonic-gate RESTARTER_NAME_INSTANCE, &(e->re_instance_name)) != 0)) { 2137c478bd9Sstevel@tonic-gate uu_warn("%s: Can't decode nvlist for event %p\n", 2147c478bd9Sstevel@tonic-gate h->reh_restarter_name, (void *)syse); 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate ret = 0; 2177c478bd9Sstevel@tonic-gate } else { 2187c478bd9Sstevel@tonic-gate ret = h->reh_handler(e); 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate uu_free(e); 2227c478bd9Sstevel@tonic-gate nvlist_free(attr_list); 2237c478bd9Sstevel@tonic-gate return (ret); 2247c478bd9Sstevel@tonic-gate } 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate /* 2277c478bd9Sstevel@tonic-gate * restarter_bind_handle(uint32_t, char *, int (*)(restarter_event_t *), int, 2287c478bd9Sstevel@tonic-gate * restarter_event_handle_t **) 2297c478bd9Sstevel@tonic-gate * 2307c478bd9Sstevel@tonic-gate * Bind to a delegated restarter event channel. 2317c478bd9Sstevel@tonic-gate * Each delegated restarter gets its own channel for resource management. 2327c478bd9Sstevel@tonic-gate * 2337c478bd9Sstevel@tonic-gate * Returns 0 on success or 2347c478bd9Sstevel@tonic-gate * ENOTSUP version mismatch 2357c478bd9Sstevel@tonic-gate * EINVAL restarter_name or event_handle is NULL 2367c478bd9Sstevel@tonic-gate * ENOMEM out of memory, too many channels, or too many subscriptions 2377c478bd9Sstevel@tonic-gate * EBUSY sysevent_evc_bind() could not establish binding 2387c478bd9Sstevel@tonic-gate * EFAULT internal sysevent_evc_bind()/sysevent_evc_subscribe() error 2397c478bd9Sstevel@tonic-gate * EMFILE out of file descriptors 2407c478bd9Sstevel@tonic-gate * EPERM insufficient privilege for sysevent_evc_bind() 2417c478bd9Sstevel@tonic-gate * EEXIST already subscribed 2427c478bd9Sstevel@tonic-gate */ 2437c478bd9Sstevel@tonic-gate int 2447c478bd9Sstevel@tonic-gate restarter_bind_handle(uint32_t version, const char *restarter_name, 2457c478bd9Sstevel@tonic-gate int (*event_handler)(restarter_event_t *), int flags, 2467c478bd9Sstevel@tonic-gate restarter_event_handle_t **rehp) 2477c478bd9Sstevel@tonic-gate { 2487c478bd9Sstevel@tonic-gate restarter_event_handle_t *h; 2497c478bd9Sstevel@tonic-gate size_t sz; 2507c478bd9Sstevel@tonic-gate int err; 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate if (version != RESTARTER_EVENT_VERSION) 2537c478bd9Sstevel@tonic-gate return (ENOTSUP); 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate if (restarter_name == NULL || event_handler == NULL) 2567c478bd9Sstevel@tonic-gate return (EINVAL); 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate if (flags & RESTARTER_FLAG_DEBUG) 2597c478bd9Sstevel@tonic-gate ndebug++; 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate if ((h = uu_zalloc(sizeof (restarter_event_handle_t))) == NULL) 2627c478bd9Sstevel@tonic-gate return (ENOMEM); 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate h->reh_delegate_subscriber_id = malloc(MAX_SUBID_LEN); 2657c478bd9Sstevel@tonic-gate h->reh_master_subscriber_id = malloc(MAX_SUBID_LEN); 2667c478bd9Sstevel@tonic-gate h->reh_restarter_name = strdup(restarter_name); 2677c478bd9Sstevel@tonic-gate if (h->reh_delegate_subscriber_id == NULL || 2687c478bd9Sstevel@tonic-gate h->reh_master_subscriber_id == NULL || 2697c478bd9Sstevel@tonic-gate h->reh_restarter_name == NULL) { 2707c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 2717c478bd9Sstevel@tonic-gate return (ENOMEM); 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate sz = strlcpy(h->reh_delegate_subscriber_id, "del", MAX_SUBID_LEN); 2757c478bd9Sstevel@tonic-gate assert(sz < MAX_SUBID_LEN); 2767c478bd9Sstevel@tonic-gate sz = strlcpy(h->reh_master_subscriber_id, "master", MAX_SUBID_LEN); 2777c478bd9Sstevel@tonic-gate assert(sz < MAX_SUBID_LEN); 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate h->reh_delegate_channel_name = 2807c478bd9Sstevel@tonic-gate _restarter_get_channel_name(restarter_name, 2817c478bd9Sstevel@tonic-gate RESTARTER_CHANNEL_DELEGATE); 2827c478bd9Sstevel@tonic-gate h->reh_master_channel_name = 2837c478bd9Sstevel@tonic-gate _restarter_get_channel_name(restarter_name, 2847c478bd9Sstevel@tonic-gate RESTARTER_CHANNEL_MASTER); 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate if (h->reh_delegate_channel_name == NULL || 2877c478bd9Sstevel@tonic-gate h->reh_master_channel_name == NULL) { 2887c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 2897c478bd9Sstevel@tonic-gate return (ENOMEM); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate if (sysevent_evc_bind(h->reh_delegate_channel_name, 2937c478bd9Sstevel@tonic-gate &h->reh_delegate_channel, EVCH_CREAT|EVCH_HOLD_PEND) != 0) { 2947c478bd9Sstevel@tonic-gate err = errno; 2957c478bd9Sstevel@tonic-gate assert(err != EINVAL); 2967c478bd9Sstevel@tonic-gate assert(err != ENOENT); 2977c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 2987c478bd9Sstevel@tonic-gate return (err); 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate if (sysevent_evc_bind(h->reh_master_channel_name, 3027c478bd9Sstevel@tonic-gate &h->reh_master_channel, EVCH_CREAT|EVCH_HOLD_PEND) != 0) { 3037c478bd9Sstevel@tonic-gate err = errno; 3047c478bd9Sstevel@tonic-gate assert(err != EINVAL); 3057c478bd9Sstevel@tonic-gate assert(err != ENOENT); 3067c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 3077c478bd9Sstevel@tonic-gate return (err); 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate h->reh_handler = event_handler; 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate assert(strlen(restarter_name) <= MAX_CLASS_LEN - 1); 3137c478bd9Sstevel@tonic-gate assert(strlen(h->reh_delegate_subscriber_id) <= MAX_SUBID_LEN - 1); 3147c478bd9Sstevel@tonic-gate assert(strlen(h->reh_master_subscriber_id) <= MAX_SUBID_LEN - 1); 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate if (sysevent_evc_subscribe(h->reh_delegate_channel, 3177c478bd9Sstevel@tonic-gate h->reh_delegate_subscriber_id, EC_ALL, cb, h, EVCH_SUB_KEEP) != 0) { 3187c478bd9Sstevel@tonic-gate err = errno; 3197c478bd9Sstevel@tonic-gate assert(err != EINVAL); 3207c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 3217c478bd9Sstevel@tonic-gate return (err); 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate *rehp = h; 3257c478bd9Sstevel@tonic-gate return (0); 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate restarter_event_handle_t * 3297c478bd9Sstevel@tonic-gate restarter_event_get_handle(restarter_event_t *e) 3307c478bd9Sstevel@tonic-gate { 3317c478bd9Sstevel@tonic-gate assert(e != NULL && e->re_event_handle != NULL); 3327c478bd9Sstevel@tonic-gate return (e->re_event_handle); 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate restarter_event_type_t 3367c478bd9Sstevel@tonic-gate restarter_event_get_type(restarter_event_t *e) 3377c478bd9Sstevel@tonic-gate { 3387c478bd9Sstevel@tonic-gate assert(e != NULL); 3397c478bd9Sstevel@tonic-gate return (e->re_type); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate ssize_t 3437c478bd9Sstevel@tonic-gate restarter_event_get_instance(restarter_event_t *e, char *inst, size_t sz) 3447c478bd9Sstevel@tonic-gate { 3457c478bd9Sstevel@tonic-gate assert(e != NULL && inst != NULL); 3467c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(inst, e->re_instance_name, sz)); 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate int 3507c478bd9Sstevel@tonic-gate restarter_event_get_current_states(restarter_event_t *e, 3517c478bd9Sstevel@tonic-gate restarter_instance_state_t *state, restarter_instance_state_t *next_state) 3527c478bd9Sstevel@tonic-gate { 3537c478bd9Sstevel@tonic-gate if (e == NULL) 3547c478bd9Sstevel@tonic-gate return (-1); 3557c478bd9Sstevel@tonic-gate *state = e->re_state; 3567c478bd9Sstevel@tonic-gate *next_state = e->re_next_state; 3577c478bd9Sstevel@tonic-gate return (0); 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate /* 3617c478bd9Sstevel@tonic-gate * Commit the state, next state, and auxiliary state into the repository. 3627c478bd9Sstevel@tonic-gate * Let the graph engine know about the state change and error. On success, 3637c478bd9Sstevel@tonic-gate * return 0. On error, return 3647c478bd9Sstevel@tonic-gate * EINVAL - aux has spaces 3657c478bd9Sstevel@tonic-gate * - inst is invalid or not an instance FMRI 3667c478bd9Sstevel@tonic-gate * EPROTO - librestart compiled against different libscf 3677c478bd9Sstevel@tonic-gate * ENOMEM - out of memory 3687c478bd9Sstevel@tonic-gate * - repository server out of resources 3697c478bd9Sstevel@tonic-gate * ENOTACTIVE - repository server not running 3707c478bd9Sstevel@tonic-gate * ECONNABORTED - repository connection established, but then broken 3717c478bd9Sstevel@tonic-gate * - unknown libscf error 3727c478bd9Sstevel@tonic-gate * ENOENT - inst does not exist in the repository 3737c478bd9Sstevel@tonic-gate * EPERM - insufficient permissions 3747c478bd9Sstevel@tonic-gate * EACCESS - backend access denied 3757c478bd9Sstevel@tonic-gate * EROFS - backend is readonly 3767c478bd9Sstevel@tonic-gate * EFAULT - internal sysevent_evc_publish() error 3777c478bd9Sstevel@tonic-gate * EBADF - h is invalid (sysevent_evc_publish() returned EINVAL) 3787c478bd9Sstevel@tonic-gate */ 3797c478bd9Sstevel@tonic-gate int 3807c478bd9Sstevel@tonic-gate restarter_set_states(restarter_event_handle_t *h, const char *inst, 3817c478bd9Sstevel@tonic-gate restarter_instance_state_t cur_state, 3827c478bd9Sstevel@tonic-gate restarter_instance_state_t new_cur_state, 3837c478bd9Sstevel@tonic-gate restarter_instance_state_t next_state, 3847c478bd9Sstevel@tonic-gate restarter_instance_state_t new_next_state, restarter_error_t e, 3857c478bd9Sstevel@tonic-gate const char *aux) 3867c478bd9Sstevel@tonic-gate { 3877c478bd9Sstevel@tonic-gate nvlist_t *attr; 3887c478bd9Sstevel@tonic-gate scf_handle_t *scf_h; 3897c478bd9Sstevel@tonic-gate instance_data_t id; 3907c478bd9Sstevel@tonic-gate useconds_t retry_int = INITIAL_COMMIT_RETRY_INT; 3917c478bd9Sstevel@tonic-gate int retries; 3927c478bd9Sstevel@tonic-gate int ret = 0; 3937c478bd9Sstevel@tonic-gate char *p = (char *)aux; 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate assert(h->reh_master_channel != NULL); 3967c478bd9Sstevel@tonic-gate assert(h->reh_master_channel_name != NULL); 3977c478bd9Sstevel@tonic-gate assert(h->reh_master_subscriber_id != NULL); 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate /* Validate format of auxiliary state: no spaces allowed */ 400ba91983eSlianep if (p != NULL) { 401ba91983eSlianep while (*p != '\0') { 4027c478bd9Sstevel@tonic-gate if (isspace(*p)) 4037c478bd9Sstevel@tonic-gate return (EINVAL); 4047c478bd9Sstevel@tonic-gate p++; 4057c478bd9Sstevel@tonic-gate } 406ba91983eSlianep } 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate if ((scf_h = scf_handle_create(SCF_VERSION)) == NULL) { 4097c478bd9Sstevel@tonic-gate switch (scf_error()) { 4107c478bd9Sstevel@tonic-gate case SCF_ERROR_VERSION_MISMATCH: 4117c478bd9Sstevel@tonic-gate return (EPROTO); 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate case SCF_ERROR_NO_MEMORY: 4147c478bd9Sstevel@tonic-gate return (ENOMEM); 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate default: 4177c478bd9Sstevel@tonic-gate bad_fail("scf_handle_create", scf_error()); 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate if (scf_handle_bind(scf_h) == -1) { 4227c478bd9Sstevel@tonic-gate scf_handle_destroy(scf_h); 4237c478bd9Sstevel@tonic-gate switch (scf_error()) { 4247c478bd9Sstevel@tonic-gate case SCF_ERROR_NO_SERVER: 4257c478bd9Sstevel@tonic-gate return (ENOTACTIVE); 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate case SCF_ERROR_NO_RESOURCES: 4287c478bd9Sstevel@tonic-gate return (ENOMEM); 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 4317c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 4327c478bd9Sstevel@tonic-gate default: 4337c478bd9Sstevel@tonic-gate bad_fail("scf_handle_bind", scf_error()); 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate if (nvlist_alloc(&attr, NV_UNIQUE_NAME, 0) != 0 || 4387c478bd9Sstevel@tonic-gate nvlist_add_int32(attr, RESTARTER_NAME_STATE, new_cur_state) != 0 || 4397c478bd9Sstevel@tonic-gate nvlist_add_int32(attr, RESTARTER_NAME_NEXT_STATE, new_next_state) 4407c478bd9Sstevel@tonic-gate != 0 || 4417c478bd9Sstevel@tonic-gate nvlist_add_int32(attr, RESTARTER_NAME_ERROR, e) != 0 || 4427c478bd9Sstevel@tonic-gate nvlist_add_string(attr, RESTARTER_NAME_INSTANCE, inst) != 0) { 4437c478bd9Sstevel@tonic-gate ret = ENOMEM; 4447c478bd9Sstevel@tonic-gate goto errout; 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate id.i_fmri = inst; 4487c478bd9Sstevel@tonic-gate id.i_state = cur_state; 4497c478bd9Sstevel@tonic-gate id.i_next_state = next_state; 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate ret = _restarter_commit_states(scf_h, &id, new_cur_state, 4527c478bd9Sstevel@tonic-gate new_next_state, aux); 4537c478bd9Sstevel@tonic-gate if (ret != 0) 4547c478bd9Sstevel@tonic-gate goto errout; 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate for (retries = 0; retries < MAX_COMMIT_RETRIES; retries++) { 4577c478bd9Sstevel@tonic-gate ret = sysevent_evc_publish(h->reh_master_channel, "master", 4587c478bd9Sstevel@tonic-gate "state_change", "com.sun", "librestart", attr, 4597c478bd9Sstevel@tonic-gate EVCH_NOSLEEP); 4607c478bd9Sstevel@tonic-gate if (ret == 0) 4617c478bd9Sstevel@tonic-gate break; 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate switch (ret) { 4647c478bd9Sstevel@tonic-gate case EAGAIN: 4657c478bd9Sstevel@tonic-gate /* Queue is full */ 4667c478bd9Sstevel@tonic-gate (void) usleep(retry_int); 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate retry_int = min(retry_int * 2, MAX_COMMIT_RETRY_INT); 4697c478bd9Sstevel@tonic-gate break; 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate case EFAULT: 4727c478bd9Sstevel@tonic-gate case ENOMEM: 4737c478bd9Sstevel@tonic-gate goto errout; 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate case EINVAL: 4767c478bd9Sstevel@tonic-gate ret = EBADF; 4777c478bd9Sstevel@tonic-gate goto errout; 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate case EOVERFLOW: 4807c478bd9Sstevel@tonic-gate default: 4817c478bd9Sstevel@tonic-gate bad_fail("sysevent_evc_publish", ret); 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate } 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate errout: 4867c478bd9Sstevel@tonic-gate nvlist_free(attr); 4877c478bd9Sstevel@tonic-gate (void) scf_handle_unbind(scf_h); 4887c478bd9Sstevel@tonic-gate scf_handle_destroy(scf_h); 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate return (ret); 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate restarter_instance_state_t 4947c478bd9Sstevel@tonic-gate restarter_string_to_state(char *string) 4957c478bd9Sstevel@tonic-gate { 4967c478bd9Sstevel@tonic-gate assert(string != NULL); 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate if (strcmp(string, SCF_STATE_STRING_NONE) == 0) 4997c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_NONE); 5007c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_UNINIT) == 0) 5017c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_UNINIT); 5027c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_MAINT) == 0) 5037c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_MAINT); 5047c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_OFFLINE) == 0) 5057c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_OFFLINE); 5067c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_DISABLED) == 0) 5077c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_DISABLED); 5087c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_ONLINE) == 0) 5097c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_ONLINE); 5107c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_DEGRADED) == 0) 5117c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_DEGRADED); 5127c478bd9Sstevel@tonic-gate else { 5137c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_NONE); 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate ssize_t 5187c478bd9Sstevel@tonic-gate restarter_state_to_string(restarter_instance_state_t state, char *string, 5197c478bd9Sstevel@tonic-gate size_t len) 5207c478bd9Sstevel@tonic-gate { 5217c478bd9Sstevel@tonic-gate assert(string != NULL); 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate if (state == RESTARTER_STATE_NONE) 5247c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_NONE, len)); 5257c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_UNINIT) 5267c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_UNINIT, len)); 5277c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_MAINT) 5287c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_MAINT, len)); 5297c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_OFFLINE) 5307c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_OFFLINE, 5317c478bd9Sstevel@tonic-gate len)); 5327c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_DISABLED) 5337c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_DISABLED, 5347c478bd9Sstevel@tonic-gate len)); 5357c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_ONLINE) 5367c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_ONLINE, len)); 5377c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_DEGRADED) 5387c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_DEGRADED, 5397c478bd9Sstevel@tonic-gate len)); 5407c478bd9Sstevel@tonic-gate else 5417c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, "unknown", len)); 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate /* 5457c478bd9Sstevel@tonic-gate * Sets pg to the name property group of s_inst. If it doesn't exist, it is 5467c478bd9Sstevel@tonic-gate * added. 5477c478bd9Sstevel@tonic-gate * 5487c478bd9Sstevel@tonic-gate * Fails with 5497c478bd9Sstevel@tonic-gate * ECONNABORTED - repository disconnection or unknown libscf error 5507c478bd9Sstevel@tonic-gate * EBADF - inst is not set 5517c478bd9Sstevel@tonic-gate * ECANCELED - inst is deleted 5527c478bd9Sstevel@tonic-gate * EPERM - permission is denied 5537c478bd9Sstevel@tonic-gate * EACCES - backend denied access 5547c478bd9Sstevel@tonic-gate * EROFS - backend readonly 5557c478bd9Sstevel@tonic-gate */ 5567c478bd9Sstevel@tonic-gate static int 5577c478bd9Sstevel@tonic-gate instance_get_or_add_pg(scf_instance_t *inst, const char *name, 5587c478bd9Sstevel@tonic-gate const char *type, uint32_t flags, scf_propertygroup_t *pg) 5597c478bd9Sstevel@tonic-gate { 5607c478bd9Sstevel@tonic-gate again: 5617c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, name, pg) == 0) 5627c478bd9Sstevel@tonic-gate return (0); 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate switch (scf_error()) { 5657c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 5667c478bd9Sstevel@tonic-gate default: 5677c478bd9Sstevel@tonic-gate return (ECONNABORTED); 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 5707c478bd9Sstevel@tonic-gate return (EBADF); 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 5737c478bd9Sstevel@tonic-gate return (ECANCELED); 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 5767c478bd9Sstevel@tonic-gate break; 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 5797c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 5807c478bd9Sstevel@tonic-gate bad_fail("scf_instance_get_pg", scf_error()); 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate if (scf_instance_add_pg(inst, name, type, flags, pg) == 0) 5847c478bd9Sstevel@tonic-gate return (0); 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate switch (scf_error()) { 5877c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 5887c478bd9Sstevel@tonic-gate default: 5897c478bd9Sstevel@tonic-gate return (ECONNABORTED); 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 5927c478bd9Sstevel@tonic-gate return (ECANCELED); 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 5957c478bd9Sstevel@tonic-gate goto again; 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 5987c478bd9Sstevel@tonic-gate return (EPERM); 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 6017c478bd9Sstevel@tonic-gate return (EACCES); 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 6047c478bd9Sstevel@tonic-gate return (EROFS); 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 6077c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 6087c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: /* should be caught above */ 6097c478bd9Sstevel@tonic-gate bad_fail("scf_instance_add_pg", scf_error()); 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate return (0); 6137c478bd9Sstevel@tonic-gate } 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate /* 6167c478bd9Sstevel@tonic-gate * Fails with 6177c478bd9Sstevel@tonic-gate * ECONNABORTED 6187c478bd9Sstevel@tonic-gate * ECANCELED - pg was deleted 6197c478bd9Sstevel@tonic-gate */ 6207c478bd9Sstevel@tonic-gate static int 6217c478bd9Sstevel@tonic-gate tx_set_value(scf_transaction_t *tx, scf_transaction_entry_t *ent, 6227c478bd9Sstevel@tonic-gate const char *pname, scf_type_t ty, scf_value_t *val) 6237c478bd9Sstevel@tonic-gate { 6247c478bd9Sstevel@tonic-gate int r; 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate for (;;) { 6277c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(tx, ent, pname, 6287c478bd9Sstevel@tonic-gate ty) == 0) 6297c478bd9Sstevel@tonic-gate break; 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate switch (scf_error()) { 6327c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 6337c478bd9Sstevel@tonic-gate default: 6347c478bd9Sstevel@tonic-gate return (ECONNABORTED); 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 6377c478bd9Sstevel@tonic-gate return (ECANCELED); 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 6407c478bd9Sstevel@tonic-gate break; 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 6437c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 6447c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 6457c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 6467c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_change_type", 6477c478bd9Sstevel@tonic-gate scf_error()); 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(tx, ent, pname, ty) == 0) 6517c478bd9Sstevel@tonic-gate break; 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate switch (scf_error()) { 6547c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 6557c478bd9Sstevel@tonic-gate default: 6567c478bd9Sstevel@tonic-gate return (ECONNABORTED); 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 6597c478bd9Sstevel@tonic-gate return (ECANCELED); 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 6627c478bd9Sstevel@tonic-gate break; 6637c478bd9Sstevel@tonic-gate 6647c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 6657c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 6667c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 6677c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 6687c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_new", scf_error()); 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate r = scf_entry_add_value(ent, val); 6737c478bd9Sstevel@tonic-gate assert(r == 0); 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate return (0); 6767c478bd9Sstevel@tonic-gate } 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate /* 6797c478bd9Sstevel@tonic-gate * Commit new_state, new_next_state, and aux to the repository for id. If 6807c478bd9Sstevel@tonic-gate * successful, also set id's state and next-state as given, and return 0. 6817c478bd9Sstevel@tonic-gate * Fails with 6827c478bd9Sstevel@tonic-gate * ENOMEM - out of memory 6837c478bd9Sstevel@tonic-gate * ECONNABORTED - repository connection broken 6847c478bd9Sstevel@tonic-gate * - unknown libscf error 6857c478bd9Sstevel@tonic-gate * EINVAL - id->i_fmri is invalid or not an instance FMRI 6867c478bd9Sstevel@tonic-gate * ENOENT - id->i_fmri does not exist 6877c478bd9Sstevel@tonic-gate * EPERM - insufficient permissions 6887c478bd9Sstevel@tonic-gate * EACCES - backend access denied 6897c478bd9Sstevel@tonic-gate * EROFS - backend is readonly 6907c478bd9Sstevel@tonic-gate */ 6917c478bd9Sstevel@tonic-gate int 6927c478bd9Sstevel@tonic-gate _restarter_commit_states(scf_handle_t *h, instance_data_t *id, 6937c478bd9Sstevel@tonic-gate restarter_instance_state_t new_state, 6947c478bd9Sstevel@tonic-gate restarter_instance_state_t new_state_next, const char *aux) 6957c478bd9Sstevel@tonic-gate { 6967c478bd9Sstevel@tonic-gate char str_state[MAX_SCF_STATE_STRING_SZ]; 6977c478bd9Sstevel@tonic-gate char str_new_state[MAX_SCF_STATE_STRING_SZ]; 6987c478bd9Sstevel@tonic-gate char str_state_next[MAX_SCF_STATE_STRING_SZ]; 6997c478bd9Sstevel@tonic-gate char str_new_state_next[MAX_SCF_STATE_STRING_SZ]; 7007c478bd9Sstevel@tonic-gate int ret = 0, r; 7017c478bd9Sstevel@tonic-gate struct timeval now; 7027c478bd9Sstevel@tonic-gate ssize_t sz; 7037c478bd9Sstevel@tonic-gate char *default_aux = "none"; 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate scf_transaction_t *t = NULL; 7067c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_state = NULL, *t_state_next = NULL; 7077c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_stime = NULL, *t_aux = NULL; 7087c478bd9Sstevel@tonic-gate scf_value_t *v_state = NULL, *v_state_next = NULL, *v_stime = NULL; 7097c478bd9Sstevel@tonic-gate scf_value_t *v_aux = NULL; 7107c478bd9Sstevel@tonic-gate scf_instance_t *s_inst = NULL; 7117c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate assert(new_state != RESTARTER_STATE_NONE); 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate /* If aux state is unset, set aux to a default string. */ 7167c478bd9Sstevel@tonic-gate if (aux == NULL) 7177c478bd9Sstevel@tonic-gate aux = default_aux; 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate if ((s_inst = scf_instance_create(h)) == NULL || 7207c478bd9Sstevel@tonic-gate (pg = scf_pg_create(h)) == NULL || 7217c478bd9Sstevel@tonic-gate (t = scf_transaction_create(h)) == NULL || 7227c478bd9Sstevel@tonic-gate (t_state = scf_entry_create(h)) == NULL || 7237c478bd9Sstevel@tonic-gate (t_state_next = scf_entry_create(h)) == NULL || 7247c478bd9Sstevel@tonic-gate (t_stime = scf_entry_create(h)) == NULL || 7257c478bd9Sstevel@tonic-gate (t_aux = scf_entry_create(h)) == NULL || 7267c478bd9Sstevel@tonic-gate (v_state = scf_value_create(h)) == NULL || 7277c478bd9Sstevel@tonic-gate (v_state_next = scf_value_create(h)) == NULL || 7287c478bd9Sstevel@tonic-gate (v_stime = scf_value_create(h)) == NULL || 7297c478bd9Sstevel@tonic-gate (v_aux = scf_value_create(h)) == NULL) { 7307c478bd9Sstevel@tonic-gate ret = ENOMEM; 7317c478bd9Sstevel@tonic-gate goto out; 7327c478bd9Sstevel@tonic-gate } 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(new_state, str_new_state, 7357c478bd9Sstevel@tonic-gate sizeof (str_new_state)); 7367c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_new_state)); 7377c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(new_state_next, str_new_state_next, 7387c478bd9Sstevel@tonic-gate sizeof (str_new_state_next)); 7397c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_new_state_next)); 7407c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(id->i_state, str_state, 7417c478bd9Sstevel@tonic-gate sizeof (str_state)); 7427c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_state)); 7437c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(id->i_next_state, str_state_next, 7447c478bd9Sstevel@tonic-gate sizeof (str_state_next)); 7457c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_state_next)); 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate ret = gettimeofday(&now, NULL); 7487c478bd9Sstevel@tonic-gate assert(ret != -1); 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, id->i_fmri, NULL, NULL, s_inst, 7517c478bd9Sstevel@tonic-gate NULL, NULL, SCF_DECODE_FMRI_EXACT) == -1) { 7527c478bd9Sstevel@tonic-gate switch (scf_error()) { 7537c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 7547c478bd9Sstevel@tonic-gate default: 7557c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 7567c478bd9Sstevel@tonic-gate break; 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 7597c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 7607c478bd9Sstevel@tonic-gate ret = EINVAL; 7617c478bd9Sstevel@tonic-gate break; 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 7647c478bd9Sstevel@tonic-gate ret = ENOENT; 7657c478bd9Sstevel@tonic-gate break; 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 7687c478bd9Sstevel@tonic-gate bad_fail("scf_handle_decode_fmri", scf_error()); 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate goto out; 7717c478bd9Sstevel@tonic-gate } 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate if (scf_value_set_astring(v_state, str_new_state) != 0 || 7757c478bd9Sstevel@tonic-gate scf_value_set_astring(v_state_next, str_new_state_next) != 0 || 7767c478bd9Sstevel@tonic-gate scf_value_set_astring(v_aux, aux) != 0) 7777c478bd9Sstevel@tonic-gate bad_fail("scf_value_set_astring", scf_error()); 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate if (scf_value_set_time(v_stime, now.tv_sec, now.tv_usec * 1000) != 0) 7807c478bd9Sstevel@tonic-gate bad_fail("scf_value_set_time", scf_error()); 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate add_pg: 7837c478bd9Sstevel@tonic-gate switch (r = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER, 7847c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg)) { 7857c478bd9Sstevel@tonic-gate case 0: 7867c478bd9Sstevel@tonic-gate break; 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate case ECONNABORTED: 7897c478bd9Sstevel@tonic-gate case EPERM: 7907c478bd9Sstevel@tonic-gate case EACCES: 7917c478bd9Sstevel@tonic-gate case EROFS: 7927c478bd9Sstevel@tonic-gate ret = r; 7937c478bd9Sstevel@tonic-gate goto out; 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate case ECANCELED: 7967c478bd9Sstevel@tonic-gate ret = ENOENT; 7977c478bd9Sstevel@tonic-gate goto out; 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate case EBADF: 8007c478bd9Sstevel@tonic-gate default: 8017c478bd9Sstevel@tonic-gate bad_fail("instance_get_or_add_pg", r); 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate for (;;) { 8057c478bd9Sstevel@tonic-gate if (scf_transaction_start(t, pg) != 0) { 8067c478bd9Sstevel@tonic-gate switch (scf_error()) { 8077c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 8087c478bd9Sstevel@tonic-gate default: 8097c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 8107c478bd9Sstevel@tonic-gate goto out; 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 8137c478bd9Sstevel@tonic-gate goto add_pg; 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 8167c478bd9Sstevel@tonic-gate ret = EPERM; 8177c478bd9Sstevel@tonic-gate goto out; 8187c478bd9Sstevel@tonic-gate 8197c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 8207c478bd9Sstevel@tonic-gate ret = EACCES; 8217c478bd9Sstevel@tonic-gate goto out; 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 8247c478bd9Sstevel@tonic-gate ret = EROFS; 8257c478bd9Sstevel@tonic-gate goto out; 8267c478bd9Sstevel@tonic-gate 8277c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 8287c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 8297c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_start", scf_error()); 8307c478bd9Sstevel@tonic-gate } 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate if ((r = tx_set_value(t, t_state, SCF_PROPERTY_STATE, 8347c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, v_state)) != 0 || 8357c478bd9Sstevel@tonic-gate (r = tx_set_value(t, t_state_next, SCF_PROPERTY_NEXT_STATE, 8367c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, v_state_next)) != 0 || 8377c478bd9Sstevel@tonic-gate (r = tx_set_value(t, t_aux, SCF_PROPERTY_AUX_STATE, 8387c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, v_aux)) != 0 || 8397c478bd9Sstevel@tonic-gate (r = tx_set_value(t, t_stime, SCF_PROPERTY_STATE_TIMESTAMP, 8407c478bd9Sstevel@tonic-gate SCF_TYPE_TIME, v_stime)) != 0) { 8417c478bd9Sstevel@tonic-gate switch (r) { 8427c478bd9Sstevel@tonic-gate case ECONNABORTED: 8437c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 8447c478bd9Sstevel@tonic-gate goto out; 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate case ECANCELED: 8477c478bd9Sstevel@tonic-gate scf_transaction_reset(t); 8487c478bd9Sstevel@tonic-gate goto add_pg; 8497c478bd9Sstevel@tonic-gate 8507c478bd9Sstevel@tonic-gate default: 8517c478bd9Sstevel@tonic-gate bad_fail("tx_set_value", r); 8527c478bd9Sstevel@tonic-gate } 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(t); 8567c478bd9Sstevel@tonic-gate if (ret == 1) 8577c478bd9Sstevel@tonic-gate break; 8587c478bd9Sstevel@tonic-gate if (ret == -1) { 8597c478bd9Sstevel@tonic-gate switch (scf_error()) { 8607c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 8617c478bd9Sstevel@tonic-gate default: 8627c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 8637c478bd9Sstevel@tonic-gate goto out; 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 8667c478bd9Sstevel@tonic-gate ret = EPERM; 8677c478bd9Sstevel@tonic-gate goto out; 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 8707c478bd9Sstevel@tonic-gate ret = EACCES; 8717c478bd9Sstevel@tonic-gate goto out; 8727c478bd9Sstevel@tonic-gate 8737c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 8747c478bd9Sstevel@tonic-gate ret = EROFS; 8757c478bd9Sstevel@tonic-gate goto out; 8767c478bd9Sstevel@tonic-gate 8777c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 8787c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_commit", scf_error()); 8797c478bd9Sstevel@tonic-gate } 8807c478bd9Sstevel@tonic-gate } 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate scf_transaction_reset(t); 8837c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 8847c478bd9Sstevel@tonic-gate switch (scf_error()) { 8857c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 8867c478bd9Sstevel@tonic-gate default: 8877c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 8887c478bd9Sstevel@tonic-gate goto out; 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 8917c478bd9Sstevel@tonic-gate goto add_pg; 8927c478bd9Sstevel@tonic-gate } 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate } 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate id->i_state = new_state; 8977c478bd9Sstevel@tonic-gate id->i_next_state = new_state_next; 8987c478bd9Sstevel@tonic-gate ret = 0; 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate out: 9017c478bd9Sstevel@tonic-gate scf_transaction_destroy(t); 9027c478bd9Sstevel@tonic-gate scf_entry_destroy(t_state); 9037c478bd9Sstevel@tonic-gate scf_entry_destroy(t_state_next); 9047c478bd9Sstevel@tonic-gate scf_entry_destroy(t_stime); 9057c478bd9Sstevel@tonic-gate scf_entry_destroy(t_aux); 9067c478bd9Sstevel@tonic-gate scf_value_destroy(v_state); 9077c478bd9Sstevel@tonic-gate scf_value_destroy(v_state_next); 9087c478bd9Sstevel@tonic-gate scf_value_destroy(v_stime); 9097c478bd9Sstevel@tonic-gate scf_value_destroy(v_aux); 9107c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 9117c478bd9Sstevel@tonic-gate scf_instance_destroy(s_inst); 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate return (ret); 9147c478bd9Sstevel@tonic-gate } 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate /* 9177c478bd9Sstevel@tonic-gate * Fails with 9187c478bd9Sstevel@tonic-gate * EINVAL - type is invalid 9197c478bd9Sstevel@tonic-gate * ENOMEM 9207c478bd9Sstevel@tonic-gate * ECONNABORTED - repository connection broken 9217c478bd9Sstevel@tonic-gate * EBADF - s_inst is not set 9227c478bd9Sstevel@tonic-gate * ECANCELED - s_inst is deleted 9237c478bd9Sstevel@tonic-gate * EPERM - permission denied 9247c478bd9Sstevel@tonic-gate * EACCES - backend access denied 9257c478bd9Sstevel@tonic-gate * EROFS - backend readonly 9267c478bd9Sstevel@tonic-gate */ 9277c478bd9Sstevel@tonic-gate int 9287c478bd9Sstevel@tonic-gate restarter_remove_contract(scf_instance_t *s_inst, ctid_t contract_id, 9297c478bd9Sstevel@tonic-gate restarter_contract_type_t type) 9307c478bd9Sstevel@tonic-gate { 9317c478bd9Sstevel@tonic-gate scf_handle_t *h; 9327c478bd9Sstevel@tonic-gate scf_transaction_t *t = NULL; 9337c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_cid = NULL; 9347c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 9357c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL; 9367c478bd9Sstevel@tonic-gate scf_value_t *val; 9377c478bd9Sstevel@tonic-gate scf_iter_t *iter = NULL; 9387c478bd9Sstevel@tonic-gate const char *pname; 9397c478bd9Sstevel@tonic-gate int ret = 0, primary; 9407c478bd9Sstevel@tonic-gate uint64_t c; 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate switch (type) { 9437c478bd9Sstevel@tonic-gate case RESTARTER_CONTRACT_PRIMARY: 9447c478bd9Sstevel@tonic-gate primary = 1; 9457c478bd9Sstevel@tonic-gate break; 9467c478bd9Sstevel@tonic-gate case RESTARTER_CONTRACT_TRANSIENT: 9477c478bd9Sstevel@tonic-gate primary = 0; 9487c478bd9Sstevel@tonic-gate break; 9497c478bd9Sstevel@tonic-gate default: 9507c478bd9Sstevel@tonic-gate return (EINVAL); 9517c478bd9Sstevel@tonic-gate } 9527c478bd9Sstevel@tonic-gate 9537c478bd9Sstevel@tonic-gate h = scf_instance_handle(s_inst); 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate pg = scf_pg_create(h); 9567c478bd9Sstevel@tonic-gate prop = scf_property_create(h); 9577c478bd9Sstevel@tonic-gate iter = scf_iter_create(h); 9587c478bd9Sstevel@tonic-gate t = scf_transaction_create(h); 9597c478bd9Sstevel@tonic-gate 9607c478bd9Sstevel@tonic-gate if (pg == NULL || prop == NULL || iter == NULL || t == NULL) { 9617c478bd9Sstevel@tonic-gate ret = ENOMEM; 9627c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 9637c478bd9Sstevel@tonic-gate } 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate add: 9667c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 9677c478bd9Sstevel@tonic-gate ret = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER, 9687c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg); 9697c478bd9Sstevel@tonic-gate if (ret != 0) 9707c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate pname = primary? SCF_PROPERTY_CONTRACT : 9737c478bd9Sstevel@tonic-gate SCF_PROPERTY_TRANSIENT_CONTRACT; 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate for (;;) { 9767c478bd9Sstevel@tonic-gate if (scf_transaction_start(t, pg) != 0) { 9777c478bd9Sstevel@tonic-gate switch (scf_error()) { 9787c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 9797c478bd9Sstevel@tonic-gate default: 9807c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 9817c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 9847c478bd9Sstevel@tonic-gate goto add; 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 9877c478bd9Sstevel@tonic-gate ret = EPERM; 9887c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 9897c478bd9Sstevel@tonic-gate 9907c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 9917c478bd9Sstevel@tonic-gate ret = EACCES; 9927c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 9957c478bd9Sstevel@tonic-gate ret = EROFS; 9967c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 9997c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 10007c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 10017c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_start", scf_error()); 10027c478bd9Sstevel@tonic-gate } 10037c478bd9Sstevel@tonic-gate } 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate t_cid = scf_entry_create(h); 10067c478bd9Sstevel@tonic-gate 10077c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, pname, prop) == 0) { 10087c478bd9Sstevel@tonic-gate replace: 10097c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(t, t_cid, 10107c478bd9Sstevel@tonic-gate pname, SCF_TYPE_COUNT) != 0) { 10117c478bd9Sstevel@tonic-gate switch (scf_error()) { 10127c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 10137c478bd9Sstevel@tonic-gate default: 10147c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 10157c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 10187c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 10197c478bd9Sstevel@tonic-gate goto add; 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 10227c478bd9Sstevel@tonic-gate goto new; 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 10257c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 10267c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 10277c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 10287c478bd9Sstevel@tonic-gate bad_fail( 10297c478bd9Sstevel@tonic-gate "scf_transaction_property_changetype", 10307c478bd9Sstevel@tonic-gate scf_error()); 10317c478bd9Sstevel@tonic-gate } 10327c478bd9Sstevel@tonic-gate } 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate if (scf_property_is_type(prop, SCF_TYPE_COUNT) == 0) { 10357c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) { 10367c478bd9Sstevel@tonic-gate switch (scf_error()) { 10377c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 10387c478bd9Sstevel@tonic-gate default: 10397c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 10407c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 10417c478bd9Sstevel@tonic-gate 10427c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 10437c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 10447c478bd9Sstevel@tonic-gate bad_fail( 10457c478bd9Sstevel@tonic-gate "scf_iter_property_values", 10467c478bd9Sstevel@tonic-gate scf_error()); 10477c478bd9Sstevel@tonic-gate } 10487c478bd9Sstevel@tonic-gate } 10497c478bd9Sstevel@tonic-gate 10507c478bd9Sstevel@tonic-gate next_val: 10517c478bd9Sstevel@tonic-gate val = scf_value_create(h); 10527c478bd9Sstevel@tonic-gate if (val == NULL) { 10537c478bd9Sstevel@tonic-gate assert(scf_error() == 10547c478bd9Sstevel@tonic-gate SCF_ERROR_NO_MEMORY); 10557c478bd9Sstevel@tonic-gate ret = ENOMEM; 10567c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 10577c478bd9Sstevel@tonic-gate } 10587c478bd9Sstevel@tonic-gate 10597c478bd9Sstevel@tonic-gate ret = scf_iter_next_value(iter, val); 10607c478bd9Sstevel@tonic-gate if (ret == -1) { 10617c478bd9Sstevel@tonic-gate switch (scf_error()) { 10627c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 10637c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 10647c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 10677c478bd9Sstevel@tonic-gate scf_value_destroy(val); 10687c478bd9Sstevel@tonic-gate goto add; 10697c478bd9Sstevel@tonic-gate 10707c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 10717c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 10727c478bd9Sstevel@tonic-gate default: 10737c478bd9Sstevel@tonic-gate bad_fail("scf_iter_next_value", 10747c478bd9Sstevel@tonic-gate scf_error()); 10757c478bd9Sstevel@tonic-gate } 10767c478bd9Sstevel@tonic-gate } 10777c478bd9Sstevel@tonic-gate 10787c478bd9Sstevel@tonic-gate if (ret == 1) { 10797c478bd9Sstevel@tonic-gate ret = scf_value_get_count(val, &c); 10807c478bd9Sstevel@tonic-gate assert(ret == 0); 10817c478bd9Sstevel@tonic-gate 10827c478bd9Sstevel@tonic-gate if (c != contract_id) { 10837c478bd9Sstevel@tonic-gate ret = scf_entry_add_value(t_cid, 10847c478bd9Sstevel@tonic-gate val); 10857c478bd9Sstevel@tonic-gate assert(ret == 0); 10867c478bd9Sstevel@tonic-gate } else { 10877c478bd9Sstevel@tonic-gate scf_value_destroy(val); 10887c478bd9Sstevel@tonic-gate } 10897c478bd9Sstevel@tonic-gate 10907c478bd9Sstevel@tonic-gate goto next_val; 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate scf_value_destroy(val); 10947c478bd9Sstevel@tonic-gate } else { 10957c478bd9Sstevel@tonic-gate switch (scf_error()) { 10967c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 10977c478bd9Sstevel@tonic-gate default: 10987c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 10997c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate case SCF_ERROR_TYPE_MISMATCH: 11027c478bd9Sstevel@tonic-gate break; 11037c478bd9Sstevel@tonic-gate 11047c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 11057c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 11067c478bd9Sstevel@tonic-gate bad_fail("scf_property_is_type", 11077c478bd9Sstevel@tonic-gate scf_error()); 11087c478bd9Sstevel@tonic-gate } 11097c478bd9Sstevel@tonic-gate } 11107c478bd9Sstevel@tonic-gate } else { 11117c478bd9Sstevel@tonic-gate switch (scf_error()) { 11127c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 11137c478bd9Sstevel@tonic-gate default: 11147c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 11157c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11167c478bd9Sstevel@tonic-gate 11177c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 11187c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 11197c478bd9Sstevel@tonic-gate goto add; 11207c478bd9Sstevel@tonic-gate 11217c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 11227c478bd9Sstevel@tonic-gate break; 11237c478bd9Sstevel@tonic-gate 11247c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 11257c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 11267c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 11277c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error()); 11287c478bd9Sstevel@tonic-gate } 11297c478bd9Sstevel@tonic-gate 11307c478bd9Sstevel@tonic-gate new: 11317c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(t, t_cid, pname, 11327c478bd9Sstevel@tonic-gate SCF_TYPE_COUNT) != 0) { 11337c478bd9Sstevel@tonic-gate switch (scf_error()) { 11347c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 11357c478bd9Sstevel@tonic-gate default: 11367c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 11377c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11387c478bd9Sstevel@tonic-gate 11397c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 11407c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 11417c478bd9Sstevel@tonic-gate goto add; 11427c478bd9Sstevel@tonic-gate 11437c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 11447c478bd9Sstevel@tonic-gate goto replace; 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 11477c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 11487c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 11497c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_new", 11507c478bd9Sstevel@tonic-gate scf_error()); 11517c478bd9Sstevel@tonic-gate } 11527c478bd9Sstevel@tonic-gate } 11537c478bd9Sstevel@tonic-gate } 11547c478bd9Sstevel@tonic-gate 11557c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(t); 11567c478bd9Sstevel@tonic-gate if (ret == -1) { 11577c478bd9Sstevel@tonic-gate switch (scf_error()) { 11587c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 11597c478bd9Sstevel@tonic-gate default: 11607c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 11617c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11627c478bd9Sstevel@tonic-gate 11637c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 11647c478bd9Sstevel@tonic-gate goto add; 11657c478bd9Sstevel@tonic-gate 11667c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 11677c478bd9Sstevel@tonic-gate ret = EPERM; 11687c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11697c478bd9Sstevel@tonic-gate 11707c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 11717c478bd9Sstevel@tonic-gate ret = EACCES; 11727c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11737c478bd9Sstevel@tonic-gate 11747c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 11757c478bd9Sstevel@tonic-gate ret = EROFS; 11767c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11777c478bd9Sstevel@tonic-gate 11787c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 11797c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_commit", scf_error()); 11807c478bd9Sstevel@tonic-gate } 11817c478bd9Sstevel@tonic-gate } 11827c478bd9Sstevel@tonic-gate if (ret == 1) { 11837c478bd9Sstevel@tonic-gate ret = 0; 11847c478bd9Sstevel@tonic-gate break; 11857c478bd9Sstevel@tonic-gate } 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 11887c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 11897c478bd9Sstevel@tonic-gate switch (scf_error()) { 11907c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 11917c478bd9Sstevel@tonic-gate default: 11927c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 11937c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 11967c478bd9Sstevel@tonic-gate goto add; 11977c478bd9Sstevel@tonic-gate 11987c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 11997c478bd9Sstevel@tonic-gate bad_fail("scf_pg_update", scf_error()); 12007c478bd9Sstevel@tonic-gate } 12017c478bd9Sstevel@tonic-gate } 12027c478bd9Sstevel@tonic-gate } 12037c478bd9Sstevel@tonic-gate 12047c478bd9Sstevel@tonic-gate remove_contract_cleanup: 12057c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 12067c478bd9Sstevel@tonic-gate scf_transaction_destroy(t); 12077c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 12087c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 12097c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 12107c478bd9Sstevel@tonic-gate 12117c478bd9Sstevel@tonic-gate return (ret); 12127c478bd9Sstevel@tonic-gate } 12137c478bd9Sstevel@tonic-gate 12147c478bd9Sstevel@tonic-gate /* 12157c478bd9Sstevel@tonic-gate * Fails with 12167c478bd9Sstevel@tonic-gate * EINVAL - type is invalid 12177c478bd9Sstevel@tonic-gate * ENOMEM 12187c478bd9Sstevel@tonic-gate * ECONNABORTED - repository disconnection 12197c478bd9Sstevel@tonic-gate * EBADF - s_inst is not set 12207c478bd9Sstevel@tonic-gate * ECANCELED - s_inst is deleted 12217c478bd9Sstevel@tonic-gate * EPERM 12227c478bd9Sstevel@tonic-gate * EACCES 12237c478bd9Sstevel@tonic-gate * EROFS 12247c478bd9Sstevel@tonic-gate */ 12257c478bd9Sstevel@tonic-gate int 12267c478bd9Sstevel@tonic-gate restarter_store_contract(scf_instance_t *s_inst, ctid_t contract_id, 12277c478bd9Sstevel@tonic-gate restarter_contract_type_t type) 12287c478bd9Sstevel@tonic-gate { 12297c478bd9Sstevel@tonic-gate scf_handle_t *h; 12307c478bd9Sstevel@tonic-gate scf_transaction_t *t = NULL; 12317c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_cid = NULL; 12327c478bd9Sstevel@tonic-gate scf_value_t *val; 12337c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 12347c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL; 12357c478bd9Sstevel@tonic-gate scf_iter_t *iter = NULL; 12367c478bd9Sstevel@tonic-gate const char *pname; 12377c478bd9Sstevel@tonic-gate int ret = 0, primary; 12387c478bd9Sstevel@tonic-gate 12397c478bd9Sstevel@tonic-gate if (type == RESTARTER_CONTRACT_PRIMARY) 12407c478bd9Sstevel@tonic-gate primary = 1; 12417c478bd9Sstevel@tonic-gate else if (type == RESTARTER_CONTRACT_TRANSIENT) 12427c478bd9Sstevel@tonic-gate primary = 0; 12437c478bd9Sstevel@tonic-gate else 12447c478bd9Sstevel@tonic-gate return (EINVAL); 12457c478bd9Sstevel@tonic-gate 12467c478bd9Sstevel@tonic-gate h = scf_instance_handle(s_inst); 12477c478bd9Sstevel@tonic-gate 12487c478bd9Sstevel@tonic-gate pg = scf_pg_create(h); 12497c478bd9Sstevel@tonic-gate prop = scf_property_create(h); 12507c478bd9Sstevel@tonic-gate iter = scf_iter_create(h); 12517c478bd9Sstevel@tonic-gate t = scf_transaction_create(h); 12527c478bd9Sstevel@tonic-gate 12537c478bd9Sstevel@tonic-gate if (pg == NULL || prop == NULL || iter == NULL || t == NULL) { 12547c478bd9Sstevel@tonic-gate ret = ENOMEM; 12557c478bd9Sstevel@tonic-gate goto out; 12567c478bd9Sstevel@tonic-gate } 12577c478bd9Sstevel@tonic-gate 12587c478bd9Sstevel@tonic-gate add: 12597c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 12607c478bd9Sstevel@tonic-gate ret = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER, 12617c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg); 12627c478bd9Sstevel@tonic-gate if (ret != 0) 12637c478bd9Sstevel@tonic-gate goto out; 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate pname = primary ? SCF_PROPERTY_CONTRACT : 12667c478bd9Sstevel@tonic-gate SCF_PROPERTY_TRANSIENT_CONTRACT; 12677c478bd9Sstevel@tonic-gate 12687c478bd9Sstevel@tonic-gate for (;;) { 12697c478bd9Sstevel@tonic-gate if (scf_transaction_start(t, pg) != 0) { 12707c478bd9Sstevel@tonic-gate switch (scf_error()) { 12717c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 12727c478bd9Sstevel@tonic-gate default: 12737c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 12747c478bd9Sstevel@tonic-gate goto out; 12757c478bd9Sstevel@tonic-gate 12767c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 12777c478bd9Sstevel@tonic-gate goto add; 12787c478bd9Sstevel@tonic-gate 12797c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 12807c478bd9Sstevel@tonic-gate ret = EPERM; 12817c478bd9Sstevel@tonic-gate goto out; 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 12847c478bd9Sstevel@tonic-gate ret = EACCES; 12857c478bd9Sstevel@tonic-gate goto out; 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 12887c478bd9Sstevel@tonic-gate ret = EROFS; 12897c478bd9Sstevel@tonic-gate goto out; 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 12927c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 12937c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 12947c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_start", scf_error()); 12957c478bd9Sstevel@tonic-gate } 12967c478bd9Sstevel@tonic-gate } 12977c478bd9Sstevel@tonic-gate 12987c478bd9Sstevel@tonic-gate t_cid = scf_entry_create(h); 12997c478bd9Sstevel@tonic-gate if (t_cid == NULL) { 13007c478bd9Sstevel@tonic-gate ret = ENOMEM; 13017c478bd9Sstevel@tonic-gate goto out; 13027c478bd9Sstevel@tonic-gate } 13037c478bd9Sstevel@tonic-gate 13047c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, pname, prop) == 0) { 13057c478bd9Sstevel@tonic-gate replace: 13067c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(t, t_cid, 13077c478bd9Sstevel@tonic-gate pname, SCF_TYPE_COUNT) != 0) { 13087c478bd9Sstevel@tonic-gate switch (scf_error()) { 13097c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 13107c478bd9Sstevel@tonic-gate default: 13117c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 13127c478bd9Sstevel@tonic-gate goto out; 13137c478bd9Sstevel@tonic-gate 13147c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 13157c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 13167c478bd9Sstevel@tonic-gate goto add; 13177c478bd9Sstevel@tonic-gate 13187c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 13197c478bd9Sstevel@tonic-gate goto new; 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 13227c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 13237c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 13247c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 13257c478bd9Sstevel@tonic-gate bad_fail( 13267c478bd9Sstevel@tonic-gate "scf_transaction_propert_change_type", 13277c478bd9Sstevel@tonic-gate scf_error()); 13287c478bd9Sstevel@tonic-gate } 13297c478bd9Sstevel@tonic-gate } 13307c478bd9Sstevel@tonic-gate 13317c478bd9Sstevel@tonic-gate if (scf_property_is_type(prop, SCF_TYPE_COUNT) == 0) { 13327c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) { 13337c478bd9Sstevel@tonic-gate switch (scf_error()) { 13347c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 13357c478bd9Sstevel@tonic-gate default: 13367c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 13377c478bd9Sstevel@tonic-gate goto out; 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 13407c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 13417c478bd9Sstevel@tonic-gate bad_fail( 13427c478bd9Sstevel@tonic-gate "scf_iter_property_values", 13437c478bd9Sstevel@tonic-gate scf_error()); 13447c478bd9Sstevel@tonic-gate } 13457c478bd9Sstevel@tonic-gate } 13467c478bd9Sstevel@tonic-gate 13477c478bd9Sstevel@tonic-gate next_val: 13487c478bd9Sstevel@tonic-gate val = scf_value_create(h); 13497c478bd9Sstevel@tonic-gate if (val == NULL) { 13507c478bd9Sstevel@tonic-gate assert(scf_error() == 13517c478bd9Sstevel@tonic-gate SCF_ERROR_NO_MEMORY); 13527c478bd9Sstevel@tonic-gate ret = ENOMEM; 13537c478bd9Sstevel@tonic-gate goto out; 13547c478bd9Sstevel@tonic-gate } 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate ret = scf_iter_next_value(iter, val); 13577c478bd9Sstevel@tonic-gate if (ret == -1) { 13587c478bd9Sstevel@tonic-gate switch (scf_error()) { 13597c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 13607c478bd9Sstevel@tonic-gate default: 13617c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 13627c478bd9Sstevel@tonic-gate goto out; 13637c478bd9Sstevel@tonic-gate 13647c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 13657c478bd9Sstevel@tonic-gate scf_value_destroy(val); 13667c478bd9Sstevel@tonic-gate goto add; 13677c478bd9Sstevel@tonic-gate 13687c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 13697c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 13707c478bd9Sstevel@tonic-gate bad_fail( 13717c478bd9Sstevel@tonic-gate "scf_iter_next_value", 13727c478bd9Sstevel@tonic-gate scf_error()); 13737c478bd9Sstevel@tonic-gate } 13747c478bd9Sstevel@tonic-gate } 13757c478bd9Sstevel@tonic-gate 13767c478bd9Sstevel@tonic-gate if (ret == 1) { 13777c478bd9Sstevel@tonic-gate ret = scf_entry_add_value(t_cid, val); 13787c478bd9Sstevel@tonic-gate assert(ret == 0); 13797c478bd9Sstevel@tonic-gate 13807c478bd9Sstevel@tonic-gate goto next_val; 13817c478bd9Sstevel@tonic-gate } 13827c478bd9Sstevel@tonic-gate 13837c478bd9Sstevel@tonic-gate scf_value_destroy(val); 13847c478bd9Sstevel@tonic-gate } else { 13857c478bd9Sstevel@tonic-gate switch (scf_error()) { 13867c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 13877c478bd9Sstevel@tonic-gate default: 13887c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 13897c478bd9Sstevel@tonic-gate goto out; 13907c478bd9Sstevel@tonic-gate 13917c478bd9Sstevel@tonic-gate case SCF_ERROR_TYPE_MISMATCH: 13927c478bd9Sstevel@tonic-gate break; 13937c478bd9Sstevel@tonic-gate 13947c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 13957c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 13967c478bd9Sstevel@tonic-gate bad_fail("scf_property_is_type", 13977c478bd9Sstevel@tonic-gate scf_error()); 13987c478bd9Sstevel@tonic-gate } 13997c478bd9Sstevel@tonic-gate } 14007c478bd9Sstevel@tonic-gate } else { 14017c478bd9Sstevel@tonic-gate switch (scf_error()) { 14027c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 14037c478bd9Sstevel@tonic-gate default: 14047c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 14057c478bd9Sstevel@tonic-gate goto out; 14067c478bd9Sstevel@tonic-gate 14077c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 14087c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 14097c478bd9Sstevel@tonic-gate goto add; 14107c478bd9Sstevel@tonic-gate 14117c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 14127c478bd9Sstevel@tonic-gate break; 14137c478bd9Sstevel@tonic-gate 14147c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 14157c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 14167c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 14177c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error()); 14187c478bd9Sstevel@tonic-gate } 14197c478bd9Sstevel@tonic-gate 14207c478bd9Sstevel@tonic-gate new: 14217c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(t, t_cid, pname, 14227c478bd9Sstevel@tonic-gate SCF_TYPE_COUNT) != 0) { 14237c478bd9Sstevel@tonic-gate switch (scf_error()) { 14247c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 14257c478bd9Sstevel@tonic-gate default: 14267c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 14277c478bd9Sstevel@tonic-gate goto out; 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 14307c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 14317c478bd9Sstevel@tonic-gate goto add; 14327c478bd9Sstevel@tonic-gate 14337c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 14347c478bd9Sstevel@tonic-gate goto replace; 14357c478bd9Sstevel@tonic-gate 14367c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 14377c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 14387c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 14397c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_new", 14407c478bd9Sstevel@tonic-gate scf_error()); 14417c478bd9Sstevel@tonic-gate } 14427c478bd9Sstevel@tonic-gate } 14437c478bd9Sstevel@tonic-gate } 14447c478bd9Sstevel@tonic-gate 14457c478bd9Sstevel@tonic-gate val = scf_value_create(h); 14467c478bd9Sstevel@tonic-gate if (val == NULL) { 14477c478bd9Sstevel@tonic-gate assert(scf_error() == SCF_ERROR_NO_MEMORY); 14487c478bd9Sstevel@tonic-gate ret = ENOMEM; 14497c478bd9Sstevel@tonic-gate goto out; 14507c478bd9Sstevel@tonic-gate } 14517c478bd9Sstevel@tonic-gate 14527c478bd9Sstevel@tonic-gate scf_value_set_count(val, contract_id); 14537c478bd9Sstevel@tonic-gate ret = scf_entry_add_value(t_cid, val); 14547c478bd9Sstevel@tonic-gate assert(ret == 0); 14557c478bd9Sstevel@tonic-gate 14567c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(t); 14577c478bd9Sstevel@tonic-gate if (ret == -1) { 14587c478bd9Sstevel@tonic-gate switch (scf_error()) { 14597c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 14607c478bd9Sstevel@tonic-gate default: 14617c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 14627c478bd9Sstevel@tonic-gate goto out; 14637c478bd9Sstevel@tonic-gate 14647c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 14657c478bd9Sstevel@tonic-gate goto add; 14667c478bd9Sstevel@tonic-gate 14677c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 14687c478bd9Sstevel@tonic-gate ret = EPERM; 14697c478bd9Sstevel@tonic-gate goto out; 14707c478bd9Sstevel@tonic-gate 14717c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 14727c478bd9Sstevel@tonic-gate ret = EACCES; 14737c478bd9Sstevel@tonic-gate goto out; 14747c478bd9Sstevel@tonic-gate 14757c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 14767c478bd9Sstevel@tonic-gate ret = EROFS; 14777c478bd9Sstevel@tonic-gate goto out; 14787c478bd9Sstevel@tonic-gate 14797c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 14807c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_commit", scf_error()); 14817c478bd9Sstevel@tonic-gate } 14827c478bd9Sstevel@tonic-gate } 14837c478bd9Sstevel@tonic-gate if (ret == 1) { 14847c478bd9Sstevel@tonic-gate ret = 0; 14857c478bd9Sstevel@tonic-gate break; 14867c478bd9Sstevel@tonic-gate } 14877c478bd9Sstevel@tonic-gate 14887c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 14897c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 14907c478bd9Sstevel@tonic-gate switch (scf_error()) { 14917c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 14927c478bd9Sstevel@tonic-gate default: 14937c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 14947c478bd9Sstevel@tonic-gate goto out; 14957c478bd9Sstevel@tonic-gate 14967c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 14977c478bd9Sstevel@tonic-gate goto add; 14987c478bd9Sstevel@tonic-gate 14997c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 15007c478bd9Sstevel@tonic-gate bad_fail("scf_pg_update", scf_error()); 15017c478bd9Sstevel@tonic-gate } 15027c478bd9Sstevel@tonic-gate } 15037c478bd9Sstevel@tonic-gate } 15047c478bd9Sstevel@tonic-gate 15057c478bd9Sstevel@tonic-gate out: 15067c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 15077c478bd9Sstevel@tonic-gate scf_transaction_destroy(t); 15087c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 15097c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 15107c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 15117c478bd9Sstevel@tonic-gate 15127c478bd9Sstevel@tonic-gate return (ret); 15137c478bd9Sstevel@tonic-gate } 15147c478bd9Sstevel@tonic-gate 15157c478bd9Sstevel@tonic-gate int 15167c478bd9Sstevel@tonic-gate restarter_rm_libs_loadable() 15177c478bd9Sstevel@tonic-gate { 15187c478bd9Sstevel@tonic-gate void *libhndl; 15197c478bd9Sstevel@tonic-gate 15207c478bd9Sstevel@tonic-gate if (method_context_safety) 15217c478bd9Sstevel@tonic-gate return (1); 15227c478bd9Sstevel@tonic-gate 15237c478bd9Sstevel@tonic-gate if ((libhndl = dlopen("libpool.so", RTLD_LAZY | RTLD_LOCAL)) == NULL) 15247c478bd9Sstevel@tonic-gate return (0); 15257c478bd9Sstevel@tonic-gate 15267c478bd9Sstevel@tonic-gate (void) dlclose(libhndl); 15277c478bd9Sstevel@tonic-gate 15287c478bd9Sstevel@tonic-gate if ((libhndl = dlopen("libproject.so", RTLD_LAZY | RTLD_LOCAL)) == NULL) 15297c478bd9Sstevel@tonic-gate return (0); 15307c478bd9Sstevel@tonic-gate 15317c478bd9Sstevel@tonic-gate (void) dlclose(libhndl); 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate method_context_safety = 1; 15347c478bd9Sstevel@tonic-gate 15357c478bd9Sstevel@tonic-gate return (1); 15367c478bd9Sstevel@tonic-gate } 15377c478bd9Sstevel@tonic-gate 15387c478bd9Sstevel@tonic-gate 15397c478bd9Sstevel@tonic-gate static int 15407c478bd9Sstevel@tonic-gate get_astring_val(scf_propertygroup_t *pg, const char *name, char *buf, 15417c478bd9Sstevel@tonic-gate size_t bufsz, scf_property_t *prop, scf_value_t *val) 15427c478bd9Sstevel@tonic-gate { 15437c478bd9Sstevel@tonic-gate ssize_t szret; 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, name, prop) != SCF_SUCCESS) { 15467c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 15477c478bd9Sstevel@tonic-gate uu_die(rcbroken); 15487c478bd9Sstevel@tonic-gate return (-1); 15497c478bd9Sstevel@tonic-gate } 15507c478bd9Sstevel@tonic-gate 15517c478bd9Sstevel@tonic-gate if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 15527c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 15537c478bd9Sstevel@tonic-gate uu_die(rcbroken); 15547c478bd9Sstevel@tonic-gate return (-1); 15557c478bd9Sstevel@tonic-gate } 15567c478bd9Sstevel@tonic-gate 15577c478bd9Sstevel@tonic-gate szret = scf_value_get_astring(val, buf, bufsz); 15587c478bd9Sstevel@tonic-gate 15597c478bd9Sstevel@tonic-gate return (szret >= 0 ? 0 : -1); 15607c478bd9Sstevel@tonic-gate } 15617c478bd9Sstevel@tonic-gate 15627c478bd9Sstevel@tonic-gate /* 15637c478bd9Sstevel@tonic-gate * Try to load mcp->pwd, if it isn't already. 15647c478bd9Sstevel@tonic-gate * Fails with 15657c478bd9Sstevel@tonic-gate * ENOMEM - malloc() failed 15667c478bd9Sstevel@tonic-gate * ENOENT - no entry found 15677c478bd9Sstevel@tonic-gate * EIO - I/O error 15687c478bd9Sstevel@tonic-gate * EMFILE - process out of file descriptors 15697c478bd9Sstevel@tonic-gate * ENFILE - system out of file handles 15707c478bd9Sstevel@tonic-gate */ 15717c478bd9Sstevel@tonic-gate static int 15727c478bd9Sstevel@tonic-gate lookup_pwd(struct method_context *mcp) 15737c478bd9Sstevel@tonic-gate { 15747c478bd9Sstevel@tonic-gate struct passwd *pwdp; 15757c478bd9Sstevel@tonic-gate 15767c478bd9Sstevel@tonic-gate if (mcp->pwbuf != NULL && mcp->pwd.pw_uid == mcp->uid) 15777c478bd9Sstevel@tonic-gate return (0); 15787c478bd9Sstevel@tonic-gate 15797c478bd9Sstevel@tonic-gate if (mcp->pwbuf == NULL) { 15807c478bd9Sstevel@tonic-gate mcp->pwbufsz = sysconf(_SC_GETPW_R_SIZE_MAX); 15817c478bd9Sstevel@tonic-gate assert(mcp->pwbufsz >= 0); 15827c478bd9Sstevel@tonic-gate mcp->pwbuf = malloc(mcp->pwbufsz); 15837c478bd9Sstevel@tonic-gate if (mcp->pwbuf == NULL) 15847c478bd9Sstevel@tonic-gate return (ENOMEM); 15857c478bd9Sstevel@tonic-gate } 15867c478bd9Sstevel@tonic-gate 15877c478bd9Sstevel@tonic-gate do { 15887c478bd9Sstevel@tonic-gate errno = 0; 15897c478bd9Sstevel@tonic-gate pwdp = getpwuid_r(mcp->uid, &mcp->pwd, mcp->pwbuf, 15907c478bd9Sstevel@tonic-gate mcp->pwbufsz); 15917c478bd9Sstevel@tonic-gate } while (pwdp == NULL && errno == EINTR); 15927c478bd9Sstevel@tonic-gate if (pwdp != NULL) 15937c478bd9Sstevel@tonic-gate return (0); 15947c478bd9Sstevel@tonic-gate 15957c478bd9Sstevel@tonic-gate free(mcp->pwbuf); 15967c478bd9Sstevel@tonic-gate mcp->pwbuf = NULL; 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate switch (errno) { 15997c478bd9Sstevel@tonic-gate case 0: 16007c478bd9Sstevel@tonic-gate default: 16017c478bd9Sstevel@tonic-gate /* 16027c478bd9Sstevel@tonic-gate * Until bug 5065780 is fixed, getpwuid_r() can fail with 16037c478bd9Sstevel@tonic-gate * ENOENT, particularly on the miniroot. Since the 16047c478bd9Sstevel@tonic-gate * documentation is inaccurate, we'll return ENOENT for unknown 16057c478bd9Sstevel@tonic-gate * errors. 16067c478bd9Sstevel@tonic-gate */ 16077c478bd9Sstevel@tonic-gate return (ENOENT); 16087c478bd9Sstevel@tonic-gate 16097c478bd9Sstevel@tonic-gate case EIO: 16107c478bd9Sstevel@tonic-gate case EMFILE: 16117c478bd9Sstevel@tonic-gate case ENFILE: 16127c478bd9Sstevel@tonic-gate return (errno); 16137c478bd9Sstevel@tonic-gate 16147c478bd9Sstevel@tonic-gate case ERANGE: 16157c478bd9Sstevel@tonic-gate bad_fail("getpwuid_r", errno); 16167c478bd9Sstevel@tonic-gate /* NOTREACHED */ 16177c478bd9Sstevel@tonic-gate } 16187c478bd9Sstevel@tonic-gate } 16197c478bd9Sstevel@tonic-gate 16207c478bd9Sstevel@tonic-gate /* 16217c478bd9Sstevel@tonic-gate * Get the user id for str. Returns 0 on success or 16227c478bd9Sstevel@tonic-gate * ERANGE the uid is too big 16237c478bd9Sstevel@tonic-gate * EINVAL the string starts with a digit, but is not a valid uid 16247c478bd9Sstevel@tonic-gate * ENOMEM out of memory 16257c478bd9Sstevel@tonic-gate * ENOENT no passwd entry for str 16267c478bd9Sstevel@tonic-gate * EIO an I/O error has occurred 16277c478bd9Sstevel@tonic-gate * EMFILE/ENFILE out of file descriptors 16287c478bd9Sstevel@tonic-gate */ 16297c478bd9Sstevel@tonic-gate int 16307c478bd9Sstevel@tonic-gate get_uid(const char *str, struct method_context *ci, uid_t *uidp) 16317c478bd9Sstevel@tonic-gate { 16327c478bd9Sstevel@tonic-gate if (isdigit(str[0])) { 16337c478bd9Sstevel@tonic-gate uid_t uid; 16347c478bd9Sstevel@tonic-gate char *cp; 16357c478bd9Sstevel@tonic-gate 16367c478bd9Sstevel@tonic-gate errno = 0; 16377c478bd9Sstevel@tonic-gate uid = strtol(str, &cp, 10); 16387c478bd9Sstevel@tonic-gate 16397c478bd9Sstevel@tonic-gate if (uid == 0 && errno != 0) { 16407c478bd9Sstevel@tonic-gate assert(errno != EINVAL); 16417c478bd9Sstevel@tonic-gate return (errno); 16427c478bd9Sstevel@tonic-gate } 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate for (; *cp != '\0'; ++cp) 16457c478bd9Sstevel@tonic-gate if (*cp != ' ' || *cp != '\t') 16467c478bd9Sstevel@tonic-gate return (EINVAL); 16477c478bd9Sstevel@tonic-gate 16487c478bd9Sstevel@tonic-gate if (uid > UID_MAX) 16497c478bd9Sstevel@tonic-gate return (EINVAL); 16507c478bd9Sstevel@tonic-gate 16517c478bd9Sstevel@tonic-gate *uidp = uid; 16527c478bd9Sstevel@tonic-gate return (0); 16537c478bd9Sstevel@tonic-gate } else { 16547c478bd9Sstevel@tonic-gate struct passwd *pwdp; 16557c478bd9Sstevel@tonic-gate 16567c478bd9Sstevel@tonic-gate if (ci->pwbuf == NULL) { 16577c478bd9Sstevel@tonic-gate ci->pwbufsz = sysconf(_SC_GETPW_R_SIZE_MAX); 16587c478bd9Sstevel@tonic-gate ci->pwbuf = malloc(ci->pwbufsz); 16597c478bd9Sstevel@tonic-gate if (ci->pwbuf == NULL) 16607c478bd9Sstevel@tonic-gate return (ENOMEM); 16617c478bd9Sstevel@tonic-gate } 16627c478bd9Sstevel@tonic-gate 16637c478bd9Sstevel@tonic-gate do { 16647c478bd9Sstevel@tonic-gate errno = 0; 16657c478bd9Sstevel@tonic-gate pwdp = 16667c478bd9Sstevel@tonic-gate getpwnam_r(str, &ci->pwd, ci->pwbuf, ci->pwbufsz); 16677c478bd9Sstevel@tonic-gate } while (pwdp == NULL && errno == EINTR); 16687c478bd9Sstevel@tonic-gate 16697c478bd9Sstevel@tonic-gate if (pwdp != NULL) { 16707c478bd9Sstevel@tonic-gate *uidp = ci->pwd.pw_uid; 16717c478bd9Sstevel@tonic-gate return (0); 16727c478bd9Sstevel@tonic-gate } else { 16737c478bd9Sstevel@tonic-gate free(ci->pwbuf); 16747c478bd9Sstevel@tonic-gate ci->pwbuf = NULL; 16757c478bd9Sstevel@tonic-gate switch (errno) { 16767c478bd9Sstevel@tonic-gate case 0: 16777c478bd9Sstevel@tonic-gate return (ENOENT); 16787c478bd9Sstevel@tonic-gate 16797c478bd9Sstevel@tonic-gate case ENOENT: 16807c478bd9Sstevel@tonic-gate case EIO: 16817c478bd9Sstevel@tonic-gate case EMFILE: 16827c478bd9Sstevel@tonic-gate case ENFILE: 16837c478bd9Sstevel@tonic-gate return (errno); 16847c478bd9Sstevel@tonic-gate 16857c478bd9Sstevel@tonic-gate case ERANGE: 16867c478bd9Sstevel@tonic-gate default: 16877c478bd9Sstevel@tonic-gate bad_fail("getpwnam_r", errno); 16887c478bd9Sstevel@tonic-gate /* NOTREACHED */ 16897c478bd9Sstevel@tonic-gate } 16907c478bd9Sstevel@tonic-gate } 16917c478bd9Sstevel@tonic-gate } 16927c478bd9Sstevel@tonic-gate } 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate gid_t 16957c478bd9Sstevel@tonic-gate get_gid(const char *str) 16967c478bd9Sstevel@tonic-gate { 16977c478bd9Sstevel@tonic-gate if (isdigit(str[0])) { 16987c478bd9Sstevel@tonic-gate gid_t gid; 16997c478bd9Sstevel@tonic-gate char *cp; 17007c478bd9Sstevel@tonic-gate 17017c478bd9Sstevel@tonic-gate errno = 0; 17027c478bd9Sstevel@tonic-gate gid = strtol(str, &cp, 10); 17037c478bd9Sstevel@tonic-gate 17047c478bd9Sstevel@tonic-gate if (gid == 0 && errno != 0) 17057c478bd9Sstevel@tonic-gate return (-1); 17067c478bd9Sstevel@tonic-gate 17077c478bd9Sstevel@tonic-gate for (; *cp != '\0'; ++cp) 17087c478bd9Sstevel@tonic-gate if (*cp != ' ' || *cp != '\t') 17097c478bd9Sstevel@tonic-gate return (-1); 17107c478bd9Sstevel@tonic-gate 17117c478bd9Sstevel@tonic-gate return (gid); 17127c478bd9Sstevel@tonic-gate } else { 17137c478bd9Sstevel@tonic-gate struct group grp, *ret; 17147c478bd9Sstevel@tonic-gate char *buffer; 17157c478bd9Sstevel@tonic-gate size_t buflen; 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate buflen = sysconf(_SC_GETGR_R_SIZE_MAX); 17187c478bd9Sstevel@tonic-gate buffer = malloc(buflen); 17197c478bd9Sstevel@tonic-gate if (buffer == NULL) 17207c478bd9Sstevel@tonic-gate uu_die(allocfail); 17217c478bd9Sstevel@tonic-gate 17227c478bd9Sstevel@tonic-gate errno = 0; 17237c478bd9Sstevel@tonic-gate ret = getgrnam_r(str, &grp, buffer, buflen); 17247c478bd9Sstevel@tonic-gate free(buffer); 17257c478bd9Sstevel@tonic-gate 17267c478bd9Sstevel@tonic-gate return (ret == NULL ? -1 : grp.gr_gid); 17277c478bd9Sstevel@tonic-gate } 17287c478bd9Sstevel@tonic-gate } 17297c478bd9Sstevel@tonic-gate 17307c478bd9Sstevel@tonic-gate /* 17317c478bd9Sstevel@tonic-gate * Fails with 17327c478bd9Sstevel@tonic-gate * ENOMEM - out of memory 17337c478bd9Sstevel@tonic-gate * ENOENT - no passwd entry 17347c478bd9Sstevel@tonic-gate * no project entry 17357c478bd9Sstevel@tonic-gate * EIO - an I/O error occurred 17367c478bd9Sstevel@tonic-gate * EMFILE - the process is out of file descriptors 17377c478bd9Sstevel@tonic-gate * ENFILE - the system is out of file handles 17387c478bd9Sstevel@tonic-gate * ERANGE - the project id is out of range 17397c478bd9Sstevel@tonic-gate * EINVAL - str is invalid 17407c478bd9Sstevel@tonic-gate * E2BIG - the project entry was too big 17417c478bd9Sstevel@tonic-gate * -1 - the name service switch is misconfigured 17427c478bd9Sstevel@tonic-gate */ 17437c478bd9Sstevel@tonic-gate int 17447c478bd9Sstevel@tonic-gate get_projid(const char *str, struct method_context *cip) 17457c478bd9Sstevel@tonic-gate { 17467c478bd9Sstevel@tonic-gate int ret; 17477c478bd9Sstevel@tonic-gate void *buf; 17487c478bd9Sstevel@tonic-gate const size_t bufsz = PROJECT_BUFSZ; 17497c478bd9Sstevel@tonic-gate struct project proj, *pp; 17507c478bd9Sstevel@tonic-gate 17517c478bd9Sstevel@tonic-gate if (strcmp(str, ":default") == 0) { 17527c478bd9Sstevel@tonic-gate if (cip->uid == 0) { 17537c478bd9Sstevel@tonic-gate /* Don't change project for root services */ 17547c478bd9Sstevel@tonic-gate cip->project = NULL; 17557c478bd9Sstevel@tonic-gate return (0); 17567c478bd9Sstevel@tonic-gate } 17577c478bd9Sstevel@tonic-gate 17587c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 17597c478bd9Sstevel@tonic-gate case 0: 17607c478bd9Sstevel@tonic-gate break; 17617c478bd9Sstevel@tonic-gate 17627c478bd9Sstevel@tonic-gate case ENOMEM: 17637c478bd9Sstevel@tonic-gate case ENOENT: 17647c478bd9Sstevel@tonic-gate case EIO: 17657c478bd9Sstevel@tonic-gate case EMFILE: 17667c478bd9Sstevel@tonic-gate case ENFILE: 17677c478bd9Sstevel@tonic-gate return (ret); 17687c478bd9Sstevel@tonic-gate 17697c478bd9Sstevel@tonic-gate default: 17707c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 17717c478bd9Sstevel@tonic-gate } 17727c478bd9Sstevel@tonic-gate 17737c478bd9Sstevel@tonic-gate buf = malloc(bufsz); 17747c478bd9Sstevel@tonic-gate if (buf == NULL) 17757c478bd9Sstevel@tonic-gate return (ENOMEM); 17767c478bd9Sstevel@tonic-gate 17777c478bd9Sstevel@tonic-gate do { 17787c478bd9Sstevel@tonic-gate errno = 0; 17797c478bd9Sstevel@tonic-gate pp = getdefaultproj(cip->pwd.pw_name, &proj, buf, 17807c478bd9Sstevel@tonic-gate bufsz); 17817c478bd9Sstevel@tonic-gate } while (pp == NULL && errno == EINTR); 17827c478bd9Sstevel@tonic-gate 17837c478bd9Sstevel@tonic-gate /* to be continued ... */ 17847c478bd9Sstevel@tonic-gate } else { 17857c478bd9Sstevel@tonic-gate projid_t projid; 17867c478bd9Sstevel@tonic-gate char *cp; 17877c478bd9Sstevel@tonic-gate 17887c478bd9Sstevel@tonic-gate if (!isdigit(str[0])) { 17897c478bd9Sstevel@tonic-gate cip->project = strdup(str); 17907c478bd9Sstevel@tonic-gate return (cip->project != NULL ? 0 : ENOMEM); 17917c478bd9Sstevel@tonic-gate } 17927c478bd9Sstevel@tonic-gate 17937c478bd9Sstevel@tonic-gate errno = 0; 17947c478bd9Sstevel@tonic-gate projid = strtol(str, &cp, 10); 17957c478bd9Sstevel@tonic-gate 17967c478bd9Sstevel@tonic-gate if (projid == 0 && errno != 0) { 17977c478bd9Sstevel@tonic-gate assert(errno == ERANGE); 17987c478bd9Sstevel@tonic-gate return (errno); 17997c478bd9Sstevel@tonic-gate } 18007c478bd9Sstevel@tonic-gate 18017c478bd9Sstevel@tonic-gate for (; *cp != '\0'; ++cp) 18027c478bd9Sstevel@tonic-gate if (*cp != ' ' || *cp != '\t') 18037c478bd9Sstevel@tonic-gate return (EINVAL); 18047c478bd9Sstevel@tonic-gate 18057c478bd9Sstevel@tonic-gate if (projid > MAXPROJID) 18067c478bd9Sstevel@tonic-gate return (ERANGE); 18077c478bd9Sstevel@tonic-gate 18087c478bd9Sstevel@tonic-gate buf = malloc(bufsz); 18097c478bd9Sstevel@tonic-gate if (buf == NULL) 18107c478bd9Sstevel@tonic-gate return (ENOMEM); 18117c478bd9Sstevel@tonic-gate 18127c478bd9Sstevel@tonic-gate do { 18137c478bd9Sstevel@tonic-gate errno = 0; 18147c478bd9Sstevel@tonic-gate pp = getprojbyid(projid, &proj, buf, bufsz); 18157c478bd9Sstevel@tonic-gate } while (pp == NULL && errno == EINTR); 18167c478bd9Sstevel@tonic-gate } 18177c478bd9Sstevel@tonic-gate 18187c478bd9Sstevel@tonic-gate if (pp) { 18197c478bd9Sstevel@tonic-gate cip->project = strdup(pp->pj_name); 18207c478bd9Sstevel@tonic-gate free(buf); 18217c478bd9Sstevel@tonic-gate return (cip->project != NULL ? 0 : ENOMEM); 18227c478bd9Sstevel@tonic-gate } 18237c478bd9Sstevel@tonic-gate 18247c478bd9Sstevel@tonic-gate free(buf); 18257c478bd9Sstevel@tonic-gate 18267c478bd9Sstevel@tonic-gate switch (errno) { 18277c478bd9Sstevel@tonic-gate case 0: 18287c478bd9Sstevel@tonic-gate return (ENOENT); 18297c478bd9Sstevel@tonic-gate 18307c478bd9Sstevel@tonic-gate case EIO: 18317c478bd9Sstevel@tonic-gate case EMFILE: 18327c478bd9Sstevel@tonic-gate case ENFILE: 18337c478bd9Sstevel@tonic-gate return (errno); 18347c478bd9Sstevel@tonic-gate 18357c478bd9Sstevel@tonic-gate case ERANGE: 18367c478bd9Sstevel@tonic-gate return (E2BIG); 18377c478bd9Sstevel@tonic-gate 18387c478bd9Sstevel@tonic-gate default: 18397c478bd9Sstevel@tonic-gate return (-1); 18407c478bd9Sstevel@tonic-gate } 18417c478bd9Sstevel@tonic-gate } 18427c478bd9Sstevel@tonic-gate 18437c478bd9Sstevel@tonic-gate /* 18447c478bd9Sstevel@tonic-gate * Parse the supp_groups property value and populate ci->groups. Returns 18457c478bd9Sstevel@tonic-gate * EINVAL (get_gid() failed for one of the components), E2BIG (the property has 18467c478bd9Sstevel@tonic-gate * more than NGROUPS_MAX-1 groups), or 0 on success. 18477c478bd9Sstevel@tonic-gate */ 18487c478bd9Sstevel@tonic-gate int 18497c478bd9Sstevel@tonic-gate get_groups(char *str, struct method_context *ci) 18507c478bd9Sstevel@tonic-gate { 18517c478bd9Sstevel@tonic-gate char *cp, *end, *next; 18527c478bd9Sstevel@tonic-gate uint_t i; 18537c478bd9Sstevel@tonic-gate 18547c478bd9Sstevel@tonic-gate const char * const whitespace = " \t"; 18557c478bd9Sstevel@tonic-gate const char * const illegal = ", \t"; 18567c478bd9Sstevel@tonic-gate 18577c478bd9Sstevel@tonic-gate if (str[0] == '\0') { 18587c478bd9Sstevel@tonic-gate ci->ngroups = 0; 18597c478bd9Sstevel@tonic-gate return (0); 18607c478bd9Sstevel@tonic-gate } 18617c478bd9Sstevel@tonic-gate 18627c478bd9Sstevel@tonic-gate for (cp = str, i = 0; *cp != '\0'; ) { 18637c478bd9Sstevel@tonic-gate /* skip whitespace */ 18647c478bd9Sstevel@tonic-gate cp += strspn(cp, whitespace); 18657c478bd9Sstevel@tonic-gate 18667c478bd9Sstevel@tonic-gate /* find the end */ 18677c478bd9Sstevel@tonic-gate end = cp + strcspn(cp, illegal); 18687c478bd9Sstevel@tonic-gate 18697c478bd9Sstevel@tonic-gate /* skip whitespace after end */ 18707c478bd9Sstevel@tonic-gate next = end + strspn(end, whitespace); 18717c478bd9Sstevel@tonic-gate 18727c478bd9Sstevel@tonic-gate /* if there's a comma, it separates the fields */ 18737c478bd9Sstevel@tonic-gate if (*next == ',') 18747c478bd9Sstevel@tonic-gate ++next; 18757c478bd9Sstevel@tonic-gate 18767c478bd9Sstevel@tonic-gate *end = '\0'; 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate if ((ci->groups[i] = get_gid(cp)) == -1) { 18797c478bd9Sstevel@tonic-gate ci->ngroups = 0; 18807c478bd9Sstevel@tonic-gate return (EINVAL); 18817c478bd9Sstevel@tonic-gate } 18827c478bd9Sstevel@tonic-gate 18837c478bd9Sstevel@tonic-gate ++i; 18847c478bd9Sstevel@tonic-gate if (i > NGROUPS_MAX - 1) { 18857c478bd9Sstevel@tonic-gate ci->ngroups = 0; 18867c478bd9Sstevel@tonic-gate return (E2BIG); 18877c478bd9Sstevel@tonic-gate } 18887c478bd9Sstevel@tonic-gate 18897c478bd9Sstevel@tonic-gate cp = next; 18907c478bd9Sstevel@tonic-gate } 18917c478bd9Sstevel@tonic-gate 18927c478bd9Sstevel@tonic-gate ci->ngroups = i; 18937c478bd9Sstevel@tonic-gate return (0); 18947c478bd9Sstevel@tonic-gate } 18957c478bd9Sstevel@tonic-gate 18967c478bd9Sstevel@tonic-gate /* 18977c478bd9Sstevel@tonic-gate * Eventually, we will return a structured error in the case of 18987c478bd9Sstevel@tonic-gate * retryable or abortable failures such as memory allocation errors and 18997c478bd9Sstevel@tonic-gate * repository connection failures. For now, these failures are just 19007c478bd9Sstevel@tonic-gate * encoded in the failure string. 19017c478bd9Sstevel@tonic-gate */ 19027c478bd9Sstevel@tonic-gate static const char * 19037c478bd9Sstevel@tonic-gate get_profile(scf_propertygroup_t *pg, scf_property_t *prop, scf_value_t *val, 19047c478bd9Sstevel@tonic-gate const char *cmdline, struct method_context *ci) 19057c478bd9Sstevel@tonic-gate { 19067c478bd9Sstevel@tonic-gate char *buf = ci->vbuf; 19077c478bd9Sstevel@tonic-gate ssize_t buf_sz = ci->vbuf_sz; 19087c478bd9Sstevel@tonic-gate char cmd[PATH_MAX]; 19097c478bd9Sstevel@tonic-gate char *cp, *value; 19107c478bd9Sstevel@tonic-gate const char *cmdp; 19117c478bd9Sstevel@tonic-gate execattr_t *eap; 19127c478bd9Sstevel@tonic-gate char *errstr = NULL; 19137c478bd9Sstevel@tonic-gate 19147c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_PROFILE, buf, buf_sz, prop, val) != 19157c478bd9Sstevel@tonic-gate 0) 19167c478bd9Sstevel@tonic-gate return ("Could not get profile property."); 19177c478bd9Sstevel@tonic-gate 19187c478bd9Sstevel@tonic-gate /* Extract the command from the command line. */ 19197c478bd9Sstevel@tonic-gate cp = strpbrk(cmdline, " \t"); 19207c478bd9Sstevel@tonic-gate 19217c478bd9Sstevel@tonic-gate if (cp == NULL) { 19227c478bd9Sstevel@tonic-gate cmdp = cmdline; 19237c478bd9Sstevel@tonic-gate } else { 19247c478bd9Sstevel@tonic-gate (void) strncpy(cmd, cmdline, cp - cmdline); 19257c478bd9Sstevel@tonic-gate cmd[cp - cmdline] = '\0'; 19267c478bd9Sstevel@tonic-gate cmdp = cmd; 19277c478bd9Sstevel@tonic-gate } 19287c478bd9Sstevel@tonic-gate 19297c478bd9Sstevel@tonic-gate /* Require that cmdp[0] == '/'? */ 19307c478bd9Sstevel@tonic-gate 19317c478bd9Sstevel@tonic-gate eap = getexecprof(buf, KV_COMMAND, cmdp, GET_ONE); 19327c478bd9Sstevel@tonic-gate if (eap == NULL) 19337c478bd9Sstevel@tonic-gate return ("Could not find profile."); 19347c478bd9Sstevel@tonic-gate 19357c478bd9Sstevel@tonic-gate /* Based on pfexec.c */ 19367c478bd9Sstevel@tonic-gate 19377c478bd9Sstevel@tonic-gate /* Get the euid first so we don't override ci->pwd for the uid. */ 19387c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_EUID_KW)) != NULL) { 19397c478bd9Sstevel@tonic-gate if (get_uid(value, ci, &ci->euid) != 0) { 19407c478bd9Sstevel@tonic-gate ci->euid = -1; 19417c478bd9Sstevel@tonic-gate errstr = "Could not interpret profile euid."; 19427c478bd9Sstevel@tonic-gate goto out; 19437c478bd9Sstevel@tonic-gate } 19447c478bd9Sstevel@tonic-gate } 19457c478bd9Sstevel@tonic-gate 19467c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_UID_KW)) != NULL) { 19477c478bd9Sstevel@tonic-gate if (get_uid(value, ci, &ci->uid) != 0) { 19487c478bd9Sstevel@tonic-gate ci->euid = ci->uid = -1; 19497c478bd9Sstevel@tonic-gate errstr = "Could not interpret profile uid."; 19507c478bd9Sstevel@tonic-gate goto out; 19517c478bd9Sstevel@tonic-gate } 19527c478bd9Sstevel@tonic-gate ci->euid = ci->uid; 19537c478bd9Sstevel@tonic-gate } 19547c478bd9Sstevel@tonic-gate 19557c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_GID_KW)) != NULL) { 19567c478bd9Sstevel@tonic-gate ci->egid = ci->gid = get_gid(value); 19577c478bd9Sstevel@tonic-gate if (ci->gid == -1) { 19587c478bd9Sstevel@tonic-gate errstr = "Could not interpret profile gid."; 19597c478bd9Sstevel@tonic-gate goto out; 19607c478bd9Sstevel@tonic-gate } 19617c478bd9Sstevel@tonic-gate } 19627c478bd9Sstevel@tonic-gate 19637c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_EGID_KW)) != NULL) { 19647c478bd9Sstevel@tonic-gate ci->egid = get_gid(value); 19657c478bd9Sstevel@tonic-gate if (ci->egid == -1) { 19667c478bd9Sstevel@tonic-gate errstr = "Could not interpret profile egid."; 19677c478bd9Sstevel@tonic-gate goto out; 19687c478bd9Sstevel@tonic-gate } 19697c478bd9Sstevel@tonic-gate } 19707c478bd9Sstevel@tonic-gate 19717c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_LPRIV_KW)) != NULL) { 19727c478bd9Sstevel@tonic-gate ci->lpriv_set = priv_str_to_set(value, ",", NULL); 19737c478bd9Sstevel@tonic-gate if (ci->lpriv_set == NULL) { 19747c478bd9Sstevel@tonic-gate if (errno != EINVAL) 19757c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 19767c478bd9Sstevel@tonic-gate else 19777c478bd9Sstevel@tonic-gate errstr = "Could not interpret profile " 19787c478bd9Sstevel@tonic-gate "limitprivs."; 19797c478bd9Sstevel@tonic-gate goto out; 19807c478bd9Sstevel@tonic-gate } 19817c478bd9Sstevel@tonic-gate } 19827c478bd9Sstevel@tonic-gate 19837c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_IPRIV_KW)) != NULL) { 19847c478bd9Sstevel@tonic-gate ci->priv_set = priv_str_to_set(value, ",", NULL); 19857c478bd9Sstevel@tonic-gate if (ci->priv_set == NULL) { 19867c478bd9Sstevel@tonic-gate if (errno != EINVAL) 19877c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 19887c478bd9Sstevel@tonic-gate else 19897c478bd9Sstevel@tonic-gate errstr = "Could not interpret profile privs."; 19907c478bd9Sstevel@tonic-gate goto out; 19917c478bd9Sstevel@tonic-gate } 19927c478bd9Sstevel@tonic-gate } 19937c478bd9Sstevel@tonic-gate 19947c478bd9Sstevel@tonic-gate out: 19957c478bd9Sstevel@tonic-gate free_execattr(eap); 19967c478bd9Sstevel@tonic-gate 19977c478bd9Sstevel@tonic-gate return (errstr); 19987c478bd9Sstevel@tonic-gate } 19997c478bd9Sstevel@tonic-gate 20007c478bd9Sstevel@tonic-gate /* 20017c478bd9Sstevel@tonic-gate * Eventually, we will return a structured error in the case of 20027c478bd9Sstevel@tonic-gate * retryable or abortable failures such as memory allocation errors and 20037c478bd9Sstevel@tonic-gate * repository connection failures. For now, these failures are just 20047c478bd9Sstevel@tonic-gate * encoded in the failure string. 20057c478bd9Sstevel@tonic-gate */ 20067c478bd9Sstevel@tonic-gate static const char * 20077c478bd9Sstevel@tonic-gate get_ids(scf_propertygroup_t *pg, scf_property_t *prop, scf_value_t *val, 20087c478bd9Sstevel@tonic-gate struct method_context *ci) 20097c478bd9Sstevel@tonic-gate { 20107c478bd9Sstevel@tonic-gate const char *errstr = NULL; 20117c478bd9Sstevel@tonic-gate char *vbuf = ci->vbuf; 20127c478bd9Sstevel@tonic-gate ssize_t vbuf_sz = ci->vbuf_sz; 20137c478bd9Sstevel@tonic-gate int r; 20147c478bd9Sstevel@tonic-gate 20157c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_USER, vbuf, vbuf_sz, prop, val) != 20167c478bd9Sstevel@tonic-gate 0) { 20177c478bd9Sstevel@tonic-gate errstr = "Could not get user property."; 20187c478bd9Sstevel@tonic-gate goto out; 20197c478bd9Sstevel@tonic-gate } 20207c478bd9Sstevel@tonic-gate 20217c478bd9Sstevel@tonic-gate if (get_uid(vbuf, ci, &ci->uid) != 0) { 20227c478bd9Sstevel@tonic-gate ci->uid = -1; 20237c478bd9Sstevel@tonic-gate errstr = "Could not interpret user property."; 20247c478bd9Sstevel@tonic-gate goto out; 20257c478bd9Sstevel@tonic-gate } 20267c478bd9Sstevel@tonic-gate 20277c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_GROUP, vbuf, vbuf_sz, prop, val) != 20287c478bd9Sstevel@tonic-gate 0) { 20297c478bd9Sstevel@tonic-gate errstr = "Could not get group property."; 20307c478bd9Sstevel@tonic-gate goto out; 20317c478bd9Sstevel@tonic-gate } 20327c478bd9Sstevel@tonic-gate 20337c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") != 0) { 20347c478bd9Sstevel@tonic-gate ci->gid = get_gid(vbuf); 20357c478bd9Sstevel@tonic-gate if (ci->gid == -1) { 20367c478bd9Sstevel@tonic-gate errstr = "Could not interpret group property."; 20377c478bd9Sstevel@tonic-gate goto out; 20387c478bd9Sstevel@tonic-gate } 20397c478bd9Sstevel@tonic-gate } else { 20407c478bd9Sstevel@tonic-gate switch (r = lookup_pwd(ci)) { 20417c478bd9Sstevel@tonic-gate case 0: 20427c478bd9Sstevel@tonic-gate ci->gid = ci->pwd.pw_gid; 20437c478bd9Sstevel@tonic-gate break; 20447c478bd9Sstevel@tonic-gate 20457c478bd9Sstevel@tonic-gate case ENOENT: 20467c478bd9Sstevel@tonic-gate ci->gid = -1; 20477c478bd9Sstevel@tonic-gate errstr = "No passwd entry."; 20487c478bd9Sstevel@tonic-gate goto out; 20497c478bd9Sstevel@tonic-gate 20507c478bd9Sstevel@tonic-gate case ENOMEM: 20517c478bd9Sstevel@tonic-gate errstr = "Out of memory."; 20527c478bd9Sstevel@tonic-gate goto out; 20537c478bd9Sstevel@tonic-gate 20547c478bd9Sstevel@tonic-gate case EIO: 20557c478bd9Sstevel@tonic-gate case EMFILE: 20567c478bd9Sstevel@tonic-gate case ENFILE: 20577c478bd9Sstevel@tonic-gate errstr = "getpwuid_r() failed."; 20587c478bd9Sstevel@tonic-gate goto out; 20597c478bd9Sstevel@tonic-gate 20607c478bd9Sstevel@tonic-gate default: 20617c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", r); 20627c478bd9Sstevel@tonic-gate } 20637c478bd9Sstevel@tonic-gate } 20647c478bd9Sstevel@tonic-gate 20657c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_SUPP_GROUPS, vbuf, vbuf_sz, prop, 20667c478bd9Sstevel@tonic-gate val) != 0) { 20677c478bd9Sstevel@tonic-gate errstr = "Could not get supplemental groups property."; 20687c478bd9Sstevel@tonic-gate goto out; 20697c478bd9Sstevel@tonic-gate } 20707c478bd9Sstevel@tonic-gate 20717c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") != 0) { 20727c478bd9Sstevel@tonic-gate switch (r = get_groups(vbuf, ci)) { 20737c478bd9Sstevel@tonic-gate case 0: 20747c478bd9Sstevel@tonic-gate break; 20757c478bd9Sstevel@tonic-gate 20767c478bd9Sstevel@tonic-gate case EINVAL: 20777c478bd9Sstevel@tonic-gate errstr = 20787c478bd9Sstevel@tonic-gate "Could not interpret supplemental groups property."; 20797c478bd9Sstevel@tonic-gate goto out; 20807c478bd9Sstevel@tonic-gate 20817c478bd9Sstevel@tonic-gate case E2BIG: 20827c478bd9Sstevel@tonic-gate errstr = "Too many supplemental groups."; 20837c478bd9Sstevel@tonic-gate goto out; 20847c478bd9Sstevel@tonic-gate 20857c478bd9Sstevel@tonic-gate default: 20867c478bd9Sstevel@tonic-gate bad_fail("get_groups", r); 20877c478bd9Sstevel@tonic-gate } 20887c478bd9Sstevel@tonic-gate } else { 20897c478bd9Sstevel@tonic-gate ci->ngroups = -1; 20907c478bd9Sstevel@tonic-gate } 20917c478bd9Sstevel@tonic-gate 20927c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_PRIVILEGES, vbuf, vbuf_sz, prop, 20937c478bd9Sstevel@tonic-gate val) != 0) { 20947c478bd9Sstevel@tonic-gate errstr = "Could not get privileges property."; 20957c478bd9Sstevel@tonic-gate goto out; 20967c478bd9Sstevel@tonic-gate } 20977c478bd9Sstevel@tonic-gate 20987c478bd9Sstevel@tonic-gate /* 20997c478bd9Sstevel@tonic-gate * For default privs, we need to keep priv_set == NULL, as 21007c478bd9Sstevel@tonic-gate * we use this test elsewhere. 21017c478bd9Sstevel@tonic-gate */ 21027c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") != 0) { 21037c478bd9Sstevel@tonic-gate ci->priv_set = priv_str_to_set(vbuf, ",", NULL); 21047c478bd9Sstevel@tonic-gate if (ci->priv_set == NULL) { 21057c478bd9Sstevel@tonic-gate if (errno != EINVAL) { 21067c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 21077c478bd9Sstevel@tonic-gate } else { 21087c478bd9Sstevel@tonic-gate errstr = "Could not interpret privileges " 21097c478bd9Sstevel@tonic-gate "property."; 21107c478bd9Sstevel@tonic-gate } 21117c478bd9Sstevel@tonic-gate goto out; 21127c478bd9Sstevel@tonic-gate } 21137c478bd9Sstevel@tonic-gate } 21147c478bd9Sstevel@tonic-gate 21157c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_LIMIT_PRIVILEGES, vbuf, vbuf_sz, 21167c478bd9Sstevel@tonic-gate prop, val) != 0) { 21177c478bd9Sstevel@tonic-gate errstr = "Could not get limit_privileges property."; 21187c478bd9Sstevel@tonic-gate goto out; 21197c478bd9Sstevel@tonic-gate } 21207c478bd9Sstevel@tonic-gate 21217c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") == 0) 21227c478bd9Sstevel@tonic-gate /* 21237c478bd9Sstevel@tonic-gate * L must default to all privileges so root NPA services see 21247c478bd9Sstevel@tonic-gate * iE = all. "zone" is all privileges available in the current 21257c478bd9Sstevel@tonic-gate * zone, equivalent to "all" in the global zone. 21267c478bd9Sstevel@tonic-gate */ 21277c478bd9Sstevel@tonic-gate (void) strcpy(vbuf, "zone"); 21287c478bd9Sstevel@tonic-gate 21297c478bd9Sstevel@tonic-gate ci->lpriv_set = priv_str_to_set(vbuf, ",", NULL); 21307c478bd9Sstevel@tonic-gate if (ci->lpriv_set == NULL) { 21317c478bd9Sstevel@tonic-gate if (errno != EINVAL) 21327c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 21337c478bd9Sstevel@tonic-gate else { 21347c478bd9Sstevel@tonic-gate errstr = "Could not interpret limit_privileges " 21357c478bd9Sstevel@tonic-gate "property."; 21367c478bd9Sstevel@tonic-gate } 21377c478bd9Sstevel@tonic-gate goto out; 21387c478bd9Sstevel@tonic-gate } 21397c478bd9Sstevel@tonic-gate 21407c478bd9Sstevel@tonic-gate out: 21417c478bd9Sstevel@tonic-gate return (errstr); 21427c478bd9Sstevel@tonic-gate } 21437c478bd9Sstevel@tonic-gate 21447c478bd9Sstevel@tonic-gate static int 21457c478bd9Sstevel@tonic-gate get_environment(scf_handle_t *h, scf_propertygroup_t *pg, 21467c478bd9Sstevel@tonic-gate struct method_context *mcp, scf_property_t *prop, scf_value_t *val) 21477c478bd9Sstevel@tonic-gate { 21487c478bd9Sstevel@tonic-gate scf_iter_t *iter; 21497c478bd9Sstevel@tonic-gate scf_type_t type; 21507c478bd9Sstevel@tonic-gate size_t i = 0; 21517c478bd9Sstevel@tonic-gate int ret; 21527c478bd9Sstevel@tonic-gate 21537c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_ENVIRONMENT, prop) != 0) { 21547c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_NOT_FOUND) 21557c478bd9Sstevel@tonic-gate return (ENOENT); 21567c478bd9Sstevel@tonic-gate return (scf_error()); 21577c478bd9Sstevel@tonic-gate } 21587c478bd9Sstevel@tonic-gate if (scf_property_type(prop, &type) != 0) 21597c478bd9Sstevel@tonic-gate return (scf_error()); 21607c478bd9Sstevel@tonic-gate if (type != SCF_TYPE_ASTRING) 21617c478bd9Sstevel@tonic-gate return (EINVAL); 21627c478bd9Sstevel@tonic-gate if ((iter = scf_iter_create(h)) == NULL) 21637c478bd9Sstevel@tonic-gate return (scf_error()); 21647c478bd9Sstevel@tonic-gate 21657c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) { 21667c478bd9Sstevel@tonic-gate ret = scf_error(); 21677c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 21687c478bd9Sstevel@tonic-gate return (ret); 21697c478bd9Sstevel@tonic-gate } 21707c478bd9Sstevel@tonic-gate 21717c478bd9Sstevel@tonic-gate mcp->env_sz = 10; 21727c478bd9Sstevel@tonic-gate 21737c478bd9Sstevel@tonic-gate if ((mcp->env = uu_zalloc(sizeof (*mcp->env) * mcp->env_sz)) == NULL) { 21747c478bd9Sstevel@tonic-gate ret = ENOMEM; 21757c478bd9Sstevel@tonic-gate goto out; 21767c478bd9Sstevel@tonic-gate } 21777c478bd9Sstevel@tonic-gate 21787c478bd9Sstevel@tonic-gate while ((ret = scf_iter_next_value(iter, val)) == 1) { 21797c478bd9Sstevel@tonic-gate ret = scf_value_get_as_string(val, mcp->vbuf, mcp->vbuf_sz); 21807c478bd9Sstevel@tonic-gate if (ret == -1) { 21817c478bd9Sstevel@tonic-gate ret = scf_error(); 21827c478bd9Sstevel@tonic-gate goto out; 21837c478bd9Sstevel@tonic-gate } 21847c478bd9Sstevel@tonic-gate 21857c478bd9Sstevel@tonic-gate if ((mcp->env[i] = strdup(mcp->vbuf)) == NULL) { 21867c478bd9Sstevel@tonic-gate ret = ENOMEM; 21877c478bd9Sstevel@tonic-gate goto out; 21887c478bd9Sstevel@tonic-gate } 21897c478bd9Sstevel@tonic-gate 21907c478bd9Sstevel@tonic-gate if (++i == mcp->env_sz) { 21917c478bd9Sstevel@tonic-gate char **env; 21927c478bd9Sstevel@tonic-gate mcp->env_sz *= 2; 21937c478bd9Sstevel@tonic-gate env = uu_zalloc(sizeof (*mcp->env) * mcp->env_sz); 21947c478bd9Sstevel@tonic-gate if (env == NULL) { 21957c478bd9Sstevel@tonic-gate ret = ENOMEM; 21967c478bd9Sstevel@tonic-gate goto out; 21977c478bd9Sstevel@tonic-gate } 21987c478bd9Sstevel@tonic-gate (void) memcpy(env, mcp->env, 21997c478bd9Sstevel@tonic-gate sizeof (*mcp->env) * (mcp->env_sz / 2)); 22007c478bd9Sstevel@tonic-gate free(mcp->env); 22017c478bd9Sstevel@tonic-gate mcp->env = env; 22027c478bd9Sstevel@tonic-gate } 22037c478bd9Sstevel@tonic-gate } 22047c478bd9Sstevel@tonic-gate 22057c478bd9Sstevel@tonic-gate if (ret == -1) 22067c478bd9Sstevel@tonic-gate ret = scf_error(); 22077c478bd9Sstevel@tonic-gate 22087c478bd9Sstevel@tonic-gate out: 22097c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 22107c478bd9Sstevel@tonic-gate return (ret); 22117c478bd9Sstevel@tonic-gate } 22127c478bd9Sstevel@tonic-gate 22137c478bd9Sstevel@tonic-gate /* 22147c478bd9Sstevel@tonic-gate * Fetch method context information from the repository, allocate and fill 22157c478bd9Sstevel@tonic-gate * a method_context structure, return it in *mcpp, and return NULL. On error, 22167c478bd9Sstevel@tonic-gate * return a human-readable string which indicates the error. 22177c478bd9Sstevel@tonic-gate * 22187c478bd9Sstevel@tonic-gate * Eventually, we will return a structured error in the case of 22197c478bd9Sstevel@tonic-gate * retryable or abortable failures such as memory allocation errors and 22207c478bd9Sstevel@tonic-gate * repository connection failures. For now, these failures are just 22217c478bd9Sstevel@tonic-gate * encoded in the failure string. 22227c478bd9Sstevel@tonic-gate */ 22237c478bd9Sstevel@tonic-gate const char * 22247c478bd9Sstevel@tonic-gate restarter_get_method_context(uint_t version, scf_instance_t *inst, 22257c478bd9Sstevel@tonic-gate scf_snapshot_t *snap, const char *mname, const char *cmdline, 22267c478bd9Sstevel@tonic-gate struct method_context **mcpp) 22277c478bd9Sstevel@tonic-gate { 22287c478bd9Sstevel@tonic-gate scf_handle_t *h; 22297c478bd9Sstevel@tonic-gate scf_propertygroup_t *methpg = NULL; 22307c478bd9Sstevel@tonic-gate scf_propertygroup_t *instpg = NULL; 22317c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 22327c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL; 22337c478bd9Sstevel@tonic-gate scf_value_t *val = NULL; 22347c478bd9Sstevel@tonic-gate scf_type_t ty; 22357c478bd9Sstevel@tonic-gate uint8_t use_profile; 22367c478bd9Sstevel@tonic-gate int ret; 22377c478bd9Sstevel@tonic-gate const char *errstr = NULL; 22387c478bd9Sstevel@tonic-gate struct method_context *cip; 22397c478bd9Sstevel@tonic-gate 22407c478bd9Sstevel@tonic-gate 22417c478bd9Sstevel@tonic-gate if (version != RESTARTER_METHOD_CONTEXT_VERSION) 22427c478bd9Sstevel@tonic-gate return ("Unknown method_context version."); 22437c478bd9Sstevel@tonic-gate 22447c478bd9Sstevel@tonic-gate /* Get the handle before we allocate anything. */ 22457c478bd9Sstevel@tonic-gate h = scf_instance_handle(inst); 22467c478bd9Sstevel@tonic-gate if (h == NULL) 22477c478bd9Sstevel@tonic-gate return (scf_strerror(scf_error())); 22487c478bd9Sstevel@tonic-gate 22497c478bd9Sstevel@tonic-gate cip = malloc(sizeof (*cip)); 22507c478bd9Sstevel@tonic-gate if (cip == NULL) 22517c478bd9Sstevel@tonic-gate return (ALLOCFAIL); 22527c478bd9Sstevel@tonic-gate 22537c478bd9Sstevel@tonic-gate (void) memset(cip, 0, sizeof (*cip)); 22547c478bd9Sstevel@tonic-gate cip->uid = -1; 22557c478bd9Sstevel@tonic-gate cip->euid = -1; 22567c478bd9Sstevel@tonic-gate cip->gid = -1; 22577c478bd9Sstevel@tonic-gate cip->egid = -1; 22587c478bd9Sstevel@tonic-gate 22597c478bd9Sstevel@tonic-gate cip->vbuf_sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 22607c478bd9Sstevel@tonic-gate assert(cip->vbuf_sz >= 0); 22617c478bd9Sstevel@tonic-gate cip->vbuf = malloc(cip->vbuf_sz); 22627c478bd9Sstevel@tonic-gate if (cip->vbuf == NULL) { 22637c478bd9Sstevel@tonic-gate free(cip); 22647c478bd9Sstevel@tonic-gate return (ALLOCFAIL); 22657c478bd9Sstevel@tonic-gate } 22667c478bd9Sstevel@tonic-gate 22677c478bd9Sstevel@tonic-gate if ((instpg = scf_pg_create(h)) == NULL || 22687c478bd9Sstevel@tonic-gate (methpg = scf_pg_create(h)) == NULL || 22697c478bd9Sstevel@tonic-gate (prop = scf_property_create(h)) == NULL || 22707c478bd9Sstevel@tonic-gate (val = scf_value_create(h)) == NULL) { 22717c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 22727c478bd9Sstevel@tonic-gate goto out; 22737c478bd9Sstevel@tonic-gate } 22747c478bd9Sstevel@tonic-gate 22757c478bd9Sstevel@tonic-gate /* 22767c478bd9Sstevel@tonic-gate * The method environment, and the credentials/profile data, 22777c478bd9Sstevel@tonic-gate * may be found either in the pg for the method (methpg), 22787c478bd9Sstevel@tonic-gate * or in the instance/service SCF_PG_METHOD_CONTEXT pg (named 22797c478bd9Sstevel@tonic-gate * instpg below). 22807c478bd9Sstevel@tonic-gate */ 22817c478bd9Sstevel@tonic-gate 22827c478bd9Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, snap, mname, methpg) != 22837c478bd9Sstevel@tonic-gate SCF_SUCCESS) { 22847c478bd9Sstevel@tonic-gate errstr = scf_strerror(scf_error()); 22857c478bd9Sstevel@tonic-gate goto out; 22867c478bd9Sstevel@tonic-gate } 22877c478bd9Sstevel@tonic-gate 22887c478bd9Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, snap, SCF_PG_METHOD_CONTEXT, 22897c478bd9Sstevel@tonic-gate instpg) != SCF_SUCCESS) { 22907c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) { 22917c478bd9Sstevel@tonic-gate errstr = scf_strerror(scf_error()); 22927c478bd9Sstevel@tonic-gate goto out; 22937c478bd9Sstevel@tonic-gate } 22947c478bd9Sstevel@tonic-gate scf_pg_destroy(instpg); 22957c478bd9Sstevel@tonic-gate instpg = NULL; 22967c478bd9Sstevel@tonic-gate } 22977c478bd9Sstevel@tonic-gate 22987c478bd9Sstevel@tonic-gate ret = get_environment(h, methpg, cip, prop, val); 22997c478bd9Sstevel@tonic-gate if (ret == ENOENT && instpg != NULL) { 23007c478bd9Sstevel@tonic-gate ret = get_environment(h, instpg, cip, prop, val); 23017c478bd9Sstevel@tonic-gate } 23027c478bd9Sstevel@tonic-gate 23037c478bd9Sstevel@tonic-gate switch (ret) { 23047c478bd9Sstevel@tonic-gate case 0: 23057c478bd9Sstevel@tonic-gate case ENOENT: 23067c478bd9Sstevel@tonic-gate break; 23077c478bd9Sstevel@tonic-gate case ENOMEM: 23087c478bd9Sstevel@tonic-gate errstr = "Out of memory."; 23097c478bd9Sstevel@tonic-gate goto out; 23107c478bd9Sstevel@tonic-gate case EINVAL: 23117c478bd9Sstevel@tonic-gate errstr = "Invalid method environment."; 23127c478bd9Sstevel@tonic-gate goto out; 23137c478bd9Sstevel@tonic-gate default: 23147c478bd9Sstevel@tonic-gate errstr = scf_strerror(ret); 23157c478bd9Sstevel@tonic-gate goto out; 23167c478bd9Sstevel@tonic-gate } 23177c478bd9Sstevel@tonic-gate 23187c478bd9Sstevel@tonic-gate pg = methpg; 23197c478bd9Sstevel@tonic-gate 23207c478bd9Sstevel@tonic-gate ret = scf_pg_get_property(pg, SCF_PROPERTY_USE_PROFILE, prop); 23217c478bd9Sstevel@tonic-gate if (ret && scf_error() == SCF_ERROR_NOT_FOUND && instpg != NULL) { 23227c478bd9Sstevel@tonic-gate pg = instpg; 23237c478bd9Sstevel@tonic-gate ret = scf_pg_get_property(pg, SCF_PROPERTY_USE_PROFILE, prop); 23247c478bd9Sstevel@tonic-gate } 23257c478bd9Sstevel@tonic-gate 23267c478bd9Sstevel@tonic-gate if (ret) { 23277c478bd9Sstevel@tonic-gate switch (scf_error()) { 23287c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 23297c478bd9Sstevel@tonic-gate /* No context: use defaults */ 23307c478bd9Sstevel@tonic-gate cip->uid = 0; 23317c478bd9Sstevel@tonic-gate cip->gid = 0; 23327c478bd9Sstevel@tonic-gate *mcpp = cip; 23337c478bd9Sstevel@tonic-gate goto out; 23347c478bd9Sstevel@tonic-gate 23357c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 23367c478bd9Sstevel@tonic-gate errstr = RCBROKEN; 23377c478bd9Sstevel@tonic-gate goto out; 23387c478bd9Sstevel@tonic-gate 23397c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 23407c478bd9Sstevel@tonic-gate errstr = "\"use_profile\" property deleted."; 23417c478bd9Sstevel@tonic-gate goto out; 23427c478bd9Sstevel@tonic-gate 23437c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 23447c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 23457c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 23467c478bd9Sstevel@tonic-gate default: 23477c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error()); 23487c478bd9Sstevel@tonic-gate } 23497c478bd9Sstevel@tonic-gate } 23507c478bd9Sstevel@tonic-gate 23517c478bd9Sstevel@tonic-gate if (scf_property_type(prop, &ty) != SCF_SUCCESS) { 23527c478bd9Sstevel@tonic-gate switch (scf_error()) { 23537c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 23547c478bd9Sstevel@tonic-gate errstr = RCBROKEN; 23557c478bd9Sstevel@tonic-gate break; 23567c478bd9Sstevel@tonic-gate 23577c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 23587c478bd9Sstevel@tonic-gate errstr = "\"use profile\" property deleted."; 23597c478bd9Sstevel@tonic-gate break; 23607c478bd9Sstevel@tonic-gate 23617c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 23627c478bd9Sstevel@tonic-gate default: 23637c478bd9Sstevel@tonic-gate bad_fail("scf_property_type", scf_error()); 23647c478bd9Sstevel@tonic-gate } 23657c478bd9Sstevel@tonic-gate 23667c478bd9Sstevel@tonic-gate goto out; 23677c478bd9Sstevel@tonic-gate } 23687c478bd9Sstevel@tonic-gate 23697c478bd9Sstevel@tonic-gate if (ty != SCF_TYPE_BOOLEAN) { 23707c478bd9Sstevel@tonic-gate errstr = "\"use profile\" property is not boolean."; 23717c478bd9Sstevel@tonic-gate goto out; 23727c478bd9Sstevel@tonic-gate } 23737c478bd9Sstevel@tonic-gate 23747c478bd9Sstevel@tonic-gate if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 23757c478bd9Sstevel@tonic-gate switch (scf_error()) { 23767c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 23777c478bd9Sstevel@tonic-gate errstr = RCBROKEN; 23787c478bd9Sstevel@tonic-gate break; 23797c478bd9Sstevel@tonic-gate 23807c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 23817c478bd9Sstevel@tonic-gate errstr = 23827c478bd9Sstevel@tonic-gate "\"use profile\" property has multiple values."; 23837c478bd9Sstevel@tonic-gate break; 23847c478bd9Sstevel@tonic-gate 23857c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 23867c478bd9Sstevel@tonic-gate errstr = "\"use profile\" property has no values."; 23877c478bd9Sstevel@tonic-gate break; 23887c478bd9Sstevel@tonic-gate 23897c478bd9Sstevel@tonic-gate default: 23907c478bd9Sstevel@tonic-gate bad_fail("scf_property_get_value", scf_error()); 23917c478bd9Sstevel@tonic-gate } 23927c478bd9Sstevel@tonic-gate 23937c478bd9Sstevel@tonic-gate goto out; 23947c478bd9Sstevel@tonic-gate } 23957c478bd9Sstevel@tonic-gate 23967c478bd9Sstevel@tonic-gate ret = scf_value_get_boolean(val, &use_profile); 23977c478bd9Sstevel@tonic-gate assert(ret == SCF_SUCCESS); 23987c478bd9Sstevel@tonic-gate 23997c478bd9Sstevel@tonic-gate /* get ids & privileges */ 24007c478bd9Sstevel@tonic-gate if (use_profile) 24017c478bd9Sstevel@tonic-gate errstr = get_profile(pg, prop, val, cmdline, cip); 24027c478bd9Sstevel@tonic-gate else 24037c478bd9Sstevel@tonic-gate errstr = get_ids(pg, prop, val, cip); 24047c478bd9Sstevel@tonic-gate if (errstr != NULL) 24057c478bd9Sstevel@tonic-gate goto out; 24067c478bd9Sstevel@tonic-gate 24077c478bd9Sstevel@tonic-gate /* get working directory */ 24087c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_WORKING_DIRECTORY, cip->vbuf, 24097c478bd9Sstevel@tonic-gate cip->vbuf_sz, prop, val) != 0) { 24107c478bd9Sstevel@tonic-gate errstr = "Could not get value for working directory."; 24117c478bd9Sstevel@tonic-gate goto out; 24127c478bd9Sstevel@tonic-gate } 24137c478bd9Sstevel@tonic-gate 24147c478bd9Sstevel@tonic-gate if (strcmp(cip->vbuf, ":default") == 0 || 24157c478bd9Sstevel@tonic-gate strcmp(cip->vbuf, ":home") == 0) { 24167c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 24177c478bd9Sstevel@tonic-gate case 0: 24187c478bd9Sstevel@tonic-gate break; 24197c478bd9Sstevel@tonic-gate 24207c478bd9Sstevel@tonic-gate case ENOMEM: 24217c478bd9Sstevel@tonic-gate errstr = "Out of memory."; 24227c478bd9Sstevel@tonic-gate goto out; 24237c478bd9Sstevel@tonic-gate 24247c478bd9Sstevel@tonic-gate case ENOENT: 24257c478bd9Sstevel@tonic-gate case EIO: 24267c478bd9Sstevel@tonic-gate case EMFILE: 24277c478bd9Sstevel@tonic-gate case ENFILE: 24287c478bd9Sstevel@tonic-gate errstr = "Could not get passwd entry."; 24297c478bd9Sstevel@tonic-gate goto out; 24307c478bd9Sstevel@tonic-gate 24317c478bd9Sstevel@tonic-gate default: 24327c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 24337c478bd9Sstevel@tonic-gate } 24347c478bd9Sstevel@tonic-gate 24357c478bd9Sstevel@tonic-gate cip->working_dir = strdup(cip->pwd.pw_dir); 24367c478bd9Sstevel@tonic-gate if (cip->working_dir == NULL) { 24377c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 24387c478bd9Sstevel@tonic-gate goto out; 24397c478bd9Sstevel@tonic-gate } 24407c478bd9Sstevel@tonic-gate } else { 24417c478bd9Sstevel@tonic-gate cip->working_dir = strdup(cip->vbuf); 24427c478bd9Sstevel@tonic-gate if (cip->working_dir == NULL) { 24437c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 24447c478bd9Sstevel@tonic-gate goto out; 24457c478bd9Sstevel@tonic-gate } 24467c478bd9Sstevel@tonic-gate } 24477c478bd9Sstevel@tonic-gate 24487c478bd9Sstevel@tonic-gate /* get (optional) corefile pattern */ 24497c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_COREFILE_PATTERN, prop) == 24507c478bd9Sstevel@tonic-gate SCF_SUCCESS) { 24517c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_COREFILE_PATTERN, 24527c478bd9Sstevel@tonic-gate cip->vbuf, cip->vbuf_sz, prop, val) != 0) { 24537c478bd9Sstevel@tonic-gate errstr = "Could not get value for corefile pattern."; 24547c478bd9Sstevel@tonic-gate goto out; 24557c478bd9Sstevel@tonic-gate } 24567c478bd9Sstevel@tonic-gate 24577c478bd9Sstevel@tonic-gate cip->corefile_pattern = strdup(cip->vbuf); 24587c478bd9Sstevel@tonic-gate if (cip->corefile_pattern == NULL) { 24597c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 24607c478bd9Sstevel@tonic-gate goto out; 24617c478bd9Sstevel@tonic-gate } 24627c478bd9Sstevel@tonic-gate } else { 24637c478bd9Sstevel@tonic-gate switch (scf_error()) { 24647c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 24657c478bd9Sstevel@tonic-gate /* okay if missing. */ 24667c478bd9Sstevel@tonic-gate break; 24677c478bd9Sstevel@tonic-gate 24687c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 24697c478bd9Sstevel@tonic-gate errstr = RCBROKEN; 24707c478bd9Sstevel@tonic-gate goto out; 24717c478bd9Sstevel@tonic-gate 24727c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 24737c478bd9Sstevel@tonic-gate errstr = "\"corefile_pattern\" property deleted."; 24747c478bd9Sstevel@tonic-gate goto out; 24757c478bd9Sstevel@tonic-gate 24767c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 24777c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 24787c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 24797c478bd9Sstevel@tonic-gate default: 24807c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error()); 24817c478bd9Sstevel@tonic-gate } 24827c478bd9Sstevel@tonic-gate } 24837c478bd9Sstevel@tonic-gate 24847c478bd9Sstevel@tonic-gate if (restarter_rm_libs_loadable()) { 24857c478bd9Sstevel@tonic-gate /* get project */ 24867c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_PROJECT, cip->vbuf, 24877c478bd9Sstevel@tonic-gate cip->vbuf_sz, prop, val) != 0) { 24887c478bd9Sstevel@tonic-gate errstr = "Could not get project."; 24897c478bd9Sstevel@tonic-gate goto out; 24907c478bd9Sstevel@tonic-gate } 24917c478bd9Sstevel@tonic-gate 24927c478bd9Sstevel@tonic-gate switch (ret = get_projid(cip->vbuf, cip)) { 24937c478bd9Sstevel@tonic-gate case 0: 24947c478bd9Sstevel@tonic-gate break; 24957c478bd9Sstevel@tonic-gate 24967c478bd9Sstevel@tonic-gate case ENOMEM: 24977c478bd9Sstevel@tonic-gate errstr = "Out of memory."; 24987c478bd9Sstevel@tonic-gate goto out; 24997c478bd9Sstevel@tonic-gate 25007c478bd9Sstevel@tonic-gate case ENOENT: 25017c478bd9Sstevel@tonic-gate errstr = "Missing passwd or project entry."; 25027c478bd9Sstevel@tonic-gate goto out; 25037c478bd9Sstevel@tonic-gate 25047c478bd9Sstevel@tonic-gate case EIO: 25057c478bd9Sstevel@tonic-gate errstr = "I/O error."; 25067c478bd9Sstevel@tonic-gate goto out; 25077c478bd9Sstevel@tonic-gate 25087c478bd9Sstevel@tonic-gate case EMFILE: 25097c478bd9Sstevel@tonic-gate case ENFILE: 25107c478bd9Sstevel@tonic-gate errstr = "Out of file descriptors."; 25117c478bd9Sstevel@tonic-gate goto out; 25127c478bd9Sstevel@tonic-gate 25137c478bd9Sstevel@tonic-gate case -1: 25147c478bd9Sstevel@tonic-gate errstr = "Name service switch is misconfigured."; 25157c478bd9Sstevel@tonic-gate goto out; 25167c478bd9Sstevel@tonic-gate 25177c478bd9Sstevel@tonic-gate case ERANGE: 25187c478bd9Sstevel@tonic-gate errstr = "Project ID too big."; 25197c478bd9Sstevel@tonic-gate goto out; 25207c478bd9Sstevel@tonic-gate 25217c478bd9Sstevel@tonic-gate case EINVAL: 25227c478bd9Sstevel@tonic-gate errstr = "Project ID is invalid."; 25237c478bd9Sstevel@tonic-gate goto out; 25247c478bd9Sstevel@tonic-gate 25257c478bd9Sstevel@tonic-gate case E2BIG: 25267c478bd9Sstevel@tonic-gate errstr = "Project entry is too big."; 25277c478bd9Sstevel@tonic-gate goto out; 25287c478bd9Sstevel@tonic-gate 25297c478bd9Sstevel@tonic-gate default: 25307c478bd9Sstevel@tonic-gate bad_fail("get_projid", ret); 25317c478bd9Sstevel@tonic-gate } 25327c478bd9Sstevel@tonic-gate 25337c478bd9Sstevel@tonic-gate /* get resource pool */ 25347c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_RESOURCE_POOL, cip->vbuf, 25357c478bd9Sstevel@tonic-gate cip->vbuf_sz, prop, val) != 0) { 25367c478bd9Sstevel@tonic-gate errstr = "Could not get value of resource pool."; 25377c478bd9Sstevel@tonic-gate goto out; 25387c478bd9Sstevel@tonic-gate } 25397c478bd9Sstevel@tonic-gate 25407c478bd9Sstevel@tonic-gate if (strcmp(cip->vbuf, ":default") != 0) { 25417c478bd9Sstevel@tonic-gate cip->resource_pool = strdup(cip->vbuf); 25427c478bd9Sstevel@tonic-gate if (cip->resource_pool == NULL) { 25437c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 25447c478bd9Sstevel@tonic-gate goto out; 25457c478bd9Sstevel@tonic-gate } 25467c478bd9Sstevel@tonic-gate } 25477c478bd9Sstevel@tonic-gate } 25487c478bd9Sstevel@tonic-gate 25497c478bd9Sstevel@tonic-gate *mcpp = cip; 25507c478bd9Sstevel@tonic-gate 25517c478bd9Sstevel@tonic-gate out: 25527c478bd9Sstevel@tonic-gate (void) scf_value_destroy(val); 25537c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 25547c478bd9Sstevel@tonic-gate scf_pg_destroy(instpg); 25557c478bd9Sstevel@tonic-gate scf_pg_destroy(methpg); 25567c478bd9Sstevel@tonic-gate 25577c478bd9Sstevel@tonic-gate if (cip->pwbuf != NULL) 25587c478bd9Sstevel@tonic-gate free(cip->pwbuf); 25597c478bd9Sstevel@tonic-gate free(cip->vbuf); 25607c478bd9Sstevel@tonic-gate 25617c478bd9Sstevel@tonic-gate if (errstr != NULL) 25627c478bd9Sstevel@tonic-gate restarter_free_method_context(cip); 25637c478bd9Sstevel@tonic-gate 25647c478bd9Sstevel@tonic-gate return (errstr); 25657c478bd9Sstevel@tonic-gate } 25667c478bd9Sstevel@tonic-gate 25677c478bd9Sstevel@tonic-gate /* 25687c478bd9Sstevel@tonic-gate * Modify the current process per the given method_context. On success, returns 25697c478bd9Sstevel@tonic-gate * 0. Note that the environment is not modified by this function to include the 25707c478bd9Sstevel@tonic-gate * environment variables in cip->env. 25717c478bd9Sstevel@tonic-gate * 25727c478bd9Sstevel@tonic-gate * On failure, sets *fp to NULL or the name of the function which failed, 25737c478bd9Sstevel@tonic-gate * and returns one of the following error codes. The words in parentheses are 25747c478bd9Sstevel@tonic-gate * the values to which *fp may be set for the error case. 25757c478bd9Sstevel@tonic-gate * ENOMEM - malloc() failed 25767c478bd9Sstevel@tonic-gate * EIO - an I/O error occurred (getpwuid_r, chdir) 25777c478bd9Sstevel@tonic-gate * EMFILE - process is out of file descriptors (getpwuid_r) 25787c478bd9Sstevel@tonic-gate * ENFILE - system is out of file handles (getpwuid_r) 25797c478bd9Sstevel@tonic-gate * EINVAL - gid or egid is out of range (setregid) 25807c478bd9Sstevel@tonic-gate * ngroups is too big (setgroups) 25817c478bd9Sstevel@tonic-gate * project's project id is bad (setproject) 25827c478bd9Sstevel@tonic-gate * uid or euid is out of range (setreuid) 25833ad28c1eSrm88369 * poolname is invalid (pool_set_binding) 25847c478bd9Sstevel@tonic-gate * EPERM - insufficient privilege (setregid, initgroups, setgroups, setppriv, 25857c478bd9Sstevel@tonic-gate * setproject, setreuid, settaskid) 25867c478bd9Sstevel@tonic-gate * ENOENT - uid has a passwd entry but no shadow entry 25877c478bd9Sstevel@tonic-gate * working_dir does not exist (chdir) 25887c478bd9Sstevel@tonic-gate * uid has no passwd entry 25897c478bd9Sstevel@tonic-gate * the pool could not be found (pool_set_binding) 25907c478bd9Sstevel@tonic-gate * EFAULT - lpriv_set or priv_set has a bad address (setppriv) 25917c478bd9Sstevel@tonic-gate * working_dir has a bad address (chdir) 25927c478bd9Sstevel@tonic-gate * EACCES - could not access working_dir (chdir) 25937c478bd9Sstevel@tonic-gate * in a TASK_FINAL task (setproject, settaskid) 25947c478bd9Sstevel@tonic-gate * no resource pool accepting default binding exists (setproject) 25957c478bd9Sstevel@tonic-gate * ELOOP - too many symbolic links in working_dir (chdir) 25967c478bd9Sstevel@tonic-gate * ENAMETOOLONG - working_dir is too long (chdir) 25977c478bd9Sstevel@tonic-gate * ENOLINK - working_dir is on an inaccessible remote machine (chdir) 25987c478bd9Sstevel@tonic-gate * ENOTDIR - working_dir is not a directory (chdir) 25997c478bd9Sstevel@tonic-gate * ESRCH - uid is not a user of project (setproject) 26007c478bd9Sstevel@tonic-gate * project is invalid (setproject) 26017c478bd9Sstevel@tonic-gate * the resource pool specified for project is unknown (setproject) 26027c478bd9Sstevel@tonic-gate * EBADF - the configuration for the pool is invalid (pool_set_binding) 26037c478bd9Sstevel@tonic-gate * -1 - core_set_process_path() failed (core_set_process_path) 26047c478bd9Sstevel@tonic-gate * a resource control assignment failed (setproject) 26057c478bd9Sstevel@tonic-gate * a system error occurred during pool_set_binding (pool_set_binding) 26067c478bd9Sstevel@tonic-gate */ 26077c478bd9Sstevel@tonic-gate int 26087c478bd9Sstevel@tonic-gate restarter_set_method_context(struct method_context *cip, const char **fp) 26097c478bd9Sstevel@tonic-gate { 26107c478bd9Sstevel@tonic-gate pid_t mypid = -1; 26117c478bd9Sstevel@tonic-gate int r, ret; 26127c478bd9Sstevel@tonic-gate 26137c478bd9Sstevel@tonic-gate cip->pwbuf = NULL; 26147c478bd9Sstevel@tonic-gate *fp = NULL; 26157c478bd9Sstevel@tonic-gate 26167c478bd9Sstevel@tonic-gate if (cip->gid != -1) { 26177c478bd9Sstevel@tonic-gate if (setregid(cip->gid, 26187c478bd9Sstevel@tonic-gate cip->egid != -1 ? cip->egid : cip->gid) != 0) { 26197c478bd9Sstevel@tonic-gate *fp = "setregid"; 26207c478bd9Sstevel@tonic-gate 26217c478bd9Sstevel@tonic-gate ret = errno; 26227c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 26237c478bd9Sstevel@tonic-gate goto out; 26247c478bd9Sstevel@tonic-gate } 26257c478bd9Sstevel@tonic-gate } else { 26267c478bd9Sstevel@tonic-gate if (cip->pwbuf == NULL) { 26277c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 26287c478bd9Sstevel@tonic-gate case 0: 26297c478bd9Sstevel@tonic-gate break; 26307c478bd9Sstevel@tonic-gate 26317c478bd9Sstevel@tonic-gate case ENOMEM: 26327c478bd9Sstevel@tonic-gate case ENOENT: 26337c478bd9Sstevel@tonic-gate *fp = NULL; 26347c478bd9Sstevel@tonic-gate goto out; 26357c478bd9Sstevel@tonic-gate 26367c478bd9Sstevel@tonic-gate case EIO: 26377c478bd9Sstevel@tonic-gate case EMFILE: 26387c478bd9Sstevel@tonic-gate case ENFILE: 26397c478bd9Sstevel@tonic-gate *fp = "getpwuid_r"; 26407c478bd9Sstevel@tonic-gate goto out; 26417c478bd9Sstevel@tonic-gate 26427c478bd9Sstevel@tonic-gate default: 26437c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 26447c478bd9Sstevel@tonic-gate } 26457c478bd9Sstevel@tonic-gate } 26467c478bd9Sstevel@tonic-gate 26477c478bd9Sstevel@tonic-gate if (setregid(cip->pwd.pw_gid, 26487c478bd9Sstevel@tonic-gate cip->egid != -1 ? cip->egid : cip->pwd.pw_gid) != 0) { 26497c478bd9Sstevel@tonic-gate *fp = "setregid"; 26507c478bd9Sstevel@tonic-gate 26517c478bd9Sstevel@tonic-gate ret = errno; 26527c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 26537c478bd9Sstevel@tonic-gate goto out; 26547c478bd9Sstevel@tonic-gate } 26557c478bd9Sstevel@tonic-gate } 26567c478bd9Sstevel@tonic-gate 26577c478bd9Sstevel@tonic-gate if (cip->ngroups == -1) { 26587c478bd9Sstevel@tonic-gate if (cip->pwbuf == NULL) { 26597c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 26607c478bd9Sstevel@tonic-gate case 0: 26617c478bd9Sstevel@tonic-gate break; 26627c478bd9Sstevel@tonic-gate 26637c478bd9Sstevel@tonic-gate case ENOMEM: 26647c478bd9Sstevel@tonic-gate case ENOENT: 26657c478bd9Sstevel@tonic-gate *fp = NULL; 26667c478bd9Sstevel@tonic-gate goto out; 26677c478bd9Sstevel@tonic-gate 26687c478bd9Sstevel@tonic-gate case EIO: 26697c478bd9Sstevel@tonic-gate case EMFILE: 26707c478bd9Sstevel@tonic-gate case ENFILE: 26717c478bd9Sstevel@tonic-gate *fp = "getpwuid_r"; 26727c478bd9Sstevel@tonic-gate goto out; 26737c478bd9Sstevel@tonic-gate 26747c478bd9Sstevel@tonic-gate default: 26757c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 26767c478bd9Sstevel@tonic-gate } 26777c478bd9Sstevel@tonic-gate } 26787c478bd9Sstevel@tonic-gate 26797c478bd9Sstevel@tonic-gate /* Ok if cip->gid == -1 */ 26807c478bd9Sstevel@tonic-gate if (initgroups(cip->pwd.pw_name, cip->gid) != 0) { 26817c478bd9Sstevel@tonic-gate *fp = "initgroups"; 26827c478bd9Sstevel@tonic-gate ret = errno; 26837c478bd9Sstevel@tonic-gate assert(ret == EPERM); 26847c478bd9Sstevel@tonic-gate goto out; 26857c478bd9Sstevel@tonic-gate } 26867c478bd9Sstevel@tonic-gate } else if (cip->ngroups > 0 && 26877c478bd9Sstevel@tonic-gate setgroups(cip->ngroups, cip->groups) != 0) { 26887c478bd9Sstevel@tonic-gate *fp = "setgroups"; 26897c478bd9Sstevel@tonic-gate 26907c478bd9Sstevel@tonic-gate ret = errno; 26917c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 26927c478bd9Sstevel@tonic-gate goto out; 26937c478bd9Sstevel@tonic-gate } 26947c478bd9Sstevel@tonic-gate 26957c478bd9Sstevel@tonic-gate *fp = "setppriv"; 26967c478bd9Sstevel@tonic-gate 26977c478bd9Sstevel@tonic-gate if (cip->lpriv_set != NULL) { 26987c478bd9Sstevel@tonic-gate if (setppriv(PRIV_SET, PRIV_LIMIT, cip->lpriv_set) != 0) { 26997c478bd9Sstevel@tonic-gate ret = errno; 27007c478bd9Sstevel@tonic-gate assert(ret == EFAULT || ret == EPERM); 27017c478bd9Sstevel@tonic-gate goto out; 27027c478bd9Sstevel@tonic-gate } 27037c478bd9Sstevel@tonic-gate } 27047c478bd9Sstevel@tonic-gate if (cip->priv_set != NULL) { 27057c478bd9Sstevel@tonic-gate if (setppriv(PRIV_SET, PRIV_INHERITABLE, cip->priv_set) != 0) { 27067c478bd9Sstevel@tonic-gate ret = errno; 27077c478bd9Sstevel@tonic-gate assert(ret == EFAULT || ret == EPERM); 27087c478bd9Sstevel@tonic-gate goto out; 27097c478bd9Sstevel@tonic-gate } 27107c478bd9Sstevel@tonic-gate } 27117c478bd9Sstevel@tonic-gate 27127c478bd9Sstevel@tonic-gate if (cip->corefile_pattern != NULL) { 27137c478bd9Sstevel@tonic-gate mypid = getpid(); 27147c478bd9Sstevel@tonic-gate 27157c478bd9Sstevel@tonic-gate if (core_set_process_path(cip->corefile_pattern, 27167c478bd9Sstevel@tonic-gate strlen(cip->corefile_pattern) + 1, mypid) != 0) { 27177c478bd9Sstevel@tonic-gate *fp = "core_set_process_path"; 27187c478bd9Sstevel@tonic-gate ret = -1; 27197c478bd9Sstevel@tonic-gate goto out; 27207c478bd9Sstevel@tonic-gate } 27217c478bd9Sstevel@tonic-gate } 27227c478bd9Sstevel@tonic-gate 27237c478bd9Sstevel@tonic-gate if (restarter_rm_libs_loadable()) { 27247c478bd9Sstevel@tonic-gate if (cip->project == NULL) { 27257c478bd9Sstevel@tonic-gate if (settaskid(getprojid(), TASK_NORMAL) == -1) { 27267c478bd9Sstevel@tonic-gate switch (errno) { 27277c478bd9Sstevel@tonic-gate case EACCES: 27287c478bd9Sstevel@tonic-gate case EPERM: 27297c478bd9Sstevel@tonic-gate *fp = "settaskid"; 27307c478bd9Sstevel@tonic-gate ret = errno; 27317c478bd9Sstevel@tonic-gate goto out; 27327c478bd9Sstevel@tonic-gate 27337c478bd9Sstevel@tonic-gate case EINVAL: 27347c478bd9Sstevel@tonic-gate default: 27357c478bd9Sstevel@tonic-gate bad_fail("settaskid", errno); 27367c478bd9Sstevel@tonic-gate } 27377c478bd9Sstevel@tonic-gate } 27387c478bd9Sstevel@tonic-gate } else { 27397c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 27407c478bd9Sstevel@tonic-gate case 0: 27417c478bd9Sstevel@tonic-gate break; 27427c478bd9Sstevel@tonic-gate 27437c478bd9Sstevel@tonic-gate case ENOMEM: 27447c478bd9Sstevel@tonic-gate case ENOENT: 27457c478bd9Sstevel@tonic-gate *fp = NULL; 27467c478bd9Sstevel@tonic-gate goto out; 27477c478bd9Sstevel@tonic-gate 27487c478bd9Sstevel@tonic-gate case EIO: 27497c478bd9Sstevel@tonic-gate case EMFILE: 27507c478bd9Sstevel@tonic-gate case ENFILE: 27517c478bd9Sstevel@tonic-gate *fp = "getpwuid_r"; 27527c478bd9Sstevel@tonic-gate goto out; 27537c478bd9Sstevel@tonic-gate 27547c478bd9Sstevel@tonic-gate default: 27557c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 27567c478bd9Sstevel@tonic-gate } 27577c478bd9Sstevel@tonic-gate 27587c478bd9Sstevel@tonic-gate *fp = "setproject"; 27597c478bd9Sstevel@tonic-gate 27607c478bd9Sstevel@tonic-gate switch (setproject(cip->project, cip->pwd.pw_name, 27617c478bd9Sstevel@tonic-gate TASK_NORMAL)) { 27627c478bd9Sstevel@tonic-gate case 0: 27637c478bd9Sstevel@tonic-gate break; 27647c478bd9Sstevel@tonic-gate 27657c478bd9Sstevel@tonic-gate case SETPROJ_ERR_TASK: 27667c478bd9Sstevel@tonic-gate case SETPROJ_ERR_POOL: 27677c478bd9Sstevel@tonic-gate ret = errno; 27687c478bd9Sstevel@tonic-gate goto out; 27697c478bd9Sstevel@tonic-gate 27707c478bd9Sstevel@tonic-gate default: 27717c478bd9Sstevel@tonic-gate ret = -1; 27727c478bd9Sstevel@tonic-gate goto out; 27737c478bd9Sstevel@tonic-gate } 27747c478bd9Sstevel@tonic-gate } 27757c478bd9Sstevel@tonic-gate 27767c478bd9Sstevel@tonic-gate if (cip->resource_pool != NULL) { 27777c478bd9Sstevel@tonic-gate if (mypid == -1) 27787c478bd9Sstevel@tonic-gate mypid = getpid(); 27797c478bd9Sstevel@tonic-gate 27807c478bd9Sstevel@tonic-gate *fp = "pool_set_binding"; 27817c478bd9Sstevel@tonic-gate 27827c478bd9Sstevel@tonic-gate if (pool_set_binding(cip->resource_pool, P_PID, 27837c478bd9Sstevel@tonic-gate mypid) != PO_SUCCESS) { 27847c478bd9Sstevel@tonic-gate switch (pool_error()) { 27853ad28c1eSrm88369 case POE_INVALID_SEARCH: 27867c478bd9Sstevel@tonic-gate ret = ENOENT; 27877c478bd9Sstevel@tonic-gate break; 27887c478bd9Sstevel@tonic-gate 27893ad28c1eSrm88369 case POE_BADPARAM: 27903ad28c1eSrm88369 ret = EINVAL; 27913ad28c1eSrm88369 break; 27923ad28c1eSrm88369 27937c478bd9Sstevel@tonic-gate case POE_INVALID_CONF: 27947c478bd9Sstevel@tonic-gate ret = EBADF; 27957c478bd9Sstevel@tonic-gate break; 27967c478bd9Sstevel@tonic-gate 27977c478bd9Sstevel@tonic-gate case POE_SYSTEM: 27987c478bd9Sstevel@tonic-gate ret = -1; 27997c478bd9Sstevel@tonic-gate break; 28007c478bd9Sstevel@tonic-gate 28017c478bd9Sstevel@tonic-gate default: 28027c478bd9Sstevel@tonic-gate bad_fail("pool_set_binding", 28037c478bd9Sstevel@tonic-gate pool_error()); 28047c478bd9Sstevel@tonic-gate } 28057c478bd9Sstevel@tonic-gate 28067c478bd9Sstevel@tonic-gate goto out; 28077c478bd9Sstevel@tonic-gate } 28087c478bd9Sstevel@tonic-gate } 28097c478bd9Sstevel@tonic-gate } 28107c478bd9Sstevel@tonic-gate 28117c478bd9Sstevel@tonic-gate /* 2812*2a3221a4Svp157776 * Now, we have to assume our ID. If the UID is 0, we want it to be 2813*2a3221a4Svp157776 * privilege-aware, otherwise the limit set gets used instead of E/P. 28147c478bd9Sstevel@tonic-gate * We can do this by setting P as well, which keeps 28157c478bd9Sstevel@tonic-gate * PA status (see priv_can_clear_PA()). 28167c478bd9Sstevel@tonic-gate */ 28177c478bd9Sstevel@tonic-gate 28187c478bd9Sstevel@tonic-gate *fp = "setreuid"; 28197c478bd9Sstevel@tonic-gate if (setreuid(cip->uid, cip->euid != -1 ? cip->euid : cip->uid) != 0) { 28207c478bd9Sstevel@tonic-gate ret = errno; 28217c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 28227c478bd9Sstevel@tonic-gate goto out; 28237c478bd9Sstevel@tonic-gate } 28247c478bd9Sstevel@tonic-gate 28257c478bd9Sstevel@tonic-gate *fp = "setppriv"; 28267c478bd9Sstevel@tonic-gate if (cip->priv_set != NULL) { 28277c478bd9Sstevel@tonic-gate if (setppriv(PRIV_SET, PRIV_PERMITTED, cip->priv_set) != 0) { 28287c478bd9Sstevel@tonic-gate ret = errno; 28297c478bd9Sstevel@tonic-gate assert(ret == EFAULT || ret == EPERM); 28307c478bd9Sstevel@tonic-gate goto out; 28317c478bd9Sstevel@tonic-gate } 28327c478bd9Sstevel@tonic-gate } 28337c478bd9Sstevel@tonic-gate 2834*2a3221a4Svp157776 /* 2835*2a3221a4Svp157776 * The last thing to do is chdir to the specified working directory. 2836*2a3221a4Svp157776 * This should come after the uid switching as only the user might 2837*2a3221a4Svp157776 * have access to the specified directory. 2838*2a3221a4Svp157776 */ 2839*2a3221a4Svp157776 if (cip->working_dir != NULL) { 2840*2a3221a4Svp157776 do 2841*2a3221a4Svp157776 r = chdir(cip->working_dir); 2842*2a3221a4Svp157776 while (r != 0 && errno == EINTR); 2843*2a3221a4Svp157776 if (r != 0) { 2844*2a3221a4Svp157776 *fp = "chdir"; 2845*2a3221a4Svp157776 ret = errno; 2846*2a3221a4Svp157776 goto out; 2847*2a3221a4Svp157776 } 2848*2a3221a4Svp157776 } 2849*2a3221a4Svp157776 28507c478bd9Sstevel@tonic-gate ret = 0; 28517c478bd9Sstevel@tonic-gate out: 28527c478bd9Sstevel@tonic-gate free(cip->pwbuf); 28537c478bd9Sstevel@tonic-gate cip->pwbuf = NULL; 28547c478bd9Sstevel@tonic-gate return (ret); 28557c478bd9Sstevel@tonic-gate } 28567c478bd9Sstevel@tonic-gate 28577c478bd9Sstevel@tonic-gate void 28587c478bd9Sstevel@tonic-gate restarter_free_method_context(struct method_context *mcp) 28597c478bd9Sstevel@tonic-gate { 28607c478bd9Sstevel@tonic-gate size_t i; 28617c478bd9Sstevel@tonic-gate 28627c478bd9Sstevel@tonic-gate if (mcp->lpriv_set != NULL) 28637c478bd9Sstevel@tonic-gate priv_freeset(mcp->lpriv_set); 28647c478bd9Sstevel@tonic-gate if (mcp->priv_set != NULL) 28657c478bd9Sstevel@tonic-gate priv_freeset(mcp->priv_set); 28667c478bd9Sstevel@tonic-gate 28677c478bd9Sstevel@tonic-gate if (mcp->env != NULL) { 28687c478bd9Sstevel@tonic-gate for (i = 0; i < mcp->env_sz; i++) 28697c478bd9Sstevel@tonic-gate free(mcp->env[i]); 28707c478bd9Sstevel@tonic-gate free(mcp->env); 28717c478bd9Sstevel@tonic-gate } 28727c478bd9Sstevel@tonic-gate 28737c478bd9Sstevel@tonic-gate free(mcp->working_dir); 28747c478bd9Sstevel@tonic-gate free(mcp->corefile_pattern); 28757c478bd9Sstevel@tonic-gate free(mcp->project); 28767c478bd9Sstevel@tonic-gate free(mcp->resource_pool); 28777c478bd9Sstevel@tonic-gate free(mcp); 28787c478bd9Sstevel@tonic-gate } 28797c478bd9Sstevel@tonic-gate 28807c478bd9Sstevel@tonic-gate /* 28817c478bd9Sstevel@tonic-gate * Method keyword functions 28827c478bd9Sstevel@tonic-gate */ 28837c478bd9Sstevel@tonic-gate 28847c478bd9Sstevel@tonic-gate int 28857c478bd9Sstevel@tonic-gate restarter_is_null_method(const char *meth) 28867c478bd9Sstevel@tonic-gate { 28877c478bd9Sstevel@tonic-gate return (strcmp(meth, MKW_TRUE) == 0); 28887c478bd9Sstevel@tonic-gate } 28897c478bd9Sstevel@tonic-gate 28907c478bd9Sstevel@tonic-gate static int 28917c478bd9Sstevel@tonic-gate is_kill_method(const char *method, const char *kill_str, 28927c478bd9Sstevel@tonic-gate size_t kill_str_len) 28937c478bd9Sstevel@tonic-gate { 28947c478bd9Sstevel@tonic-gate const char *cp; 28957c478bd9Sstevel@tonic-gate int sig; 28967c478bd9Sstevel@tonic-gate 28977c478bd9Sstevel@tonic-gate if (strncmp(method, kill_str, kill_str_len) != 0 || 28987c478bd9Sstevel@tonic-gate (method[kill_str_len] != '\0' && 28997c478bd9Sstevel@tonic-gate !isspace(method[kill_str_len]))) 29007c478bd9Sstevel@tonic-gate return (-1); 29017c478bd9Sstevel@tonic-gate 29027c478bd9Sstevel@tonic-gate cp = method + kill_str_len; 29037c478bd9Sstevel@tonic-gate while (*cp != '\0' && isspace(*cp)) 29047c478bd9Sstevel@tonic-gate ++cp; 29057c478bd9Sstevel@tonic-gate 29067c478bd9Sstevel@tonic-gate if (*cp == '\0') 29077c478bd9Sstevel@tonic-gate return (SIGTERM); 29087c478bd9Sstevel@tonic-gate 29097c478bd9Sstevel@tonic-gate if (*cp != '-') 29107c478bd9Sstevel@tonic-gate return (-1); 29117c478bd9Sstevel@tonic-gate 29127c478bd9Sstevel@tonic-gate return (str2sig(cp + 1, &sig) == 0 ? sig : -1); 29137c478bd9Sstevel@tonic-gate } 29147c478bd9Sstevel@tonic-gate 29157c478bd9Sstevel@tonic-gate int 29167c478bd9Sstevel@tonic-gate restarter_is_kill_proc_method(const char *method) 29177c478bd9Sstevel@tonic-gate { 29187c478bd9Sstevel@tonic-gate return (is_kill_method(method, MKW_KILL_PROC, 29197c478bd9Sstevel@tonic-gate sizeof (MKW_KILL_PROC) - 1)); 29207c478bd9Sstevel@tonic-gate } 29217c478bd9Sstevel@tonic-gate 29227c478bd9Sstevel@tonic-gate int 29237c478bd9Sstevel@tonic-gate restarter_is_kill_method(const char *method) 29247c478bd9Sstevel@tonic-gate { 29257c478bd9Sstevel@tonic-gate return (is_kill_method(method, MKW_KILL, sizeof (MKW_KILL) - 1)); 29267c478bd9Sstevel@tonic-gate } 29277c478bd9Sstevel@tonic-gate 29287c478bd9Sstevel@tonic-gate /* 29297c478bd9Sstevel@tonic-gate * Stubs for now. 29307c478bd9Sstevel@tonic-gate */ 29317c478bd9Sstevel@tonic-gate 29327c478bd9Sstevel@tonic-gate /* ARGSUSED */ 29337c478bd9Sstevel@tonic-gate int 29347c478bd9Sstevel@tonic-gate restarter_event_get_enabled(restarter_event_t *e) 29357c478bd9Sstevel@tonic-gate { 29367c478bd9Sstevel@tonic-gate return (-1); 29377c478bd9Sstevel@tonic-gate } 29387c478bd9Sstevel@tonic-gate 29397c478bd9Sstevel@tonic-gate /* ARGSUSED */ 29407c478bd9Sstevel@tonic-gate uint64_t 29417c478bd9Sstevel@tonic-gate restarter_event_get_seq(restarter_event_t *e) 29427c478bd9Sstevel@tonic-gate { 29437c478bd9Sstevel@tonic-gate return (-1); 29447c478bd9Sstevel@tonic-gate } 29457c478bd9Sstevel@tonic-gate 29467c478bd9Sstevel@tonic-gate /* ARGSUSED */ 29477c478bd9Sstevel@tonic-gate void 29487c478bd9Sstevel@tonic-gate restarter_event_get_time(restarter_event_t *e, hrtime_t *time) 29497c478bd9Sstevel@tonic-gate { 29507c478bd9Sstevel@tonic-gate } 2951