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