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