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