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