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 */ 217257d1b4Sraf 227c478bd9Sstevel@tonic-gate /* 23eb1a3463STruong Nguyen * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <librestart.h> 287c478bd9Sstevel@tonic-gate #include <librestart_priv.h> 297c478bd9Sstevel@tonic-gate #include <libscf.h> 307c478bd9Sstevel@tonic-gate #include <libscf_priv.h> 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <assert.h> 337c478bd9Sstevel@tonic-gate #include <ctype.h> 347c478bd9Sstevel@tonic-gate #include <dlfcn.h> 357c478bd9Sstevel@tonic-gate #include <errno.h> 367c478bd9Sstevel@tonic-gate #include <exec_attr.h> 377c478bd9Sstevel@tonic-gate #include <grp.h> 387c478bd9Sstevel@tonic-gate #include <libsysevent.h> 397c478bd9Sstevel@tonic-gate #include <libuutil.h> 407c478bd9Sstevel@tonic-gate #include <limits.h> 417c478bd9Sstevel@tonic-gate #include <link.h> 427c478bd9Sstevel@tonic-gate #include <malloc.h> 437c478bd9Sstevel@tonic-gate #include <pool.h> 447c478bd9Sstevel@tonic-gate #include <priv.h> 457c478bd9Sstevel@tonic-gate #include <project.h> 467c478bd9Sstevel@tonic-gate #include <pthread.h> 477c478bd9Sstevel@tonic-gate #include <pwd.h> 487c478bd9Sstevel@tonic-gate #include <secdb.h> 497c478bd9Sstevel@tonic-gate #include <signal.h> 507c478bd9Sstevel@tonic-gate #include <stdlib.h> 517c478bd9Sstevel@tonic-gate #include <string.h> 527c478bd9Sstevel@tonic-gate #include <syslog.h> 537c478bd9Sstevel@tonic-gate #include <sys/corectl.h> 547c478bd9Sstevel@tonic-gate #include <sys/machelf.h> 557c478bd9Sstevel@tonic-gate #include <sys/task.h> 567c478bd9Sstevel@tonic-gate #include <sys/types.h> 577c478bd9Sstevel@tonic-gate #include <time.h> 587c478bd9Sstevel@tonic-gate #include <unistd.h> 597c478bd9Sstevel@tonic-gate #include <ucontext.h> 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate #define min(a, b) ((a) > (b) ? (b) : (a)) 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate #define MKW_TRUE ":true" 647c478bd9Sstevel@tonic-gate #define MKW_KILL ":kill" 657c478bd9Sstevel@tonic-gate #define MKW_KILL_PROC ":kill_process" 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate #define ALLOCFAIL ((char *)"Allocation failure.") 687c478bd9Sstevel@tonic-gate #define RCBROKEN ((char *)"Repository connection broken.") 697c478bd9Sstevel@tonic-gate 702c65c8b0Srm88369 #define MAX_COMMIT_RETRIES 10 717c478bd9Sstevel@tonic-gate #define MAX_COMMIT_RETRY_INT (5 * 1000000) /* 5 seconds */ 727c478bd9Sstevel@tonic-gate #define INITIAL_COMMIT_RETRY_INT (10000) /* 1/100th second */ 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate /* 757c478bd9Sstevel@tonic-gate * bad_fail() catches bugs in this and lower layers by reporting supposedly 767c478bd9Sstevel@tonic-gate * impossible function failures. The NDEBUG case keeps the strings out of the 777c478bd9Sstevel@tonic-gate * library but still calls abort() so we can root-cause from the coredump. 787c478bd9Sstevel@tonic-gate */ 797c478bd9Sstevel@tonic-gate #ifndef NDEBUG 807c478bd9Sstevel@tonic-gate #define bad_fail(func, err) { \ 817c478bd9Sstevel@tonic-gate (void) fprintf(stderr, \ 827c478bd9Sstevel@tonic-gate "At %s:%d, %s() failed with unexpected error %d. Aborting.\n", \ 837c478bd9Sstevel@tonic-gate __FILE__, __LINE__, (func), (err)); \ 847c478bd9Sstevel@tonic-gate abort(); \ 857c478bd9Sstevel@tonic-gate } 867c478bd9Sstevel@tonic-gate #else 877c478bd9Sstevel@tonic-gate #define bad_fail(func, err) abort() 887c478bd9Sstevel@tonic-gate #endif 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate struct restarter_event_handle { 917c478bd9Sstevel@tonic-gate char *reh_restarter_name; 927c478bd9Sstevel@tonic-gate char *reh_delegate_channel_name; 937c478bd9Sstevel@tonic-gate evchan_t *reh_delegate_channel; 947c478bd9Sstevel@tonic-gate char *reh_delegate_subscriber_id; 957c478bd9Sstevel@tonic-gate char *reh_master_channel_name; 967c478bd9Sstevel@tonic-gate evchan_t *reh_master_channel; 977c478bd9Sstevel@tonic-gate char *reh_master_subscriber_id; 987c478bd9Sstevel@tonic-gate int (*reh_handler)(restarter_event_t *); 997c478bd9Sstevel@tonic-gate }; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate struct restarter_event { 1027c478bd9Sstevel@tonic-gate sysevent_t *re_sysevent; 1037c478bd9Sstevel@tonic-gate restarter_event_type_t re_type; 1047c478bd9Sstevel@tonic-gate char *re_instance_name; 1057c478bd9Sstevel@tonic-gate restarter_event_handle_t *re_event_handle; 1067c478bd9Sstevel@tonic-gate restarter_instance_state_t re_state; 1077c478bd9Sstevel@tonic-gate restarter_instance_state_t re_next_state; 1087c478bd9Sstevel@tonic-gate }; 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate static const char * const allocfail = "Allocation failure.\n"; 1117c478bd9Sstevel@tonic-gate static const char * const rcbroken = "Repository connection broken.\n"; 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate static int method_context_safety = 0; /* Can safely call pools/projects. */ 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate int ndebug = 1; 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate static void 1187c478bd9Sstevel@tonic-gate free_restarter_event_handle(struct restarter_event_handle *h) 1197c478bd9Sstevel@tonic-gate { 1207c478bd9Sstevel@tonic-gate if (h == NULL) 1217c478bd9Sstevel@tonic-gate return; 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate /* 1247c478bd9Sstevel@tonic-gate * Just free the memory -- don't unbind the sysevent handle, 1257c478bd9Sstevel@tonic-gate * as otherwise events may be lost if this is just a restarter 1267c478bd9Sstevel@tonic-gate * restart. 1277c478bd9Sstevel@tonic-gate */ 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate if (h->reh_restarter_name != NULL) 1307c478bd9Sstevel@tonic-gate free(h->reh_restarter_name); 1317c478bd9Sstevel@tonic-gate if (h->reh_delegate_channel_name != NULL) 1327c478bd9Sstevel@tonic-gate free(h->reh_delegate_channel_name); 1337c478bd9Sstevel@tonic-gate if (h->reh_delegate_subscriber_id != NULL) 1347c478bd9Sstevel@tonic-gate free(h->reh_delegate_subscriber_id); 1357c478bd9Sstevel@tonic-gate if (h->reh_master_channel_name != NULL) 1367c478bd9Sstevel@tonic-gate free(h->reh_master_channel_name); 1377c478bd9Sstevel@tonic-gate if (h->reh_master_subscriber_id != NULL) 1387c478bd9Sstevel@tonic-gate free(h->reh_master_subscriber_id); 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate free(h); 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate char * 1447c478bd9Sstevel@tonic-gate _restarter_get_channel_name(const char *fmri, int type) 1457c478bd9Sstevel@tonic-gate { 146*13d8aaa1SSean Wilcox char *name; 1477c478bd9Sstevel@tonic-gate char *chan_name = malloc(MAX_CHNAME_LEN); 1487c478bd9Sstevel@tonic-gate char prefix_name[3]; 149*13d8aaa1SSean Wilcox int i; 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate if (chan_name == NULL) 1527c478bd9Sstevel@tonic-gate return (NULL); 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate if (type == RESTARTER_CHANNEL_DELEGATE) 1557c478bd9Sstevel@tonic-gate (void) strcpy(prefix_name, "d_"); 1567c478bd9Sstevel@tonic-gate else if (type == RESTARTER_CHANNEL_MASTER) 1577c478bd9Sstevel@tonic-gate (void) strcpy(prefix_name, "m_"); 1587c478bd9Sstevel@tonic-gate else { 1597c478bd9Sstevel@tonic-gate free(chan_name); 1607c478bd9Sstevel@tonic-gate return (NULL); 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate 163*13d8aaa1SSean Wilcox /* 164*13d8aaa1SSean Wilcox * Create a unique name 165*13d8aaa1SSean Wilcox * 166*13d8aaa1SSean Wilcox * Use the entire name, using a replacement of the / 167*13d8aaa1SSean Wilcox * characters to get a better name. 168*13d8aaa1SSean Wilcox * 169*13d8aaa1SSean Wilcox * Remove the svc:/ from the beginning as this really 170*13d8aaa1SSean Wilcox * isn't going to provide any uniqueness... 171*13d8aaa1SSean Wilcox * 172*13d8aaa1SSean Wilcox * An fmri name greater than MAX_CHNAME_LEN is going 173*13d8aaa1SSean Wilcox * to be rejected as too long for the chan_name below 174*13d8aaa1SSean Wilcox * in the snprintf call. 175*13d8aaa1SSean Wilcox */ 176*13d8aaa1SSean Wilcox if ((name = strdup(strchr(fmri, '/') + 1)) == NULL) { 177*13d8aaa1SSean Wilcox free(chan_name); 178*13d8aaa1SSean Wilcox return (NULL); 179*13d8aaa1SSean Wilcox } 180*13d8aaa1SSean Wilcox i = 0; 181*13d8aaa1SSean Wilcox while (name[i]) { 182*13d8aaa1SSean Wilcox if (name[i] == '/') { 183*13d8aaa1SSean Wilcox name[i] = '_'; 184*13d8aaa1SSean Wilcox } 185*13d8aaa1SSean Wilcox 186*13d8aaa1SSean Wilcox i++; 187*13d8aaa1SSean Wilcox } 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate /* 1907c478bd9Sstevel@tonic-gate * Should check for [a-z],[A-Z],[0-9],.,_,-,: 1917c478bd9Sstevel@tonic-gate */ 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate if (snprintf(chan_name, MAX_CHNAME_LEN, "com.sun:scf:%s%s", 1947c478bd9Sstevel@tonic-gate prefix_name, name) > MAX_CHNAME_LEN) { 1957c478bd9Sstevel@tonic-gate free(chan_name); 196*13d8aaa1SSean Wilcox chan_name = NULL; 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate 199*13d8aaa1SSean Wilcox free(name); 2007c478bd9Sstevel@tonic-gate return (chan_name); 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate int 2047c478bd9Sstevel@tonic-gate cb(sysevent_t *syse, void *cookie) 2057c478bd9Sstevel@tonic-gate { 2067c478bd9Sstevel@tonic-gate restarter_event_handle_t *h = (restarter_event_handle_t *)cookie; 2077c478bd9Sstevel@tonic-gate restarter_event_t *e; 2087c478bd9Sstevel@tonic-gate nvlist_t *attr_list = NULL; 2097c478bd9Sstevel@tonic-gate int ret = 0; 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate e = uu_zalloc(sizeof (restarter_event_t)); 2127c478bd9Sstevel@tonic-gate if (e == NULL) 2137c478bd9Sstevel@tonic-gate uu_die(allocfail); 2147c478bd9Sstevel@tonic-gate e->re_event_handle = h; 2157c478bd9Sstevel@tonic-gate e->re_sysevent = syse; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate if (sysevent_get_attr_list(syse, &attr_list) != 0) 2187c478bd9Sstevel@tonic-gate uu_die(allocfail); 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate if ((nvlist_lookup_uint32(attr_list, RESTARTER_NAME_TYPE, 2217c478bd9Sstevel@tonic-gate &(e->re_type)) != 0) || 2227c478bd9Sstevel@tonic-gate (nvlist_lookup_string(attr_list, 2237c478bd9Sstevel@tonic-gate RESTARTER_NAME_INSTANCE, &(e->re_instance_name)) != 0)) { 2247c478bd9Sstevel@tonic-gate uu_warn("%s: Can't decode nvlist for event %p\n", 2257c478bd9Sstevel@tonic-gate h->reh_restarter_name, (void *)syse); 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate ret = 0; 2287c478bd9Sstevel@tonic-gate } else { 2297c478bd9Sstevel@tonic-gate ret = h->reh_handler(e); 2307c478bd9Sstevel@tonic-gate } 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate uu_free(e); 2337c478bd9Sstevel@tonic-gate nvlist_free(attr_list); 2347c478bd9Sstevel@tonic-gate return (ret); 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate /* 2387c478bd9Sstevel@tonic-gate * restarter_bind_handle(uint32_t, char *, int (*)(restarter_event_t *), int, 2397c478bd9Sstevel@tonic-gate * restarter_event_handle_t **) 2407c478bd9Sstevel@tonic-gate * 2417c478bd9Sstevel@tonic-gate * Bind to a delegated restarter event channel. 2427c478bd9Sstevel@tonic-gate * Each delegated restarter gets its own channel for resource management. 2437c478bd9Sstevel@tonic-gate * 2447c478bd9Sstevel@tonic-gate * Returns 0 on success or 2457c478bd9Sstevel@tonic-gate * ENOTSUP version mismatch 2467c478bd9Sstevel@tonic-gate * EINVAL restarter_name or event_handle is NULL 2477c478bd9Sstevel@tonic-gate * ENOMEM out of memory, too many channels, or too many subscriptions 2487c478bd9Sstevel@tonic-gate * EBUSY sysevent_evc_bind() could not establish binding 2497c478bd9Sstevel@tonic-gate * EFAULT internal sysevent_evc_bind()/sysevent_evc_subscribe() error 2507c478bd9Sstevel@tonic-gate * EMFILE out of file descriptors 2517c478bd9Sstevel@tonic-gate * EPERM insufficient privilege for sysevent_evc_bind() 2527c478bd9Sstevel@tonic-gate * EEXIST already subscribed 2537c478bd9Sstevel@tonic-gate */ 2547c478bd9Sstevel@tonic-gate int 2557c478bd9Sstevel@tonic-gate restarter_bind_handle(uint32_t version, const char *restarter_name, 2567c478bd9Sstevel@tonic-gate int (*event_handler)(restarter_event_t *), int flags, 2577c478bd9Sstevel@tonic-gate restarter_event_handle_t **rehp) 2587c478bd9Sstevel@tonic-gate { 2597c478bd9Sstevel@tonic-gate restarter_event_handle_t *h; 2607c478bd9Sstevel@tonic-gate size_t sz; 2617c478bd9Sstevel@tonic-gate int err; 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate if (version != RESTARTER_EVENT_VERSION) 2647c478bd9Sstevel@tonic-gate return (ENOTSUP); 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate if (restarter_name == NULL || event_handler == NULL) 2677c478bd9Sstevel@tonic-gate return (EINVAL); 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate if (flags & RESTARTER_FLAG_DEBUG) 2707c478bd9Sstevel@tonic-gate ndebug++; 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate if ((h = uu_zalloc(sizeof (restarter_event_handle_t))) == NULL) 2737c478bd9Sstevel@tonic-gate return (ENOMEM); 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate h->reh_delegate_subscriber_id = malloc(MAX_SUBID_LEN); 2767c478bd9Sstevel@tonic-gate h->reh_master_subscriber_id = malloc(MAX_SUBID_LEN); 2777c478bd9Sstevel@tonic-gate h->reh_restarter_name = strdup(restarter_name); 2787c478bd9Sstevel@tonic-gate if (h->reh_delegate_subscriber_id == NULL || 2797c478bd9Sstevel@tonic-gate h->reh_master_subscriber_id == NULL || 2807c478bd9Sstevel@tonic-gate h->reh_restarter_name == NULL) { 2817c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 2827c478bd9Sstevel@tonic-gate return (ENOMEM); 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate sz = strlcpy(h->reh_delegate_subscriber_id, "del", MAX_SUBID_LEN); 2867c478bd9Sstevel@tonic-gate assert(sz < MAX_SUBID_LEN); 2877c478bd9Sstevel@tonic-gate sz = strlcpy(h->reh_master_subscriber_id, "master", MAX_SUBID_LEN); 2887c478bd9Sstevel@tonic-gate assert(sz < MAX_SUBID_LEN); 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate h->reh_delegate_channel_name = 2917c478bd9Sstevel@tonic-gate _restarter_get_channel_name(restarter_name, 2927c478bd9Sstevel@tonic-gate RESTARTER_CHANNEL_DELEGATE); 2937c478bd9Sstevel@tonic-gate h->reh_master_channel_name = 2947c478bd9Sstevel@tonic-gate _restarter_get_channel_name(restarter_name, 2957c478bd9Sstevel@tonic-gate RESTARTER_CHANNEL_MASTER); 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate if (h->reh_delegate_channel_name == NULL || 2987c478bd9Sstevel@tonic-gate h->reh_master_channel_name == NULL) { 2997c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 3007c478bd9Sstevel@tonic-gate return (ENOMEM); 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate if (sysevent_evc_bind(h->reh_delegate_channel_name, 3047c478bd9Sstevel@tonic-gate &h->reh_delegate_channel, EVCH_CREAT|EVCH_HOLD_PEND) != 0) { 3057c478bd9Sstevel@tonic-gate err = errno; 3067c478bd9Sstevel@tonic-gate assert(err != EINVAL); 3077c478bd9Sstevel@tonic-gate assert(err != ENOENT); 3087c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 3097c478bd9Sstevel@tonic-gate return (err); 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate if (sysevent_evc_bind(h->reh_master_channel_name, 3137c478bd9Sstevel@tonic-gate &h->reh_master_channel, EVCH_CREAT|EVCH_HOLD_PEND) != 0) { 3147c478bd9Sstevel@tonic-gate err = errno; 3157c478bd9Sstevel@tonic-gate assert(err != EINVAL); 3167c478bd9Sstevel@tonic-gate assert(err != ENOENT); 3177c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 3187c478bd9Sstevel@tonic-gate return (err); 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate h->reh_handler = event_handler; 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate assert(strlen(restarter_name) <= MAX_CLASS_LEN - 1); 3247c478bd9Sstevel@tonic-gate assert(strlen(h->reh_delegate_subscriber_id) <= MAX_SUBID_LEN - 1); 3257c478bd9Sstevel@tonic-gate assert(strlen(h->reh_master_subscriber_id) <= MAX_SUBID_LEN - 1); 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate if (sysevent_evc_subscribe(h->reh_delegate_channel, 3287c478bd9Sstevel@tonic-gate h->reh_delegate_subscriber_id, EC_ALL, cb, h, EVCH_SUB_KEEP) != 0) { 3297c478bd9Sstevel@tonic-gate err = errno; 3307c478bd9Sstevel@tonic-gate assert(err != EINVAL); 3317c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 3327c478bd9Sstevel@tonic-gate return (err); 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate *rehp = h; 3367c478bd9Sstevel@tonic-gate return (0); 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate restarter_event_handle_t * 3407c478bd9Sstevel@tonic-gate restarter_event_get_handle(restarter_event_t *e) 3417c478bd9Sstevel@tonic-gate { 3427c478bd9Sstevel@tonic-gate assert(e != NULL && e->re_event_handle != NULL); 3437c478bd9Sstevel@tonic-gate return (e->re_event_handle); 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate restarter_event_type_t 3477c478bd9Sstevel@tonic-gate restarter_event_get_type(restarter_event_t *e) 3487c478bd9Sstevel@tonic-gate { 3497c478bd9Sstevel@tonic-gate assert(e != NULL); 3507c478bd9Sstevel@tonic-gate return (e->re_type); 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate ssize_t 3547c478bd9Sstevel@tonic-gate restarter_event_get_instance(restarter_event_t *e, char *inst, size_t sz) 3557c478bd9Sstevel@tonic-gate { 3567c478bd9Sstevel@tonic-gate assert(e != NULL && inst != NULL); 3577c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(inst, e->re_instance_name, sz)); 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate int 3617c478bd9Sstevel@tonic-gate restarter_event_get_current_states(restarter_event_t *e, 3627c478bd9Sstevel@tonic-gate restarter_instance_state_t *state, restarter_instance_state_t *next_state) 3637c478bd9Sstevel@tonic-gate { 3647c478bd9Sstevel@tonic-gate if (e == NULL) 3657c478bd9Sstevel@tonic-gate return (-1); 3667c478bd9Sstevel@tonic-gate *state = e->re_state; 3677c478bd9Sstevel@tonic-gate *next_state = e->re_next_state; 3687c478bd9Sstevel@tonic-gate return (0); 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate /* 3722c65c8b0Srm88369 * restarter_event_publish_retry() is a wrapper around sysevent_evc_publish(). 3732c65c8b0Srm88369 * In case, the event cannot be sent at the first attempt (sysevent_evc_publish 3742c65c8b0Srm88369 * returned EAGAIN - sysevent queue full), this function retries a few time 3752c65c8b0Srm88369 * and return ENOSPC if it reaches the retry limit. 3762c65c8b0Srm88369 * 3772c65c8b0Srm88369 * The arguments to this function map the arguments of sysevent_evc_publish(). 3782c65c8b0Srm88369 * 3792c65c8b0Srm88369 * On success, return 0. On error, return 3802c65c8b0Srm88369 * 3812c65c8b0Srm88369 * EFAULT - internal sysevent_evc_publish() error 3822c65c8b0Srm88369 * ENOMEM - internal sysevent_evc_publish() error 3832c65c8b0Srm88369 * EBADF - scp is invalid (sysevent_evc_publish() returned EINVAL) 3842c65c8b0Srm88369 * ENOSPC - sysevent queue full (sysevent_evc_publish() returned EAGAIN) 3852c65c8b0Srm88369 */ 3862c65c8b0Srm88369 int 3872c65c8b0Srm88369 restarter_event_publish_retry(evchan_t *scp, const char *class, 3882c65c8b0Srm88369 const char *subclass, const char *vendor, const char *pub_name, 3892c65c8b0Srm88369 nvlist_t *attr_list, uint32_t flags) 3902c65c8b0Srm88369 { 3912c65c8b0Srm88369 int retries, ret; 3922c65c8b0Srm88369 useconds_t retry_int = INITIAL_COMMIT_RETRY_INT; 3932c65c8b0Srm88369 3942c65c8b0Srm88369 for (retries = 0; retries < MAX_COMMIT_RETRIES; retries++) { 3952c65c8b0Srm88369 ret = sysevent_evc_publish(scp, class, subclass, vendor, 3962c65c8b0Srm88369 pub_name, attr_list, flags); 3972c65c8b0Srm88369 if (ret == 0) 3982c65c8b0Srm88369 break; 3992c65c8b0Srm88369 4002c65c8b0Srm88369 switch (ret) { 4012c65c8b0Srm88369 case EAGAIN: 4022c65c8b0Srm88369 /* Queue is full */ 4032c65c8b0Srm88369 (void) usleep(retry_int); 4042c65c8b0Srm88369 4052c65c8b0Srm88369 retry_int = min(retry_int * 2, MAX_COMMIT_RETRY_INT); 4062c65c8b0Srm88369 break; 4072c65c8b0Srm88369 4082c65c8b0Srm88369 case EINVAL: 4092c65c8b0Srm88369 ret = EBADF; 4102c65c8b0Srm88369 /* FALLTHROUGH */ 4112c65c8b0Srm88369 4122c65c8b0Srm88369 case EFAULT: 4132c65c8b0Srm88369 case ENOMEM: 4142c65c8b0Srm88369 return (ret); 4152c65c8b0Srm88369 4162c65c8b0Srm88369 case EOVERFLOW: 4172c65c8b0Srm88369 default: 4182c65c8b0Srm88369 /* internal error - abort */ 4192c65c8b0Srm88369 bad_fail("sysevent_evc_publish", ret); 4202c65c8b0Srm88369 } 4212c65c8b0Srm88369 } 4222c65c8b0Srm88369 4232c65c8b0Srm88369 if (retries == MAX_COMMIT_RETRIES) 4242c65c8b0Srm88369 ret = ENOSPC; 4252c65c8b0Srm88369 4262c65c8b0Srm88369 return (ret); 4272c65c8b0Srm88369 } 4282c65c8b0Srm88369 4292c65c8b0Srm88369 /* 4307c478bd9Sstevel@tonic-gate * Commit the state, next state, and auxiliary state into the repository. 4317c478bd9Sstevel@tonic-gate * Let the graph engine know about the state change and error. On success, 4327c478bd9Sstevel@tonic-gate * return 0. On error, return 4337c478bd9Sstevel@tonic-gate * EINVAL - aux has spaces 4347c478bd9Sstevel@tonic-gate * - inst is invalid or not an instance FMRI 4357c478bd9Sstevel@tonic-gate * EPROTO - librestart compiled against different libscf 4367c478bd9Sstevel@tonic-gate * ENOMEM - out of memory 4377c478bd9Sstevel@tonic-gate * - repository server out of resources 4387c478bd9Sstevel@tonic-gate * ENOTACTIVE - repository server not running 4397c478bd9Sstevel@tonic-gate * ECONNABORTED - repository connection established, but then broken 4407c478bd9Sstevel@tonic-gate * - unknown libscf error 4417c478bd9Sstevel@tonic-gate * ENOENT - inst does not exist in the repository 4427c478bd9Sstevel@tonic-gate * EPERM - insufficient permissions 4437c478bd9Sstevel@tonic-gate * EACCESS - backend access denied 4447c478bd9Sstevel@tonic-gate * EROFS - backend is readonly 4457c478bd9Sstevel@tonic-gate * EFAULT - internal sysevent_evc_publish() error 4467c478bd9Sstevel@tonic-gate * EBADF - h is invalid (sysevent_evc_publish() returned EINVAL) 4472c65c8b0Srm88369 * ENOSPC - sysevent queue full (sysevent_evc_publish() returned EAGAIN) 4487c478bd9Sstevel@tonic-gate */ 4497c478bd9Sstevel@tonic-gate int 4507c478bd9Sstevel@tonic-gate restarter_set_states(restarter_event_handle_t *h, const char *inst, 4517c478bd9Sstevel@tonic-gate restarter_instance_state_t cur_state, 4527c478bd9Sstevel@tonic-gate restarter_instance_state_t new_cur_state, 4537c478bd9Sstevel@tonic-gate restarter_instance_state_t next_state, 4547c478bd9Sstevel@tonic-gate restarter_instance_state_t new_next_state, restarter_error_t e, 4557c478bd9Sstevel@tonic-gate const char *aux) 4567c478bd9Sstevel@tonic-gate { 4577c478bd9Sstevel@tonic-gate nvlist_t *attr; 4587c478bd9Sstevel@tonic-gate scf_handle_t *scf_h; 4597c478bd9Sstevel@tonic-gate instance_data_t id; 4607c478bd9Sstevel@tonic-gate int ret = 0; 4617c478bd9Sstevel@tonic-gate char *p = (char *)aux; 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate assert(h->reh_master_channel != NULL); 4647c478bd9Sstevel@tonic-gate assert(h->reh_master_channel_name != NULL); 4657c478bd9Sstevel@tonic-gate assert(h->reh_master_subscriber_id != NULL); 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate /* Validate format of auxiliary state: no spaces allowed */ 468ba91983eSlianep if (p != NULL) { 469ba91983eSlianep while (*p != '\0') { 4707c478bd9Sstevel@tonic-gate if (isspace(*p)) 4717c478bd9Sstevel@tonic-gate return (EINVAL); 4727c478bd9Sstevel@tonic-gate p++; 4737c478bd9Sstevel@tonic-gate } 474ba91983eSlianep } 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate if ((scf_h = scf_handle_create(SCF_VERSION)) == NULL) { 4777c478bd9Sstevel@tonic-gate switch (scf_error()) { 4787c478bd9Sstevel@tonic-gate case SCF_ERROR_VERSION_MISMATCH: 4797c478bd9Sstevel@tonic-gate return (EPROTO); 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate case SCF_ERROR_NO_MEMORY: 4827c478bd9Sstevel@tonic-gate return (ENOMEM); 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate default: 4857c478bd9Sstevel@tonic-gate bad_fail("scf_handle_create", scf_error()); 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate if (scf_handle_bind(scf_h) == -1) { 4907c478bd9Sstevel@tonic-gate scf_handle_destroy(scf_h); 4917c478bd9Sstevel@tonic-gate switch (scf_error()) { 4927c478bd9Sstevel@tonic-gate case SCF_ERROR_NO_SERVER: 4937c478bd9Sstevel@tonic-gate return (ENOTACTIVE); 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate case SCF_ERROR_NO_RESOURCES: 4967c478bd9Sstevel@tonic-gate return (ENOMEM); 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 4997c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 5007c478bd9Sstevel@tonic-gate default: 5017c478bd9Sstevel@tonic-gate bad_fail("scf_handle_bind", scf_error()); 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate if (nvlist_alloc(&attr, NV_UNIQUE_NAME, 0) != 0 || 5067c478bd9Sstevel@tonic-gate nvlist_add_int32(attr, RESTARTER_NAME_STATE, new_cur_state) != 0 || 5077c478bd9Sstevel@tonic-gate nvlist_add_int32(attr, RESTARTER_NAME_NEXT_STATE, new_next_state) 5087c478bd9Sstevel@tonic-gate != 0 || 5097c478bd9Sstevel@tonic-gate nvlist_add_int32(attr, RESTARTER_NAME_ERROR, e) != 0 || 5107c478bd9Sstevel@tonic-gate nvlist_add_string(attr, RESTARTER_NAME_INSTANCE, inst) != 0) { 5117c478bd9Sstevel@tonic-gate ret = ENOMEM; 5122c65c8b0Srm88369 } else { 5137c478bd9Sstevel@tonic-gate id.i_fmri = inst; 5147c478bd9Sstevel@tonic-gate id.i_state = cur_state; 5157c478bd9Sstevel@tonic-gate id.i_next_state = next_state; 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate ret = _restarter_commit_states(scf_h, &id, new_cur_state, 5187c478bd9Sstevel@tonic-gate new_next_state, aux); 5197c478bd9Sstevel@tonic-gate 5202c65c8b0Srm88369 if (ret == 0) { 5212c65c8b0Srm88369 ret = restarter_event_publish_retry( 5222c65c8b0Srm88369 h->reh_master_channel, "master", "state_change", 5232c65c8b0Srm88369 "com.sun", "librestart", attr, EVCH_NOSLEEP); 5247c478bd9Sstevel@tonic-gate } 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate nvlist_free(attr); 5287c478bd9Sstevel@tonic-gate (void) scf_handle_unbind(scf_h); 5297c478bd9Sstevel@tonic-gate scf_handle_destroy(scf_h); 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate return (ret); 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate restarter_instance_state_t 5357c478bd9Sstevel@tonic-gate restarter_string_to_state(char *string) 5367c478bd9Sstevel@tonic-gate { 5377c478bd9Sstevel@tonic-gate assert(string != NULL); 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate if (strcmp(string, SCF_STATE_STRING_NONE) == 0) 5407c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_NONE); 5417c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_UNINIT) == 0) 5427c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_UNINIT); 5437c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_MAINT) == 0) 5447c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_MAINT); 5457c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_OFFLINE) == 0) 5467c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_OFFLINE); 5477c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_DISABLED) == 0) 5487c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_DISABLED); 5497c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_ONLINE) == 0) 5507c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_ONLINE); 5517c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_DEGRADED) == 0) 5527c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_DEGRADED); 5537c478bd9Sstevel@tonic-gate else { 5547c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_NONE); 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate ssize_t 5597c478bd9Sstevel@tonic-gate restarter_state_to_string(restarter_instance_state_t state, char *string, 5607c478bd9Sstevel@tonic-gate size_t len) 5617c478bd9Sstevel@tonic-gate { 5627c478bd9Sstevel@tonic-gate assert(string != NULL); 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate if (state == RESTARTER_STATE_NONE) 5657c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_NONE, len)); 5667c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_UNINIT) 5677c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_UNINIT, len)); 5687c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_MAINT) 5697c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_MAINT, len)); 5707c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_OFFLINE) 5717c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_OFFLINE, 5727c478bd9Sstevel@tonic-gate len)); 5737c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_DISABLED) 5747c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_DISABLED, 5757c478bd9Sstevel@tonic-gate len)); 5767c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_ONLINE) 5777c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_ONLINE, len)); 5787c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_DEGRADED) 5797c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_DEGRADED, 5807c478bd9Sstevel@tonic-gate len)); 5817c478bd9Sstevel@tonic-gate else 5827c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, "unknown", len)); 5837c478bd9Sstevel@tonic-gate } 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate /* 5867c478bd9Sstevel@tonic-gate * Sets pg to the name property group of s_inst. If it doesn't exist, it is 5877c478bd9Sstevel@tonic-gate * added. 5887c478bd9Sstevel@tonic-gate * 5897c478bd9Sstevel@tonic-gate * Fails with 5907c478bd9Sstevel@tonic-gate * ECONNABORTED - repository disconnection or unknown libscf error 5917c478bd9Sstevel@tonic-gate * EBADF - inst is not set 5927c478bd9Sstevel@tonic-gate * ECANCELED - inst is deleted 5937c478bd9Sstevel@tonic-gate * EPERM - permission is denied 5947c478bd9Sstevel@tonic-gate * EACCES - backend denied access 5957c478bd9Sstevel@tonic-gate * EROFS - backend readonly 5967c478bd9Sstevel@tonic-gate */ 5977c478bd9Sstevel@tonic-gate static int 5987c478bd9Sstevel@tonic-gate instance_get_or_add_pg(scf_instance_t *inst, const char *name, 5997c478bd9Sstevel@tonic-gate const char *type, uint32_t flags, scf_propertygroup_t *pg) 6007c478bd9Sstevel@tonic-gate { 6017c478bd9Sstevel@tonic-gate again: 6027c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, name, pg) == 0) 6037c478bd9Sstevel@tonic-gate return (0); 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate switch (scf_error()) { 6067c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 6077c478bd9Sstevel@tonic-gate default: 6087c478bd9Sstevel@tonic-gate return (ECONNABORTED); 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 6117c478bd9Sstevel@tonic-gate return (EBADF); 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 6147c478bd9Sstevel@tonic-gate return (ECANCELED); 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 6177c478bd9Sstevel@tonic-gate break; 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 6207c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 6217c478bd9Sstevel@tonic-gate bad_fail("scf_instance_get_pg", scf_error()); 6227c478bd9Sstevel@tonic-gate } 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate if (scf_instance_add_pg(inst, name, type, flags, pg) == 0) 6257c478bd9Sstevel@tonic-gate return (0); 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate switch (scf_error()) { 6287c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 6297c478bd9Sstevel@tonic-gate default: 6307c478bd9Sstevel@tonic-gate return (ECONNABORTED); 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 6337c478bd9Sstevel@tonic-gate return (ECANCELED); 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 6367c478bd9Sstevel@tonic-gate goto again; 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 6397c478bd9Sstevel@tonic-gate return (EPERM); 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 6427c478bd9Sstevel@tonic-gate return (EACCES); 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 6457c478bd9Sstevel@tonic-gate return (EROFS); 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 6487c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 6497c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: /* should be caught above */ 6507c478bd9Sstevel@tonic-gate bad_fail("scf_instance_add_pg", scf_error()); 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate return (0); 6547c478bd9Sstevel@tonic-gate } 6557c478bd9Sstevel@tonic-gate 6567c478bd9Sstevel@tonic-gate /* 6577c478bd9Sstevel@tonic-gate * Fails with 6587c478bd9Sstevel@tonic-gate * ECONNABORTED 6597c478bd9Sstevel@tonic-gate * ECANCELED - pg was deleted 6607c478bd9Sstevel@tonic-gate */ 6617c478bd9Sstevel@tonic-gate static int 6627c478bd9Sstevel@tonic-gate tx_set_value(scf_transaction_t *tx, scf_transaction_entry_t *ent, 6637c478bd9Sstevel@tonic-gate const char *pname, scf_type_t ty, scf_value_t *val) 6647c478bd9Sstevel@tonic-gate { 6657c478bd9Sstevel@tonic-gate int r; 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate for (;;) { 6687c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(tx, ent, pname, 6697c478bd9Sstevel@tonic-gate ty) == 0) 6707c478bd9Sstevel@tonic-gate break; 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate switch (scf_error()) { 6737c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 6747c478bd9Sstevel@tonic-gate default: 6757c478bd9Sstevel@tonic-gate return (ECONNABORTED); 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 6787c478bd9Sstevel@tonic-gate return (ECANCELED); 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 6817c478bd9Sstevel@tonic-gate break; 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 6847c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 6857c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 6867c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 6877c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_change_type", 6887c478bd9Sstevel@tonic-gate scf_error()); 6897c478bd9Sstevel@tonic-gate } 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(tx, ent, pname, ty) == 0) 6927c478bd9Sstevel@tonic-gate break; 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate switch (scf_error()) { 6957c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 6967c478bd9Sstevel@tonic-gate default: 6977c478bd9Sstevel@tonic-gate return (ECONNABORTED); 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 7007c478bd9Sstevel@tonic-gate return (ECANCELED); 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 7037c478bd9Sstevel@tonic-gate break; 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 7067c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 7077c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 7087c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 7097c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_new", scf_error()); 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate r = scf_entry_add_value(ent, val); 7147c478bd9Sstevel@tonic-gate assert(r == 0); 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate return (0); 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate /* 7207c478bd9Sstevel@tonic-gate * Commit new_state, new_next_state, and aux to the repository for id. If 7217c478bd9Sstevel@tonic-gate * successful, also set id's state and next-state as given, and return 0. 7227c478bd9Sstevel@tonic-gate * Fails with 7237c478bd9Sstevel@tonic-gate * ENOMEM - out of memory 7247c478bd9Sstevel@tonic-gate * ECONNABORTED - repository connection broken 7257c478bd9Sstevel@tonic-gate * - unknown libscf error 7267c478bd9Sstevel@tonic-gate * EINVAL - id->i_fmri is invalid or not an instance FMRI 7277c478bd9Sstevel@tonic-gate * ENOENT - id->i_fmri does not exist 7287c478bd9Sstevel@tonic-gate * EPERM - insufficient permissions 7297c478bd9Sstevel@tonic-gate * EACCES - backend access denied 7307c478bd9Sstevel@tonic-gate * EROFS - backend is readonly 7317c478bd9Sstevel@tonic-gate */ 7327c478bd9Sstevel@tonic-gate int 7337c478bd9Sstevel@tonic-gate _restarter_commit_states(scf_handle_t *h, instance_data_t *id, 7347c478bd9Sstevel@tonic-gate restarter_instance_state_t new_state, 7357c478bd9Sstevel@tonic-gate restarter_instance_state_t new_state_next, const char *aux) 7367c478bd9Sstevel@tonic-gate { 7377c478bd9Sstevel@tonic-gate char str_state[MAX_SCF_STATE_STRING_SZ]; 7387c478bd9Sstevel@tonic-gate char str_new_state[MAX_SCF_STATE_STRING_SZ]; 7397c478bd9Sstevel@tonic-gate char str_state_next[MAX_SCF_STATE_STRING_SZ]; 7407c478bd9Sstevel@tonic-gate char str_new_state_next[MAX_SCF_STATE_STRING_SZ]; 7417c478bd9Sstevel@tonic-gate int ret = 0, r; 7427c478bd9Sstevel@tonic-gate struct timeval now; 7437c478bd9Sstevel@tonic-gate ssize_t sz; 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate scf_transaction_t *t = NULL; 7467c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_state = NULL, *t_state_next = NULL; 7477c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_stime = NULL, *t_aux = NULL; 7487c478bd9Sstevel@tonic-gate scf_value_t *v_state = NULL, *v_state_next = NULL, *v_stime = NULL; 7497c478bd9Sstevel@tonic-gate scf_value_t *v_aux = NULL; 7507c478bd9Sstevel@tonic-gate scf_instance_t *s_inst = NULL; 7517c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 7527c478bd9Sstevel@tonic-gate 7537c478bd9Sstevel@tonic-gate assert(new_state != RESTARTER_STATE_NONE); 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate if ((s_inst = scf_instance_create(h)) == NULL || 7567c478bd9Sstevel@tonic-gate (pg = scf_pg_create(h)) == NULL || 7577c478bd9Sstevel@tonic-gate (t = scf_transaction_create(h)) == NULL || 7587c478bd9Sstevel@tonic-gate (t_state = scf_entry_create(h)) == NULL || 7597c478bd9Sstevel@tonic-gate (t_state_next = scf_entry_create(h)) == NULL || 7607c478bd9Sstevel@tonic-gate (t_stime = scf_entry_create(h)) == NULL || 7617c478bd9Sstevel@tonic-gate (t_aux = scf_entry_create(h)) == NULL || 7627c478bd9Sstevel@tonic-gate (v_state = scf_value_create(h)) == NULL || 7637c478bd9Sstevel@tonic-gate (v_state_next = scf_value_create(h)) == NULL || 7647c478bd9Sstevel@tonic-gate (v_stime = scf_value_create(h)) == NULL || 7657c478bd9Sstevel@tonic-gate (v_aux = scf_value_create(h)) == NULL) { 7667c478bd9Sstevel@tonic-gate ret = ENOMEM; 7677c478bd9Sstevel@tonic-gate goto out; 7687c478bd9Sstevel@tonic-gate } 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(new_state, str_new_state, 7717c478bd9Sstevel@tonic-gate sizeof (str_new_state)); 7727c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_new_state)); 7737c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(new_state_next, str_new_state_next, 7747c478bd9Sstevel@tonic-gate sizeof (str_new_state_next)); 7757c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_new_state_next)); 7767c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(id->i_state, str_state, 7777c478bd9Sstevel@tonic-gate sizeof (str_state)); 7787c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_state)); 7797c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(id->i_next_state, str_state_next, 7807c478bd9Sstevel@tonic-gate sizeof (str_state_next)); 7817c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_state_next)); 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate ret = gettimeofday(&now, NULL); 7847c478bd9Sstevel@tonic-gate assert(ret != -1); 7857c478bd9Sstevel@tonic-gate 7867c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, id->i_fmri, NULL, NULL, s_inst, 7877c478bd9Sstevel@tonic-gate NULL, NULL, SCF_DECODE_FMRI_EXACT) == -1) { 7887c478bd9Sstevel@tonic-gate switch (scf_error()) { 7897c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 7907c478bd9Sstevel@tonic-gate default: 7917c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 7927c478bd9Sstevel@tonic-gate break; 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 7957c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 7967c478bd9Sstevel@tonic-gate ret = EINVAL; 7977c478bd9Sstevel@tonic-gate break; 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 8007c478bd9Sstevel@tonic-gate ret = ENOENT; 8017c478bd9Sstevel@tonic-gate break; 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 8047c478bd9Sstevel@tonic-gate bad_fail("scf_handle_decode_fmri", scf_error()); 8057c478bd9Sstevel@tonic-gate } 8067c478bd9Sstevel@tonic-gate goto out; 8077c478bd9Sstevel@tonic-gate } 8087c478bd9Sstevel@tonic-gate 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate if (scf_value_set_astring(v_state, str_new_state) != 0 || 811eb1a3463STruong Nguyen scf_value_set_astring(v_state_next, str_new_state_next) != 0) 8127c478bd9Sstevel@tonic-gate bad_fail("scf_value_set_astring", scf_error()); 8137c478bd9Sstevel@tonic-gate 814eb1a3463STruong Nguyen if (aux) { 815eb1a3463STruong Nguyen if (scf_value_set_astring(v_aux, aux) != 0) 816eb1a3463STruong Nguyen bad_fail("scf_value_set_astring", scf_error()); 817eb1a3463STruong Nguyen } 818eb1a3463STruong Nguyen 8197c478bd9Sstevel@tonic-gate if (scf_value_set_time(v_stime, now.tv_sec, now.tv_usec * 1000) != 0) 8207c478bd9Sstevel@tonic-gate bad_fail("scf_value_set_time", scf_error()); 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate add_pg: 8237c478bd9Sstevel@tonic-gate switch (r = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER, 8247c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg)) { 8257c478bd9Sstevel@tonic-gate case 0: 8267c478bd9Sstevel@tonic-gate break; 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate case ECONNABORTED: 8297c478bd9Sstevel@tonic-gate case EPERM: 8307c478bd9Sstevel@tonic-gate case EACCES: 8317c478bd9Sstevel@tonic-gate case EROFS: 8327c478bd9Sstevel@tonic-gate ret = r; 8337c478bd9Sstevel@tonic-gate goto out; 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate case ECANCELED: 8367c478bd9Sstevel@tonic-gate ret = ENOENT; 8377c478bd9Sstevel@tonic-gate goto out; 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate case EBADF: 8407c478bd9Sstevel@tonic-gate default: 8417c478bd9Sstevel@tonic-gate bad_fail("instance_get_or_add_pg", r); 8427c478bd9Sstevel@tonic-gate } 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate for (;;) { 8457c478bd9Sstevel@tonic-gate if (scf_transaction_start(t, pg) != 0) { 8467c478bd9Sstevel@tonic-gate switch (scf_error()) { 8477c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 8487c478bd9Sstevel@tonic-gate default: 8497c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 8507c478bd9Sstevel@tonic-gate goto out; 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 8537c478bd9Sstevel@tonic-gate goto add_pg; 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 8567c478bd9Sstevel@tonic-gate ret = EPERM; 8577c478bd9Sstevel@tonic-gate goto out; 8587c478bd9Sstevel@tonic-gate 8597c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 8607c478bd9Sstevel@tonic-gate ret = EACCES; 8617c478bd9Sstevel@tonic-gate goto out; 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 8647c478bd9Sstevel@tonic-gate ret = EROFS; 8657c478bd9Sstevel@tonic-gate goto out; 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 8687c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 8697c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_start", scf_error()); 8707c478bd9Sstevel@tonic-gate } 8717c478bd9Sstevel@tonic-gate } 8727c478bd9Sstevel@tonic-gate 8737c478bd9Sstevel@tonic-gate if ((r = tx_set_value(t, t_state, SCF_PROPERTY_STATE, 8747c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, v_state)) != 0 || 8757c478bd9Sstevel@tonic-gate (r = tx_set_value(t, t_state_next, SCF_PROPERTY_NEXT_STATE, 8767c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, v_state_next)) != 0 || 8777c478bd9Sstevel@tonic-gate (r = tx_set_value(t, t_stime, SCF_PROPERTY_STATE_TIMESTAMP, 8787c478bd9Sstevel@tonic-gate SCF_TYPE_TIME, v_stime)) != 0) { 8797c478bd9Sstevel@tonic-gate switch (r) { 8807c478bd9Sstevel@tonic-gate case ECONNABORTED: 8817c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 8827c478bd9Sstevel@tonic-gate goto out; 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate case ECANCELED: 8857c478bd9Sstevel@tonic-gate scf_transaction_reset(t); 8867c478bd9Sstevel@tonic-gate goto add_pg; 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate default: 8897c478bd9Sstevel@tonic-gate bad_fail("tx_set_value", r); 8907c478bd9Sstevel@tonic-gate } 8917c478bd9Sstevel@tonic-gate } 8927c478bd9Sstevel@tonic-gate 893eb1a3463STruong Nguyen if (aux) { 894eb1a3463STruong Nguyen if ((r = tx_set_value(t, t_aux, SCF_PROPERTY_AUX_STATE, 895eb1a3463STruong Nguyen SCF_TYPE_ASTRING, v_aux)) != 0) { 896eb1a3463STruong Nguyen switch (r) { 897eb1a3463STruong Nguyen case ECONNABORTED: 898eb1a3463STruong Nguyen ret = ECONNABORTED; 899eb1a3463STruong Nguyen goto out; 900eb1a3463STruong Nguyen 901eb1a3463STruong Nguyen case ECANCELED: 902eb1a3463STruong Nguyen scf_transaction_reset(t); 903eb1a3463STruong Nguyen goto add_pg; 904eb1a3463STruong Nguyen 905eb1a3463STruong Nguyen default: 906eb1a3463STruong Nguyen bad_fail("tx_set_value", r); 907eb1a3463STruong Nguyen } 908eb1a3463STruong Nguyen } 909eb1a3463STruong Nguyen } 910eb1a3463STruong Nguyen 9117c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(t); 9127c478bd9Sstevel@tonic-gate if (ret == 1) 9137c478bd9Sstevel@tonic-gate break; 9147c478bd9Sstevel@tonic-gate if (ret == -1) { 9157c478bd9Sstevel@tonic-gate switch (scf_error()) { 9167c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 9177c478bd9Sstevel@tonic-gate default: 9187c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 9197c478bd9Sstevel@tonic-gate goto out; 9207c478bd9Sstevel@tonic-gate 9217c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 9227c478bd9Sstevel@tonic-gate ret = EPERM; 9237c478bd9Sstevel@tonic-gate goto out; 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 9267c478bd9Sstevel@tonic-gate ret = EACCES; 9277c478bd9Sstevel@tonic-gate goto out; 9287c478bd9Sstevel@tonic-gate 9297c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 9307c478bd9Sstevel@tonic-gate ret = EROFS; 9317c478bd9Sstevel@tonic-gate goto out; 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 9347c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_commit", scf_error()); 9357c478bd9Sstevel@tonic-gate } 9367c478bd9Sstevel@tonic-gate } 9377c478bd9Sstevel@tonic-gate 9387c478bd9Sstevel@tonic-gate scf_transaction_reset(t); 9397c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 9407c478bd9Sstevel@tonic-gate switch (scf_error()) { 9417c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 9427c478bd9Sstevel@tonic-gate default: 9437c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 9447c478bd9Sstevel@tonic-gate goto out; 9457c478bd9Sstevel@tonic-gate 9467c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 9477c478bd9Sstevel@tonic-gate goto add_pg; 9487c478bd9Sstevel@tonic-gate } 9497c478bd9Sstevel@tonic-gate } 9507c478bd9Sstevel@tonic-gate } 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate id->i_state = new_state; 9537c478bd9Sstevel@tonic-gate id->i_next_state = new_state_next; 9547c478bd9Sstevel@tonic-gate ret = 0; 9557c478bd9Sstevel@tonic-gate 9567c478bd9Sstevel@tonic-gate out: 9577c478bd9Sstevel@tonic-gate scf_transaction_destroy(t); 9587c478bd9Sstevel@tonic-gate scf_entry_destroy(t_state); 9597c478bd9Sstevel@tonic-gate scf_entry_destroy(t_state_next); 9607c478bd9Sstevel@tonic-gate scf_entry_destroy(t_stime); 9617c478bd9Sstevel@tonic-gate scf_entry_destroy(t_aux); 9627c478bd9Sstevel@tonic-gate scf_value_destroy(v_state); 9637c478bd9Sstevel@tonic-gate scf_value_destroy(v_state_next); 9647c478bd9Sstevel@tonic-gate scf_value_destroy(v_stime); 9657c478bd9Sstevel@tonic-gate scf_value_destroy(v_aux); 9667c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 9677c478bd9Sstevel@tonic-gate scf_instance_destroy(s_inst); 9687c478bd9Sstevel@tonic-gate 9697c478bd9Sstevel@tonic-gate return (ret); 9707c478bd9Sstevel@tonic-gate } 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate /* 9737c478bd9Sstevel@tonic-gate * Fails with 9747c478bd9Sstevel@tonic-gate * EINVAL - type is invalid 9757c478bd9Sstevel@tonic-gate * ENOMEM 9767c478bd9Sstevel@tonic-gate * ECONNABORTED - repository connection broken 9777c478bd9Sstevel@tonic-gate * EBADF - s_inst is not set 9787c478bd9Sstevel@tonic-gate * ECANCELED - s_inst is deleted 9797c478bd9Sstevel@tonic-gate * EPERM - permission denied 9807c478bd9Sstevel@tonic-gate * EACCES - backend access denied 9817c478bd9Sstevel@tonic-gate * EROFS - backend readonly 9827c478bd9Sstevel@tonic-gate */ 9837c478bd9Sstevel@tonic-gate int 9847c478bd9Sstevel@tonic-gate restarter_remove_contract(scf_instance_t *s_inst, ctid_t contract_id, 9857c478bd9Sstevel@tonic-gate restarter_contract_type_t type) 9867c478bd9Sstevel@tonic-gate { 9877c478bd9Sstevel@tonic-gate scf_handle_t *h; 9887c478bd9Sstevel@tonic-gate scf_transaction_t *t = NULL; 9897c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_cid = NULL; 9907c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 9917c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL; 9927c478bd9Sstevel@tonic-gate scf_value_t *val; 9937c478bd9Sstevel@tonic-gate scf_iter_t *iter = NULL; 9947c478bd9Sstevel@tonic-gate const char *pname; 9957c478bd9Sstevel@tonic-gate int ret = 0, primary; 9967c478bd9Sstevel@tonic-gate uint64_t c; 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate switch (type) { 9997c478bd9Sstevel@tonic-gate case RESTARTER_CONTRACT_PRIMARY: 10007c478bd9Sstevel@tonic-gate primary = 1; 10017c478bd9Sstevel@tonic-gate break; 10027c478bd9Sstevel@tonic-gate case RESTARTER_CONTRACT_TRANSIENT: 10037c478bd9Sstevel@tonic-gate primary = 0; 10047c478bd9Sstevel@tonic-gate break; 10057c478bd9Sstevel@tonic-gate default: 10067c478bd9Sstevel@tonic-gate return (EINVAL); 10077c478bd9Sstevel@tonic-gate } 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate h = scf_instance_handle(s_inst); 10107c478bd9Sstevel@tonic-gate 10117c478bd9Sstevel@tonic-gate pg = scf_pg_create(h); 10127c478bd9Sstevel@tonic-gate prop = scf_property_create(h); 10137c478bd9Sstevel@tonic-gate iter = scf_iter_create(h); 10147c478bd9Sstevel@tonic-gate t = scf_transaction_create(h); 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate if (pg == NULL || prop == NULL || iter == NULL || t == NULL) { 10177c478bd9Sstevel@tonic-gate ret = ENOMEM; 10187c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 10197c478bd9Sstevel@tonic-gate } 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate add: 10227c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 10237c478bd9Sstevel@tonic-gate ret = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER, 10247c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg); 10257c478bd9Sstevel@tonic-gate if (ret != 0) 10267c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate pname = primary? SCF_PROPERTY_CONTRACT : 10297c478bd9Sstevel@tonic-gate SCF_PROPERTY_TRANSIENT_CONTRACT; 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate for (;;) { 10327c478bd9Sstevel@tonic-gate if (scf_transaction_start(t, pg) != 0) { 10337c478bd9Sstevel@tonic-gate switch (scf_error()) { 10347c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 10357c478bd9Sstevel@tonic-gate default: 10367c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 10377c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 10407c478bd9Sstevel@tonic-gate goto add; 10417c478bd9Sstevel@tonic-gate 10427c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 10437c478bd9Sstevel@tonic-gate ret = EPERM; 10447c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 10477c478bd9Sstevel@tonic-gate ret = EACCES; 10487c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 10497c478bd9Sstevel@tonic-gate 10507c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 10517c478bd9Sstevel@tonic-gate ret = EROFS; 10527c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 10537c478bd9Sstevel@tonic-gate 10547c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 10557c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 10567c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 10577c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_start", scf_error()); 10587c478bd9Sstevel@tonic-gate } 10597c478bd9Sstevel@tonic-gate } 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate t_cid = scf_entry_create(h); 10627c478bd9Sstevel@tonic-gate 10637c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, pname, prop) == 0) { 10647c478bd9Sstevel@tonic-gate replace: 10657c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(t, t_cid, 10667c478bd9Sstevel@tonic-gate pname, SCF_TYPE_COUNT) != 0) { 10677c478bd9Sstevel@tonic-gate switch (scf_error()) { 10687c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 10697c478bd9Sstevel@tonic-gate default: 10707c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 10717c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 10727c478bd9Sstevel@tonic-gate 10737c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 10747c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 10757c478bd9Sstevel@tonic-gate goto add; 10767c478bd9Sstevel@tonic-gate 10777c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 10787c478bd9Sstevel@tonic-gate goto new; 10797c478bd9Sstevel@tonic-gate 10807c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 10817c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 10827c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 10837c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 10847c478bd9Sstevel@tonic-gate bad_fail( 10857c478bd9Sstevel@tonic-gate "scf_transaction_property_changetype", 10867c478bd9Sstevel@tonic-gate scf_error()); 10877c478bd9Sstevel@tonic-gate } 10887c478bd9Sstevel@tonic-gate } 10897c478bd9Sstevel@tonic-gate 10907c478bd9Sstevel@tonic-gate if (scf_property_is_type(prop, SCF_TYPE_COUNT) == 0) { 10917c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) { 10927c478bd9Sstevel@tonic-gate switch (scf_error()) { 10937c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 10947c478bd9Sstevel@tonic-gate default: 10957c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 10967c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 10977c478bd9Sstevel@tonic-gate 10987c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 10997c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 11007c478bd9Sstevel@tonic-gate bad_fail( 11017c478bd9Sstevel@tonic-gate "scf_iter_property_values", 11027c478bd9Sstevel@tonic-gate scf_error()); 11037c478bd9Sstevel@tonic-gate } 11047c478bd9Sstevel@tonic-gate } 11057c478bd9Sstevel@tonic-gate 11067c478bd9Sstevel@tonic-gate next_val: 11077c478bd9Sstevel@tonic-gate val = scf_value_create(h); 11087c478bd9Sstevel@tonic-gate if (val == NULL) { 11097c478bd9Sstevel@tonic-gate assert(scf_error() == 11107c478bd9Sstevel@tonic-gate SCF_ERROR_NO_MEMORY); 11117c478bd9Sstevel@tonic-gate ret = ENOMEM; 11127c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate ret = scf_iter_next_value(iter, val); 11167c478bd9Sstevel@tonic-gate if (ret == -1) { 11177c478bd9Sstevel@tonic-gate switch (scf_error()) { 11187c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 11197c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 11207c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11217c478bd9Sstevel@tonic-gate 11227c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 11237c478bd9Sstevel@tonic-gate scf_value_destroy(val); 11247c478bd9Sstevel@tonic-gate goto add; 11257c478bd9Sstevel@tonic-gate 11267c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 11277c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 11283eae19d9Swesolows case SCF_ERROR_PERMISSION_DENIED: 11297c478bd9Sstevel@tonic-gate default: 11307c478bd9Sstevel@tonic-gate bad_fail("scf_iter_next_value", 11317c478bd9Sstevel@tonic-gate scf_error()); 11327c478bd9Sstevel@tonic-gate } 11337c478bd9Sstevel@tonic-gate } 11347c478bd9Sstevel@tonic-gate 11357c478bd9Sstevel@tonic-gate if (ret == 1) { 11367c478bd9Sstevel@tonic-gate ret = scf_value_get_count(val, &c); 11377c478bd9Sstevel@tonic-gate assert(ret == 0); 11387c478bd9Sstevel@tonic-gate 11397c478bd9Sstevel@tonic-gate if (c != contract_id) { 11407c478bd9Sstevel@tonic-gate ret = scf_entry_add_value(t_cid, 11417c478bd9Sstevel@tonic-gate val); 11427c478bd9Sstevel@tonic-gate assert(ret == 0); 11437c478bd9Sstevel@tonic-gate } else { 11447c478bd9Sstevel@tonic-gate scf_value_destroy(val); 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate goto next_val; 11487c478bd9Sstevel@tonic-gate } 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate scf_value_destroy(val); 11517c478bd9Sstevel@tonic-gate } else { 11527c478bd9Sstevel@tonic-gate switch (scf_error()) { 11537c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 11547c478bd9Sstevel@tonic-gate default: 11557c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 11567c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate case SCF_ERROR_TYPE_MISMATCH: 11597c478bd9Sstevel@tonic-gate break; 11607c478bd9Sstevel@tonic-gate 11617c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 11627c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 11637c478bd9Sstevel@tonic-gate bad_fail("scf_property_is_type", 11647c478bd9Sstevel@tonic-gate scf_error()); 11657c478bd9Sstevel@tonic-gate } 11667c478bd9Sstevel@tonic-gate } 11677c478bd9Sstevel@tonic-gate } else { 11687c478bd9Sstevel@tonic-gate switch (scf_error()) { 11697c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 11707c478bd9Sstevel@tonic-gate default: 11717c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 11727c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11737c478bd9Sstevel@tonic-gate 11747c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 11757c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 11767c478bd9Sstevel@tonic-gate goto add; 11777c478bd9Sstevel@tonic-gate 11787c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 11797c478bd9Sstevel@tonic-gate break; 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 11827c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 11837c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 11847c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error()); 11857c478bd9Sstevel@tonic-gate } 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate new: 11887c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(t, t_cid, pname, 11897c478bd9Sstevel@tonic-gate SCF_TYPE_COUNT) != 0) { 11907c478bd9Sstevel@tonic-gate switch (scf_error()) { 11917c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 11927c478bd9Sstevel@tonic-gate default: 11937c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 11947c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 11957c478bd9Sstevel@tonic-gate 11967c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 11977c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 11987c478bd9Sstevel@tonic-gate goto add; 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 12017c478bd9Sstevel@tonic-gate goto replace; 12027c478bd9Sstevel@tonic-gate 12037c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 12047c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 12057c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 12067c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_new", 12077c478bd9Sstevel@tonic-gate scf_error()); 12087c478bd9Sstevel@tonic-gate } 12097c478bd9Sstevel@tonic-gate } 12107c478bd9Sstevel@tonic-gate } 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(t); 12137c478bd9Sstevel@tonic-gate if (ret == -1) { 12147c478bd9Sstevel@tonic-gate switch (scf_error()) { 12157c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 12167c478bd9Sstevel@tonic-gate default: 12177c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 12187c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 12197c478bd9Sstevel@tonic-gate 12207c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 12217c478bd9Sstevel@tonic-gate goto add; 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 12247c478bd9Sstevel@tonic-gate ret = EPERM; 12257c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 12287c478bd9Sstevel@tonic-gate ret = EACCES; 12297c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 12307c478bd9Sstevel@tonic-gate 12317c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 12327c478bd9Sstevel@tonic-gate ret = EROFS; 12337c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 12367c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_commit", scf_error()); 12377c478bd9Sstevel@tonic-gate } 12387c478bd9Sstevel@tonic-gate } 12397c478bd9Sstevel@tonic-gate if (ret == 1) { 12407c478bd9Sstevel@tonic-gate ret = 0; 12417c478bd9Sstevel@tonic-gate break; 12427c478bd9Sstevel@tonic-gate } 12437c478bd9Sstevel@tonic-gate 12447c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 12457c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 12467c478bd9Sstevel@tonic-gate switch (scf_error()) { 12477c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 12487c478bd9Sstevel@tonic-gate default: 12497c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 12507c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 12517c478bd9Sstevel@tonic-gate 12527c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 12537c478bd9Sstevel@tonic-gate goto add; 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 12567c478bd9Sstevel@tonic-gate bad_fail("scf_pg_update", scf_error()); 12577c478bd9Sstevel@tonic-gate } 12587c478bd9Sstevel@tonic-gate } 12597c478bd9Sstevel@tonic-gate } 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate remove_contract_cleanup: 12627c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 12637c478bd9Sstevel@tonic-gate scf_transaction_destroy(t); 12647c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 12657c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 12667c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 12677c478bd9Sstevel@tonic-gate 12687c478bd9Sstevel@tonic-gate return (ret); 12697c478bd9Sstevel@tonic-gate } 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate /* 12727c478bd9Sstevel@tonic-gate * Fails with 12737c478bd9Sstevel@tonic-gate * EINVAL - type is invalid 12747c478bd9Sstevel@tonic-gate * ENOMEM 12757c478bd9Sstevel@tonic-gate * ECONNABORTED - repository disconnection 12767c478bd9Sstevel@tonic-gate * EBADF - s_inst is not set 12777c478bd9Sstevel@tonic-gate * ECANCELED - s_inst is deleted 12787c478bd9Sstevel@tonic-gate * EPERM 12797c478bd9Sstevel@tonic-gate * EACCES 12807c478bd9Sstevel@tonic-gate * EROFS 12817c478bd9Sstevel@tonic-gate */ 12827c478bd9Sstevel@tonic-gate int 12837c478bd9Sstevel@tonic-gate restarter_store_contract(scf_instance_t *s_inst, ctid_t contract_id, 12847c478bd9Sstevel@tonic-gate restarter_contract_type_t type) 12857c478bd9Sstevel@tonic-gate { 12867c478bd9Sstevel@tonic-gate scf_handle_t *h; 12877c478bd9Sstevel@tonic-gate scf_transaction_t *t = NULL; 12887c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_cid = NULL; 12897c478bd9Sstevel@tonic-gate scf_value_t *val; 12907c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 12917c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL; 12927c478bd9Sstevel@tonic-gate scf_iter_t *iter = NULL; 12937c478bd9Sstevel@tonic-gate const char *pname; 12947c478bd9Sstevel@tonic-gate int ret = 0, primary; 12957c478bd9Sstevel@tonic-gate 12967c478bd9Sstevel@tonic-gate if (type == RESTARTER_CONTRACT_PRIMARY) 12977c478bd9Sstevel@tonic-gate primary = 1; 12987c478bd9Sstevel@tonic-gate else if (type == RESTARTER_CONTRACT_TRANSIENT) 12997c478bd9Sstevel@tonic-gate primary = 0; 13007c478bd9Sstevel@tonic-gate else 13017c478bd9Sstevel@tonic-gate return (EINVAL); 13027c478bd9Sstevel@tonic-gate 13037c478bd9Sstevel@tonic-gate h = scf_instance_handle(s_inst); 13047c478bd9Sstevel@tonic-gate 13057c478bd9Sstevel@tonic-gate pg = scf_pg_create(h); 13067c478bd9Sstevel@tonic-gate prop = scf_property_create(h); 13077c478bd9Sstevel@tonic-gate iter = scf_iter_create(h); 13087c478bd9Sstevel@tonic-gate t = scf_transaction_create(h); 13097c478bd9Sstevel@tonic-gate 13107c478bd9Sstevel@tonic-gate if (pg == NULL || prop == NULL || iter == NULL || t == NULL) { 13117c478bd9Sstevel@tonic-gate ret = ENOMEM; 13127c478bd9Sstevel@tonic-gate goto out; 13137c478bd9Sstevel@tonic-gate } 13147c478bd9Sstevel@tonic-gate 13157c478bd9Sstevel@tonic-gate add: 13167c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 13177c478bd9Sstevel@tonic-gate ret = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER, 13187c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg); 13197c478bd9Sstevel@tonic-gate if (ret != 0) 13207c478bd9Sstevel@tonic-gate goto out; 13217c478bd9Sstevel@tonic-gate 13227c478bd9Sstevel@tonic-gate pname = primary ? SCF_PROPERTY_CONTRACT : 13237c478bd9Sstevel@tonic-gate SCF_PROPERTY_TRANSIENT_CONTRACT; 13247c478bd9Sstevel@tonic-gate 13257c478bd9Sstevel@tonic-gate for (;;) { 13267c478bd9Sstevel@tonic-gate if (scf_transaction_start(t, pg) != 0) { 13277c478bd9Sstevel@tonic-gate switch (scf_error()) { 13287c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 13297c478bd9Sstevel@tonic-gate default: 13307c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 13317c478bd9Sstevel@tonic-gate goto out; 13327c478bd9Sstevel@tonic-gate 13337c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 13347c478bd9Sstevel@tonic-gate goto add; 13357c478bd9Sstevel@tonic-gate 13367c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 13377c478bd9Sstevel@tonic-gate ret = EPERM; 13387c478bd9Sstevel@tonic-gate goto out; 13397c478bd9Sstevel@tonic-gate 13407c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 13417c478bd9Sstevel@tonic-gate ret = EACCES; 13427c478bd9Sstevel@tonic-gate goto out; 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 13457c478bd9Sstevel@tonic-gate ret = EROFS; 13467c478bd9Sstevel@tonic-gate goto out; 13477c478bd9Sstevel@tonic-gate 13487c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 13497c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 13507c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 13517c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_start", scf_error()); 13527c478bd9Sstevel@tonic-gate } 13537c478bd9Sstevel@tonic-gate } 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate t_cid = scf_entry_create(h); 13567c478bd9Sstevel@tonic-gate if (t_cid == NULL) { 13577c478bd9Sstevel@tonic-gate ret = ENOMEM; 13587c478bd9Sstevel@tonic-gate goto out; 13597c478bd9Sstevel@tonic-gate } 13607c478bd9Sstevel@tonic-gate 13617c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, pname, prop) == 0) { 13627c478bd9Sstevel@tonic-gate replace: 13637c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(t, t_cid, 13647c478bd9Sstevel@tonic-gate pname, SCF_TYPE_COUNT) != 0) { 13657c478bd9Sstevel@tonic-gate switch (scf_error()) { 13667c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 13677c478bd9Sstevel@tonic-gate default: 13687c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 13697c478bd9Sstevel@tonic-gate goto out; 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 13727c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 13737c478bd9Sstevel@tonic-gate goto add; 13747c478bd9Sstevel@tonic-gate 13757c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 13767c478bd9Sstevel@tonic-gate goto new; 13777c478bd9Sstevel@tonic-gate 13787c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 13797c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 13807c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 13817c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 13827c478bd9Sstevel@tonic-gate bad_fail( 13837c478bd9Sstevel@tonic-gate "scf_transaction_propert_change_type", 13847c478bd9Sstevel@tonic-gate scf_error()); 13857c478bd9Sstevel@tonic-gate } 13867c478bd9Sstevel@tonic-gate } 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate if (scf_property_is_type(prop, SCF_TYPE_COUNT) == 0) { 13897c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) { 13907c478bd9Sstevel@tonic-gate switch (scf_error()) { 13917c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 13927c478bd9Sstevel@tonic-gate default: 13937c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 13947c478bd9Sstevel@tonic-gate goto out; 13957c478bd9Sstevel@tonic-gate 13967c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 13977c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 13987c478bd9Sstevel@tonic-gate bad_fail( 13997c478bd9Sstevel@tonic-gate "scf_iter_property_values", 14007c478bd9Sstevel@tonic-gate scf_error()); 14017c478bd9Sstevel@tonic-gate } 14027c478bd9Sstevel@tonic-gate } 14037c478bd9Sstevel@tonic-gate 14047c478bd9Sstevel@tonic-gate next_val: 14057c478bd9Sstevel@tonic-gate val = scf_value_create(h); 14067c478bd9Sstevel@tonic-gate if (val == NULL) { 14077c478bd9Sstevel@tonic-gate assert(scf_error() == 14087c478bd9Sstevel@tonic-gate SCF_ERROR_NO_MEMORY); 14097c478bd9Sstevel@tonic-gate ret = ENOMEM; 14107c478bd9Sstevel@tonic-gate goto out; 14117c478bd9Sstevel@tonic-gate } 14127c478bd9Sstevel@tonic-gate 14137c478bd9Sstevel@tonic-gate ret = scf_iter_next_value(iter, val); 14147c478bd9Sstevel@tonic-gate if (ret == -1) { 14157c478bd9Sstevel@tonic-gate switch (scf_error()) { 14167c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 14177c478bd9Sstevel@tonic-gate default: 14187c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 14197c478bd9Sstevel@tonic-gate goto out; 14207c478bd9Sstevel@tonic-gate 14217c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 14227c478bd9Sstevel@tonic-gate scf_value_destroy(val); 14237c478bd9Sstevel@tonic-gate goto add; 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 14267c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 14273eae19d9Swesolows case SCF_ERROR_PERMISSION_DENIED: 14287c478bd9Sstevel@tonic-gate bad_fail( 14297c478bd9Sstevel@tonic-gate "scf_iter_next_value", 14307c478bd9Sstevel@tonic-gate scf_error()); 14317c478bd9Sstevel@tonic-gate } 14327c478bd9Sstevel@tonic-gate } 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate if (ret == 1) { 14357c478bd9Sstevel@tonic-gate ret = scf_entry_add_value(t_cid, val); 14367c478bd9Sstevel@tonic-gate assert(ret == 0); 14377c478bd9Sstevel@tonic-gate 14387c478bd9Sstevel@tonic-gate goto next_val; 14397c478bd9Sstevel@tonic-gate } 14407c478bd9Sstevel@tonic-gate 14417c478bd9Sstevel@tonic-gate scf_value_destroy(val); 14427c478bd9Sstevel@tonic-gate } else { 14437c478bd9Sstevel@tonic-gate switch (scf_error()) { 14447c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 14457c478bd9Sstevel@tonic-gate default: 14467c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 14477c478bd9Sstevel@tonic-gate goto out; 14487c478bd9Sstevel@tonic-gate 14497c478bd9Sstevel@tonic-gate case SCF_ERROR_TYPE_MISMATCH: 14507c478bd9Sstevel@tonic-gate break; 14517c478bd9Sstevel@tonic-gate 14527c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 14537c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 14547c478bd9Sstevel@tonic-gate bad_fail("scf_property_is_type", 14557c478bd9Sstevel@tonic-gate scf_error()); 14567c478bd9Sstevel@tonic-gate } 14577c478bd9Sstevel@tonic-gate } 14587c478bd9Sstevel@tonic-gate } else { 14597c478bd9Sstevel@tonic-gate switch (scf_error()) { 14607c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 14617c478bd9Sstevel@tonic-gate default: 14627c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 14637c478bd9Sstevel@tonic-gate goto out; 14647c478bd9Sstevel@tonic-gate 14657c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 14667c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 14677c478bd9Sstevel@tonic-gate goto add; 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 14707c478bd9Sstevel@tonic-gate break; 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 14737c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 14747c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 14757c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error()); 14767c478bd9Sstevel@tonic-gate } 14777c478bd9Sstevel@tonic-gate 14787c478bd9Sstevel@tonic-gate new: 14797c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(t, t_cid, pname, 14807c478bd9Sstevel@tonic-gate SCF_TYPE_COUNT) != 0) { 14817c478bd9Sstevel@tonic-gate switch (scf_error()) { 14827c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 14837c478bd9Sstevel@tonic-gate default: 14847c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 14857c478bd9Sstevel@tonic-gate goto out; 14867c478bd9Sstevel@tonic-gate 14877c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 14887c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 14897c478bd9Sstevel@tonic-gate goto add; 14907c478bd9Sstevel@tonic-gate 14917c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 14927c478bd9Sstevel@tonic-gate goto replace; 14937c478bd9Sstevel@tonic-gate 14947c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 14957c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 14967c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 14977c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_new", 14987c478bd9Sstevel@tonic-gate scf_error()); 14997c478bd9Sstevel@tonic-gate } 15007c478bd9Sstevel@tonic-gate } 15017c478bd9Sstevel@tonic-gate } 15027c478bd9Sstevel@tonic-gate 15037c478bd9Sstevel@tonic-gate val = scf_value_create(h); 15047c478bd9Sstevel@tonic-gate if (val == NULL) { 15057c478bd9Sstevel@tonic-gate assert(scf_error() == SCF_ERROR_NO_MEMORY); 15067c478bd9Sstevel@tonic-gate ret = ENOMEM; 15077c478bd9Sstevel@tonic-gate goto out; 15087c478bd9Sstevel@tonic-gate } 15097c478bd9Sstevel@tonic-gate 15107c478bd9Sstevel@tonic-gate scf_value_set_count(val, contract_id); 15117c478bd9Sstevel@tonic-gate ret = scf_entry_add_value(t_cid, val); 15127c478bd9Sstevel@tonic-gate assert(ret == 0); 15137c478bd9Sstevel@tonic-gate 15147c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(t); 15157c478bd9Sstevel@tonic-gate if (ret == -1) { 15167c478bd9Sstevel@tonic-gate switch (scf_error()) { 15177c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 15187c478bd9Sstevel@tonic-gate default: 15197c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 15207c478bd9Sstevel@tonic-gate goto out; 15217c478bd9Sstevel@tonic-gate 15227c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 15237c478bd9Sstevel@tonic-gate goto add; 15247c478bd9Sstevel@tonic-gate 15257c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 15267c478bd9Sstevel@tonic-gate ret = EPERM; 15277c478bd9Sstevel@tonic-gate goto out; 15287c478bd9Sstevel@tonic-gate 15297c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 15307c478bd9Sstevel@tonic-gate ret = EACCES; 15317c478bd9Sstevel@tonic-gate goto out; 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 15347c478bd9Sstevel@tonic-gate ret = EROFS; 15357c478bd9Sstevel@tonic-gate goto out; 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 15387c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_commit", scf_error()); 15397c478bd9Sstevel@tonic-gate } 15407c478bd9Sstevel@tonic-gate } 15417c478bd9Sstevel@tonic-gate if (ret == 1) { 15427c478bd9Sstevel@tonic-gate ret = 0; 15437c478bd9Sstevel@tonic-gate break; 15447c478bd9Sstevel@tonic-gate } 15457c478bd9Sstevel@tonic-gate 15467c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 15477c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 15487c478bd9Sstevel@tonic-gate switch (scf_error()) { 15497c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 15507c478bd9Sstevel@tonic-gate default: 15517c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 15527c478bd9Sstevel@tonic-gate goto out; 15537c478bd9Sstevel@tonic-gate 15547c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 15557c478bd9Sstevel@tonic-gate goto add; 15567c478bd9Sstevel@tonic-gate 15577c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 15587c478bd9Sstevel@tonic-gate bad_fail("scf_pg_update", scf_error()); 15597c478bd9Sstevel@tonic-gate } 15607c478bd9Sstevel@tonic-gate } 15617c478bd9Sstevel@tonic-gate } 15627c478bd9Sstevel@tonic-gate 15637c478bd9Sstevel@tonic-gate out: 15647c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 15657c478bd9Sstevel@tonic-gate scf_transaction_destroy(t); 15667c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 15677c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 15687c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 15697c478bd9Sstevel@tonic-gate 15707c478bd9Sstevel@tonic-gate return (ret); 15717c478bd9Sstevel@tonic-gate } 15727c478bd9Sstevel@tonic-gate 15737c478bd9Sstevel@tonic-gate int 15747c478bd9Sstevel@tonic-gate restarter_rm_libs_loadable() 15757c478bd9Sstevel@tonic-gate { 15767c478bd9Sstevel@tonic-gate void *libhndl; 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate if (method_context_safety) 15797c478bd9Sstevel@tonic-gate return (1); 15807c478bd9Sstevel@tonic-gate 15817c478bd9Sstevel@tonic-gate if ((libhndl = dlopen("libpool.so", RTLD_LAZY | RTLD_LOCAL)) == NULL) 15827c478bd9Sstevel@tonic-gate return (0); 15837c478bd9Sstevel@tonic-gate 15847c478bd9Sstevel@tonic-gate (void) dlclose(libhndl); 15857c478bd9Sstevel@tonic-gate 15867c478bd9Sstevel@tonic-gate if ((libhndl = dlopen("libproject.so", RTLD_LAZY | RTLD_LOCAL)) == NULL) 15877c478bd9Sstevel@tonic-gate return (0); 15887c478bd9Sstevel@tonic-gate 15897c478bd9Sstevel@tonic-gate (void) dlclose(libhndl); 15907c478bd9Sstevel@tonic-gate 15917c478bd9Sstevel@tonic-gate method_context_safety = 1; 15927c478bd9Sstevel@tonic-gate 15937c478bd9Sstevel@tonic-gate return (1); 15947c478bd9Sstevel@tonic-gate } 15957c478bd9Sstevel@tonic-gate 15967c478bd9Sstevel@tonic-gate static int 15977c478bd9Sstevel@tonic-gate get_astring_val(scf_propertygroup_t *pg, const char *name, char *buf, 15987c478bd9Sstevel@tonic-gate size_t bufsz, scf_property_t *prop, scf_value_t *val) 15997c478bd9Sstevel@tonic-gate { 16007c478bd9Sstevel@tonic-gate ssize_t szret; 16017c478bd9Sstevel@tonic-gate 1602*13d8aaa1SSean Wilcox if (pg == NULL) 1603*13d8aaa1SSean Wilcox return (-1); 1604*13d8aaa1SSean Wilcox 16057c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, name, prop) != SCF_SUCCESS) { 16067c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 16077c478bd9Sstevel@tonic-gate uu_die(rcbroken); 16087c478bd9Sstevel@tonic-gate return (-1); 16097c478bd9Sstevel@tonic-gate } 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 16127c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 16137c478bd9Sstevel@tonic-gate uu_die(rcbroken); 16147c478bd9Sstevel@tonic-gate return (-1); 16157c478bd9Sstevel@tonic-gate } 16167c478bd9Sstevel@tonic-gate 16177c478bd9Sstevel@tonic-gate szret = scf_value_get_astring(val, buf, bufsz); 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate return (szret >= 0 ? 0 : -1); 16207c478bd9Sstevel@tonic-gate } 16217c478bd9Sstevel@tonic-gate 1622eb1a3463STruong Nguyen static int 1623eb1a3463STruong Nguyen get_boolean_val(scf_propertygroup_t *pg, const char *name, uint8_t *b, 1624eb1a3463STruong Nguyen scf_property_t *prop, scf_value_t *val) 1625eb1a3463STruong Nguyen { 1626eb1a3463STruong Nguyen if (scf_pg_get_property(pg, name, prop) != SCF_SUCCESS) { 1627eb1a3463STruong Nguyen if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 1628eb1a3463STruong Nguyen uu_die(rcbroken); 1629eb1a3463STruong Nguyen return (-1); 1630eb1a3463STruong Nguyen } 1631eb1a3463STruong Nguyen 1632eb1a3463STruong Nguyen if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 1633eb1a3463STruong Nguyen if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 1634eb1a3463STruong Nguyen uu_die(rcbroken); 1635eb1a3463STruong Nguyen return (-1); 1636eb1a3463STruong Nguyen } 1637eb1a3463STruong Nguyen 1638eb1a3463STruong Nguyen if (scf_value_get_boolean(val, b)) 1639eb1a3463STruong Nguyen return (-1); 1640eb1a3463STruong Nguyen 1641eb1a3463STruong Nguyen return (0); 1642eb1a3463STruong Nguyen } 1643eb1a3463STruong Nguyen 16447c478bd9Sstevel@tonic-gate /* 16457c478bd9Sstevel@tonic-gate * Try to load mcp->pwd, if it isn't already. 16467c478bd9Sstevel@tonic-gate * Fails with 16477c478bd9Sstevel@tonic-gate * ENOMEM - malloc() failed 16487c478bd9Sstevel@tonic-gate * ENOENT - no entry found 16497c478bd9Sstevel@tonic-gate * EIO - I/O error 16507c478bd9Sstevel@tonic-gate * EMFILE - process out of file descriptors 16517c478bd9Sstevel@tonic-gate * ENFILE - system out of file handles 16527c478bd9Sstevel@tonic-gate */ 16537c478bd9Sstevel@tonic-gate static int 16547c478bd9Sstevel@tonic-gate lookup_pwd(struct method_context *mcp) 16557c478bd9Sstevel@tonic-gate { 16567c478bd9Sstevel@tonic-gate struct passwd *pwdp; 16577c478bd9Sstevel@tonic-gate 16587c478bd9Sstevel@tonic-gate if (mcp->pwbuf != NULL && mcp->pwd.pw_uid == mcp->uid) 16597c478bd9Sstevel@tonic-gate return (0); 16607c478bd9Sstevel@tonic-gate 16617c478bd9Sstevel@tonic-gate if (mcp->pwbuf == NULL) { 16627c478bd9Sstevel@tonic-gate mcp->pwbufsz = sysconf(_SC_GETPW_R_SIZE_MAX); 16637c478bd9Sstevel@tonic-gate assert(mcp->pwbufsz >= 0); 16647c478bd9Sstevel@tonic-gate mcp->pwbuf = malloc(mcp->pwbufsz); 16657c478bd9Sstevel@tonic-gate if (mcp->pwbuf == NULL) 16667c478bd9Sstevel@tonic-gate return (ENOMEM); 16677c478bd9Sstevel@tonic-gate } 16687c478bd9Sstevel@tonic-gate 16697c478bd9Sstevel@tonic-gate do { 16707c478bd9Sstevel@tonic-gate errno = 0; 16717c478bd9Sstevel@tonic-gate pwdp = getpwuid_r(mcp->uid, &mcp->pwd, mcp->pwbuf, 16727c478bd9Sstevel@tonic-gate mcp->pwbufsz); 16737c478bd9Sstevel@tonic-gate } while (pwdp == NULL && errno == EINTR); 16747c478bd9Sstevel@tonic-gate if (pwdp != NULL) 16757c478bd9Sstevel@tonic-gate return (0); 16767c478bd9Sstevel@tonic-gate 16777c478bd9Sstevel@tonic-gate free(mcp->pwbuf); 16787c478bd9Sstevel@tonic-gate mcp->pwbuf = NULL; 16797c478bd9Sstevel@tonic-gate 16807c478bd9Sstevel@tonic-gate switch (errno) { 16817c478bd9Sstevel@tonic-gate case 0: 16827c478bd9Sstevel@tonic-gate default: 16837c478bd9Sstevel@tonic-gate /* 16847c478bd9Sstevel@tonic-gate * Until bug 5065780 is fixed, getpwuid_r() can fail with 16857c478bd9Sstevel@tonic-gate * ENOENT, particularly on the miniroot. Since the 16867c478bd9Sstevel@tonic-gate * documentation is inaccurate, we'll return ENOENT for unknown 16877c478bd9Sstevel@tonic-gate * errors. 16887c478bd9Sstevel@tonic-gate */ 16897c478bd9Sstevel@tonic-gate return (ENOENT); 16907c478bd9Sstevel@tonic-gate 16917c478bd9Sstevel@tonic-gate case EIO: 16927c478bd9Sstevel@tonic-gate case EMFILE: 16937c478bd9Sstevel@tonic-gate case ENFILE: 16947c478bd9Sstevel@tonic-gate return (errno); 16957c478bd9Sstevel@tonic-gate 16967c478bd9Sstevel@tonic-gate case ERANGE: 16977c478bd9Sstevel@tonic-gate bad_fail("getpwuid_r", errno); 16987c478bd9Sstevel@tonic-gate /* NOTREACHED */ 16997c478bd9Sstevel@tonic-gate } 17007c478bd9Sstevel@tonic-gate } 17017c478bd9Sstevel@tonic-gate 17027c478bd9Sstevel@tonic-gate /* 17037c478bd9Sstevel@tonic-gate * Get the user id for str. Returns 0 on success or 17047c478bd9Sstevel@tonic-gate * ERANGE the uid is too big 17057c478bd9Sstevel@tonic-gate * EINVAL the string starts with a digit, but is not a valid uid 17067c478bd9Sstevel@tonic-gate * ENOMEM out of memory 17077c478bd9Sstevel@tonic-gate * ENOENT no passwd entry for str 17087c478bd9Sstevel@tonic-gate * EIO an I/O error has occurred 17097c478bd9Sstevel@tonic-gate * EMFILE/ENFILE out of file descriptors 17107c478bd9Sstevel@tonic-gate */ 17117c478bd9Sstevel@tonic-gate int 17127c478bd9Sstevel@tonic-gate get_uid(const char *str, struct method_context *ci, uid_t *uidp) 17137c478bd9Sstevel@tonic-gate { 17147c478bd9Sstevel@tonic-gate if (isdigit(str[0])) { 17157c478bd9Sstevel@tonic-gate uid_t uid; 17167c478bd9Sstevel@tonic-gate char *cp; 17177c478bd9Sstevel@tonic-gate 17187c478bd9Sstevel@tonic-gate errno = 0; 17197c478bd9Sstevel@tonic-gate uid = strtol(str, &cp, 10); 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate if (uid == 0 && errno != 0) { 17227c478bd9Sstevel@tonic-gate assert(errno != EINVAL); 17237c478bd9Sstevel@tonic-gate return (errno); 17247c478bd9Sstevel@tonic-gate } 17257c478bd9Sstevel@tonic-gate 17267c478bd9Sstevel@tonic-gate for (; *cp != '\0'; ++cp) 17277c478bd9Sstevel@tonic-gate if (*cp != ' ' || *cp != '\t') 17287c478bd9Sstevel@tonic-gate return (EINVAL); 17297c478bd9Sstevel@tonic-gate 17307c478bd9Sstevel@tonic-gate if (uid > UID_MAX) 17317c478bd9Sstevel@tonic-gate return (EINVAL); 17327c478bd9Sstevel@tonic-gate 17337c478bd9Sstevel@tonic-gate *uidp = uid; 17347c478bd9Sstevel@tonic-gate return (0); 17357c478bd9Sstevel@tonic-gate } else { 17367c478bd9Sstevel@tonic-gate struct passwd *pwdp; 17377c478bd9Sstevel@tonic-gate 17387c478bd9Sstevel@tonic-gate if (ci->pwbuf == NULL) { 17397c478bd9Sstevel@tonic-gate ci->pwbufsz = sysconf(_SC_GETPW_R_SIZE_MAX); 17407c478bd9Sstevel@tonic-gate ci->pwbuf = malloc(ci->pwbufsz); 17417c478bd9Sstevel@tonic-gate if (ci->pwbuf == NULL) 17427c478bd9Sstevel@tonic-gate return (ENOMEM); 17437c478bd9Sstevel@tonic-gate } 17447c478bd9Sstevel@tonic-gate 17457c478bd9Sstevel@tonic-gate do { 17467c478bd9Sstevel@tonic-gate errno = 0; 17477c478bd9Sstevel@tonic-gate pwdp = 17487c478bd9Sstevel@tonic-gate getpwnam_r(str, &ci->pwd, ci->pwbuf, ci->pwbufsz); 17497c478bd9Sstevel@tonic-gate } while (pwdp == NULL && errno == EINTR); 17507c478bd9Sstevel@tonic-gate 17517c478bd9Sstevel@tonic-gate if (pwdp != NULL) { 17527c478bd9Sstevel@tonic-gate *uidp = ci->pwd.pw_uid; 17537c478bd9Sstevel@tonic-gate return (0); 17547c478bd9Sstevel@tonic-gate } else { 17557c478bd9Sstevel@tonic-gate free(ci->pwbuf); 17567c478bd9Sstevel@tonic-gate ci->pwbuf = NULL; 17577c478bd9Sstevel@tonic-gate switch (errno) { 17587c478bd9Sstevel@tonic-gate case 0: 17597c478bd9Sstevel@tonic-gate return (ENOENT); 17607c478bd9Sstevel@tonic-gate 17617c478bd9Sstevel@tonic-gate case ENOENT: 17627c478bd9Sstevel@tonic-gate case EIO: 17637c478bd9Sstevel@tonic-gate case EMFILE: 17647c478bd9Sstevel@tonic-gate case ENFILE: 17657c478bd9Sstevel@tonic-gate return (errno); 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate case ERANGE: 17687c478bd9Sstevel@tonic-gate default: 17697c478bd9Sstevel@tonic-gate bad_fail("getpwnam_r", errno); 17707c478bd9Sstevel@tonic-gate /* NOTREACHED */ 17717c478bd9Sstevel@tonic-gate } 17727c478bd9Sstevel@tonic-gate } 17737c478bd9Sstevel@tonic-gate } 17747c478bd9Sstevel@tonic-gate } 17757c478bd9Sstevel@tonic-gate 17767c478bd9Sstevel@tonic-gate gid_t 17777c478bd9Sstevel@tonic-gate get_gid(const char *str) 17787c478bd9Sstevel@tonic-gate { 17797c478bd9Sstevel@tonic-gate if (isdigit(str[0])) { 17807c478bd9Sstevel@tonic-gate gid_t gid; 17817c478bd9Sstevel@tonic-gate char *cp; 17827c478bd9Sstevel@tonic-gate 17837c478bd9Sstevel@tonic-gate errno = 0; 17847c478bd9Sstevel@tonic-gate gid = strtol(str, &cp, 10); 17857c478bd9Sstevel@tonic-gate 17867c478bd9Sstevel@tonic-gate if (gid == 0 && errno != 0) 1787f48205beScasper return ((gid_t)-1); 17887c478bd9Sstevel@tonic-gate 17897c478bd9Sstevel@tonic-gate for (; *cp != '\0'; ++cp) 17907c478bd9Sstevel@tonic-gate if (*cp != ' ' || *cp != '\t') 1791f48205beScasper return ((gid_t)-1); 17927c478bd9Sstevel@tonic-gate 17937c478bd9Sstevel@tonic-gate return (gid); 17947c478bd9Sstevel@tonic-gate } else { 17957c478bd9Sstevel@tonic-gate struct group grp, *ret; 17967c478bd9Sstevel@tonic-gate char *buffer; 17977c478bd9Sstevel@tonic-gate size_t buflen; 17987c478bd9Sstevel@tonic-gate 17997c478bd9Sstevel@tonic-gate buflen = sysconf(_SC_GETGR_R_SIZE_MAX); 18007c478bd9Sstevel@tonic-gate buffer = malloc(buflen); 18017c478bd9Sstevel@tonic-gate if (buffer == NULL) 18027c478bd9Sstevel@tonic-gate uu_die(allocfail); 18037c478bd9Sstevel@tonic-gate 18047c478bd9Sstevel@tonic-gate errno = 0; 18057c478bd9Sstevel@tonic-gate ret = getgrnam_r(str, &grp, buffer, buflen); 18067c478bd9Sstevel@tonic-gate free(buffer); 18077c478bd9Sstevel@tonic-gate 1808f48205beScasper return (ret == NULL ? (gid_t)-1 : grp.gr_gid); 18097c478bd9Sstevel@tonic-gate } 18107c478bd9Sstevel@tonic-gate } 18117c478bd9Sstevel@tonic-gate 18127c478bd9Sstevel@tonic-gate /* 18137c478bd9Sstevel@tonic-gate * Fails with 18147c478bd9Sstevel@tonic-gate * ENOMEM - out of memory 18157c478bd9Sstevel@tonic-gate * ENOENT - no passwd entry 18167c478bd9Sstevel@tonic-gate * no project entry 18177c478bd9Sstevel@tonic-gate * EIO - an I/O error occurred 18187c478bd9Sstevel@tonic-gate * EMFILE - the process is out of file descriptors 18197c478bd9Sstevel@tonic-gate * ENFILE - the system is out of file handles 18207c478bd9Sstevel@tonic-gate * ERANGE - the project id is out of range 18217c478bd9Sstevel@tonic-gate * EINVAL - str is invalid 18227c478bd9Sstevel@tonic-gate * E2BIG - the project entry was too big 18237c478bd9Sstevel@tonic-gate * -1 - the name service switch is misconfigured 18247c478bd9Sstevel@tonic-gate */ 18257c478bd9Sstevel@tonic-gate int 18267c478bd9Sstevel@tonic-gate get_projid(const char *str, struct method_context *cip) 18277c478bd9Sstevel@tonic-gate { 18287c478bd9Sstevel@tonic-gate int ret; 18297c478bd9Sstevel@tonic-gate void *buf; 18307c478bd9Sstevel@tonic-gate const size_t bufsz = PROJECT_BUFSZ; 18317c478bd9Sstevel@tonic-gate struct project proj, *pp; 18327c478bd9Sstevel@tonic-gate 18337c478bd9Sstevel@tonic-gate if (strcmp(str, ":default") == 0) { 18347c478bd9Sstevel@tonic-gate if (cip->uid == 0) { 18357c478bd9Sstevel@tonic-gate /* Don't change project for root services */ 18367c478bd9Sstevel@tonic-gate cip->project = NULL; 18377c478bd9Sstevel@tonic-gate return (0); 18387c478bd9Sstevel@tonic-gate } 18397c478bd9Sstevel@tonic-gate 18407c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 18417c478bd9Sstevel@tonic-gate case 0: 18427c478bd9Sstevel@tonic-gate break; 18437c478bd9Sstevel@tonic-gate 18447c478bd9Sstevel@tonic-gate case ENOMEM: 18457c478bd9Sstevel@tonic-gate case ENOENT: 18467c478bd9Sstevel@tonic-gate case EIO: 18477c478bd9Sstevel@tonic-gate case EMFILE: 18487c478bd9Sstevel@tonic-gate case ENFILE: 18497c478bd9Sstevel@tonic-gate return (ret); 18507c478bd9Sstevel@tonic-gate 18517c478bd9Sstevel@tonic-gate default: 18527c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 18537c478bd9Sstevel@tonic-gate } 18547c478bd9Sstevel@tonic-gate 18557c478bd9Sstevel@tonic-gate buf = malloc(bufsz); 18567c478bd9Sstevel@tonic-gate if (buf == NULL) 18577c478bd9Sstevel@tonic-gate return (ENOMEM); 18587c478bd9Sstevel@tonic-gate 18597c478bd9Sstevel@tonic-gate do { 18607c478bd9Sstevel@tonic-gate errno = 0; 18617c478bd9Sstevel@tonic-gate pp = getdefaultproj(cip->pwd.pw_name, &proj, buf, 18627c478bd9Sstevel@tonic-gate bufsz); 18637c478bd9Sstevel@tonic-gate } while (pp == NULL && errno == EINTR); 18647c478bd9Sstevel@tonic-gate 18657c478bd9Sstevel@tonic-gate /* to be continued ... */ 18667c478bd9Sstevel@tonic-gate } else { 18677c478bd9Sstevel@tonic-gate projid_t projid; 18687c478bd9Sstevel@tonic-gate char *cp; 18697c478bd9Sstevel@tonic-gate 18707c478bd9Sstevel@tonic-gate if (!isdigit(str[0])) { 18717c478bd9Sstevel@tonic-gate cip->project = strdup(str); 18727c478bd9Sstevel@tonic-gate return (cip->project != NULL ? 0 : ENOMEM); 18737c478bd9Sstevel@tonic-gate } 18747c478bd9Sstevel@tonic-gate 18757c478bd9Sstevel@tonic-gate errno = 0; 18767c478bd9Sstevel@tonic-gate projid = strtol(str, &cp, 10); 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate if (projid == 0 && errno != 0) { 18797c478bd9Sstevel@tonic-gate assert(errno == ERANGE); 18807c478bd9Sstevel@tonic-gate return (errno); 18817c478bd9Sstevel@tonic-gate } 18827c478bd9Sstevel@tonic-gate 18837c478bd9Sstevel@tonic-gate for (; *cp != '\0'; ++cp) 18847c478bd9Sstevel@tonic-gate if (*cp != ' ' || *cp != '\t') 18857c478bd9Sstevel@tonic-gate return (EINVAL); 18867c478bd9Sstevel@tonic-gate 18877c478bd9Sstevel@tonic-gate if (projid > MAXPROJID) 18887c478bd9Sstevel@tonic-gate return (ERANGE); 18897c478bd9Sstevel@tonic-gate 18907c478bd9Sstevel@tonic-gate buf = malloc(bufsz); 18917c478bd9Sstevel@tonic-gate if (buf == NULL) 18927c478bd9Sstevel@tonic-gate return (ENOMEM); 18937c478bd9Sstevel@tonic-gate 18947c478bd9Sstevel@tonic-gate do { 18957c478bd9Sstevel@tonic-gate errno = 0; 18967c478bd9Sstevel@tonic-gate pp = getprojbyid(projid, &proj, buf, bufsz); 18977c478bd9Sstevel@tonic-gate } while (pp == NULL && errno == EINTR); 18987c478bd9Sstevel@tonic-gate } 18997c478bd9Sstevel@tonic-gate 19007c478bd9Sstevel@tonic-gate if (pp) { 19017c478bd9Sstevel@tonic-gate cip->project = strdup(pp->pj_name); 19027c478bd9Sstevel@tonic-gate free(buf); 19037c478bd9Sstevel@tonic-gate return (cip->project != NULL ? 0 : ENOMEM); 19047c478bd9Sstevel@tonic-gate } 19057c478bd9Sstevel@tonic-gate 19067c478bd9Sstevel@tonic-gate free(buf); 19077c478bd9Sstevel@tonic-gate 19087c478bd9Sstevel@tonic-gate switch (errno) { 19097c478bd9Sstevel@tonic-gate case 0: 19107c478bd9Sstevel@tonic-gate return (ENOENT); 19117c478bd9Sstevel@tonic-gate 19127c478bd9Sstevel@tonic-gate case EIO: 19137c478bd9Sstevel@tonic-gate case EMFILE: 19147c478bd9Sstevel@tonic-gate case ENFILE: 19157c478bd9Sstevel@tonic-gate return (errno); 19167c478bd9Sstevel@tonic-gate 19177c478bd9Sstevel@tonic-gate case ERANGE: 19187c478bd9Sstevel@tonic-gate return (E2BIG); 19197c478bd9Sstevel@tonic-gate 19207c478bd9Sstevel@tonic-gate default: 19217c478bd9Sstevel@tonic-gate return (-1); 19227c478bd9Sstevel@tonic-gate } 19237c478bd9Sstevel@tonic-gate } 19247c478bd9Sstevel@tonic-gate 19257c478bd9Sstevel@tonic-gate /* 19267c478bd9Sstevel@tonic-gate * Parse the supp_groups property value and populate ci->groups. Returns 19277c478bd9Sstevel@tonic-gate * EINVAL (get_gid() failed for one of the components), E2BIG (the property has 19287c478bd9Sstevel@tonic-gate * more than NGROUPS_MAX-1 groups), or 0 on success. 19297c478bd9Sstevel@tonic-gate */ 19307c478bd9Sstevel@tonic-gate int 19317c478bd9Sstevel@tonic-gate get_groups(char *str, struct method_context *ci) 19327c478bd9Sstevel@tonic-gate { 19337c478bd9Sstevel@tonic-gate char *cp, *end, *next; 19347c478bd9Sstevel@tonic-gate uint_t i; 19357c478bd9Sstevel@tonic-gate 19367c478bd9Sstevel@tonic-gate const char * const whitespace = " \t"; 19377c478bd9Sstevel@tonic-gate const char * const illegal = ", \t"; 19387c478bd9Sstevel@tonic-gate 19397c478bd9Sstevel@tonic-gate if (str[0] == '\0') { 19407c478bd9Sstevel@tonic-gate ci->ngroups = 0; 19417c478bd9Sstevel@tonic-gate return (0); 19427c478bd9Sstevel@tonic-gate } 19437c478bd9Sstevel@tonic-gate 19447c478bd9Sstevel@tonic-gate for (cp = str, i = 0; *cp != '\0'; ) { 19457c478bd9Sstevel@tonic-gate /* skip whitespace */ 19467c478bd9Sstevel@tonic-gate cp += strspn(cp, whitespace); 19477c478bd9Sstevel@tonic-gate 19487c478bd9Sstevel@tonic-gate /* find the end */ 19497c478bd9Sstevel@tonic-gate end = cp + strcspn(cp, illegal); 19507c478bd9Sstevel@tonic-gate 19517c478bd9Sstevel@tonic-gate /* skip whitespace after end */ 19527c478bd9Sstevel@tonic-gate next = end + strspn(end, whitespace); 19537c478bd9Sstevel@tonic-gate 19547c478bd9Sstevel@tonic-gate /* if there's a comma, it separates the fields */ 19557c478bd9Sstevel@tonic-gate if (*next == ',') 19567c478bd9Sstevel@tonic-gate ++next; 19577c478bd9Sstevel@tonic-gate 19587c478bd9Sstevel@tonic-gate *end = '\0'; 19597c478bd9Sstevel@tonic-gate 1960f48205beScasper if ((ci->groups[i] = get_gid(cp)) == (gid_t)-1) { 19617c478bd9Sstevel@tonic-gate ci->ngroups = 0; 19627c478bd9Sstevel@tonic-gate return (EINVAL); 19637c478bd9Sstevel@tonic-gate } 19647c478bd9Sstevel@tonic-gate 19657c478bd9Sstevel@tonic-gate ++i; 19667c478bd9Sstevel@tonic-gate if (i > NGROUPS_MAX - 1) { 19677c478bd9Sstevel@tonic-gate ci->ngroups = 0; 19687c478bd9Sstevel@tonic-gate return (E2BIG); 19697c478bd9Sstevel@tonic-gate } 19707c478bd9Sstevel@tonic-gate 19717c478bd9Sstevel@tonic-gate cp = next; 19727c478bd9Sstevel@tonic-gate } 19737c478bd9Sstevel@tonic-gate 19747c478bd9Sstevel@tonic-gate ci->ngroups = i; 19757c478bd9Sstevel@tonic-gate return (0); 19767c478bd9Sstevel@tonic-gate } 19777c478bd9Sstevel@tonic-gate 19787c478bd9Sstevel@tonic-gate /* 19797c478bd9Sstevel@tonic-gate * Eventually, we will return a structured error in the case of 19807c478bd9Sstevel@tonic-gate * retryable or abortable failures such as memory allocation errors and 19817c478bd9Sstevel@tonic-gate * repository connection failures. For now, these failures are just 19827c478bd9Sstevel@tonic-gate * encoded in the failure string. 19837c478bd9Sstevel@tonic-gate */ 19847c478bd9Sstevel@tonic-gate static const char * 1985*13d8aaa1SSean Wilcox get_profile(scf_propertygroup_t *methpg, scf_propertygroup_t *instpg, 1986*13d8aaa1SSean Wilcox scf_property_t *prop, scf_value_t *val, const char *cmdline, 1987*13d8aaa1SSean Wilcox struct method_context *ci) 19887c478bd9Sstevel@tonic-gate { 19897c478bd9Sstevel@tonic-gate char *buf = ci->vbuf; 19907c478bd9Sstevel@tonic-gate ssize_t buf_sz = ci->vbuf_sz; 19917c478bd9Sstevel@tonic-gate char cmd[PATH_MAX]; 19927c478bd9Sstevel@tonic-gate char *cp, *value; 19937c478bd9Sstevel@tonic-gate const char *cmdp; 19947c478bd9Sstevel@tonic-gate execattr_t *eap; 1995*13d8aaa1SSean Wilcox const char *errstr = NULL; 19967c478bd9Sstevel@tonic-gate 1997*13d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_PROFILE, buf, buf_sz, prop, 1998*13d8aaa1SSean Wilcox val) == 0 || get_astring_val(instpg, SCF_PROPERTY_PROFILE, buf, 1999*13d8aaa1SSean Wilcox buf_sz, prop, val) == 0)) 20007c478bd9Sstevel@tonic-gate return ("Could not get profile property."); 20017c478bd9Sstevel@tonic-gate 20027c478bd9Sstevel@tonic-gate /* Extract the command from the command line. */ 20037c478bd9Sstevel@tonic-gate cp = strpbrk(cmdline, " \t"); 20047c478bd9Sstevel@tonic-gate 20057c478bd9Sstevel@tonic-gate if (cp == NULL) { 20067c478bd9Sstevel@tonic-gate cmdp = cmdline; 20077c478bd9Sstevel@tonic-gate } else { 20087c478bd9Sstevel@tonic-gate (void) strncpy(cmd, cmdline, cp - cmdline); 20097c478bd9Sstevel@tonic-gate cmd[cp - cmdline] = '\0'; 20107c478bd9Sstevel@tonic-gate cmdp = cmd; 20117c478bd9Sstevel@tonic-gate } 20127c478bd9Sstevel@tonic-gate 20137c478bd9Sstevel@tonic-gate /* Require that cmdp[0] == '/'? */ 20147c478bd9Sstevel@tonic-gate 20157c478bd9Sstevel@tonic-gate eap = getexecprof(buf, KV_COMMAND, cmdp, GET_ONE); 20167c478bd9Sstevel@tonic-gate if (eap == NULL) 20177c478bd9Sstevel@tonic-gate return ("Could not find profile."); 20187c478bd9Sstevel@tonic-gate 20197c478bd9Sstevel@tonic-gate /* Based on pfexec.c */ 20207c478bd9Sstevel@tonic-gate 20217c478bd9Sstevel@tonic-gate /* Get the euid first so we don't override ci->pwd for the uid. */ 20227c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_EUID_KW)) != NULL) { 20237c478bd9Sstevel@tonic-gate if (get_uid(value, ci, &ci->euid) != 0) { 2024f48205beScasper ci->euid = (uid_t)-1; 20257c478bd9Sstevel@tonic-gate errstr = "Could not interpret profile euid."; 20267c478bd9Sstevel@tonic-gate goto out; 20277c478bd9Sstevel@tonic-gate } 20287c478bd9Sstevel@tonic-gate } 20297c478bd9Sstevel@tonic-gate 20307c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_UID_KW)) != NULL) { 20317c478bd9Sstevel@tonic-gate if (get_uid(value, ci, &ci->uid) != 0) { 2032f48205beScasper ci->euid = ci->uid = (uid_t)-1; 20337c478bd9Sstevel@tonic-gate errstr = "Could not interpret profile uid."; 20347c478bd9Sstevel@tonic-gate goto out; 20357c478bd9Sstevel@tonic-gate } 20367c478bd9Sstevel@tonic-gate ci->euid = ci->uid; 20377c478bd9Sstevel@tonic-gate } 20387c478bd9Sstevel@tonic-gate 20397c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_GID_KW)) != NULL) { 20407c478bd9Sstevel@tonic-gate ci->egid = ci->gid = get_gid(value); 2041f48205beScasper if (ci->gid == (gid_t)-1) { 20427c478bd9Sstevel@tonic-gate errstr = "Could not interpret profile gid."; 20437c478bd9Sstevel@tonic-gate goto out; 20447c478bd9Sstevel@tonic-gate } 20457c478bd9Sstevel@tonic-gate } 20467c478bd9Sstevel@tonic-gate 20477c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_EGID_KW)) != NULL) { 20487c478bd9Sstevel@tonic-gate ci->egid = get_gid(value); 2049f48205beScasper if (ci->egid == (gid_t)-1) { 20507c478bd9Sstevel@tonic-gate errstr = "Could not interpret profile egid."; 20517c478bd9Sstevel@tonic-gate goto out; 20527c478bd9Sstevel@tonic-gate } 20537c478bd9Sstevel@tonic-gate } 20547c478bd9Sstevel@tonic-gate 20557c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_LPRIV_KW)) != NULL) { 20567c478bd9Sstevel@tonic-gate ci->lpriv_set = priv_str_to_set(value, ",", NULL); 20577c478bd9Sstevel@tonic-gate if (ci->lpriv_set == NULL) { 20587c478bd9Sstevel@tonic-gate if (errno != EINVAL) 20597c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 20607c478bd9Sstevel@tonic-gate else 20617c478bd9Sstevel@tonic-gate errstr = "Could not interpret profile " 20627c478bd9Sstevel@tonic-gate "limitprivs."; 20637c478bd9Sstevel@tonic-gate goto out; 20647c478bd9Sstevel@tonic-gate } 20657c478bd9Sstevel@tonic-gate } 20667c478bd9Sstevel@tonic-gate 20677c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_IPRIV_KW)) != NULL) { 20687c478bd9Sstevel@tonic-gate ci->priv_set = priv_str_to_set(value, ",", NULL); 20697c478bd9Sstevel@tonic-gate if (ci->priv_set == NULL) { 20707c478bd9Sstevel@tonic-gate if (errno != EINVAL) 20717c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 20727c478bd9Sstevel@tonic-gate else 20737c478bd9Sstevel@tonic-gate errstr = "Could not interpret profile privs."; 20747c478bd9Sstevel@tonic-gate goto out; 20757c478bd9Sstevel@tonic-gate } 20767c478bd9Sstevel@tonic-gate } 20777c478bd9Sstevel@tonic-gate 20787c478bd9Sstevel@tonic-gate out: 20797c478bd9Sstevel@tonic-gate free_execattr(eap); 20807c478bd9Sstevel@tonic-gate 20817c478bd9Sstevel@tonic-gate return (errstr); 20827c478bd9Sstevel@tonic-gate } 20837c478bd9Sstevel@tonic-gate 20847c478bd9Sstevel@tonic-gate /* 20857c478bd9Sstevel@tonic-gate * Eventually, we will return a structured error in the case of 20867c478bd9Sstevel@tonic-gate * retryable or abortable failures such as memory allocation errors and 20877c478bd9Sstevel@tonic-gate * repository connection failures. For now, these failures are just 20887c478bd9Sstevel@tonic-gate * encoded in the failure string. 20897c478bd9Sstevel@tonic-gate */ 20907c478bd9Sstevel@tonic-gate static const char * 2091*13d8aaa1SSean Wilcox get_ids(scf_propertygroup_t *methpg, scf_propertygroup_t *instpg, 2092*13d8aaa1SSean Wilcox scf_property_t *prop, scf_value_t *val, struct method_context *ci) 20937c478bd9Sstevel@tonic-gate { 2094*13d8aaa1SSean Wilcox char *errstr = NULL; 20957c478bd9Sstevel@tonic-gate char *vbuf = ci->vbuf; 20967c478bd9Sstevel@tonic-gate ssize_t vbuf_sz = ci->vbuf_sz; 20977c478bd9Sstevel@tonic-gate int r; 20987c478bd9Sstevel@tonic-gate 2099*13d8aaa1SSean Wilcox /* 2100*13d8aaa1SSean Wilcox * This should never happen because the caller should fall through 2101*13d8aaa1SSean Wilcox * another path of just setting the ids to defaults, instead of 2102*13d8aaa1SSean Wilcox * attempting to get the ids here. 2103*13d8aaa1SSean Wilcox */ 2104*13d8aaa1SSean Wilcox if (methpg == NULL && instpg == NULL) { 2105*13d8aaa1SSean Wilcox errstr = "No property groups to get ids from."; 2106*13d8aaa1SSean Wilcox goto out; 2107*13d8aaa1SSean Wilcox } 2108*13d8aaa1SSean Wilcox 2109*13d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_USER, 2110*13d8aaa1SSean Wilcox vbuf, vbuf_sz, prop, val) == 0 || get_astring_val(instpg, 2111*13d8aaa1SSean Wilcox SCF_PROPERTY_USER, vbuf, vbuf_sz, prop, 2112*13d8aaa1SSean Wilcox val) == 0)) { 21137c478bd9Sstevel@tonic-gate errstr = "Could not get user property."; 21147c478bd9Sstevel@tonic-gate goto out; 21157c478bd9Sstevel@tonic-gate } 21167c478bd9Sstevel@tonic-gate 21177c478bd9Sstevel@tonic-gate if (get_uid(vbuf, ci, &ci->uid) != 0) { 2118f48205beScasper ci->uid = (uid_t)-1; 21197c478bd9Sstevel@tonic-gate errstr = "Could not interpret user property."; 21207c478bd9Sstevel@tonic-gate goto out; 21217c478bd9Sstevel@tonic-gate } 21227c478bd9Sstevel@tonic-gate 2123*13d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_GROUP, vbuf, vbuf_sz, prop, 2124*13d8aaa1SSean Wilcox val) == 0 || get_astring_val(instpg, SCF_PROPERTY_GROUP, vbuf, 2125*13d8aaa1SSean Wilcox vbuf_sz, prop, val) == 0)) { 2126*13d8aaa1SSean Wilcox if (scf_error() == SCF_ERROR_NOT_FOUND) { 2127*13d8aaa1SSean Wilcox (void) strcpy(vbuf, ":default"); 2128*13d8aaa1SSean Wilcox } else { 21297c478bd9Sstevel@tonic-gate errstr = "Could not get group property."; 21307c478bd9Sstevel@tonic-gate goto out; 21317c478bd9Sstevel@tonic-gate } 2132*13d8aaa1SSean Wilcox } 21337c478bd9Sstevel@tonic-gate 21347c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") != 0) { 21357c478bd9Sstevel@tonic-gate ci->gid = get_gid(vbuf); 2136f48205beScasper if (ci->gid == (gid_t)-1) { 21377c478bd9Sstevel@tonic-gate errstr = "Could not interpret group property."; 21387c478bd9Sstevel@tonic-gate goto out; 21397c478bd9Sstevel@tonic-gate } 21407c478bd9Sstevel@tonic-gate } else { 21417c478bd9Sstevel@tonic-gate switch (r = lookup_pwd(ci)) { 21427c478bd9Sstevel@tonic-gate case 0: 21437c478bd9Sstevel@tonic-gate ci->gid = ci->pwd.pw_gid; 21447c478bd9Sstevel@tonic-gate break; 21457c478bd9Sstevel@tonic-gate 21467c478bd9Sstevel@tonic-gate case ENOENT: 2147f48205beScasper ci->gid = (gid_t)-1; 21487c478bd9Sstevel@tonic-gate errstr = "No passwd entry."; 21497c478bd9Sstevel@tonic-gate goto out; 21507c478bd9Sstevel@tonic-gate 21517c478bd9Sstevel@tonic-gate case ENOMEM: 21527c478bd9Sstevel@tonic-gate errstr = "Out of memory."; 21537c478bd9Sstevel@tonic-gate goto out; 21547c478bd9Sstevel@tonic-gate 21557c478bd9Sstevel@tonic-gate case EIO: 21567c478bd9Sstevel@tonic-gate case EMFILE: 21577c478bd9Sstevel@tonic-gate case ENFILE: 21587c478bd9Sstevel@tonic-gate errstr = "getpwuid_r() failed."; 21597c478bd9Sstevel@tonic-gate goto out; 21607c478bd9Sstevel@tonic-gate 21617c478bd9Sstevel@tonic-gate default: 21627c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", r); 21637c478bd9Sstevel@tonic-gate } 21647c478bd9Sstevel@tonic-gate } 21657c478bd9Sstevel@tonic-gate 2166*13d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_SUPP_GROUPS, vbuf, vbuf_sz, 2167*13d8aaa1SSean Wilcox prop, val) == 0 || get_astring_val(instpg, 2168*13d8aaa1SSean Wilcox SCF_PROPERTY_SUPP_GROUPS, vbuf, vbuf_sz, prop, val) == 0)) { 2169*13d8aaa1SSean Wilcox if (scf_error() == SCF_ERROR_NOT_FOUND) { 2170*13d8aaa1SSean Wilcox (void) strcpy(vbuf, ":default"); 2171*13d8aaa1SSean Wilcox } else { 21727c478bd9Sstevel@tonic-gate errstr = "Could not get supplemental groups property."; 21737c478bd9Sstevel@tonic-gate goto out; 21747c478bd9Sstevel@tonic-gate } 2175*13d8aaa1SSean Wilcox } 21767c478bd9Sstevel@tonic-gate 21777c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") != 0) { 21787c478bd9Sstevel@tonic-gate switch (r = get_groups(vbuf, ci)) { 21797c478bd9Sstevel@tonic-gate case 0: 21807c478bd9Sstevel@tonic-gate break; 21817c478bd9Sstevel@tonic-gate 21827c478bd9Sstevel@tonic-gate case EINVAL: 21837c478bd9Sstevel@tonic-gate errstr = 21847c478bd9Sstevel@tonic-gate "Could not interpret supplemental groups property."; 21857c478bd9Sstevel@tonic-gate goto out; 21867c478bd9Sstevel@tonic-gate 21877c478bd9Sstevel@tonic-gate case E2BIG: 21887c478bd9Sstevel@tonic-gate errstr = "Too many supplemental groups."; 21897c478bd9Sstevel@tonic-gate goto out; 21907c478bd9Sstevel@tonic-gate 21917c478bd9Sstevel@tonic-gate default: 21927c478bd9Sstevel@tonic-gate bad_fail("get_groups", r); 21937c478bd9Sstevel@tonic-gate } 21947c478bd9Sstevel@tonic-gate } else { 21957c478bd9Sstevel@tonic-gate ci->ngroups = -1; 21967c478bd9Sstevel@tonic-gate } 21977c478bd9Sstevel@tonic-gate 2198*13d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_PRIVILEGES, vbuf, vbuf_sz, 2199*13d8aaa1SSean Wilcox prop, val) == 0 || get_astring_val(instpg, SCF_PROPERTY_PRIVILEGES, 2200*13d8aaa1SSean Wilcox vbuf, vbuf_sz, prop, val) == 0)) { 2201*13d8aaa1SSean Wilcox if (scf_error() == SCF_ERROR_NOT_FOUND) { 2202*13d8aaa1SSean Wilcox (void) strcpy(vbuf, ":default"); 2203*13d8aaa1SSean Wilcox } else { 22047c478bd9Sstevel@tonic-gate errstr = "Could not get privileges property."; 22057c478bd9Sstevel@tonic-gate goto out; 22067c478bd9Sstevel@tonic-gate } 2207*13d8aaa1SSean Wilcox } 22087c478bd9Sstevel@tonic-gate 22097c478bd9Sstevel@tonic-gate /* 22107c478bd9Sstevel@tonic-gate * For default privs, we need to keep priv_set == NULL, as 22117c478bd9Sstevel@tonic-gate * we use this test elsewhere. 22127c478bd9Sstevel@tonic-gate */ 22137c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") != 0) { 22147c478bd9Sstevel@tonic-gate ci->priv_set = priv_str_to_set(vbuf, ",", NULL); 22157c478bd9Sstevel@tonic-gate if (ci->priv_set == NULL) { 22167c478bd9Sstevel@tonic-gate if (errno != EINVAL) { 22177c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 22187c478bd9Sstevel@tonic-gate } else { 2219*13d8aaa1SSean Wilcox errstr = 2220*13d8aaa1SSean Wilcox "Could not interpret privileges property."; 22217c478bd9Sstevel@tonic-gate } 22227c478bd9Sstevel@tonic-gate goto out; 22237c478bd9Sstevel@tonic-gate } 22247c478bd9Sstevel@tonic-gate } 22257c478bd9Sstevel@tonic-gate 2226*13d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_LIMIT_PRIVILEGES, vbuf, 2227*13d8aaa1SSean Wilcox vbuf_sz, prop, val) == 0 || get_astring_val(instpg, 2228*13d8aaa1SSean Wilcox SCF_PROPERTY_LIMIT_PRIVILEGES, vbuf, vbuf_sz, prop, val) == 0)) { 2229*13d8aaa1SSean Wilcox if (scf_error() == SCF_ERROR_NOT_FOUND) { 2230*13d8aaa1SSean Wilcox (void) strcpy(vbuf, ":default"); 2231*13d8aaa1SSean Wilcox } else { 22327c478bd9Sstevel@tonic-gate errstr = "Could not get limit_privileges property."; 22337c478bd9Sstevel@tonic-gate goto out; 22347c478bd9Sstevel@tonic-gate } 2235*13d8aaa1SSean Wilcox } 22367c478bd9Sstevel@tonic-gate 22377c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") == 0) 22387c478bd9Sstevel@tonic-gate /* 22397c478bd9Sstevel@tonic-gate * L must default to all privileges so root NPA services see 22407c478bd9Sstevel@tonic-gate * iE = all. "zone" is all privileges available in the current 22417c478bd9Sstevel@tonic-gate * zone, equivalent to "all" in the global zone. 22427c478bd9Sstevel@tonic-gate */ 22437c478bd9Sstevel@tonic-gate (void) strcpy(vbuf, "zone"); 22447c478bd9Sstevel@tonic-gate 22457c478bd9Sstevel@tonic-gate ci->lpriv_set = priv_str_to_set(vbuf, ",", NULL); 22467c478bd9Sstevel@tonic-gate if (ci->lpriv_set == NULL) { 22477c478bd9Sstevel@tonic-gate if (errno != EINVAL) 22487c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 22497c478bd9Sstevel@tonic-gate else { 2250*13d8aaa1SSean Wilcox errstr = 2251*13d8aaa1SSean Wilcox "Could not interpret limit_privileges property."; 22527c478bd9Sstevel@tonic-gate } 22537c478bd9Sstevel@tonic-gate goto out; 22547c478bd9Sstevel@tonic-gate } 22557c478bd9Sstevel@tonic-gate 22567c478bd9Sstevel@tonic-gate out: 22577c478bd9Sstevel@tonic-gate return (errstr); 22587c478bd9Sstevel@tonic-gate } 22597c478bd9Sstevel@tonic-gate 22607c478bd9Sstevel@tonic-gate static int 22617c478bd9Sstevel@tonic-gate get_environment(scf_handle_t *h, scf_propertygroup_t *pg, 22627c478bd9Sstevel@tonic-gate struct method_context *mcp, scf_property_t *prop, scf_value_t *val) 22637c478bd9Sstevel@tonic-gate { 22647c478bd9Sstevel@tonic-gate scf_iter_t *iter; 22657c478bd9Sstevel@tonic-gate scf_type_t type; 22667c478bd9Sstevel@tonic-gate size_t i = 0; 22677c478bd9Sstevel@tonic-gate int ret; 22687c478bd9Sstevel@tonic-gate 22697c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_ENVIRONMENT, prop) != 0) { 22707c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_NOT_FOUND) 22717c478bd9Sstevel@tonic-gate return (ENOENT); 22727c478bd9Sstevel@tonic-gate return (scf_error()); 22737c478bd9Sstevel@tonic-gate } 22747c478bd9Sstevel@tonic-gate if (scf_property_type(prop, &type) != 0) 22757c478bd9Sstevel@tonic-gate return (scf_error()); 22767c478bd9Sstevel@tonic-gate if (type != SCF_TYPE_ASTRING) 22777c478bd9Sstevel@tonic-gate return (EINVAL); 22787c478bd9Sstevel@tonic-gate if ((iter = scf_iter_create(h)) == NULL) 22797c478bd9Sstevel@tonic-gate return (scf_error()); 22807c478bd9Sstevel@tonic-gate 22817c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) { 22827c478bd9Sstevel@tonic-gate ret = scf_error(); 22837c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 22847c478bd9Sstevel@tonic-gate return (ret); 22857c478bd9Sstevel@tonic-gate } 22867c478bd9Sstevel@tonic-gate 22877c478bd9Sstevel@tonic-gate mcp->env_sz = 10; 22887c478bd9Sstevel@tonic-gate 22897c478bd9Sstevel@tonic-gate if ((mcp->env = uu_zalloc(sizeof (*mcp->env) * mcp->env_sz)) == NULL) { 22907c478bd9Sstevel@tonic-gate ret = ENOMEM; 22917c478bd9Sstevel@tonic-gate goto out; 22927c478bd9Sstevel@tonic-gate } 22937c478bd9Sstevel@tonic-gate 22947c478bd9Sstevel@tonic-gate while ((ret = scf_iter_next_value(iter, val)) == 1) { 22957c478bd9Sstevel@tonic-gate ret = scf_value_get_as_string(val, mcp->vbuf, mcp->vbuf_sz); 22967c478bd9Sstevel@tonic-gate if (ret == -1) { 22977c478bd9Sstevel@tonic-gate ret = scf_error(); 22987c478bd9Sstevel@tonic-gate goto out; 22997c478bd9Sstevel@tonic-gate } 23007c478bd9Sstevel@tonic-gate 23017c478bd9Sstevel@tonic-gate if ((mcp->env[i] = strdup(mcp->vbuf)) == NULL) { 23027c478bd9Sstevel@tonic-gate ret = ENOMEM; 23037c478bd9Sstevel@tonic-gate goto out; 23047c478bd9Sstevel@tonic-gate } 23057c478bd9Sstevel@tonic-gate 23067c478bd9Sstevel@tonic-gate if (++i == mcp->env_sz) { 23077c478bd9Sstevel@tonic-gate char **env; 23087c478bd9Sstevel@tonic-gate mcp->env_sz *= 2; 23097c478bd9Sstevel@tonic-gate env = uu_zalloc(sizeof (*mcp->env) * mcp->env_sz); 23107c478bd9Sstevel@tonic-gate if (env == NULL) { 23117c478bd9Sstevel@tonic-gate ret = ENOMEM; 23127c478bd9Sstevel@tonic-gate goto out; 23137c478bd9Sstevel@tonic-gate } 23147c478bd9Sstevel@tonic-gate (void) memcpy(env, mcp->env, 23157c478bd9Sstevel@tonic-gate sizeof (*mcp->env) * (mcp->env_sz / 2)); 23167c478bd9Sstevel@tonic-gate free(mcp->env); 23177c478bd9Sstevel@tonic-gate mcp->env = env; 23187c478bd9Sstevel@tonic-gate } 23197c478bd9Sstevel@tonic-gate } 23207c478bd9Sstevel@tonic-gate 23217c478bd9Sstevel@tonic-gate if (ret == -1) 23227c478bd9Sstevel@tonic-gate ret = scf_error(); 23237c478bd9Sstevel@tonic-gate 23247c478bd9Sstevel@tonic-gate out: 23257c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 23267c478bd9Sstevel@tonic-gate return (ret); 23277c478bd9Sstevel@tonic-gate } 23287c478bd9Sstevel@tonic-gate 23297c478bd9Sstevel@tonic-gate /* 23307c478bd9Sstevel@tonic-gate * Fetch method context information from the repository, allocate and fill 23317c478bd9Sstevel@tonic-gate * a method_context structure, return it in *mcpp, and return NULL. On error, 23327c478bd9Sstevel@tonic-gate * return a human-readable string which indicates the error. 23337c478bd9Sstevel@tonic-gate * 2334*13d8aaa1SSean Wilcox * If no method_context is defined, original init context is provided, where 2335*13d8aaa1SSean Wilcox * the working directory is '/', and uid/gid are 0/0. But if a method_context 2336*13d8aaa1SSean Wilcox * is defined at any level the smf_method(5) method_context defaults are used. 2337*13d8aaa1SSean Wilcox * 23387c478bd9Sstevel@tonic-gate * Eventually, we will return a structured error in the case of 23397c478bd9Sstevel@tonic-gate * retryable or abortable failures such as memory allocation errors and 23407c478bd9Sstevel@tonic-gate * repository connection failures. For now, these failures are just 23417c478bd9Sstevel@tonic-gate * encoded in the failure string. 23427c478bd9Sstevel@tonic-gate */ 23437c478bd9Sstevel@tonic-gate const char * 23447c478bd9Sstevel@tonic-gate restarter_get_method_context(uint_t version, scf_instance_t *inst, 23457c478bd9Sstevel@tonic-gate scf_snapshot_t *snap, const char *mname, const char *cmdline, 23467c478bd9Sstevel@tonic-gate struct method_context **mcpp) 23477c478bd9Sstevel@tonic-gate { 23487c478bd9Sstevel@tonic-gate scf_handle_t *h; 23497c478bd9Sstevel@tonic-gate scf_propertygroup_t *methpg = NULL; 23507c478bd9Sstevel@tonic-gate scf_propertygroup_t *instpg = NULL; 23517c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 23527c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL; 23537c478bd9Sstevel@tonic-gate scf_value_t *val = NULL; 23547c478bd9Sstevel@tonic-gate scf_type_t ty; 23557c478bd9Sstevel@tonic-gate uint8_t use_profile; 23567c478bd9Sstevel@tonic-gate int ret; 2357*13d8aaa1SSean Wilcox int mc_used = 0; 23587c478bd9Sstevel@tonic-gate const char *errstr = NULL; 23597c478bd9Sstevel@tonic-gate struct method_context *cip; 23607c478bd9Sstevel@tonic-gate 23617c478bd9Sstevel@tonic-gate if (version != RESTARTER_METHOD_CONTEXT_VERSION) 23627c478bd9Sstevel@tonic-gate return ("Unknown method_context version."); 23637c478bd9Sstevel@tonic-gate 23647c478bd9Sstevel@tonic-gate /* Get the handle before we allocate anything. */ 23657c478bd9Sstevel@tonic-gate h = scf_instance_handle(inst); 23667c478bd9Sstevel@tonic-gate if (h == NULL) 23677c478bd9Sstevel@tonic-gate return (scf_strerror(scf_error())); 23687c478bd9Sstevel@tonic-gate 23697c478bd9Sstevel@tonic-gate cip = malloc(sizeof (*cip)); 23707c478bd9Sstevel@tonic-gate if (cip == NULL) 23717c478bd9Sstevel@tonic-gate return (ALLOCFAIL); 23727c478bd9Sstevel@tonic-gate 23737c478bd9Sstevel@tonic-gate (void) memset(cip, 0, sizeof (*cip)); 2374f48205beScasper cip->uid = (uid_t)-1; 2375f48205beScasper cip->euid = (uid_t)-1; 2376f48205beScasper cip->gid = (gid_t)-1; 2377f48205beScasper cip->egid = (gid_t)-1; 23787c478bd9Sstevel@tonic-gate 23797c478bd9Sstevel@tonic-gate cip->vbuf_sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 23807c478bd9Sstevel@tonic-gate assert(cip->vbuf_sz >= 0); 23817c478bd9Sstevel@tonic-gate cip->vbuf = malloc(cip->vbuf_sz); 23827c478bd9Sstevel@tonic-gate if (cip->vbuf == NULL) { 23837c478bd9Sstevel@tonic-gate free(cip); 23847c478bd9Sstevel@tonic-gate return (ALLOCFAIL); 23857c478bd9Sstevel@tonic-gate } 23867c478bd9Sstevel@tonic-gate 23877c478bd9Sstevel@tonic-gate if ((instpg = scf_pg_create(h)) == NULL || 23887c478bd9Sstevel@tonic-gate (methpg = scf_pg_create(h)) == NULL || 23897c478bd9Sstevel@tonic-gate (prop = scf_property_create(h)) == NULL || 23907c478bd9Sstevel@tonic-gate (val = scf_value_create(h)) == NULL) { 23917c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 23927c478bd9Sstevel@tonic-gate goto out; 23937c478bd9Sstevel@tonic-gate } 23947c478bd9Sstevel@tonic-gate 23957c478bd9Sstevel@tonic-gate /* 23967c478bd9Sstevel@tonic-gate * The method environment, and the credentials/profile data, 23977c478bd9Sstevel@tonic-gate * may be found either in the pg for the method (methpg), 23987c478bd9Sstevel@tonic-gate * or in the instance/service SCF_PG_METHOD_CONTEXT pg (named 23997c478bd9Sstevel@tonic-gate * instpg below). 24007c478bd9Sstevel@tonic-gate */ 24017c478bd9Sstevel@tonic-gate 24027c478bd9Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, snap, mname, methpg) != 24037c478bd9Sstevel@tonic-gate SCF_SUCCESS) { 24047c478bd9Sstevel@tonic-gate errstr = scf_strerror(scf_error()); 24057c478bd9Sstevel@tonic-gate goto out; 24067c478bd9Sstevel@tonic-gate } 24077c478bd9Sstevel@tonic-gate 24087c478bd9Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, snap, SCF_PG_METHOD_CONTEXT, 24097c478bd9Sstevel@tonic-gate instpg) != SCF_SUCCESS) { 24107c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) { 24117c478bd9Sstevel@tonic-gate errstr = scf_strerror(scf_error()); 24127c478bd9Sstevel@tonic-gate goto out; 24137c478bd9Sstevel@tonic-gate } 24147c478bd9Sstevel@tonic-gate scf_pg_destroy(instpg); 24157c478bd9Sstevel@tonic-gate instpg = NULL; 2416*13d8aaa1SSean Wilcox } else { 2417*13d8aaa1SSean Wilcox mc_used++; 24187c478bd9Sstevel@tonic-gate } 24197c478bd9Sstevel@tonic-gate 24207c478bd9Sstevel@tonic-gate ret = get_environment(h, methpg, cip, prop, val); 24217c478bd9Sstevel@tonic-gate if (ret == ENOENT && instpg != NULL) { 24227c478bd9Sstevel@tonic-gate ret = get_environment(h, instpg, cip, prop, val); 24237c478bd9Sstevel@tonic-gate } 24247c478bd9Sstevel@tonic-gate 24257c478bd9Sstevel@tonic-gate switch (ret) { 24267c478bd9Sstevel@tonic-gate case 0: 2427*13d8aaa1SSean Wilcox mc_used++; 2428*13d8aaa1SSean Wilcox break; 24297c478bd9Sstevel@tonic-gate case ENOENT: 24307c478bd9Sstevel@tonic-gate break; 24317c478bd9Sstevel@tonic-gate case ENOMEM: 24327c478bd9Sstevel@tonic-gate errstr = "Out of memory."; 24337c478bd9Sstevel@tonic-gate goto out; 24347c478bd9Sstevel@tonic-gate case EINVAL: 24357c478bd9Sstevel@tonic-gate errstr = "Invalid method environment."; 24367c478bd9Sstevel@tonic-gate goto out; 24377c478bd9Sstevel@tonic-gate default: 24387c478bd9Sstevel@tonic-gate errstr = scf_strerror(ret); 24397c478bd9Sstevel@tonic-gate goto out; 24407c478bd9Sstevel@tonic-gate } 24417c478bd9Sstevel@tonic-gate 24427c478bd9Sstevel@tonic-gate pg = methpg; 24437c478bd9Sstevel@tonic-gate 24447c478bd9Sstevel@tonic-gate ret = scf_pg_get_property(pg, SCF_PROPERTY_USE_PROFILE, prop); 24457c478bd9Sstevel@tonic-gate if (ret && scf_error() == SCF_ERROR_NOT_FOUND && instpg != NULL) { 2446*13d8aaa1SSean Wilcox pg = NULL; 2447*13d8aaa1SSean Wilcox ret = scf_pg_get_property(instpg, SCF_PROPERTY_USE_PROFILE, 2448*13d8aaa1SSean Wilcox prop); 24497c478bd9Sstevel@tonic-gate } 24507c478bd9Sstevel@tonic-gate 24517c478bd9Sstevel@tonic-gate if (ret) { 24527c478bd9Sstevel@tonic-gate switch (scf_error()) { 24537c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 2454*13d8aaa1SSean Wilcox /* No profile context: use default credentials */ 24557c478bd9Sstevel@tonic-gate cip->uid = 0; 24567c478bd9Sstevel@tonic-gate cip->gid = 0; 2457*13d8aaa1SSean Wilcox break; 24587c478bd9Sstevel@tonic-gate 24597c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 24607c478bd9Sstevel@tonic-gate errstr = RCBROKEN; 24617c478bd9Sstevel@tonic-gate goto out; 24627c478bd9Sstevel@tonic-gate 24637c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 24647c478bd9Sstevel@tonic-gate errstr = "\"use_profile\" property deleted."; 24657c478bd9Sstevel@tonic-gate goto out; 24667c478bd9Sstevel@tonic-gate 24677c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 24687c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 24697c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 24707c478bd9Sstevel@tonic-gate default: 24717c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error()); 24727c478bd9Sstevel@tonic-gate } 2473*13d8aaa1SSean Wilcox } else { 24747c478bd9Sstevel@tonic-gate if (scf_property_type(prop, &ty) != SCF_SUCCESS) { 24757c478bd9Sstevel@tonic-gate switch (scf_error()) { 24767c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 24777c478bd9Sstevel@tonic-gate errstr = RCBROKEN; 24787c478bd9Sstevel@tonic-gate break; 24797c478bd9Sstevel@tonic-gate 24807c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 24817c478bd9Sstevel@tonic-gate errstr = "\"use profile\" property deleted."; 24827c478bd9Sstevel@tonic-gate break; 24837c478bd9Sstevel@tonic-gate 24847c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 24857c478bd9Sstevel@tonic-gate default: 24867c478bd9Sstevel@tonic-gate bad_fail("scf_property_type", scf_error()); 24877c478bd9Sstevel@tonic-gate } 24887c478bd9Sstevel@tonic-gate 24897c478bd9Sstevel@tonic-gate goto out; 24907c478bd9Sstevel@tonic-gate } 24917c478bd9Sstevel@tonic-gate 24927c478bd9Sstevel@tonic-gate if (ty != SCF_TYPE_BOOLEAN) { 24937c478bd9Sstevel@tonic-gate errstr = "\"use profile\" property is not boolean."; 24947c478bd9Sstevel@tonic-gate goto out; 24957c478bd9Sstevel@tonic-gate } 24967c478bd9Sstevel@tonic-gate 24977c478bd9Sstevel@tonic-gate if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 24987c478bd9Sstevel@tonic-gate switch (scf_error()) { 24997c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 25007c478bd9Sstevel@tonic-gate errstr = RCBROKEN; 25017c478bd9Sstevel@tonic-gate break; 25027c478bd9Sstevel@tonic-gate 25037c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 25047c478bd9Sstevel@tonic-gate errstr = 2505*13d8aaa1SSean Wilcox "\"use profile\" property has multiple " 2506*13d8aaa1SSean Wilcox "values."; 25077c478bd9Sstevel@tonic-gate break; 25087c478bd9Sstevel@tonic-gate 25097c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 2510*13d8aaa1SSean Wilcox errstr = "\"use profile\" property has no " 2511*13d8aaa1SSean Wilcox "values."; 25127c478bd9Sstevel@tonic-gate break; 25137c478bd9Sstevel@tonic-gate 25147c478bd9Sstevel@tonic-gate default: 25157c478bd9Sstevel@tonic-gate bad_fail("scf_property_get_value", scf_error()); 25167c478bd9Sstevel@tonic-gate } 25177c478bd9Sstevel@tonic-gate 25187c478bd9Sstevel@tonic-gate goto out; 25197c478bd9Sstevel@tonic-gate } 25207c478bd9Sstevel@tonic-gate 2521*13d8aaa1SSean Wilcox mc_used++; 25227c478bd9Sstevel@tonic-gate ret = scf_value_get_boolean(val, &use_profile); 25237c478bd9Sstevel@tonic-gate assert(ret == SCF_SUCCESS); 25247c478bd9Sstevel@tonic-gate 25257c478bd9Sstevel@tonic-gate /* get ids & privileges */ 25267c478bd9Sstevel@tonic-gate if (use_profile) 2527*13d8aaa1SSean Wilcox errstr = get_profile(pg, instpg, prop, val, cmdline, 2528*13d8aaa1SSean Wilcox cip); 25297c478bd9Sstevel@tonic-gate else 2530*13d8aaa1SSean Wilcox errstr = get_ids(pg, instpg, prop, val, cip); 2531*13d8aaa1SSean Wilcox 25327c478bd9Sstevel@tonic-gate if (errstr != NULL) 25337c478bd9Sstevel@tonic-gate goto out; 2534*13d8aaa1SSean Wilcox } 25357c478bd9Sstevel@tonic-gate 25367c478bd9Sstevel@tonic-gate /* get working directory */ 2537*13d8aaa1SSean Wilcox if ((methpg != NULL && scf_pg_get_property(methpg, 2538*13d8aaa1SSean Wilcox SCF_PROPERTY_WORKING_DIRECTORY, prop) == SCF_SUCCESS) || 2539*13d8aaa1SSean Wilcox (instpg != NULL && scf_pg_get_property(instpg, 2540*13d8aaa1SSean Wilcox SCF_PROPERTY_WORKING_DIRECTORY, prop) == SCF_SUCCESS)) { 2541*13d8aaa1SSean Wilcox if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 2542*13d8aaa1SSean Wilcox switch (scf_error()) { 2543*13d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN: 2544*13d8aaa1SSean Wilcox errstr = RCBROKEN; 2545*13d8aaa1SSean Wilcox break; 2546*13d8aaa1SSean Wilcox 2547*13d8aaa1SSean Wilcox case SCF_ERROR_CONSTRAINT_VIOLATED: 2548*13d8aaa1SSean Wilcox errstr = 2549*13d8aaa1SSean Wilcox "\"working directory\" property has " 2550*13d8aaa1SSean Wilcox "multiple values."; 2551*13d8aaa1SSean Wilcox break; 2552*13d8aaa1SSean Wilcox 2553*13d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND: 2554*13d8aaa1SSean Wilcox errstr = "\"working directory\" property has " 2555*13d8aaa1SSean Wilcox "no values."; 2556*13d8aaa1SSean Wilcox break; 2557*13d8aaa1SSean Wilcox 2558*13d8aaa1SSean Wilcox default: 2559*13d8aaa1SSean Wilcox bad_fail("scf_property_get_value", scf_error()); 2560*13d8aaa1SSean Wilcox } 2561*13d8aaa1SSean Wilcox 25627c478bd9Sstevel@tonic-gate goto out; 25637c478bd9Sstevel@tonic-gate } 25647c478bd9Sstevel@tonic-gate 2565*13d8aaa1SSean Wilcox mc_used++; 2566*13d8aaa1SSean Wilcox ret = scf_value_get_astring(val, cip->vbuf, cip->vbuf_sz); 2567*13d8aaa1SSean Wilcox assert(ret != -1); 2568*13d8aaa1SSean Wilcox } else { 2569*13d8aaa1SSean Wilcox switch (scf_error()) { 2570*13d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND: 2571*13d8aaa1SSean Wilcox /* okay if missing. */ 2572*13d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default"); 2573*13d8aaa1SSean Wilcox break; 2574*13d8aaa1SSean Wilcox 2575*13d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN: 2576*13d8aaa1SSean Wilcox errstr = RCBROKEN; 2577*13d8aaa1SSean Wilcox goto out; 2578*13d8aaa1SSean Wilcox 2579*13d8aaa1SSean Wilcox case SCF_ERROR_DELETED: 2580*13d8aaa1SSean Wilcox errstr = "\"working_directory\" property deleted."; 2581*13d8aaa1SSean Wilcox goto out; 2582*13d8aaa1SSean Wilcox 2583*13d8aaa1SSean Wilcox case SCF_ERROR_HANDLE_MISMATCH: 2584*13d8aaa1SSean Wilcox case SCF_ERROR_INVALID_ARGUMENT: 2585*13d8aaa1SSean Wilcox case SCF_ERROR_NOT_SET: 2586*13d8aaa1SSean Wilcox default: 2587*13d8aaa1SSean Wilcox bad_fail("scf_pg_get_property", scf_error()); 2588*13d8aaa1SSean Wilcox } 2589*13d8aaa1SSean Wilcox } 2590*13d8aaa1SSean Wilcox 25917c478bd9Sstevel@tonic-gate if (strcmp(cip->vbuf, ":default") == 0 || 25927c478bd9Sstevel@tonic-gate strcmp(cip->vbuf, ":home") == 0) { 25937c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 25947c478bd9Sstevel@tonic-gate case 0: 25957c478bd9Sstevel@tonic-gate break; 25967c478bd9Sstevel@tonic-gate 25977c478bd9Sstevel@tonic-gate case ENOMEM: 25987c478bd9Sstevel@tonic-gate errstr = "Out of memory."; 25997c478bd9Sstevel@tonic-gate goto out; 26007c478bd9Sstevel@tonic-gate 26017c478bd9Sstevel@tonic-gate case ENOENT: 26027c478bd9Sstevel@tonic-gate case EIO: 26037c478bd9Sstevel@tonic-gate case EMFILE: 26047c478bd9Sstevel@tonic-gate case ENFILE: 26057c478bd9Sstevel@tonic-gate errstr = "Could not get passwd entry."; 26067c478bd9Sstevel@tonic-gate goto out; 26077c478bd9Sstevel@tonic-gate 26087c478bd9Sstevel@tonic-gate default: 26097c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 26107c478bd9Sstevel@tonic-gate } 26117c478bd9Sstevel@tonic-gate 26127c478bd9Sstevel@tonic-gate cip->working_dir = strdup(cip->pwd.pw_dir); 26137c478bd9Sstevel@tonic-gate if (cip->working_dir == NULL) { 26147c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 26157c478bd9Sstevel@tonic-gate goto out; 26167c478bd9Sstevel@tonic-gate } 26177c478bd9Sstevel@tonic-gate } else { 26187c478bd9Sstevel@tonic-gate cip->working_dir = strdup(cip->vbuf); 26197c478bd9Sstevel@tonic-gate if (cip->working_dir == NULL) { 26207c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 26217c478bd9Sstevel@tonic-gate goto out; 26227c478bd9Sstevel@tonic-gate } 26237c478bd9Sstevel@tonic-gate } 26247c478bd9Sstevel@tonic-gate 26257c478bd9Sstevel@tonic-gate /* get (optional) corefile pattern */ 2626*13d8aaa1SSean Wilcox if ((methpg != NULL && scf_pg_get_property(methpg, 2627*13d8aaa1SSean Wilcox SCF_PROPERTY_COREFILE_PATTERN, prop) == SCF_SUCCESS) || 2628*13d8aaa1SSean Wilcox (instpg != NULL && scf_pg_get_property(instpg, 2629*13d8aaa1SSean Wilcox SCF_PROPERTY_COREFILE_PATTERN, prop) == SCF_SUCCESS)) { 2630*13d8aaa1SSean Wilcox if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 2631*13d8aaa1SSean Wilcox switch (scf_error()) { 2632*13d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN: 2633*13d8aaa1SSean Wilcox errstr = RCBROKEN; 2634*13d8aaa1SSean Wilcox break; 2635*13d8aaa1SSean Wilcox 2636*13d8aaa1SSean Wilcox case SCF_ERROR_CONSTRAINT_VIOLATED: 2637*13d8aaa1SSean Wilcox errstr = 2638*13d8aaa1SSean Wilcox "\"core_pattern\" property has multiple " 2639*13d8aaa1SSean Wilcox "values."; 2640*13d8aaa1SSean Wilcox break; 2641*13d8aaa1SSean Wilcox 2642*13d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND: 2643*13d8aaa1SSean Wilcox errstr = "\"core_pattern\" property has no " 2644*13d8aaa1SSean Wilcox "values."; 2645*13d8aaa1SSean Wilcox break; 2646*13d8aaa1SSean Wilcox 2647*13d8aaa1SSean Wilcox default: 2648*13d8aaa1SSean Wilcox bad_fail("scf_property_get_value", scf_error()); 26497c478bd9Sstevel@tonic-gate } 26507c478bd9Sstevel@tonic-gate 2651*13d8aaa1SSean Wilcox } else { 2652*13d8aaa1SSean Wilcox 2653*13d8aaa1SSean Wilcox ret = scf_value_get_astring(val, cip->vbuf, 2654*13d8aaa1SSean Wilcox cip->vbuf_sz); 2655*13d8aaa1SSean Wilcox assert(ret != -1); 2656*13d8aaa1SSean Wilcox 26577c478bd9Sstevel@tonic-gate cip->corefile_pattern = strdup(cip->vbuf); 26587c478bd9Sstevel@tonic-gate if (cip->corefile_pattern == NULL) { 26597c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 26607c478bd9Sstevel@tonic-gate goto out; 26617c478bd9Sstevel@tonic-gate } 2662*13d8aaa1SSean Wilcox } 2663*13d8aaa1SSean Wilcox 2664*13d8aaa1SSean Wilcox mc_used++; 26657c478bd9Sstevel@tonic-gate } else { 26667c478bd9Sstevel@tonic-gate switch (scf_error()) { 26677c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 26687c478bd9Sstevel@tonic-gate /* okay if missing. */ 26697c478bd9Sstevel@tonic-gate break; 26707c478bd9Sstevel@tonic-gate 26717c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 26727c478bd9Sstevel@tonic-gate errstr = RCBROKEN; 26737c478bd9Sstevel@tonic-gate goto out; 26747c478bd9Sstevel@tonic-gate 26757c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 26767c478bd9Sstevel@tonic-gate errstr = "\"corefile_pattern\" property deleted."; 26777c478bd9Sstevel@tonic-gate goto out; 26787c478bd9Sstevel@tonic-gate 26797c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 26807c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 26817c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 26827c478bd9Sstevel@tonic-gate default: 26837c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error()); 26847c478bd9Sstevel@tonic-gate } 26857c478bd9Sstevel@tonic-gate } 26867c478bd9Sstevel@tonic-gate 26877c478bd9Sstevel@tonic-gate if (restarter_rm_libs_loadable()) { 26887c478bd9Sstevel@tonic-gate /* get project */ 2689*13d8aaa1SSean Wilcox if ((methpg != NULL && scf_pg_get_property(methpg, 2690*13d8aaa1SSean Wilcox SCF_PROPERTY_PROJECT, prop) == SCF_SUCCESS) || 2691*13d8aaa1SSean Wilcox (instpg != NULL && scf_pg_get_property(instpg, 2692*13d8aaa1SSean Wilcox SCF_PROPERTY_PROJECT, prop) == SCF_SUCCESS)) { 2693*13d8aaa1SSean Wilcox if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 2694*13d8aaa1SSean Wilcox switch (scf_error()) { 2695*13d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN: 2696*13d8aaa1SSean Wilcox errstr = RCBROKEN; 2697*13d8aaa1SSean Wilcox break; 2698*13d8aaa1SSean Wilcox 2699*13d8aaa1SSean Wilcox case SCF_ERROR_CONSTRAINT_VIOLATED: 2700*13d8aaa1SSean Wilcox errstr = 2701*13d8aaa1SSean Wilcox "\"project\" property has " 2702*13d8aaa1SSean Wilcox "multiple values."; 2703*13d8aaa1SSean Wilcox break; 2704*13d8aaa1SSean Wilcox 2705*13d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND: 2706*13d8aaa1SSean Wilcox errstr = "\"project\" property has " 2707*13d8aaa1SSean Wilcox "no values."; 2708*13d8aaa1SSean Wilcox break; 2709*13d8aaa1SSean Wilcox 2710*13d8aaa1SSean Wilcox default: 2711*13d8aaa1SSean Wilcox bad_fail("scf_property_get_value", 2712*13d8aaa1SSean Wilcox scf_error()); 2713*13d8aaa1SSean Wilcox } 2714*13d8aaa1SSean Wilcox 2715*13d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default"); 2716*13d8aaa1SSean Wilcox } else { 2717*13d8aaa1SSean Wilcox ret = scf_value_get_astring(val, cip->vbuf, 2718*13d8aaa1SSean Wilcox cip->vbuf_sz); 2719*13d8aaa1SSean Wilcox assert(ret != -1); 2720*13d8aaa1SSean Wilcox } 2721*13d8aaa1SSean Wilcox 2722*13d8aaa1SSean Wilcox mc_used++; 2723*13d8aaa1SSean Wilcox } else { 2724*13d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default"); 27257c478bd9Sstevel@tonic-gate } 27267c478bd9Sstevel@tonic-gate 27277c478bd9Sstevel@tonic-gate switch (ret = get_projid(cip->vbuf, cip)) { 27287c478bd9Sstevel@tonic-gate case 0: 27297c478bd9Sstevel@tonic-gate break; 27307c478bd9Sstevel@tonic-gate 27317c478bd9Sstevel@tonic-gate case ENOMEM: 27327c478bd9Sstevel@tonic-gate errstr = "Out of memory."; 27337c478bd9Sstevel@tonic-gate goto out; 27347c478bd9Sstevel@tonic-gate 27357c478bd9Sstevel@tonic-gate case ENOENT: 27367c478bd9Sstevel@tonic-gate errstr = "Missing passwd or project entry."; 27377c478bd9Sstevel@tonic-gate goto out; 27387c478bd9Sstevel@tonic-gate 27397c478bd9Sstevel@tonic-gate case EIO: 27407c478bd9Sstevel@tonic-gate errstr = "I/O error."; 27417c478bd9Sstevel@tonic-gate goto out; 27427c478bd9Sstevel@tonic-gate 27437c478bd9Sstevel@tonic-gate case EMFILE: 27447c478bd9Sstevel@tonic-gate case ENFILE: 27457c478bd9Sstevel@tonic-gate errstr = "Out of file descriptors."; 27467c478bd9Sstevel@tonic-gate goto out; 27477c478bd9Sstevel@tonic-gate 27487c478bd9Sstevel@tonic-gate case -1: 27497c478bd9Sstevel@tonic-gate errstr = "Name service switch is misconfigured."; 27507c478bd9Sstevel@tonic-gate goto out; 27517c478bd9Sstevel@tonic-gate 27527c478bd9Sstevel@tonic-gate case ERANGE: 27537c478bd9Sstevel@tonic-gate errstr = "Project ID too big."; 27547c478bd9Sstevel@tonic-gate goto out; 27557c478bd9Sstevel@tonic-gate 27567c478bd9Sstevel@tonic-gate case EINVAL: 27577c478bd9Sstevel@tonic-gate errstr = "Project ID is invalid."; 27587c478bd9Sstevel@tonic-gate goto out; 27597c478bd9Sstevel@tonic-gate 27607c478bd9Sstevel@tonic-gate case E2BIG: 27617c478bd9Sstevel@tonic-gate errstr = "Project entry is too big."; 27627c478bd9Sstevel@tonic-gate goto out; 27637c478bd9Sstevel@tonic-gate 27647c478bd9Sstevel@tonic-gate default: 27657c478bd9Sstevel@tonic-gate bad_fail("get_projid", ret); 27667c478bd9Sstevel@tonic-gate } 27677c478bd9Sstevel@tonic-gate 27687c478bd9Sstevel@tonic-gate /* get resource pool */ 2769*13d8aaa1SSean Wilcox if ((methpg != NULL && scf_pg_get_property(methpg, 2770*13d8aaa1SSean Wilcox SCF_PROPERTY_RESOURCE_POOL, prop) == SCF_SUCCESS) || 2771*13d8aaa1SSean Wilcox (instpg != NULL && scf_pg_get_property(instpg, 2772*13d8aaa1SSean Wilcox SCF_PROPERTY_RESOURCE_POOL, prop) == SCF_SUCCESS)) { 2773*13d8aaa1SSean Wilcox if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 2774*13d8aaa1SSean Wilcox switch (scf_error()) { 2775*13d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN: 2776*13d8aaa1SSean Wilcox errstr = RCBROKEN; 2777*13d8aaa1SSean Wilcox break; 2778*13d8aaa1SSean Wilcox 2779*13d8aaa1SSean Wilcox case SCF_ERROR_CONSTRAINT_VIOLATED: 2780*13d8aaa1SSean Wilcox errstr = 2781*13d8aaa1SSean Wilcox "\"resource_pool\" property has " 2782*13d8aaa1SSean Wilcox "multiple values."; 2783*13d8aaa1SSean Wilcox break; 2784*13d8aaa1SSean Wilcox 2785*13d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND: 2786*13d8aaa1SSean Wilcox errstr = "\"resource_pool\" property " 2787*13d8aaa1SSean Wilcox "has no values."; 2788*13d8aaa1SSean Wilcox break; 2789*13d8aaa1SSean Wilcox 2790*13d8aaa1SSean Wilcox default: 2791*13d8aaa1SSean Wilcox bad_fail("scf_property_get_value", 2792*13d8aaa1SSean Wilcox scf_error()); 2793*13d8aaa1SSean Wilcox } 2794*13d8aaa1SSean Wilcox 2795*13d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default"); 2796*13d8aaa1SSean Wilcox } else { 2797*13d8aaa1SSean Wilcox ret = scf_value_get_astring(val, cip->vbuf, 2798*13d8aaa1SSean Wilcox cip->vbuf_sz); 2799*13d8aaa1SSean Wilcox assert(ret != -1); 2800*13d8aaa1SSean Wilcox } 2801*13d8aaa1SSean Wilcox 2802*13d8aaa1SSean Wilcox mc_used++; 2803*13d8aaa1SSean Wilcox } else { 2804*13d8aaa1SSean Wilcox switch (scf_error()) { 2805*13d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND: 2806*13d8aaa1SSean Wilcox /* okay if missing. */ 2807*13d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default"); 2808*13d8aaa1SSean Wilcox break; 2809*13d8aaa1SSean Wilcox 2810*13d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN: 2811*13d8aaa1SSean Wilcox errstr = RCBROKEN; 28127c478bd9Sstevel@tonic-gate goto out; 2813*13d8aaa1SSean Wilcox 2814*13d8aaa1SSean Wilcox case SCF_ERROR_DELETED: 2815*13d8aaa1SSean Wilcox errstr = "\"resource_pool\" property deleted."; 2816*13d8aaa1SSean Wilcox goto out; 2817*13d8aaa1SSean Wilcox 2818*13d8aaa1SSean Wilcox case SCF_ERROR_HANDLE_MISMATCH: 2819*13d8aaa1SSean Wilcox case SCF_ERROR_INVALID_ARGUMENT: 2820*13d8aaa1SSean Wilcox case SCF_ERROR_NOT_SET: 2821*13d8aaa1SSean Wilcox default: 2822*13d8aaa1SSean Wilcox bad_fail("scf_pg_get_property", scf_error()); 2823*13d8aaa1SSean Wilcox } 28247c478bd9Sstevel@tonic-gate } 28257c478bd9Sstevel@tonic-gate 28267c478bd9Sstevel@tonic-gate if (strcmp(cip->vbuf, ":default") != 0) { 28277c478bd9Sstevel@tonic-gate cip->resource_pool = strdup(cip->vbuf); 28287c478bd9Sstevel@tonic-gate if (cip->resource_pool == NULL) { 28297c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 28307c478bd9Sstevel@tonic-gate goto out; 28317c478bd9Sstevel@tonic-gate } 28327c478bd9Sstevel@tonic-gate } 28337c478bd9Sstevel@tonic-gate } 28347c478bd9Sstevel@tonic-gate 2835*13d8aaa1SSean Wilcox /* 2836*13d8aaa1SSean Wilcox * A method_context was not used for any configurable 2837*13d8aaa1SSean Wilcox * elements or attributes, so reset and use the simple 2838*13d8aaa1SSean Wilcox * defaults that provide historic init behavior. 2839*13d8aaa1SSean Wilcox */ 2840*13d8aaa1SSean Wilcox if (mc_used == 0) { 2841*13d8aaa1SSean Wilcox (void) memset(cip, 0, sizeof (*cip)); 2842*13d8aaa1SSean Wilcox cip->uid = 0; 2843*13d8aaa1SSean Wilcox cip->gid = 0; 2844*13d8aaa1SSean Wilcox cip->euid = (uid_t)-1; 2845*13d8aaa1SSean Wilcox cip->egid = (gid_t)-1; 2846*13d8aaa1SSean Wilcox } 2847*13d8aaa1SSean Wilcox 28487c478bd9Sstevel@tonic-gate *mcpp = cip; 28497c478bd9Sstevel@tonic-gate 28507c478bd9Sstevel@tonic-gate out: 28517c478bd9Sstevel@tonic-gate (void) scf_value_destroy(val); 28527c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 28537c478bd9Sstevel@tonic-gate scf_pg_destroy(instpg); 28547c478bd9Sstevel@tonic-gate scf_pg_destroy(methpg); 28557c478bd9Sstevel@tonic-gate 28567c478bd9Sstevel@tonic-gate if (cip->pwbuf != NULL) 28577c478bd9Sstevel@tonic-gate free(cip->pwbuf); 28587c478bd9Sstevel@tonic-gate free(cip->vbuf); 28597c478bd9Sstevel@tonic-gate 28607c478bd9Sstevel@tonic-gate if (errstr != NULL) 28617c478bd9Sstevel@tonic-gate restarter_free_method_context(cip); 28627c478bd9Sstevel@tonic-gate 28637c478bd9Sstevel@tonic-gate return (errstr); 28647c478bd9Sstevel@tonic-gate } 28657c478bd9Sstevel@tonic-gate 28667c478bd9Sstevel@tonic-gate /* 28677c478bd9Sstevel@tonic-gate * Modify the current process per the given method_context. On success, returns 28687c478bd9Sstevel@tonic-gate * 0. Note that the environment is not modified by this function to include the 28697c478bd9Sstevel@tonic-gate * environment variables in cip->env. 28707c478bd9Sstevel@tonic-gate * 28717c478bd9Sstevel@tonic-gate * On failure, sets *fp to NULL or the name of the function which failed, 28727c478bd9Sstevel@tonic-gate * and returns one of the following error codes. The words in parentheses are 28737c478bd9Sstevel@tonic-gate * the values to which *fp may be set for the error case. 28747c478bd9Sstevel@tonic-gate * ENOMEM - malloc() failed 28757c478bd9Sstevel@tonic-gate * EIO - an I/O error occurred (getpwuid_r, chdir) 28767c478bd9Sstevel@tonic-gate * EMFILE - process is out of file descriptors (getpwuid_r) 28777c478bd9Sstevel@tonic-gate * ENFILE - system is out of file handles (getpwuid_r) 28787c478bd9Sstevel@tonic-gate * EINVAL - gid or egid is out of range (setregid) 28797c478bd9Sstevel@tonic-gate * ngroups is too big (setgroups) 28807c478bd9Sstevel@tonic-gate * project's project id is bad (setproject) 28817c478bd9Sstevel@tonic-gate * uid or euid is out of range (setreuid) 28823ad28c1eSrm88369 * poolname is invalid (pool_set_binding) 28837c478bd9Sstevel@tonic-gate * EPERM - insufficient privilege (setregid, initgroups, setgroups, setppriv, 28847c478bd9Sstevel@tonic-gate * setproject, setreuid, settaskid) 28857c478bd9Sstevel@tonic-gate * ENOENT - uid has a passwd entry but no shadow entry 28867c478bd9Sstevel@tonic-gate * working_dir does not exist (chdir) 28877c478bd9Sstevel@tonic-gate * uid has no passwd entry 28887c478bd9Sstevel@tonic-gate * the pool could not be found (pool_set_binding) 28897c478bd9Sstevel@tonic-gate * EFAULT - lpriv_set or priv_set has a bad address (setppriv) 28907c478bd9Sstevel@tonic-gate * working_dir has a bad address (chdir) 28917c478bd9Sstevel@tonic-gate * EACCES - could not access working_dir (chdir) 28927c478bd9Sstevel@tonic-gate * in a TASK_FINAL task (setproject, settaskid) 28937c478bd9Sstevel@tonic-gate * no resource pool accepting default binding exists (setproject) 28947c478bd9Sstevel@tonic-gate * ELOOP - too many symbolic links in working_dir (chdir) 28957c478bd9Sstevel@tonic-gate * ENAMETOOLONG - working_dir is too long (chdir) 28967c478bd9Sstevel@tonic-gate * ENOLINK - working_dir is on an inaccessible remote machine (chdir) 28977c478bd9Sstevel@tonic-gate * ENOTDIR - working_dir is not a directory (chdir) 28987c478bd9Sstevel@tonic-gate * ESRCH - uid is not a user of project (setproject) 28997c478bd9Sstevel@tonic-gate * project is invalid (setproject) 29007c478bd9Sstevel@tonic-gate * the resource pool specified for project is unknown (setproject) 29017c478bd9Sstevel@tonic-gate * EBADF - the configuration for the pool is invalid (pool_set_binding) 29027c478bd9Sstevel@tonic-gate * -1 - core_set_process_path() failed (core_set_process_path) 29037c478bd9Sstevel@tonic-gate * a resource control assignment failed (setproject) 29047c478bd9Sstevel@tonic-gate * a system error occurred during pool_set_binding (pool_set_binding) 29057c478bd9Sstevel@tonic-gate */ 29067c478bd9Sstevel@tonic-gate int 29077c478bd9Sstevel@tonic-gate restarter_set_method_context(struct method_context *cip, const char **fp) 29087c478bd9Sstevel@tonic-gate { 29097c478bd9Sstevel@tonic-gate pid_t mypid = -1; 29107c478bd9Sstevel@tonic-gate int r, ret; 29117c478bd9Sstevel@tonic-gate 29127c478bd9Sstevel@tonic-gate cip->pwbuf = NULL; 29137c478bd9Sstevel@tonic-gate *fp = NULL; 29147c478bd9Sstevel@tonic-gate 2915f48205beScasper if (cip->gid != (gid_t)-1) { 29167c478bd9Sstevel@tonic-gate if (setregid(cip->gid, 2917f48205beScasper cip->egid != (gid_t)-1 ? cip->egid : cip->gid) != 0) { 29187c478bd9Sstevel@tonic-gate *fp = "setregid"; 29197c478bd9Sstevel@tonic-gate 29207c478bd9Sstevel@tonic-gate ret = errno; 29217c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 29227c478bd9Sstevel@tonic-gate goto out; 29237c478bd9Sstevel@tonic-gate } 29247c478bd9Sstevel@tonic-gate } else { 29257c478bd9Sstevel@tonic-gate if (cip->pwbuf == NULL) { 29267c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 29277c478bd9Sstevel@tonic-gate case 0: 29287c478bd9Sstevel@tonic-gate break; 29297c478bd9Sstevel@tonic-gate 29307c478bd9Sstevel@tonic-gate case ENOMEM: 29317c478bd9Sstevel@tonic-gate case ENOENT: 29327c478bd9Sstevel@tonic-gate *fp = NULL; 29337c478bd9Sstevel@tonic-gate goto out; 29347c478bd9Sstevel@tonic-gate 29357c478bd9Sstevel@tonic-gate case EIO: 29367c478bd9Sstevel@tonic-gate case EMFILE: 29377c478bd9Sstevel@tonic-gate case ENFILE: 29387c478bd9Sstevel@tonic-gate *fp = "getpwuid_r"; 29397c478bd9Sstevel@tonic-gate goto out; 29407c478bd9Sstevel@tonic-gate 29417c478bd9Sstevel@tonic-gate default: 29427c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 29437c478bd9Sstevel@tonic-gate } 29447c478bd9Sstevel@tonic-gate } 29457c478bd9Sstevel@tonic-gate 29467c478bd9Sstevel@tonic-gate if (setregid(cip->pwd.pw_gid, 2947f48205beScasper cip->egid != (gid_t)-1 ? 2948f48205beScasper cip->egid : cip->pwd.pw_gid) != 0) { 29497c478bd9Sstevel@tonic-gate *fp = "setregid"; 29507c478bd9Sstevel@tonic-gate 29517c478bd9Sstevel@tonic-gate ret = errno; 29527c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 29537c478bd9Sstevel@tonic-gate goto out; 29547c478bd9Sstevel@tonic-gate } 29557c478bd9Sstevel@tonic-gate } 29567c478bd9Sstevel@tonic-gate 29577c478bd9Sstevel@tonic-gate if (cip->ngroups == -1) { 29587c478bd9Sstevel@tonic-gate if (cip->pwbuf == NULL) { 29597c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 29607c478bd9Sstevel@tonic-gate case 0: 29617c478bd9Sstevel@tonic-gate break; 29627c478bd9Sstevel@tonic-gate 29637c478bd9Sstevel@tonic-gate case ENOMEM: 29647c478bd9Sstevel@tonic-gate case ENOENT: 29657c478bd9Sstevel@tonic-gate *fp = NULL; 29667c478bd9Sstevel@tonic-gate goto out; 29677c478bd9Sstevel@tonic-gate 29687c478bd9Sstevel@tonic-gate case EIO: 29697c478bd9Sstevel@tonic-gate case EMFILE: 29707c478bd9Sstevel@tonic-gate case ENFILE: 29717c478bd9Sstevel@tonic-gate *fp = "getpwuid_r"; 29727c478bd9Sstevel@tonic-gate goto out; 29737c478bd9Sstevel@tonic-gate 29747c478bd9Sstevel@tonic-gate default: 29757c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 29767c478bd9Sstevel@tonic-gate } 29777c478bd9Sstevel@tonic-gate } 29787c478bd9Sstevel@tonic-gate 29797c478bd9Sstevel@tonic-gate /* Ok if cip->gid == -1 */ 29807c478bd9Sstevel@tonic-gate if (initgroups(cip->pwd.pw_name, cip->gid) != 0) { 29817c478bd9Sstevel@tonic-gate *fp = "initgroups"; 29827c478bd9Sstevel@tonic-gate ret = errno; 29837c478bd9Sstevel@tonic-gate assert(ret == EPERM); 29847c478bd9Sstevel@tonic-gate goto out; 29857c478bd9Sstevel@tonic-gate } 29867c478bd9Sstevel@tonic-gate } else if (cip->ngroups > 0 && 29877c478bd9Sstevel@tonic-gate setgroups(cip->ngroups, cip->groups) != 0) { 29887c478bd9Sstevel@tonic-gate *fp = "setgroups"; 29897c478bd9Sstevel@tonic-gate 29907c478bd9Sstevel@tonic-gate ret = errno; 29917c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 29927c478bd9Sstevel@tonic-gate goto out; 29937c478bd9Sstevel@tonic-gate } 29947c478bd9Sstevel@tonic-gate 29957c478bd9Sstevel@tonic-gate if (cip->corefile_pattern != NULL) { 29967c478bd9Sstevel@tonic-gate mypid = getpid(); 29977c478bd9Sstevel@tonic-gate 29987c478bd9Sstevel@tonic-gate if (core_set_process_path(cip->corefile_pattern, 29997c478bd9Sstevel@tonic-gate strlen(cip->corefile_pattern) + 1, mypid) != 0) { 30007c478bd9Sstevel@tonic-gate *fp = "core_set_process_path"; 30017c478bd9Sstevel@tonic-gate ret = -1; 30027c478bd9Sstevel@tonic-gate goto out; 30037c478bd9Sstevel@tonic-gate } 30047c478bd9Sstevel@tonic-gate } 30057c478bd9Sstevel@tonic-gate 30067c478bd9Sstevel@tonic-gate if (restarter_rm_libs_loadable()) { 30077c478bd9Sstevel@tonic-gate if (cip->project == NULL) { 30087c478bd9Sstevel@tonic-gate if (settaskid(getprojid(), TASK_NORMAL) == -1) { 30097c478bd9Sstevel@tonic-gate switch (errno) { 30107c478bd9Sstevel@tonic-gate case EACCES: 30117c478bd9Sstevel@tonic-gate case EPERM: 30127c478bd9Sstevel@tonic-gate *fp = "settaskid"; 30137c478bd9Sstevel@tonic-gate ret = errno; 30147c478bd9Sstevel@tonic-gate goto out; 30157c478bd9Sstevel@tonic-gate 30167c478bd9Sstevel@tonic-gate case EINVAL: 30177c478bd9Sstevel@tonic-gate default: 30187c478bd9Sstevel@tonic-gate bad_fail("settaskid", errno); 30197c478bd9Sstevel@tonic-gate } 30207c478bd9Sstevel@tonic-gate } 30217c478bd9Sstevel@tonic-gate } else { 30227c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 30237c478bd9Sstevel@tonic-gate case 0: 30247c478bd9Sstevel@tonic-gate break; 30257c478bd9Sstevel@tonic-gate 30267c478bd9Sstevel@tonic-gate case ENOMEM: 30277c478bd9Sstevel@tonic-gate case ENOENT: 30287c478bd9Sstevel@tonic-gate *fp = NULL; 30297c478bd9Sstevel@tonic-gate goto out; 30307c478bd9Sstevel@tonic-gate 30317c478bd9Sstevel@tonic-gate case EIO: 30327c478bd9Sstevel@tonic-gate case EMFILE: 30337c478bd9Sstevel@tonic-gate case ENFILE: 30347c478bd9Sstevel@tonic-gate *fp = "getpwuid_r"; 30357c478bd9Sstevel@tonic-gate goto out; 30367c478bd9Sstevel@tonic-gate 30377c478bd9Sstevel@tonic-gate default: 30387c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 30397c478bd9Sstevel@tonic-gate } 30407c478bd9Sstevel@tonic-gate 30417c478bd9Sstevel@tonic-gate *fp = "setproject"; 30427c478bd9Sstevel@tonic-gate 30437c478bd9Sstevel@tonic-gate switch (setproject(cip->project, cip->pwd.pw_name, 30447c478bd9Sstevel@tonic-gate TASK_NORMAL)) { 30457c478bd9Sstevel@tonic-gate case 0: 30467c478bd9Sstevel@tonic-gate break; 30477c478bd9Sstevel@tonic-gate 30487c478bd9Sstevel@tonic-gate case SETPROJ_ERR_TASK: 30497c478bd9Sstevel@tonic-gate case SETPROJ_ERR_POOL: 30507c478bd9Sstevel@tonic-gate ret = errno; 30517c478bd9Sstevel@tonic-gate goto out; 30527c478bd9Sstevel@tonic-gate 30537c478bd9Sstevel@tonic-gate default: 30547c478bd9Sstevel@tonic-gate ret = -1; 30557c478bd9Sstevel@tonic-gate goto out; 30567c478bd9Sstevel@tonic-gate } 30577c478bd9Sstevel@tonic-gate } 30587c478bd9Sstevel@tonic-gate 30597c478bd9Sstevel@tonic-gate if (cip->resource_pool != NULL) { 30607c478bd9Sstevel@tonic-gate if (mypid == -1) 30617c478bd9Sstevel@tonic-gate mypid = getpid(); 30627c478bd9Sstevel@tonic-gate 30637c478bd9Sstevel@tonic-gate *fp = "pool_set_binding"; 30647c478bd9Sstevel@tonic-gate 30657c478bd9Sstevel@tonic-gate if (pool_set_binding(cip->resource_pool, P_PID, 30667c478bd9Sstevel@tonic-gate mypid) != PO_SUCCESS) { 30677c478bd9Sstevel@tonic-gate switch (pool_error()) { 30683ad28c1eSrm88369 case POE_INVALID_SEARCH: 30697c478bd9Sstevel@tonic-gate ret = ENOENT; 30707c478bd9Sstevel@tonic-gate break; 30717c478bd9Sstevel@tonic-gate 30723ad28c1eSrm88369 case POE_BADPARAM: 30733ad28c1eSrm88369 ret = EINVAL; 30743ad28c1eSrm88369 break; 30753ad28c1eSrm88369 30767c478bd9Sstevel@tonic-gate case POE_INVALID_CONF: 30777c478bd9Sstevel@tonic-gate ret = EBADF; 30787c478bd9Sstevel@tonic-gate break; 30797c478bd9Sstevel@tonic-gate 30807c478bd9Sstevel@tonic-gate case POE_SYSTEM: 30817c478bd9Sstevel@tonic-gate ret = -1; 30827c478bd9Sstevel@tonic-gate break; 30837c478bd9Sstevel@tonic-gate 30847c478bd9Sstevel@tonic-gate default: 30857c478bd9Sstevel@tonic-gate bad_fail("pool_set_binding", 30867c478bd9Sstevel@tonic-gate pool_error()); 30877c478bd9Sstevel@tonic-gate } 30887c478bd9Sstevel@tonic-gate 30897c478bd9Sstevel@tonic-gate goto out; 30907c478bd9Sstevel@tonic-gate } 30917c478bd9Sstevel@tonic-gate } 30927c478bd9Sstevel@tonic-gate } 30937c478bd9Sstevel@tonic-gate 30947c478bd9Sstevel@tonic-gate /* 30952a3221a4Svp157776 * Now, we have to assume our ID. If the UID is 0, we want it to be 30962a3221a4Svp157776 * privilege-aware, otherwise the limit set gets used instead of E/P. 30977c478bd9Sstevel@tonic-gate * We can do this by setting P as well, which keeps 30987c478bd9Sstevel@tonic-gate * PA status (see priv_can_clear_PA()). 30997c478bd9Sstevel@tonic-gate */ 31007c478bd9Sstevel@tonic-gate 3101*13d8aaa1SSean Wilcox *fp = "setppriv"; 3102*13d8aaa1SSean Wilcox 3103*13d8aaa1SSean Wilcox if (cip->lpriv_set != NULL) { 3104*13d8aaa1SSean Wilcox if (setppriv(PRIV_SET, PRIV_LIMIT, cip->lpriv_set) != 0) { 3105*13d8aaa1SSean Wilcox ret = errno; 3106*13d8aaa1SSean Wilcox assert(ret == EFAULT || ret == EPERM); 3107*13d8aaa1SSean Wilcox goto out; 3108*13d8aaa1SSean Wilcox } 3109*13d8aaa1SSean Wilcox } 3110*13d8aaa1SSean Wilcox if (cip->priv_set != NULL) { 3111*13d8aaa1SSean Wilcox if (setppriv(PRIV_SET, PRIV_INHERITABLE, cip->priv_set) != 0) { 3112*13d8aaa1SSean Wilcox ret = errno; 3113*13d8aaa1SSean Wilcox assert(ret == EFAULT || ret == EPERM); 3114*13d8aaa1SSean Wilcox goto out; 3115*13d8aaa1SSean Wilcox } 3116*13d8aaa1SSean Wilcox } 3117*13d8aaa1SSean Wilcox 3118*13d8aaa1SSean Wilcox /* 3119*13d8aaa1SSean Wilcox * If the limit privset is already set, then must be privilege 3120*13d8aaa1SSean Wilcox * aware. Otherwise, don't assume anything, and force privilege 3121*13d8aaa1SSean Wilcox * aware status. 3122*13d8aaa1SSean Wilcox */ 3123*13d8aaa1SSean Wilcox 3124*13d8aaa1SSean Wilcox if (cip->lpriv_set == NULL && cip->priv_set != NULL) { 3125*13d8aaa1SSean Wilcox ret = setpflags(PRIV_AWARE, 1); 3126*13d8aaa1SSean Wilcox assert(ret == 0); 3127*13d8aaa1SSean Wilcox } 3128*13d8aaa1SSean Wilcox 31297c478bd9Sstevel@tonic-gate *fp = "setreuid"; 3130f48205beScasper if (setreuid(cip->uid, 3131f48205beScasper cip->euid != (uid_t)-1 ? cip->euid : cip->uid) != 0) { 31327c478bd9Sstevel@tonic-gate ret = errno; 31337c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 31347c478bd9Sstevel@tonic-gate goto out; 31357c478bd9Sstevel@tonic-gate } 31367c478bd9Sstevel@tonic-gate 31377c478bd9Sstevel@tonic-gate *fp = "setppriv"; 31387c478bd9Sstevel@tonic-gate if (cip->priv_set != NULL) { 31397c478bd9Sstevel@tonic-gate if (setppriv(PRIV_SET, PRIV_PERMITTED, cip->priv_set) != 0) { 31407c478bd9Sstevel@tonic-gate ret = errno; 31417c478bd9Sstevel@tonic-gate assert(ret == EFAULT || ret == EPERM); 31427c478bd9Sstevel@tonic-gate goto out; 31437c478bd9Sstevel@tonic-gate } 31447c478bd9Sstevel@tonic-gate } 31457c478bd9Sstevel@tonic-gate 31462a3221a4Svp157776 /* 31472a3221a4Svp157776 * The last thing to do is chdir to the specified working directory. 31482a3221a4Svp157776 * This should come after the uid switching as only the user might 31492a3221a4Svp157776 * have access to the specified directory. 31502a3221a4Svp157776 */ 31512a3221a4Svp157776 if (cip->working_dir != NULL) { 31523eae19d9Swesolows do { 31532a3221a4Svp157776 r = chdir(cip->working_dir); 31543eae19d9Swesolows } while (r != 0 && errno == EINTR); 31552a3221a4Svp157776 if (r != 0) { 31562a3221a4Svp157776 *fp = "chdir"; 31572a3221a4Svp157776 ret = errno; 31582a3221a4Svp157776 goto out; 31592a3221a4Svp157776 } 31602a3221a4Svp157776 } 31612a3221a4Svp157776 31627c478bd9Sstevel@tonic-gate ret = 0; 31637c478bd9Sstevel@tonic-gate out: 31647c478bd9Sstevel@tonic-gate free(cip->pwbuf); 31657c478bd9Sstevel@tonic-gate cip->pwbuf = NULL; 31667c478bd9Sstevel@tonic-gate return (ret); 31677c478bd9Sstevel@tonic-gate } 31687c478bd9Sstevel@tonic-gate 31697c478bd9Sstevel@tonic-gate void 31707c478bd9Sstevel@tonic-gate restarter_free_method_context(struct method_context *mcp) 31717c478bd9Sstevel@tonic-gate { 31727c478bd9Sstevel@tonic-gate size_t i; 31737c478bd9Sstevel@tonic-gate 31747c478bd9Sstevel@tonic-gate if (mcp->lpriv_set != NULL) 31757c478bd9Sstevel@tonic-gate priv_freeset(mcp->lpriv_set); 31767c478bd9Sstevel@tonic-gate if (mcp->priv_set != NULL) 31777c478bd9Sstevel@tonic-gate priv_freeset(mcp->priv_set); 31787c478bd9Sstevel@tonic-gate 31797c478bd9Sstevel@tonic-gate if (mcp->env != NULL) { 31807c478bd9Sstevel@tonic-gate for (i = 0; i < mcp->env_sz; i++) 31817c478bd9Sstevel@tonic-gate free(mcp->env[i]); 31827c478bd9Sstevel@tonic-gate free(mcp->env); 31837c478bd9Sstevel@tonic-gate } 31847c478bd9Sstevel@tonic-gate 31857c478bd9Sstevel@tonic-gate free(mcp->working_dir); 31867c478bd9Sstevel@tonic-gate free(mcp->corefile_pattern); 31877c478bd9Sstevel@tonic-gate free(mcp->project); 31887c478bd9Sstevel@tonic-gate free(mcp->resource_pool); 31897c478bd9Sstevel@tonic-gate free(mcp); 31907c478bd9Sstevel@tonic-gate } 31917c478bd9Sstevel@tonic-gate 31927c478bd9Sstevel@tonic-gate /* 31937c478bd9Sstevel@tonic-gate * Method keyword functions 31947c478bd9Sstevel@tonic-gate */ 31957c478bd9Sstevel@tonic-gate 31967c478bd9Sstevel@tonic-gate int 31977c478bd9Sstevel@tonic-gate restarter_is_null_method(const char *meth) 31987c478bd9Sstevel@tonic-gate { 31997c478bd9Sstevel@tonic-gate return (strcmp(meth, MKW_TRUE) == 0); 32007c478bd9Sstevel@tonic-gate } 32017c478bd9Sstevel@tonic-gate 32027c478bd9Sstevel@tonic-gate static int 32037c478bd9Sstevel@tonic-gate is_kill_method(const char *method, const char *kill_str, 32047c478bd9Sstevel@tonic-gate size_t kill_str_len) 32057c478bd9Sstevel@tonic-gate { 32067c478bd9Sstevel@tonic-gate const char *cp; 32077c478bd9Sstevel@tonic-gate int sig; 32087c478bd9Sstevel@tonic-gate 32097c478bd9Sstevel@tonic-gate if (strncmp(method, kill_str, kill_str_len) != 0 || 32107c478bd9Sstevel@tonic-gate (method[kill_str_len] != '\0' && 32117c478bd9Sstevel@tonic-gate !isspace(method[kill_str_len]))) 32127c478bd9Sstevel@tonic-gate return (-1); 32137c478bd9Sstevel@tonic-gate 32147c478bd9Sstevel@tonic-gate cp = method + kill_str_len; 32157c478bd9Sstevel@tonic-gate while (*cp != '\0' && isspace(*cp)) 32167c478bd9Sstevel@tonic-gate ++cp; 32177c478bd9Sstevel@tonic-gate 32187c478bd9Sstevel@tonic-gate if (*cp == '\0') 32197c478bd9Sstevel@tonic-gate return (SIGTERM); 32207c478bd9Sstevel@tonic-gate 32217c478bd9Sstevel@tonic-gate if (*cp != '-') 32227c478bd9Sstevel@tonic-gate return (-1); 32237c478bd9Sstevel@tonic-gate 32247c478bd9Sstevel@tonic-gate return (str2sig(cp + 1, &sig) == 0 ? sig : -1); 32257c478bd9Sstevel@tonic-gate } 32267c478bd9Sstevel@tonic-gate 32277c478bd9Sstevel@tonic-gate int 32287c478bd9Sstevel@tonic-gate restarter_is_kill_proc_method(const char *method) 32297c478bd9Sstevel@tonic-gate { 32307c478bd9Sstevel@tonic-gate return (is_kill_method(method, MKW_KILL_PROC, 32317c478bd9Sstevel@tonic-gate sizeof (MKW_KILL_PROC) - 1)); 32327c478bd9Sstevel@tonic-gate } 32337c478bd9Sstevel@tonic-gate 32347c478bd9Sstevel@tonic-gate int 32357c478bd9Sstevel@tonic-gate restarter_is_kill_method(const char *method) 32367c478bd9Sstevel@tonic-gate { 32377c478bd9Sstevel@tonic-gate return (is_kill_method(method, MKW_KILL, sizeof (MKW_KILL) - 1)); 32387c478bd9Sstevel@tonic-gate } 32397c478bd9Sstevel@tonic-gate 32407c478bd9Sstevel@tonic-gate /* 32417c478bd9Sstevel@tonic-gate * Stubs for now. 32427c478bd9Sstevel@tonic-gate */ 32437c478bd9Sstevel@tonic-gate 32447c478bd9Sstevel@tonic-gate /* ARGSUSED */ 32457c478bd9Sstevel@tonic-gate int 32467c478bd9Sstevel@tonic-gate restarter_event_get_enabled(restarter_event_t *e) 32477c478bd9Sstevel@tonic-gate { 32487c478bd9Sstevel@tonic-gate return (-1); 32497c478bd9Sstevel@tonic-gate } 32507c478bd9Sstevel@tonic-gate 32517c478bd9Sstevel@tonic-gate /* ARGSUSED */ 32527c478bd9Sstevel@tonic-gate uint64_t 32537c478bd9Sstevel@tonic-gate restarter_event_get_seq(restarter_event_t *e) 32547c478bd9Sstevel@tonic-gate { 32557c478bd9Sstevel@tonic-gate return (-1); 32567c478bd9Sstevel@tonic-gate } 32577c478bd9Sstevel@tonic-gate 32587c478bd9Sstevel@tonic-gate /* ARGSUSED */ 32597c478bd9Sstevel@tonic-gate void 32607c478bd9Sstevel@tonic-gate restarter_event_get_time(restarter_event_t *e, hrtime_t *time) 32617c478bd9Sstevel@tonic-gate { 32627c478bd9Sstevel@tonic-gate } 3263eb1a3463STruong Nguyen 3264eb1a3463STruong Nguyen /* 3265eb1a3463STruong Nguyen * Check for and validate fmri specified in restarter_actions/auxiliary_fmri 3266eb1a3463STruong Nguyen * 0 - Success 3267eb1a3463STruong Nguyen * 1 - Failure 3268eb1a3463STruong Nguyen */ 3269eb1a3463STruong Nguyen int 3270eb1a3463STruong Nguyen restarter_inst_validate_ractions_aux_fmri(scf_instance_t *inst) 3271eb1a3463STruong Nguyen { 3272eb1a3463STruong Nguyen scf_handle_t *h; 3273eb1a3463STruong Nguyen scf_propertygroup_t *pg; 3274eb1a3463STruong Nguyen scf_property_t *prop; 3275eb1a3463STruong Nguyen scf_value_t *val; 3276eb1a3463STruong Nguyen char *aux_fmri; 3277eb1a3463STruong Nguyen size_t size = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 3278eb1a3463STruong Nguyen int ret = 1; 3279eb1a3463STruong Nguyen 3280eb1a3463STruong Nguyen if ((aux_fmri = malloc(size)) == NULL) 3281eb1a3463STruong Nguyen return (1); 3282eb1a3463STruong Nguyen 3283eb1a3463STruong Nguyen h = scf_instance_handle(inst); 3284eb1a3463STruong Nguyen 3285eb1a3463STruong Nguyen pg = scf_pg_create(h); 3286eb1a3463STruong Nguyen prop = scf_property_create(h); 3287eb1a3463STruong Nguyen val = scf_value_create(h); 3288eb1a3463STruong Nguyen if (pg == NULL || prop == NULL || val == NULL) 3289eb1a3463STruong Nguyen goto out; 3290eb1a3463STruong Nguyen 3291eb1a3463STruong Nguyen if (instance_get_or_add_pg(inst, SCF_PG_RESTARTER_ACTIONS, 3292eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS_TYPE, SCF_PG_RESTARTER_ACTIONS_FLAGS, 3293eb1a3463STruong Nguyen pg) != SCF_SUCCESS) 3294eb1a3463STruong Nguyen goto out; 3295eb1a3463STruong Nguyen 3296eb1a3463STruong Nguyen if (get_astring_val(pg, SCF_PROPERTY_AUX_FMRI, aux_fmri, size, 3297eb1a3463STruong Nguyen prop, val) != SCF_SUCCESS) 3298eb1a3463STruong Nguyen goto out; 3299eb1a3463STruong Nguyen 3300eb1a3463STruong Nguyen if (scf_parse_fmri(aux_fmri, NULL, NULL, NULL, NULL, NULL, 3301eb1a3463STruong Nguyen NULL) != SCF_SUCCESS) 3302eb1a3463STruong Nguyen goto out; 3303eb1a3463STruong Nguyen 3304eb1a3463STruong Nguyen ret = 0; 3305eb1a3463STruong Nguyen 3306eb1a3463STruong Nguyen out: 3307eb1a3463STruong Nguyen free(aux_fmri); 3308eb1a3463STruong Nguyen scf_value_destroy(val); 3309eb1a3463STruong Nguyen scf_property_destroy(prop); 3310eb1a3463STruong Nguyen scf_pg_destroy(pg); 3311eb1a3463STruong Nguyen return (ret); 3312eb1a3463STruong Nguyen } 3313eb1a3463STruong Nguyen 3314eb1a3463STruong Nguyen /* 3315eb1a3463STruong Nguyen * Get instance's boolean value in restarter_actions/auxiliary_tty 3316eb1a3463STruong Nguyen * Return -1 on failure 3317eb1a3463STruong Nguyen */ 3318eb1a3463STruong Nguyen int 3319eb1a3463STruong Nguyen restarter_inst_ractions_from_tty(scf_instance_t *inst) 3320eb1a3463STruong Nguyen { 3321eb1a3463STruong Nguyen scf_handle_t *h; 3322eb1a3463STruong Nguyen scf_propertygroup_t *pg; 3323eb1a3463STruong Nguyen scf_property_t *prop; 3324eb1a3463STruong Nguyen scf_value_t *val; 3325eb1a3463STruong Nguyen uint8_t has_tty; 3326eb1a3463STruong Nguyen int ret = -1; 3327eb1a3463STruong Nguyen 3328eb1a3463STruong Nguyen h = scf_instance_handle(inst); 3329eb1a3463STruong Nguyen pg = scf_pg_create(h); 3330eb1a3463STruong Nguyen prop = scf_property_create(h); 3331eb1a3463STruong Nguyen val = scf_value_create(h); 3332eb1a3463STruong Nguyen if (pg == NULL || prop == NULL || val == NULL) 3333eb1a3463STruong Nguyen goto out; 3334eb1a3463STruong Nguyen 3335eb1a3463STruong Nguyen if (instance_get_or_add_pg(inst, SCF_PG_RESTARTER_ACTIONS, 3336eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS_TYPE, SCF_PG_RESTARTER_ACTIONS_FLAGS, 3337eb1a3463STruong Nguyen pg) != SCF_SUCCESS) 3338eb1a3463STruong Nguyen goto out; 3339eb1a3463STruong Nguyen 3340eb1a3463STruong Nguyen if (get_boolean_val(pg, SCF_PROPERTY_AUX_TTY, &has_tty, prop, 3341eb1a3463STruong Nguyen val) != SCF_SUCCESS) 3342eb1a3463STruong Nguyen goto out; 3343eb1a3463STruong Nguyen 3344eb1a3463STruong Nguyen ret = has_tty; 3345eb1a3463STruong Nguyen 3346eb1a3463STruong Nguyen out: 3347eb1a3463STruong Nguyen scf_value_destroy(val); 3348eb1a3463STruong Nguyen scf_property_destroy(prop); 3349eb1a3463STruong Nguyen scf_pg_destroy(pg); 3350eb1a3463STruong Nguyen return (ret); 3351eb1a3463STruong Nguyen } 3352eb1a3463STruong Nguyen 3353eb1a3463STruong Nguyen static int 3354eb1a3463STruong Nguyen restarter_inst_set_astring_prop(scf_instance_t *inst, const char *pgname, 3355eb1a3463STruong Nguyen const char *pgtype, uint32_t pgflags, const char *pname, const char *str) 3356eb1a3463STruong Nguyen { 3357eb1a3463STruong Nguyen scf_handle_t *h; 3358eb1a3463STruong Nguyen scf_propertygroup_t *pg; 3359eb1a3463STruong Nguyen scf_transaction_t *t; 3360eb1a3463STruong Nguyen scf_transaction_entry_t *e; 3361eb1a3463STruong Nguyen scf_value_t *v; 3362eb1a3463STruong Nguyen int ret = 1, r; 3363eb1a3463STruong Nguyen 3364eb1a3463STruong Nguyen h = scf_instance_handle(inst); 3365eb1a3463STruong Nguyen 3366eb1a3463STruong Nguyen pg = scf_pg_create(h); 3367eb1a3463STruong Nguyen t = scf_transaction_create(h); 3368eb1a3463STruong Nguyen e = scf_entry_create(h); 3369eb1a3463STruong Nguyen v = scf_value_create(h); 3370eb1a3463STruong Nguyen if (pg == NULL || t == NULL || e == NULL || v == NULL) 3371eb1a3463STruong Nguyen goto out; 3372eb1a3463STruong Nguyen 3373eb1a3463STruong Nguyen if (instance_get_or_add_pg(inst, pgname, pgtype, pgflags, pg)) 3374eb1a3463STruong Nguyen goto out; 3375eb1a3463STruong Nguyen 3376eb1a3463STruong Nguyen if (scf_value_set_astring(v, str) != SCF_SUCCESS) 3377eb1a3463STruong Nguyen goto out; 3378eb1a3463STruong Nguyen 3379eb1a3463STruong Nguyen for (;;) { 3380eb1a3463STruong Nguyen if (scf_transaction_start(t, pg) != 0) 3381eb1a3463STruong Nguyen goto out; 3382eb1a3463STruong Nguyen 3383eb1a3463STruong Nguyen if (tx_set_value(t, e, pname, SCF_TYPE_ASTRING, v) != 0) 3384eb1a3463STruong Nguyen goto out; 3385eb1a3463STruong Nguyen 3386eb1a3463STruong Nguyen if ((r = scf_transaction_commit(t)) == 1) 3387eb1a3463STruong Nguyen break; 3388eb1a3463STruong Nguyen 3389eb1a3463STruong Nguyen if (r == -1) 3390eb1a3463STruong Nguyen goto out; 3391eb1a3463STruong Nguyen 3392eb1a3463STruong Nguyen scf_transaction_reset(t); 3393eb1a3463STruong Nguyen if (scf_pg_update(pg) == -1) 3394eb1a3463STruong Nguyen goto out; 3395eb1a3463STruong Nguyen } 3396eb1a3463STruong Nguyen ret = 0; 3397eb1a3463STruong Nguyen 3398eb1a3463STruong Nguyen out: 3399eb1a3463STruong Nguyen scf_transaction_destroy(t); 3400eb1a3463STruong Nguyen scf_entry_destroy(e); 3401eb1a3463STruong Nguyen scf_value_destroy(v); 3402eb1a3463STruong Nguyen scf_pg_destroy(pg); 3403eb1a3463STruong Nguyen 3404eb1a3463STruong Nguyen return (ret); 3405eb1a3463STruong Nguyen } 3406eb1a3463STruong Nguyen 3407eb1a3463STruong Nguyen int 3408eb1a3463STruong Nguyen restarter_inst_set_aux_fmri(scf_instance_t *inst) 3409eb1a3463STruong Nguyen { 3410eb1a3463STruong Nguyen scf_handle_t *h; 3411eb1a3463STruong Nguyen scf_propertygroup_t *pg; 3412eb1a3463STruong Nguyen scf_property_t *prop; 3413eb1a3463STruong Nguyen scf_value_t *val; 3414eb1a3463STruong Nguyen char *aux_fmri; 3415eb1a3463STruong Nguyen size_t size = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 3416eb1a3463STruong Nguyen int ret = 1; 3417eb1a3463STruong Nguyen 3418eb1a3463STruong Nguyen if ((aux_fmri = malloc(size)) == NULL) 3419eb1a3463STruong Nguyen return (1); 3420eb1a3463STruong Nguyen 3421eb1a3463STruong Nguyen h = scf_instance_handle(inst); 3422eb1a3463STruong Nguyen 3423eb1a3463STruong Nguyen pg = scf_pg_create(h); 3424eb1a3463STruong Nguyen prop = scf_property_create(h); 3425eb1a3463STruong Nguyen val = scf_value_create(h); 3426eb1a3463STruong Nguyen if (pg == NULL || prop == NULL || val == NULL) 3427eb1a3463STruong Nguyen goto out; 3428eb1a3463STruong Nguyen 3429eb1a3463STruong Nguyen /* 3430eb1a3463STruong Nguyen * Get auxiliary_fmri value from restarter_actions pg 3431eb1a3463STruong Nguyen */ 3432eb1a3463STruong Nguyen if (instance_get_or_add_pg(inst, SCF_PG_RESTARTER_ACTIONS, 3433eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS_TYPE, SCF_PG_RESTARTER_ACTIONS_FLAGS, 3434eb1a3463STruong Nguyen pg) != SCF_SUCCESS) 3435eb1a3463STruong Nguyen goto out; 3436eb1a3463STruong Nguyen 3437eb1a3463STruong Nguyen if (get_astring_val(pg, SCF_PROPERTY_AUX_FMRI, aux_fmri, size, 3438eb1a3463STruong Nguyen prop, val) != SCF_SUCCESS) 3439eb1a3463STruong Nguyen goto out; 3440eb1a3463STruong Nguyen 3441eb1a3463STruong Nguyen /* 3442eb1a3463STruong Nguyen * Populate restarter/auxiliary_fmri with the obtained fmri. 3443eb1a3463STruong Nguyen */ 3444eb1a3463STruong Nguyen ret = restarter_inst_set_astring_prop(inst, SCF_PG_RESTARTER, 3445eb1a3463STruong Nguyen SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, 3446eb1a3463STruong Nguyen SCF_PROPERTY_AUX_FMRI, aux_fmri); 3447eb1a3463STruong Nguyen 3448eb1a3463STruong Nguyen out: 3449eb1a3463STruong Nguyen free(aux_fmri); 3450eb1a3463STruong Nguyen scf_value_destroy(val); 3451eb1a3463STruong Nguyen scf_property_destroy(prop); 3452eb1a3463STruong Nguyen scf_pg_destroy(pg); 3453eb1a3463STruong Nguyen return (ret); 3454eb1a3463STruong Nguyen } 3455eb1a3463STruong Nguyen 3456eb1a3463STruong Nguyen int 3457eb1a3463STruong Nguyen restarter_inst_reset_aux_fmri(scf_instance_t *inst) 3458eb1a3463STruong Nguyen { 3459eb1a3463STruong Nguyen return (scf_instance_delete_prop(inst, 3460eb1a3463STruong Nguyen SCF_PG_RESTARTER, SCF_PROPERTY_AUX_FMRI)); 3461eb1a3463STruong Nguyen } 3462eb1a3463STruong Nguyen 3463eb1a3463STruong Nguyen int 3464eb1a3463STruong Nguyen restarter_inst_reset_ractions_aux_fmri(scf_instance_t *inst) 3465eb1a3463STruong Nguyen { 3466eb1a3463STruong Nguyen return (scf_instance_delete_prop(inst, 3467eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS, SCF_PROPERTY_AUX_FMRI)); 3468eb1a3463STruong Nguyen } 3469