17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 53ad28c1eSrm88369 * Common Development and Distribution License (the "License"). 63ad28c1eSrm88369 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217257d1b4Sraf 227c478bd9Sstevel@tonic-gate /* 23f6e214c7SGavin Maltby * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 24*ac0324d2SJerry Jelinek * Copyright (c) 2013, Joyent, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 27f6e214c7SGavin Maltby #include <libintl.h> 287c478bd9Sstevel@tonic-gate #include <librestart.h> 297c478bd9Sstevel@tonic-gate #include <librestart_priv.h> 307c478bd9Sstevel@tonic-gate #include <libscf.h> 317c478bd9Sstevel@tonic-gate #include <libscf_priv.h> 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include <assert.h> 347c478bd9Sstevel@tonic-gate #include <ctype.h> 357c478bd9Sstevel@tonic-gate #include <dlfcn.h> 367c478bd9Sstevel@tonic-gate #include <errno.h> 377c478bd9Sstevel@tonic-gate #include <exec_attr.h> 387c478bd9Sstevel@tonic-gate #include <grp.h> 397c478bd9Sstevel@tonic-gate #include <libsysevent.h> 407c478bd9Sstevel@tonic-gate #include <libuutil.h> 417c478bd9Sstevel@tonic-gate #include <limits.h> 427c478bd9Sstevel@tonic-gate #include <link.h> 437c478bd9Sstevel@tonic-gate #include <malloc.h> 447c478bd9Sstevel@tonic-gate #include <pool.h> 457c478bd9Sstevel@tonic-gate #include <priv.h> 467c478bd9Sstevel@tonic-gate #include <project.h> 477c478bd9Sstevel@tonic-gate #include <pthread.h> 487c478bd9Sstevel@tonic-gate #include <pwd.h> 497c478bd9Sstevel@tonic-gate #include <secdb.h> 507c478bd9Sstevel@tonic-gate #include <signal.h> 517c478bd9Sstevel@tonic-gate #include <stdlib.h> 527c478bd9Sstevel@tonic-gate #include <string.h> 537c478bd9Sstevel@tonic-gate #include <syslog.h> 547c478bd9Sstevel@tonic-gate #include <sys/corectl.h> 557c478bd9Sstevel@tonic-gate #include <sys/machelf.h> 567c478bd9Sstevel@tonic-gate #include <sys/task.h> 577c478bd9Sstevel@tonic-gate #include <sys/types.h> 587c478bd9Sstevel@tonic-gate #include <time.h> 597c478bd9Sstevel@tonic-gate #include <unistd.h> 607c478bd9Sstevel@tonic-gate #include <ucontext.h> 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate #define min(a, b) ((a) > (b) ? (b) : (a)) 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate #define MKW_TRUE ":true" 657c478bd9Sstevel@tonic-gate #define MKW_KILL ":kill" 667c478bd9Sstevel@tonic-gate #define MKW_KILL_PROC ":kill_process" 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate #define ALLOCFAIL ((char *)"Allocation failure.") 697c478bd9Sstevel@tonic-gate #define RCBROKEN ((char *)"Repository connection broken.") 707c478bd9Sstevel@tonic-gate 712c65c8b0Srm88369 #define MAX_COMMIT_RETRIES 10 727c478bd9Sstevel@tonic-gate #define MAX_COMMIT_RETRY_INT (5 * 1000000) /* 5 seconds */ 737c478bd9Sstevel@tonic-gate #define INITIAL_COMMIT_RETRY_INT (10000) /* 1/100th second */ 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate /* 767c478bd9Sstevel@tonic-gate * bad_fail() catches bugs in this and lower layers by reporting supposedly 777c478bd9Sstevel@tonic-gate * impossible function failures. The NDEBUG case keeps the strings out of the 787c478bd9Sstevel@tonic-gate * library but still calls abort() so we can root-cause from the coredump. 797c478bd9Sstevel@tonic-gate */ 807c478bd9Sstevel@tonic-gate #ifndef NDEBUG 817c478bd9Sstevel@tonic-gate #define bad_fail(func, err) { \ 827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, \ 837c478bd9Sstevel@tonic-gate "At %s:%d, %s() failed with unexpected error %d. Aborting.\n", \ 847c478bd9Sstevel@tonic-gate __FILE__, __LINE__, (func), (err)); \ 857c478bd9Sstevel@tonic-gate abort(); \ 867c478bd9Sstevel@tonic-gate } 877c478bd9Sstevel@tonic-gate #else 887c478bd9Sstevel@tonic-gate #define bad_fail(func, err) abort() 897c478bd9Sstevel@tonic-gate #endif 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate struct restarter_event_handle { 927c478bd9Sstevel@tonic-gate char *reh_restarter_name; 937c478bd9Sstevel@tonic-gate char *reh_delegate_channel_name; 947c478bd9Sstevel@tonic-gate evchan_t *reh_delegate_channel; 957c478bd9Sstevel@tonic-gate char *reh_delegate_subscriber_id; 967c478bd9Sstevel@tonic-gate char *reh_master_channel_name; 977c478bd9Sstevel@tonic-gate evchan_t *reh_master_channel; 987c478bd9Sstevel@tonic-gate char *reh_master_subscriber_id; 997c478bd9Sstevel@tonic-gate int (*reh_handler)(restarter_event_t *); 1007c478bd9Sstevel@tonic-gate }; 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate struct restarter_event { 1037c478bd9Sstevel@tonic-gate sysevent_t *re_sysevent; 1047c478bd9Sstevel@tonic-gate restarter_event_type_t re_type; 1057c478bd9Sstevel@tonic-gate char *re_instance_name; 1067c478bd9Sstevel@tonic-gate restarter_event_handle_t *re_event_handle; 1077c478bd9Sstevel@tonic-gate restarter_instance_state_t re_state; 1087c478bd9Sstevel@tonic-gate restarter_instance_state_t re_next_state; 1097c478bd9Sstevel@tonic-gate }; 1107c478bd9Sstevel@tonic-gate 111870ad75aSSean Wilcox /* 112f6e214c7SGavin Maltby * Long reasons must all parse/read correctly in the following contexts: 113f6e214c7SGavin Maltby * 114f6e214c7SGavin Maltby * "A service instance transitioned state: %s." 115f6e214c7SGavin Maltby * "A service failed: %s." 116f6e214c7SGavin Maltby * "Reason: %s." 117f6e214c7SGavin Maltby * "The service transitioned state (%s) and ..." 118f6e214c7SGavin Maltby * 119f6e214c7SGavin Maltby * With the exception of restart_str_none they must also fit the following 120f6e214c7SGavin Maltby * moulds: 121f6e214c7SGavin Maltby * 122f6e214c7SGavin Maltby * "An instance transitioned because %s, and ..." 123f6e214c7SGavin Maltby * "An instance transitioned to <new-state> because %s, and ..." 124f6e214c7SGavin Maltby * 125f6e214c7SGavin Maltby * Note that whoever is rendering the long message must provide the 126f6e214c7SGavin Maltby * terminal punctuation - don't include it here. Similarly, do not 127f6e214c7SGavin Maltby * provide an initial capital letter in reason-long. 128f6e214c7SGavin Maltby * 129f6e214c7SGavin Maltby * The long reason strings are Volatile - within the grammatical constraints 130f6e214c7SGavin Maltby * above we may improve them as need be. The intention is that a consumer 131f6e214c7SGavin Maltby * may blindly render the string along the lines of the above examples, 132f6e214c7SGavin Maltby * but has no other guarantees as to the exact wording. Long reasons 133f6e214c7SGavin Maltby * are localized. 134f6e214c7SGavin Maltby * 135f6e214c7SGavin Maltby * We define revisions of the set of short reason strings in use. Within 136f6e214c7SGavin Maltby * a given revision, all short reasons are Committed. Consumers must check 137f6e214c7SGavin Maltby * the revision in use before relying on the semantics of the short reason 138f6e214c7SGavin Maltby * codes - if the version exceeds that which they are familiar with they should 139f6e214c7SGavin Maltby * fail gracefully. Having checked for version compatability, a consumer 140f6e214c7SGavin Maltby * is assured that 141f6e214c7SGavin Maltby * 142f6e214c7SGavin Maltby * "short_reason_A iff semantic_A", provided: 143f6e214c7SGavin Maltby * 144f6e214c7SGavin Maltby * . the restarter uses this short reason code at all, 145f6e214c7SGavin Maltby * . the short reason is not "none" (which a restarter could 146f6e214c7SGavin Maltby * specifiy for any transition semantics) 147f6e214c7SGavin Maltby * 148f6e214c7SGavin Maltby * To split/refine such a Committed semantic_A into further cases, 149f6e214c7SGavin Maltby * we are required to bump the revision number. This should be an 150f6e214c7SGavin Maltby * infrequent occurence. If you bump the revision number you may 151f6e214c7SGavin Maltby * need to make corresponding changes in any source that calls 152f6e214c7SGavin Maltby * restarter_str_version (e.g., FMA event generation). 153f6e214c7SGavin Maltby * 154f6e214c7SGavin Maltby * To add additional reasons to the set you must also bump the version 155f6e214c7SGavin Maltby * number. 156f6e214c7SGavin Maltby */ 157f6e214c7SGavin Maltby 158f6e214c7SGavin Maltby /* 159f6e214c7SGavin Maltby * The following describes revision 0 of the set of transition reasons. 160f6e214c7SGavin Maltby * Read the preceding block comment before making any changes. 161f6e214c7SGavin Maltby */ 162f6e214c7SGavin Maltby static const struct restarter_state_transition_reason restarter_str[] = { 163f6e214c7SGavin Maltby /* 164f6e214c7SGavin Maltby * Any transition for which the restarter has not provided a reason. 165f6e214c7SGavin Maltby */ 166f6e214c7SGavin Maltby { 167f6e214c7SGavin Maltby restarter_str_none, 168f6e214c7SGavin Maltby "none", 169f6e214c7SGavin Maltby "the restarter gave no reason" 170f6e214c7SGavin Maltby }, 171f6e214c7SGavin Maltby 172f6e214c7SGavin Maltby /* 173f6e214c7SGavin Maltby * A transition to maintenance state due to a 174f6e214c7SGavin Maltby * 'svcadm mark maintenance <fmri>'. *Not* used if the libscf 175f6e214c7SGavin Maltby * interface smf_maintain_instance(3SCF) is used to request maintenance. 176f6e214c7SGavin Maltby */ 177f6e214c7SGavin Maltby { 178f6e214c7SGavin Maltby restarter_str_administrative_request, 179f6e214c7SGavin Maltby "administrative_request", 180f6e214c7SGavin Maltby "maintenance was requested by an administrator" 181f6e214c7SGavin Maltby }, 182f6e214c7SGavin Maltby 183f6e214c7SGavin Maltby /* 184f6e214c7SGavin Maltby * A transition to maintenance state if a repository inconsistency 185f6e214c7SGavin Maltby * exists when the service/instance state is first read by startd 186f6e214c7SGavin Maltby * into the graph engine (this can also happen during startd restart). 187f6e214c7SGavin Maltby */ 188f6e214c7SGavin Maltby { 189f6e214c7SGavin Maltby restarter_str_bad_repo_state, 190f6e214c7SGavin Maltby "bad_repo_state", 191f6e214c7SGavin Maltby "an SMF repository inconsistecy exists" 192f6e214c7SGavin Maltby }, 193f6e214c7SGavin Maltby 194f6e214c7SGavin Maltby /* 195f6e214c7SGavin Maltby * A transition 'maintenance -> uninitialized' resulting always 196f6e214c7SGavin Maltby * from 'svcadm clear <fmri>'. *Not* used if the libscf interface 197f6e214c7SGavin Maltby * smf_restore_instance(3SCF) is used. 198f6e214c7SGavin Maltby */ 199f6e214c7SGavin Maltby { 200f6e214c7SGavin Maltby restarter_str_clear_request, 201f6e214c7SGavin Maltby "clear_request", 202f6e214c7SGavin Maltby "maintenance clear was requested by an administrator" 203f6e214c7SGavin Maltby }, 204f6e214c7SGavin Maltby 205f6e214c7SGavin Maltby /* 206f6e214c7SGavin Maltby * A transition 'online -> offline' due to a process core dump. 207f6e214c7SGavin Maltby */ 208f6e214c7SGavin Maltby { 209f6e214c7SGavin Maltby restarter_str_ct_ev_core, 210f6e214c7SGavin Maltby "ct_ev_core", 211f6e214c7SGavin Maltby "a process dumped core" 212f6e214c7SGavin Maltby }, 213f6e214c7SGavin Maltby 214f6e214c7SGavin Maltby /* 215f6e214c7SGavin Maltby * A transition 'online -> offline' due to an empty process contract, 216f6e214c7SGavin Maltby * i.e., the last process in a contract type service has exited. 217f6e214c7SGavin Maltby */ 218f6e214c7SGavin Maltby { 219f6e214c7SGavin Maltby restarter_str_ct_ev_exit, 220f6e214c7SGavin Maltby "ct_ev_exit", 221f6e214c7SGavin Maltby "all processes in the service have exited" 222f6e214c7SGavin Maltby }, 223f6e214c7SGavin Maltby 224f6e214c7SGavin Maltby /* 225f6e214c7SGavin Maltby * A transition 'online -> offline' due to a hardware error. 226f6e214c7SGavin Maltby */ 227f6e214c7SGavin Maltby { 228f6e214c7SGavin Maltby restarter_str_ct_ev_hwerr, 229f6e214c7SGavin Maltby "ct_ev_hwerr", 230f6e214c7SGavin Maltby "a process was killed due to uncorrectable hardware error" 231f6e214c7SGavin Maltby }, 232f6e214c7SGavin Maltby 233f6e214c7SGavin Maltby /* 234f6e214c7SGavin Maltby * A transition 'online -> offline' due to a process in the service 235f6e214c7SGavin Maltby * having received a fatal signal originating from outside the 236f6e214c7SGavin Maltby * service process contract. 237f6e214c7SGavin Maltby */ 238f6e214c7SGavin Maltby { 239f6e214c7SGavin Maltby restarter_str_ct_ev_signal, 240f6e214c7SGavin Maltby "ct_ev_signal", 241f6e214c7SGavin Maltby "a process received a fatal signal from outside the service" 242f6e214c7SGavin Maltby }, 243f6e214c7SGavin Maltby 244f6e214c7SGavin Maltby /* 245f6e214c7SGavin Maltby * A transition 'offline -> online' when all dependencies for the 246f6e214c7SGavin Maltby * service have been met. 247f6e214c7SGavin Maltby */ 248f6e214c7SGavin Maltby { 249f6e214c7SGavin Maltby restarter_str_dependencies_satisfied, 250f6e214c7SGavin Maltby "dependencies_satisfied", 251f6e214c7SGavin Maltby "all dependencies have been satisfied" 252f6e214c7SGavin Maltby }, 253f6e214c7SGavin Maltby 254f6e214c7SGavin Maltby /* 255f6e214c7SGavin Maltby * A transition 'online -> offline' because some dependency for the 256f6e214c7SGavin Maltby * service is no-longer met. 257f6e214c7SGavin Maltby */ 258f6e214c7SGavin Maltby { 259f6e214c7SGavin Maltby restarter_str_dependency_activity, 260f6e214c7SGavin Maltby "dependency_activity", 261f6e214c7SGavin Maltby "a dependency activity required a stop" 262f6e214c7SGavin Maltby }, 263f6e214c7SGavin Maltby 264f6e214c7SGavin Maltby /* 265f6e214c7SGavin Maltby * A transition to maintenance state due to a cycle in the 266f6e214c7SGavin Maltby * service dependencies. 267f6e214c7SGavin Maltby */ 268f6e214c7SGavin Maltby { 269f6e214c7SGavin Maltby restarter_str_dependency_cycle, 270f6e214c7SGavin Maltby "dependency_cycle", 271f6e214c7SGavin Maltby "a dependency cycle exists" 272f6e214c7SGavin Maltby }, 273f6e214c7SGavin Maltby 274f6e214c7SGavin Maltby /* 275f6e214c7SGavin Maltby * A transition 'online -> offline -> disabled' due to a 276f6e214c7SGavin Maltby * 'svcadm disable [-t] <fmri>' or smf_disable_instance(3SCF) call. 277f6e214c7SGavin Maltby */ 278f6e214c7SGavin Maltby { 279f6e214c7SGavin Maltby restarter_str_disable_request, 280f6e214c7SGavin Maltby "disable_request", 281f6e214c7SGavin Maltby "a disable was requested" 282f6e214c7SGavin Maltby }, 283f6e214c7SGavin Maltby 284f6e214c7SGavin Maltby /* 285f6e214c7SGavin Maltby * A transition 'disabled -> offline' due to a 286f6e214c7SGavin Maltby * 'svcadm enable [-t] <fmri>' or smf_enable_instance(3SCF) call. 287f6e214c7SGavin Maltby */ 288f6e214c7SGavin Maltby { 289f6e214c7SGavin Maltby restarter_str_enable_request, 290f6e214c7SGavin Maltby "enable_request", 291f6e214c7SGavin Maltby "an enable was requested" 292f6e214c7SGavin Maltby }, 293f6e214c7SGavin Maltby 294f6e214c7SGavin Maltby /* 295f6e214c7SGavin Maltby * A transition to maintenance state when a method fails 296f6e214c7SGavin Maltby * repeatedly for a retryable reason. 297f6e214c7SGavin Maltby */ 298f6e214c7SGavin Maltby { 299f6e214c7SGavin Maltby restarter_str_fault_threshold_reached, 300f6e214c7SGavin Maltby "fault_threshold_reached", 301f6e214c7SGavin Maltby "a method is failing in a retryable manner but too often" 302f6e214c7SGavin Maltby }, 303f6e214c7SGavin Maltby 304f6e214c7SGavin Maltby /* 305f6e214c7SGavin Maltby * A transition to uninitialized state when startd reads the service 306f6e214c7SGavin Maltby * configuration and inserts it into the graph engine. 307f6e214c7SGavin Maltby */ 308f6e214c7SGavin Maltby { 309f6e214c7SGavin Maltby restarter_str_insert_in_graph, 310f6e214c7SGavin Maltby "insert_in_graph", 311f6e214c7SGavin Maltby "the instance was inserted in the graph" 312f6e214c7SGavin Maltby }, 313f6e214c7SGavin Maltby 314f6e214c7SGavin Maltby /* 315f6e214c7SGavin Maltby * A transition to maintenance state due to an invalid dependency 316f6e214c7SGavin Maltby * declared for the service. 317f6e214c7SGavin Maltby */ 318f6e214c7SGavin Maltby { 319f6e214c7SGavin Maltby restarter_str_invalid_dependency, 320f6e214c7SGavin Maltby "invalid_dependency", 321f6e214c7SGavin Maltby "a service has an invalid dependency" 322f6e214c7SGavin Maltby }, 323f6e214c7SGavin Maltby 324f6e214c7SGavin Maltby /* 325f6e214c7SGavin Maltby * A transition to maintenance state because the service-declared 326f6e214c7SGavin Maltby * restarter is invalid. 327f6e214c7SGavin Maltby */ 328f6e214c7SGavin Maltby { 329f6e214c7SGavin Maltby restarter_str_invalid_restarter, 330f6e214c7SGavin Maltby "invalid_restarter", 331f6e214c7SGavin Maltby "the service restarter is invalid" 332f6e214c7SGavin Maltby }, 333f6e214c7SGavin Maltby 334f6e214c7SGavin Maltby /* 335f6e214c7SGavin Maltby * A transition to maintenance state because a restarter method 336f6e214c7SGavin Maltby * exited with one of SMF_EXIT_ERR_CONFIG, SMF_EXIT_ERR_NOSMF, 337f6e214c7SGavin Maltby * SMF_EXIT_ERR_PERM, or SMF_EXIT_ERR_FATAL. 338f6e214c7SGavin Maltby */ 339f6e214c7SGavin Maltby { 340f6e214c7SGavin Maltby restarter_str_method_failed, 341f6e214c7SGavin Maltby "method_failed", 342f6e214c7SGavin Maltby "a start, stop or refresh method failed" 343f6e214c7SGavin Maltby }, 344f6e214c7SGavin Maltby 345f6e214c7SGavin Maltby /* 346f6e214c7SGavin Maltby * A transition 'uninitialized -> {disabled|offline}' after 347f6e214c7SGavin Maltby * "insert_in_graph" to match the state configured in the 348f6e214c7SGavin Maltby * repository. 349f6e214c7SGavin Maltby */ 350f6e214c7SGavin Maltby { 351f6e214c7SGavin Maltby restarter_str_per_configuration, 352f6e214c7SGavin Maltby "per_configuration", 353f6e214c7SGavin Maltby "the SMF repository configuration specifies this state" 354f6e214c7SGavin Maltby }, 355f6e214c7SGavin Maltby 356f6e214c7SGavin Maltby /* 357f6e214c7SGavin Maltby * Refresh requested - no state change. 358f6e214c7SGavin Maltby */ 359f6e214c7SGavin Maltby { 360f6e214c7SGavin Maltby restarter_str_refresh, 361f6e214c7SGavin Maltby NULL, 362f6e214c7SGavin Maltby "a refresh was requested (no change of state)" 363f6e214c7SGavin Maltby }, 364f6e214c7SGavin Maltby 365f6e214c7SGavin Maltby /* 366f6e214c7SGavin Maltby * A transition 'online -> offline -> online' due to a 367f6e214c7SGavin Maltby * 'svcadm restart <fmri> or equivlaent libscf API call. 368f6e214c7SGavin Maltby * Both the 'online -> offline' and 'offline -> online' transtions 369f6e214c7SGavin Maltby * specify this reason. 370f6e214c7SGavin Maltby */ 371f6e214c7SGavin Maltby { 372f6e214c7SGavin Maltby restarter_str_restart_request, 373f6e214c7SGavin Maltby "restart_request", 374f6e214c7SGavin Maltby "a restart was requested" 375f6e214c7SGavin Maltby }, 376f6e214c7SGavin Maltby 377f6e214c7SGavin Maltby /* 378f6e214c7SGavin Maltby * A transition to maintenance state because the start method is 379f6e214c7SGavin Maltby * being executed successfully but too frequently. 380f6e214c7SGavin Maltby */ 381f6e214c7SGavin Maltby { 382f6e214c7SGavin Maltby restarter_str_restarting_too_quickly, 383f6e214c7SGavin Maltby "restarting_too_quickly", 384f6e214c7SGavin Maltby "the instance is restarting too quickly" 385f6e214c7SGavin Maltby }, 386f6e214c7SGavin Maltby 387f6e214c7SGavin Maltby /* 388f6e214c7SGavin Maltby * A transition to maintenance state due a service requesting 389f6e214c7SGavin Maltby * 'svcadm mark maintenance <fmri>' or equivalent libscf API call. 390f6e214c7SGavin Maltby * A command line 'svcadm mark maintenance <fmri>' does not produce 391f6e214c7SGavin Maltby * this reason - it produces administrative_request instead. 392f6e214c7SGavin Maltby */ 393f6e214c7SGavin Maltby { 394f6e214c7SGavin Maltby restarter_str_service_request, 395f6e214c7SGavin Maltby "service_request", 396f6e214c7SGavin Maltby "maintenance was requested by another service" 397f6e214c7SGavin Maltby }, 398f6e214c7SGavin Maltby 399f6e214c7SGavin Maltby /* 400f6e214c7SGavin Maltby * An instanced inserted into the graph at its existing state 401f6e214c7SGavin Maltby * during a startd restart - no state change. 402f6e214c7SGavin Maltby */ 403f6e214c7SGavin Maltby { 404f6e214c7SGavin Maltby restarter_str_startd_restart, 405f6e214c7SGavin Maltby NULL, 406f6e214c7SGavin Maltby "the instance was inserted in the graph due to startd restart" 407f6e214c7SGavin Maltby } 408f6e214c7SGavin Maltby }; 409f6e214c7SGavin Maltby 410f6e214c7SGavin Maltby uint32_t 411f6e214c7SGavin Maltby restarter_str_version(void) 412f6e214c7SGavin Maltby { 413f6e214c7SGavin Maltby return (RESTARTER_STRING_VERSION); 414f6e214c7SGavin Maltby } 415f6e214c7SGavin Maltby 416f6e214c7SGavin Maltby const char * 417f6e214c7SGavin Maltby restarter_get_str_short(restarter_str_t key) 418f6e214c7SGavin Maltby { 419f6e214c7SGavin Maltby int i; 420f6e214c7SGavin Maltby for (i = 0; i < sizeof (restarter_str) / 421f6e214c7SGavin Maltby sizeof (struct restarter_state_transition_reason); i++) 422f6e214c7SGavin Maltby if (key == restarter_str[i].str_key) 423f6e214c7SGavin Maltby return (restarter_str[i].str_short); 424f6e214c7SGavin Maltby return (NULL); 425f6e214c7SGavin Maltby } 426f6e214c7SGavin Maltby 427f6e214c7SGavin Maltby const char * 428f6e214c7SGavin Maltby restarter_get_str_long(restarter_str_t key) 429f6e214c7SGavin Maltby { 430f6e214c7SGavin Maltby int i; 431f6e214c7SGavin Maltby for (i = 0; i < sizeof (restarter_str) / 432f6e214c7SGavin Maltby sizeof (struct restarter_state_transition_reason); i++) 433f6e214c7SGavin Maltby if (key == restarter_str[i].str_key) 434f6e214c7SGavin Maltby return (dgettext(TEXT_DOMAIN, 435f6e214c7SGavin Maltby restarter_str[i].str_long)); 436f6e214c7SGavin Maltby return (NULL); 437f6e214c7SGavin Maltby } 438f6e214c7SGavin Maltby 439f6e214c7SGavin Maltby /* 440870ad75aSSean Wilcox * A static no memory error message mc_error_t structure 441870ad75aSSean Wilcox * to be used in cases when memory errors are to be returned 442870ad75aSSean Wilcox * This avoids the need to attempt to allocate memory for the 443870ad75aSSean Wilcox * message, therefore getting into a cycle of no memory failures. 444870ad75aSSean Wilcox */ 445870ad75aSSean Wilcox mc_error_t mc_nomem_err = { 446870ad75aSSean Wilcox 0, ENOMEM, sizeof ("Out of memory") - 1, "Out of memory" 447870ad75aSSean Wilcox }; 448870ad75aSSean Wilcox 4497c478bd9Sstevel@tonic-gate static const char * const allocfail = "Allocation failure.\n"; 4507c478bd9Sstevel@tonic-gate static const char * const rcbroken = "Repository connection broken.\n"; 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate static int method_context_safety = 0; /* Can safely call pools/projects. */ 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate int ndebug = 1; 4557c478bd9Sstevel@tonic-gate 456870ad75aSSean Wilcox /* PRINTFLIKE3 */ 457870ad75aSSean Wilcox static mc_error_t * 458870ad75aSSean Wilcox mc_error_create(mc_error_t *e, int type, const char *format, ...) 459870ad75aSSean Wilcox { 460870ad75aSSean Wilcox mc_error_t *le; 461870ad75aSSean Wilcox va_list args; 462870ad75aSSean Wilcox int size; 463870ad75aSSean Wilcox 464870ad75aSSean Wilcox /* 465870ad75aSSean Wilcox * If the type is ENOMEM and format is NULL, then 466870ad75aSSean Wilcox * go ahead and return the default nomem error. 467870ad75aSSean Wilcox * Otherwise, attempt to allocate the memory and if 468870ad75aSSean Wilcox * that fails then there is no reason to continue. 469870ad75aSSean Wilcox */ 470870ad75aSSean Wilcox if (type == ENOMEM && format == NULL) 471870ad75aSSean Wilcox return (&mc_nomem_err); 472870ad75aSSean Wilcox 473870ad75aSSean Wilcox if (e == NULL && (le = malloc(sizeof (mc_error_t))) == NULL) 474870ad75aSSean Wilcox return (&mc_nomem_err); 475870ad75aSSean Wilcox else 476870ad75aSSean Wilcox le = e; 477870ad75aSSean Wilcox 478870ad75aSSean Wilcox le->type = type; 479870ad75aSSean Wilcox le->destroy = 1; 480870ad75aSSean Wilcox va_start(args, format); 481870ad75aSSean Wilcox size = vsnprintf(NULL, 0, format, args) + 1; 482870ad75aSSean Wilcox if (size >= RESTARTER_ERRMSGSZ) { 483870ad75aSSean Wilcox if ((le = realloc(e, sizeof (mc_error_t) + 484870ad75aSSean Wilcox (size - RESTARTER_ERRMSGSZ))) == NULL) { 485870ad75aSSean Wilcox size = RESTARTER_ERRMSGSZ - 1; 486870ad75aSSean Wilcox le = e; 487870ad75aSSean Wilcox } 488870ad75aSSean Wilcox } 489870ad75aSSean Wilcox 490870ad75aSSean Wilcox le->size = size; 491870ad75aSSean Wilcox (void) vsnprintf(le->msg, le->size, format, args); 492870ad75aSSean Wilcox va_end(args); 493870ad75aSSean Wilcox 494870ad75aSSean Wilcox return (le); 495870ad75aSSean Wilcox } 496870ad75aSSean Wilcox 497870ad75aSSean Wilcox void 498870ad75aSSean Wilcox restarter_mc_error_destroy(mc_error_t *mc_err) 499870ad75aSSean Wilcox { 500870ad75aSSean Wilcox if (mc_err == NULL) 501870ad75aSSean Wilcox return; 502870ad75aSSean Wilcox 503870ad75aSSean Wilcox /* 504870ad75aSSean Wilcox * If the error messages was allocated then free. 505870ad75aSSean Wilcox */ 506870ad75aSSean Wilcox if (mc_err->destroy) { 507870ad75aSSean Wilcox free(mc_err); 508870ad75aSSean Wilcox } 509870ad75aSSean Wilcox } 510870ad75aSSean Wilcox 5117c478bd9Sstevel@tonic-gate static void 5127c478bd9Sstevel@tonic-gate free_restarter_event_handle(struct restarter_event_handle *h) 5137c478bd9Sstevel@tonic-gate { 5147c478bd9Sstevel@tonic-gate if (h == NULL) 5157c478bd9Sstevel@tonic-gate return; 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate /* 5187c478bd9Sstevel@tonic-gate * Just free the memory -- don't unbind the sysevent handle, 5197c478bd9Sstevel@tonic-gate * as otherwise events may be lost if this is just a restarter 5207c478bd9Sstevel@tonic-gate * restart. 5217c478bd9Sstevel@tonic-gate */ 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate if (h->reh_restarter_name != NULL) 5247c478bd9Sstevel@tonic-gate free(h->reh_restarter_name); 5257c478bd9Sstevel@tonic-gate if (h->reh_delegate_channel_name != NULL) 5267c478bd9Sstevel@tonic-gate free(h->reh_delegate_channel_name); 5277c478bd9Sstevel@tonic-gate if (h->reh_delegate_subscriber_id != NULL) 5287c478bd9Sstevel@tonic-gate free(h->reh_delegate_subscriber_id); 5297c478bd9Sstevel@tonic-gate if (h->reh_master_channel_name != NULL) 5307c478bd9Sstevel@tonic-gate free(h->reh_master_channel_name); 5317c478bd9Sstevel@tonic-gate if (h->reh_master_subscriber_id != NULL) 5327c478bd9Sstevel@tonic-gate free(h->reh_master_subscriber_id); 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate free(h); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate char * 5387c478bd9Sstevel@tonic-gate _restarter_get_channel_name(const char *fmri, int type) 5397c478bd9Sstevel@tonic-gate { 54013d8aaa1SSean Wilcox char *name; 5417c478bd9Sstevel@tonic-gate char *chan_name = malloc(MAX_CHNAME_LEN); 5427c478bd9Sstevel@tonic-gate char prefix_name[3]; 54313d8aaa1SSean Wilcox int i; 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate if (chan_name == NULL) 5467c478bd9Sstevel@tonic-gate return (NULL); 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate if (type == RESTARTER_CHANNEL_DELEGATE) 5497c478bd9Sstevel@tonic-gate (void) strcpy(prefix_name, "d_"); 5507c478bd9Sstevel@tonic-gate else if (type == RESTARTER_CHANNEL_MASTER) 5517c478bd9Sstevel@tonic-gate (void) strcpy(prefix_name, "m_"); 5527c478bd9Sstevel@tonic-gate else { 5537c478bd9Sstevel@tonic-gate free(chan_name); 5547c478bd9Sstevel@tonic-gate return (NULL); 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate 55713d8aaa1SSean Wilcox /* 55813d8aaa1SSean Wilcox * Create a unique name 55913d8aaa1SSean Wilcox * 56013d8aaa1SSean Wilcox * Use the entire name, using a replacement of the / 56113d8aaa1SSean Wilcox * characters to get a better name. 56213d8aaa1SSean Wilcox * 56313d8aaa1SSean Wilcox * Remove the svc:/ from the beginning as this really 56413d8aaa1SSean Wilcox * isn't going to provide any uniqueness... 56513d8aaa1SSean Wilcox * 56613d8aaa1SSean Wilcox * An fmri name greater than MAX_CHNAME_LEN is going 56713d8aaa1SSean Wilcox * to be rejected as too long for the chan_name below 56813d8aaa1SSean Wilcox * in the snprintf call. 56913d8aaa1SSean Wilcox */ 57013d8aaa1SSean Wilcox if ((name = strdup(strchr(fmri, '/') + 1)) == NULL) { 57113d8aaa1SSean Wilcox free(chan_name); 57213d8aaa1SSean Wilcox return (NULL); 57313d8aaa1SSean Wilcox } 57413d8aaa1SSean Wilcox i = 0; 57513d8aaa1SSean Wilcox while (name[i]) { 57613d8aaa1SSean Wilcox if (name[i] == '/') { 57713d8aaa1SSean Wilcox name[i] = '_'; 57813d8aaa1SSean Wilcox } 57913d8aaa1SSean Wilcox 58013d8aaa1SSean Wilcox i++; 58113d8aaa1SSean Wilcox } 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate /* 5847c478bd9Sstevel@tonic-gate * Should check for [a-z],[A-Z],[0-9],.,_,-,: 5857c478bd9Sstevel@tonic-gate */ 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate if (snprintf(chan_name, MAX_CHNAME_LEN, "com.sun:scf:%s%s", 5887c478bd9Sstevel@tonic-gate prefix_name, name) > MAX_CHNAME_LEN) { 5897c478bd9Sstevel@tonic-gate free(chan_name); 59013d8aaa1SSean Wilcox chan_name = NULL; 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate 59313d8aaa1SSean Wilcox free(name); 5947c478bd9Sstevel@tonic-gate return (chan_name); 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate int 5987c478bd9Sstevel@tonic-gate cb(sysevent_t *syse, void *cookie) 5997c478bd9Sstevel@tonic-gate { 6007c478bd9Sstevel@tonic-gate restarter_event_handle_t *h = (restarter_event_handle_t *)cookie; 6017c478bd9Sstevel@tonic-gate restarter_event_t *e; 6027c478bd9Sstevel@tonic-gate nvlist_t *attr_list = NULL; 6037c478bd9Sstevel@tonic-gate int ret = 0; 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate e = uu_zalloc(sizeof (restarter_event_t)); 6067c478bd9Sstevel@tonic-gate if (e == NULL) 6077c478bd9Sstevel@tonic-gate uu_die(allocfail); 6087c478bd9Sstevel@tonic-gate e->re_event_handle = h; 6097c478bd9Sstevel@tonic-gate e->re_sysevent = syse; 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate if (sysevent_get_attr_list(syse, &attr_list) != 0) 6127c478bd9Sstevel@tonic-gate uu_die(allocfail); 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate if ((nvlist_lookup_uint32(attr_list, RESTARTER_NAME_TYPE, 6157c478bd9Sstevel@tonic-gate &(e->re_type)) != 0) || 6167c478bd9Sstevel@tonic-gate (nvlist_lookup_string(attr_list, 6177c478bd9Sstevel@tonic-gate RESTARTER_NAME_INSTANCE, &(e->re_instance_name)) != 0)) { 6187c478bd9Sstevel@tonic-gate uu_warn("%s: Can't decode nvlist for event %p\n", 6197c478bd9Sstevel@tonic-gate h->reh_restarter_name, (void *)syse); 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate ret = 0; 6227c478bd9Sstevel@tonic-gate } else { 6237c478bd9Sstevel@tonic-gate ret = h->reh_handler(e); 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate uu_free(e); 6277c478bd9Sstevel@tonic-gate nvlist_free(attr_list); 6287c478bd9Sstevel@tonic-gate return (ret); 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate /* 6327c478bd9Sstevel@tonic-gate * restarter_bind_handle(uint32_t, char *, int (*)(restarter_event_t *), int, 6337c478bd9Sstevel@tonic-gate * restarter_event_handle_t **) 6347c478bd9Sstevel@tonic-gate * 6357c478bd9Sstevel@tonic-gate * Bind to a delegated restarter event channel. 6367c478bd9Sstevel@tonic-gate * Each delegated restarter gets its own channel for resource management. 6377c478bd9Sstevel@tonic-gate * 6387c478bd9Sstevel@tonic-gate * Returns 0 on success or 6397c478bd9Sstevel@tonic-gate * ENOTSUP version mismatch 6407c478bd9Sstevel@tonic-gate * EINVAL restarter_name or event_handle is NULL 6417c478bd9Sstevel@tonic-gate * ENOMEM out of memory, too many channels, or too many subscriptions 6427c478bd9Sstevel@tonic-gate * EBUSY sysevent_evc_bind() could not establish binding 6437c478bd9Sstevel@tonic-gate * EFAULT internal sysevent_evc_bind()/sysevent_evc_subscribe() error 6447c478bd9Sstevel@tonic-gate * EMFILE out of file descriptors 6457c478bd9Sstevel@tonic-gate * EPERM insufficient privilege for sysevent_evc_bind() 6467c478bd9Sstevel@tonic-gate * EEXIST already subscribed 6477c478bd9Sstevel@tonic-gate */ 6487c478bd9Sstevel@tonic-gate int 6497c478bd9Sstevel@tonic-gate restarter_bind_handle(uint32_t version, const char *restarter_name, 6507c478bd9Sstevel@tonic-gate int (*event_handler)(restarter_event_t *), int flags, 6517c478bd9Sstevel@tonic-gate restarter_event_handle_t **rehp) 6527c478bd9Sstevel@tonic-gate { 6537c478bd9Sstevel@tonic-gate restarter_event_handle_t *h; 6547c478bd9Sstevel@tonic-gate size_t sz; 6557c478bd9Sstevel@tonic-gate int err; 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate if (version != RESTARTER_EVENT_VERSION) 6587c478bd9Sstevel@tonic-gate return (ENOTSUP); 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate if (restarter_name == NULL || event_handler == NULL) 6617c478bd9Sstevel@tonic-gate return (EINVAL); 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate if (flags & RESTARTER_FLAG_DEBUG) 6647c478bd9Sstevel@tonic-gate ndebug++; 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate if ((h = uu_zalloc(sizeof (restarter_event_handle_t))) == NULL) 6677c478bd9Sstevel@tonic-gate return (ENOMEM); 6687c478bd9Sstevel@tonic-gate 6697c478bd9Sstevel@tonic-gate h->reh_delegate_subscriber_id = malloc(MAX_SUBID_LEN); 6707c478bd9Sstevel@tonic-gate h->reh_master_subscriber_id = malloc(MAX_SUBID_LEN); 6717c478bd9Sstevel@tonic-gate h->reh_restarter_name = strdup(restarter_name); 6727c478bd9Sstevel@tonic-gate if (h->reh_delegate_subscriber_id == NULL || 6737c478bd9Sstevel@tonic-gate h->reh_master_subscriber_id == NULL || 6747c478bd9Sstevel@tonic-gate h->reh_restarter_name == NULL) { 6757c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 6767c478bd9Sstevel@tonic-gate return (ENOMEM); 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate sz = strlcpy(h->reh_delegate_subscriber_id, "del", MAX_SUBID_LEN); 6807c478bd9Sstevel@tonic-gate assert(sz < MAX_SUBID_LEN); 6817c478bd9Sstevel@tonic-gate sz = strlcpy(h->reh_master_subscriber_id, "master", MAX_SUBID_LEN); 6827c478bd9Sstevel@tonic-gate assert(sz < MAX_SUBID_LEN); 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate h->reh_delegate_channel_name = 6857c478bd9Sstevel@tonic-gate _restarter_get_channel_name(restarter_name, 6867c478bd9Sstevel@tonic-gate RESTARTER_CHANNEL_DELEGATE); 6877c478bd9Sstevel@tonic-gate h->reh_master_channel_name = 6887c478bd9Sstevel@tonic-gate _restarter_get_channel_name(restarter_name, 6897c478bd9Sstevel@tonic-gate RESTARTER_CHANNEL_MASTER); 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate if (h->reh_delegate_channel_name == NULL || 6927c478bd9Sstevel@tonic-gate h->reh_master_channel_name == NULL) { 6937c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 6947c478bd9Sstevel@tonic-gate return (ENOMEM); 6957c478bd9Sstevel@tonic-gate } 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate if (sysevent_evc_bind(h->reh_delegate_channel_name, 6987c478bd9Sstevel@tonic-gate &h->reh_delegate_channel, EVCH_CREAT|EVCH_HOLD_PEND) != 0) { 6997c478bd9Sstevel@tonic-gate err = errno; 7007c478bd9Sstevel@tonic-gate assert(err != EINVAL); 7017c478bd9Sstevel@tonic-gate assert(err != ENOENT); 7027c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 7037c478bd9Sstevel@tonic-gate return (err); 7047c478bd9Sstevel@tonic-gate } 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate if (sysevent_evc_bind(h->reh_master_channel_name, 7077c478bd9Sstevel@tonic-gate &h->reh_master_channel, EVCH_CREAT|EVCH_HOLD_PEND) != 0) { 7087c478bd9Sstevel@tonic-gate err = errno; 7097c478bd9Sstevel@tonic-gate assert(err != EINVAL); 7107c478bd9Sstevel@tonic-gate assert(err != ENOENT); 7117c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 7127c478bd9Sstevel@tonic-gate return (err); 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate h->reh_handler = event_handler; 7167c478bd9Sstevel@tonic-gate 7177c478bd9Sstevel@tonic-gate assert(strlen(restarter_name) <= MAX_CLASS_LEN - 1); 7187c478bd9Sstevel@tonic-gate assert(strlen(h->reh_delegate_subscriber_id) <= MAX_SUBID_LEN - 1); 7197c478bd9Sstevel@tonic-gate assert(strlen(h->reh_master_subscriber_id) <= MAX_SUBID_LEN - 1); 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate if (sysevent_evc_subscribe(h->reh_delegate_channel, 7227c478bd9Sstevel@tonic-gate h->reh_delegate_subscriber_id, EC_ALL, cb, h, EVCH_SUB_KEEP) != 0) { 7237c478bd9Sstevel@tonic-gate err = errno; 7247c478bd9Sstevel@tonic-gate assert(err != EINVAL); 7257c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 7267c478bd9Sstevel@tonic-gate return (err); 7277c478bd9Sstevel@tonic-gate } 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate *rehp = h; 7307c478bd9Sstevel@tonic-gate return (0); 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate restarter_event_handle_t * 7347c478bd9Sstevel@tonic-gate restarter_event_get_handle(restarter_event_t *e) 7357c478bd9Sstevel@tonic-gate { 7367c478bd9Sstevel@tonic-gate assert(e != NULL && e->re_event_handle != NULL); 7377c478bd9Sstevel@tonic-gate return (e->re_event_handle); 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate restarter_event_type_t 7417c478bd9Sstevel@tonic-gate restarter_event_get_type(restarter_event_t *e) 7427c478bd9Sstevel@tonic-gate { 7437c478bd9Sstevel@tonic-gate assert(e != NULL); 7447c478bd9Sstevel@tonic-gate return (e->re_type); 7457c478bd9Sstevel@tonic-gate } 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate ssize_t 7487c478bd9Sstevel@tonic-gate restarter_event_get_instance(restarter_event_t *e, char *inst, size_t sz) 7497c478bd9Sstevel@tonic-gate { 7507c478bd9Sstevel@tonic-gate assert(e != NULL && inst != NULL); 7517c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(inst, e->re_instance_name, sz)); 7527c478bd9Sstevel@tonic-gate } 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate int 7557c478bd9Sstevel@tonic-gate restarter_event_get_current_states(restarter_event_t *e, 7567c478bd9Sstevel@tonic-gate restarter_instance_state_t *state, restarter_instance_state_t *next_state) 7577c478bd9Sstevel@tonic-gate { 7587c478bd9Sstevel@tonic-gate if (e == NULL) 7597c478bd9Sstevel@tonic-gate return (-1); 7607c478bd9Sstevel@tonic-gate *state = e->re_state; 7617c478bd9Sstevel@tonic-gate *next_state = e->re_next_state; 7627c478bd9Sstevel@tonic-gate return (0); 7637c478bd9Sstevel@tonic-gate } 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate /* 7662c65c8b0Srm88369 * restarter_event_publish_retry() is a wrapper around sysevent_evc_publish(). 7672c65c8b0Srm88369 * In case, the event cannot be sent at the first attempt (sysevent_evc_publish 7682c65c8b0Srm88369 * returned EAGAIN - sysevent queue full), this function retries a few time 7692c65c8b0Srm88369 * and return ENOSPC if it reaches the retry limit. 7702c65c8b0Srm88369 * 7712c65c8b0Srm88369 * The arguments to this function map the arguments of sysevent_evc_publish(). 7722c65c8b0Srm88369 * 7732c65c8b0Srm88369 * On success, return 0. On error, return 7742c65c8b0Srm88369 * 7752c65c8b0Srm88369 * EFAULT - internal sysevent_evc_publish() error 7762c65c8b0Srm88369 * ENOMEM - internal sysevent_evc_publish() error 7772c65c8b0Srm88369 * EBADF - scp is invalid (sysevent_evc_publish() returned EINVAL) 7782c65c8b0Srm88369 * ENOSPC - sysevent queue full (sysevent_evc_publish() returned EAGAIN) 7792c65c8b0Srm88369 */ 7802c65c8b0Srm88369 int 7812c65c8b0Srm88369 restarter_event_publish_retry(evchan_t *scp, const char *class, 7822c65c8b0Srm88369 const char *subclass, const char *vendor, const char *pub_name, 7832c65c8b0Srm88369 nvlist_t *attr_list, uint32_t flags) 7842c65c8b0Srm88369 { 7852c65c8b0Srm88369 int retries, ret; 7862c65c8b0Srm88369 useconds_t retry_int = INITIAL_COMMIT_RETRY_INT; 7872c65c8b0Srm88369 7882c65c8b0Srm88369 for (retries = 0; retries < MAX_COMMIT_RETRIES; retries++) { 7892c65c8b0Srm88369 ret = sysevent_evc_publish(scp, class, subclass, vendor, 7902c65c8b0Srm88369 pub_name, attr_list, flags); 7912c65c8b0Srm88369 if (ret == 0) 7922c65c8b0Srm88369 break; 7932c65c8b0Srm88369 7942c65c8b0Srm88369 switch (ret) { 7952c65c8b0Srm88369 case EAGAIN: 7962c65c8b0Srm88369 /* Queue is full */ 7972c65c8b0Srm88369 (void) usleep(retry_int); 7982c65c8b0Srm88369 7992c65c8b0Srm88369 retry_int = min(retry_int * 2, MAX_COMMIT_RETRY_INT); 8002c65c8b0Srm88369 break; 8012c65c8b0Srm88369 8022c65c8b0Srm88369 case EINVAL: 8032c65c8b0Srm88369 ret = EBADF; 8042c65c8b0Srm88369 /* FALLTHROUGH */ 8052c65c8b0Srm88369 8062c65c8b0Srm88369 case EFAULT: 8072c65c8b0Srm88369 case ENOMEM: 8082c65c8b0Srm88369 return (ret); 8092c65c8b0Srm88369 8102c65c8b0Srm88369 case EOVERFLOW: 8112c65c8b0Srm88369 default: 8122c65c8b0Srm88369 /* internal error - abort */ 8132c65c8b0Srm88369 bad_fail("sysevent_evc_publish", ret); 8142c65c8b0Srm88369 } 8152c65c8b0Srm88369 } 8162c65c8b0Srm88369 8172c65c8b0Srm88369 if (retries == MAX_COMMIT_RETRIES) 8182c65c8b0Srm88369 ret = ENOSPC; 8192c65c8b0Srm88369 8202c65c8b0Srm88369 return (ret); 8212c65c8b0Srm88369 } 8222c65c8b0Srm88369 8232c65c8b0Srm88369 /* 8247c478bd9Sstevel@tonic-gate * Commit the state, next state, and auxiliary state into the repository. 8257c478bd9Sstevel@tonic-gate * Let the graph engine know about the state change and error. On success, 8267c478bd9Sstevel@tonic-gate * return 0. On error, return 8277c478bd9Sstevel@tonic-gate * EPROTO - librestart compiled against different libscf 8287c478bd9Sstevel@tonic-gate * ENOMEM - out of memory 8297c478bd9Sstevel@tonic-gate * - repository server out of resources 8307c478bd9Sstevel@tonic-gate * ENOTACTIVE - repository server not running 8317c478bd9Sstevel@tonic-gate * ECONNABORTED - repository connection established, but then broken 8327c478bd9Sstevel@tonic-gate * - unknown libscf error 8337c478bd9Sstevel@tonic-gate * ENOENT - inst does not exist in the repository 8347c478bd9Sstevel@tonic-gate * EPERM - insufficient permissions 8357c478bd9Sstevel@tonic-gate * EACCESS - backend access denied 8367c478bd9Sstevel@tonic-gate * EROFS - backend is readonly 8377c478bd9Sstevel@tonic-gate * EFAULT - internal sysevent_evc_publish() error 8387c478bd9Sstevel@tonic-gate * EBADF - h is invalid (sysevent_evc_publish() returned EINVAL) 8392c65c8b0Srm88369 * ENOSPC - sysevent queue full (sysevent_evc_publish() returned EAGAIN) 8407c478bd9Sstevel@tonic-gate */ 8417c478bd9Sstevel@tonic-gate int 8427c478bd9Sstevel@tonic-gate restarter_set_states(restarter_event_handle_t *h, const char *inst, 8437c478bd9Sstevel@tonic-gate restarter_instance_state_t cur_state, 8447c478bd9Sstevel@tonic-gate restarter_instance_state_t new_cur_state, 8457c478bd9Sstevel@tonic-gate restarter_instance_state_t next_state, 8467c478bd9Sstevel@tonic-gate restarter_instance_state_t new_next_state, restarter_error_t e, 847f6e214c7SGavin Maltby restarter_str_t aux) 8487c478bd9Sstevel@tonic-gate { 8497c478bd9Sstevel@tonic-gate nvlist_t *attr; 8507c478bd9Sstevel@tonic-gate scf_handle_t *scf_h; 8517c478bd9Sstevel@tonic-gate instance_data_t id; 8527c478bd9Sstevel@tonic-gate int ret = 0; 853f6e214c7SGavin Maltby const char *p = restarter_get_str_short(aux); 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate assert(h->reh_master_channel != NULL); 8567c478bd9Sstevel@tonic-gate assert(h->reh_master_channel_name != NULL); 8577c478bd9Sstevel@tonic-gate assert(h->reh_master_subscriber_id != NULL); 8587c478bd9Sstevel@tonic-gate 8597c478bd9Sstevel@tonic-gate if ((scf_h = scf_handle_create(SCF_VERSION)) == NULL) { 8607c478bd9Sstevel@tonic-gate switch (scf_error()) { 8617c478bd9Sstevel@tonic-gate case SCF_ERROR_VERSION_MISMATCH: 8627c478bd9Sstevel@tonic-gate return (EPROTO); 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate case SCF_ERROR_NO_MEMORY: 8657c478bd9Sstevel@tonic-gate return (ENOMEM); 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate default: 8687c478bd9Sstevel@tonic-gate bad_fail("scf_handle_create", scf_error()); 8697c478bd9Sstevel@tonic-gate } 8707c478bd9Sstevel@tonic-gate } 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate if (scf_handle_bind(scf_h) == -1) { 8737c478bd9Sstevel@tonic-gate scf_handle_destroy(scf_h); 8747c478bd9Sstevel@tonic-gate switch (scf_error()) { 8757c478bd9Sstevel@tonic-gate case SCF_ERROR_NO_SERVER: 8767c478bd9Sstevel@tonic-gate return (ENOTACTIVE); 8777c478bd9Sstevel@tonic-gate 8787c478bd9Sstevel@tonic-gate case SCF_ERROR_NO_RESOURCES: 8797c478bd9Sstevel@tonic-gate return (ENOMEM); 8807c478bd9Sstevel@tonic-gate 8817c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 8827c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 8837c478bd9Sstevel@tonic-gate default: 8847c478bd9Sstevel@tonic-gate bad_fail("scf_handle_bind", scf_error()); 8857c478bd9Sstevel@tonic-gate } 8867c478bd9Sstevel@tonic-gate } 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate if (nvlist_alloc(&attr, NV_UNIQUE_NAME, 0) != 0 || 8897c478bd9Sstevel@tonic-gate nvlist_add_int32(attr, RESTARTER_NAME_STATE, new_cur_state) != 0 || 8907c478bd9Sstevel@tonic-gate nvlist_add_int32(attr, RESTARTER_NAME_NEXT_STATE, new_next_state) 8917c478bd9Sstevel@tonic-gate != 0 || 8927c478bd9Sstevel@tonic-gate nvlist_add_int32(attr, RESTARTER_NAME_ERROR, e) != 0 || 893f6e214c7SGavin Maltby nvlist_add_string(attr, RESTARTER_NAME_INSTANCE, inst) != 0 || 894f6e214c7SGavin Maltby nvlist_add_int32(attr, RESTARTER_NAME_REASON, aux) != 0) { 8957c478bd9Sstevel@tonic-gate ret = ENOMEM; 8962c65c8b0Srm88369 } else { 8977c478bd9Sstevel@tonic-gate id.i_fmri = inst; 8987c478bd9Sstevel@tonic-gate id.i_state = cur_state; 8997c478bd9Sstevel@tonic-gate id.i_next_state = next_state; 9007c478bd9Sstevel@tonic-gate 9017c478bd9Sstevel@tonic-gate ret = _restarter_commit_states(scf_h, &id, new_cur_state, 902f6e214c7SGavin Maltby new_next_state, p); 9037c478bd9Sstevel@tonic-gate 9042c65c8b0Srm88369 if (ret == 0) { 9052c65c8b0Srm88369 ret = restarter_event_publish_retry( 9062c65c8b0Srm88369 h->reh_master_channel, "master", "state_change", 9072c65c8b0Srm88369 "com.sun", "librestart", attr, EVCH_NOSLEEP); 9087c478bd9Sstevel@tonic-gate } 9097c478bd9Sstevel@tonic-gate } 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate nvlist_free(attr); 9127c478bd9Sstevel@tonic-gate (void) scf_handle_unbind(scf_h); 9137c478bd9Sstevel@tonic-gate scf_handle_destroy(scf_h); 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate return (ret); 9167c478bd9Sstevel@tonic-gate } 9177c478bd9Sstevel@tonic-gate 9187c478bd9Sstevel@tonic-gate restarter_instance_state_t 9197c478bd9Sstevel@tonic-gate restarter_string_to_state(char *string) 9207c478bd9Sstevel@tonic-gate { 9217c478bd9Sstevel@tonic-gate assert(string != NULL); 9227c478bd9Sstevel@tonic-gate 9237c478bd9Sstevel@tonic-gate if (strcmp(string, SCF_STATE_STRING_NONE) == 0) 9247c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_NONE); 9257c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_UNINIT) == 0) 9267c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_UNINIT); 9277c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_MAINT) == 0) 9287c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_MAINT); 9297c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_OFFLINE) == 0) 9307c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_OFFLINE); 9317c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_DISABLED) == 0) 9327c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_DISABLED); 9337c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_ONLINE) == 0) 9347c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_ONLINE); 9357c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_DEGRADED) == 0) 9367c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_DEGRADED); 9377c478bd9Sstevel@tonic-gate else { 9387c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_NONE); 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate } 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate ssize_t 9437c478bd9Sstevel@tonic-gate restarter_state_to_string(restarter_instance_state_t state, char *string, 9447c478bd9Sstevel@tonic-gate size_t len) 9457c478bd9Sstevel@tonic-gate { 9467c478bd9Sstevel@tonic-gate assert(string != NULL); 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate if (state == RESTARTER_STATE_NONE) 9497c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_NONE, len)); 9507c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_UNINIT) 9517c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_UNINIT, len)); 9527c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_MAINT) 9537c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_MAINT, len)); 9547c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_OFFLINE) 9557c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_OFFLINE, 9567c478bd9Sstevel@tonic-gate len)); 9577c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_DISABLED) 9587c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_DISABLED, 9597c478bd9Sstevel@tonic-gate len)); 9607c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_ONLINE) 9617c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_ONLINE, len)); 9627c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_DEGRADED) 9637c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_DEGRADED, 9647c478bd9Sstevel@tonic-gate len)); 9657c478bd9Sstevel@tonic-gate else 9667c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, "unknown", len)); 9677c478bd9Sstevel@tonic-gate } 9687c478bd9Sstevel@tonic-gate 9697c478bd9Sstevel@tonic-gate /* 9707c478bd9Sstevel@tonic-gate * Sets pg to the name property group of s_inst. If it doesn't exist, it is 9717c478bd9Sstevel@tonic-gate * added. 9727c478bd9Sstevel@tonic-gate * 9737c478bd9Sstevel@tonic-gate * Fails with 9747c478bd9Sstevel@tonic-gate * ECONNABORTED - repository disconnection or unknown libscf error 9757c478bd9Sstevel@tonic-gate * EBADF - inst is not set 9767c478bd9Sstevel@tonic-gate * ECANCELED - inst is deleted 9777c478bd9Sstevel@tonic-gate * EPERM - permission is denied 9787c478bd9Sstevel@tonic-gate * EACCES - backend denied access 9797c478bd9Sstevel@tonic-gate * EROFS - backend readonly 9807c478bd9Sstevel@tonic-gate */ 9817c478bd9Sstevel@tonic-gate static int 9827c478bd9Sstevel@tonic-gate instance_get_or_add_pg(scf_instance_t *inst, const char *name, 9837c478bd9Sstevel@tonic-gate const char *type, uint32_t flags, scf_propertygroup_t *pg) 9847c478bd9Sstevel@tonic-gate { 9857c478bd9Sstevel@tonic-gate again: 9867c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, name, pg) == 0) 9877c478bd9Sstevel@tonic-gate return (0); 9887c478bd9Sstevel@tonic-gate 9897c478bd9Sstevel@tonic-gate switch (scf_error()) { 9907c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 9917c478bd9Sstevel@tonic-gate default: 9927c478bd9Sstevel@tonic-gate return (ECONNABORTED); 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 9957c478bd9Sstevel@tonic-gate return (EBADF); 9967c478bd9Sstevel@tonic-gate 9977c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 9987c478bd9Sstevel@tonic-gate return (ECANCELED); 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 10017c478bd9Sstevel@tonic-gate break; 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 10047c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 10057c478bd9Sstevel@tonic-gate bad_fail("scf_instance_get_pg", scf_error()); 10067c478bd9Sstevel@tonic-gate } 10077c478bd9Sstevel@tonic-gate 10087c478bd9Sstevel@tonic-gate if (scf_instance_add_pg(inst, name, type, flags, pg) == 0) 10097c478bd9Sstevel@tonic-gate return (0); 10107c478bd9Sstevel@tonic-gate 10117c478bd9Sstevel@tonic-gate switch (scf_error()) { 10127c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 10137c478bd9Sstevel@tonic-gate default: 10147c478bd9Sstevel@tonic-gate return (ECONNABORTED); 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 10177c478bd9Sstevel@tonic-gate return (ECANCELED); 10187c478bd9Sstevel@tonic-gate 10197c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 10207c478bd9Sstevel@tonic-gate goto again; 10217c478bd9Sstevel@tonic-gate 10227c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 10237c478bd9Sstevel@tonic-gate return (EPERM); 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 10267c478bd9Sstevel@tonic-gate return (EACCES); 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 10297c478bd9Sstevel@tonic-gate return (EROFS); 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 10327c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 10337c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: /* should be caught above */ 10347c478bd9Sstevel@tonic-gate bad_fail("scf_instance_add_pg", scf_error()); 10357c478bd9Sstevel@tonic-gate } 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate return (0); 10387c478bd9Sstevel@tonic-gate } 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate /* 10417c478bd9Sstevel@tonic-gate * Fails with 10427c478bd9Sstevel@tonic-gate * ECONNABORTED 10437c478bd9Sstevel@tonic-gate * ECANCELED - pg was deleted 10447c478bd9Sstevel@tonic-gate */ 10457c478bd9Sstevel@tonic-gate static int 10467c478bd9Sstevel@tonic-gate tx_set_value(scf_transaction_t *tx, scf_transaction_entry_t *ent, 10477c478bd9Sstevel@tonic-gate const char *pname, scf_type_t ty, scf_value_t *val) 10487c478bd9Sstevel@tonic-gate { 10497c478bd9Sstevel@tonic-gate int r; 10507c478bd9Sstevel@tonic-gate 10517c478bd9Sstevel@tonic-gate for (;;) { 10527c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(tx, ent, pname, 10537c478bd9Sstevel@tonic-gate ty) == 0) 10547c478bd9Sstevel@tonic-gate break; 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate switch (scf_error()) { 10577c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 10587c478bd9Sstevel@tonic-gate default: 10597c478bd9Sstevel@tonic-gate return (ECONNABORTED); 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 10627c478bd9Sstevel@tonic-gate return (ECANCELED); 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 10657c478bd9Sstevel@tonic-gate break; 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 10687c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 10697c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 10707c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 10717c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_change_type", 10727c478bd9Sstevel@tonic-gate scf_error()); 10737c478bd9Sstevel@tonic-gate } 10747c478bd9Sstevel@tonic-gate 10757c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(tx, ent, pname, ty) == 0) 10767c478bd9Sstevel@tonic-gate break; 10777c478bd9Sstevel@tonic-gate 10787c478bd9Sstevel@tonic-gate switch (scf_error()) { 10797c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 10807c478bd9Sstevel@tonic-gate default: 10817c478bd9Sstevel@tonic-gate return (ECONNABORTED); 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 10847c478bd9Sstevel@tonic-gate return (ECANCELED); 10857c478bd9Sstevel@tonic-gate 10867c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 10877c478bd9Sstevel@tonic-gate break; 10887c478bd9Sstevel@tonic-gate 10897c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 10907c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 10917c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 10927c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 10937c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_new", scf_error()); 10947c478bd9Sstevel@tonic-gate } 10957c478bd9Sstevel@tonic-gate } 10967c478bd9Sstevel@tonic-gate 10977c478bd9Sstevel@tonic-gate r = scf_entry_add_value(ent, val); 10987c478bd9Sstevel@tonic-gate assert(r == 0); 10997c478bd9Sstevel@tonic-gate 11007c478bd9Sstevel@tonic-gate return (0); 11017c478bd9Sstevel@tonic-gate } 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate /* 11047c478bd9Sstevel@tonic-gate * Commit new_state, new_next_state, and aux to the repository for id. If 11057c478bd9Sstevel@tonic-gate * successful, also set id's state and next-state as given, and return 0. 11067c478bd9Sstevel@tonic-gate * Fails with 11077c478bd9Sstevel@tonic-gate * ENOMEM - out of memory 11087c478bd9Sstevel@tonic-gate * ECONNABORTED - repository connection broken 11097c478bd9Sstevel@tonic-gate * - unknown libscf error 11107c478bd9Sstevel@tonic-gate * EINVAL - id->i_fmri is invalid or not an instance FMRI 11117c478bd9Sstevel@tonic-gate * ENOENT - id->i_fmri does not exist 11127c478bd9Sstevel@tonic-gate * EPERM - insufficient permissions 11137c478bd9Sstevel@tonic-gate * EACCES - backend access denied 11147c478bd9Sstevel@tonic-gate * EROFS - backend is readonly 11157c478bd9Sstevel@tonic-gate */ 11167c478bd9Sstevel@tonic-gate int 11177c478bd9Sstevel@tonic-gate _restarter_commit_states(scf_handle_t *h, instance_data_t *id, 11187c478bd9Sstevel@tonic-gate restarter_instance_state_t new_state, 11197c478bd9Sstevel@tonic-gate restarter_instance_state_t new_state_next, const char *aux) 11207c478bd9Sstevel@tonic-gate { 11217c478bd9Sstevel@tonic-gate char str_state[MAX_SCF_STATE_STRING_SZ]; 11227c478bd9Sstevel@tonic-gate char str_new_state[MAX_SCF_STATE_STRING_SZ]; 11237c478bd9Sstevel@tonic-gate char str_state_next[MAX_SCF_STATE_STRING_SZ]; 11247c478bd9Sstevel@tonic-gate char str_new_state_next[MAX_SCF_STATE_STRING_SZ]; 11257c478bd9Sstevel@tonic-gate int ret = 0, r; 11267c478bd9Sstevel@tonic-gate struct timeval now; 11277c478bd9Sstevel@tonic-gate ssize_t sz; 11287c478bd9Sstevel@tonic-gate 11297c478bd9Sstevel@tonic-gate scf_transaction_t *t = NULL; 11307c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_state = NULL, *t_state_next = NULL; 11317c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_stime = NULL, *t_aux = NULL; 11327c478bd9Sstevel@tonic-gate scf_value_t *v_state = NULL, *v_state_next = NULL, *v_stime = NULL; 11337c478bd9Sstevel@tonic-gate scf_value_t *v_aux = NULL; 11347c478bd9Sstevel@tonic-gate scf_instance_t *s_inst = NULL; 11357c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 11367c478bd9Sstevel@tonic-gate 11377c478bd9Sstevel@tonic-gate assert(new_state != RESTARTER_STATE_NONE); 11387c478bd9Sstevel@tonic-gate 11397c478bd9Sstevel@tonic-gate if ((s_inst = scf_instance_create(h)) == NULL || 11407c478bd9Sstevel@tonic-gate (pg = scf_pg_create(h)) == NULL || 11417c478bd9Sstevel@tonic-gate (t = scf_transaction_create(h)) == NULL || 11427c478bd9Sstevel@tonic-gate (t_state = scf_entry_create(h)) == NULL || 11437c478bd9Sstevel@tonic-gate (t_state_next = scf_entry_create(h)) == NULL || 11447c478bd9Sstevel@tonic-gate (t_stime = scf_entry_create(h)) == NULL || 11457c478bd9Sstevel@tonic-gate (t_aux = scf_entry_create(h)) == NULL || 11467c478bd9Sstevel@tonic-gate (v_state = scf_value_create(h)) == NULL || 11477c478bd9Sstevel@tonic-gate (v_state_next = scf_value_create(h)) == NULL || 11487c478bd9Sstevel@tonic-gate (v_stime = scf_value_create(h)) == NULL || 11497c478bd9Sstevel@tonic-gate (v_aux = scf_value_create(h)) == NULL) { 11507c478bd9Sstevel@tonic-gate ret = ENOMEM; 11517c478bd9Sstevel@tonic-gate goto out; 11527c478bd9Sstevel@tonic-gate } 11537c478bd9Sstevel@tonic-gate 11547c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(new_state, str_new_state, 11557c478bd9Sstevel@tonic-gate sizeof (str_new_state)); 11567c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_new_state)); 11577c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(new_state_next, str_new_state_next, 11587c478bd9Sstevel@tonic-gate sizeof (str_new_state_next)); 11597c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_new_state_next)); 11607c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(id->i_state, str_state, 11617c478bd9Sstevel@tonic-gate sizeof (str_state)); 11627c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_state)); 11637c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(id->i_next_state, str_state_next, 11647c478bd9Sstevel@tonic-gate sizeof (str_state_next)); 11657c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_state_next)); 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate ret = gettimeofday(&now, NULL); 11687c478bd9Sstevel@tonic-gate assert(ret != -1); 11697c478bd9Sstevel@tonic-gate 11707c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, id->i_fmri, NULL, NULL, s_inst, 11717c478bd9Sstevel@tonic-gate NULL, NULL, SCF_DECODE_FMRI_EXACT) == -1) { 11727c478bd9Sstevel@tonic-gate switch (scf_error()) { 11737c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 11747c478bd9Sstevel@tonic-gate default: 11757c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 11767c478bd9Sstevel@tonic-gate break; 11777c478bd9Sstevel@tonic-gate 11787c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 11797c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 11807c478bd9Sstevel@tonic-gate ret = EINVAL; 11817c478bd9Sstevel@tonic-gate break; 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 11847c478bd9Sstevel@tonic-gate ret = ENOENT; 11857c478bd9Sstevel@tonic-gate break; 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 11887c478bd9Sstevel@tonic-gate bad_fail("scf_handle_decode_fmri", scf_error()); 11897c478bd9Sstevel@tonic-gate } 11907c478bd9Sstevel@tonic-gate goto out; 11917c478bd9Sstevel@tonic-gate } 11927c478bd9Sstevel@tonic-gate 11937c478bd9Sstevel@tonic-gate 11947c478bd9Sstevel@tonic-gate if (scf_value_set_astring(v_state, str_new_state) != 0 || 1195eb1a3463STruong Nguyen scf_value_set_astring(v_state_next, str_new_state_next) != 0) 11967c478bd9Sstevel@tonic-gate bad_fail("scf_value_set_astring", scf_error()); 11977c478bd9Sstevel@tonic-gate 1198eb1a3463STruong Nguyen if (aux) { 1199eb1a3463STruong Nguyen if (scf_value_set_astring(v_aux, aux) != 0) 1200eb1a3463STruong Nguyen bad_fail("scf_value_set_astring", scf_error()); 1201eb1a3463STruong Nguyen } 1202eb1a3463STruong Nguyen 12037c478bd9Sstevel@tonic-gate if (scf_value_set_time(v_stime, now.tv_sec, now.tv_usec * 1000) != 0) 12047c478bd9Sstevel@tonic-gate bad_fail("scf_value_set_time", scf_error()); 12057c478bd9Sstevel@tonic-gate 12067c478bd9Sstevel@tonic-gate add_pg: 12077c478bd9Sstevel@tonic-gate switch (r = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER, 12087c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg)) { 12097c478bd9Sstevel@tonic-gate case 0: 12107c478bd9Sstevel@tonic-gate break; 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate case ECONNABORTED: 12137c478bd9Sstevel@tonic-gate case EPERM: 12147c478bd9Sstevel@tonic-gate case EACCES: 12157c478bd9Sstevel@tonic-gate case EROFS: 12167c478bd9Sstevel@tonic-gate ret = r; 12177c478bd9Sstevel@tonic-gate goto out; 12187c478bd9Sstevel@tonic-gate 12197c478bd9Sstevel@tonic-gate case ECANCELED: 12207c478bd9Sstevel@tonic-gate ret = ENOENT; 12217c478bd9Sstevel@tonic-gate goto out; 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate case EBADF: 12247c478bd9Sstevel@tonic-gate default: 12257c478bd9Sstevel@tonic-gate bad_fail("instance_get_or_add_pg", r); 12267c478bd9Sstevel@tonic-gate } 12277c478bd9Sstevel@tonic-gate 12287c478bd9Sstevel@tonic-gate for (;;) { 12297c478bd9Sstevel@tonic-gate if (scf_transaction_start(t, pg) != 0) { 12307c478bd9Sstevel@tonic-gate switch (scf_error()) { 12317c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 12327c478bd9Sstevel@tonic-gate default: 12337c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 12347c478bd9Sstevel@tonic-gate goto out; 12357c478bd9Sstevel@tonic-gate 12367c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 12377c478bd9Sstevel@tonic-gate goto add_pg; 12387c478bd9Sstevel@tonic-gate 12397c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 12407c478bd9Sstevel@tonic-gate ret = EPERM; 12417c478bd9Sstevel@tonic-gate goto out; 12427c478bd9Sstevel@tonic-gate 12437c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 12447c478bd9Sstevel@tonic-gate ret = EACCES; 12457c478bd9Sstevel@tonic-gate goto out; 12467c478bd9Sstevel@tonic-gate 12477c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 12487c478bd9Sstevel@tonic-gate ret = EROFS; 12497c478bd9Sstevel@tonic-gate goto out; 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 12527c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 12537c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_start", scf_error()); 12547c478bd9Sstevel@tonic-gate } 12557c478bd9Sstevel@tonic-gate } 12567c478bd9Sstevel@tonic-gate 12577c478bd9Sstevel@tonic-gate if ((r = tx_set_value(t, t_state, SCF_PROPERTY_STATE, 12587c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, v_state)) != 0 || 12597c478bd9Sstevel@tonic-gate (r = tx_set_value(t, t_state_next, SCF_PROPERTY_NEXT_STATE, 12607c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, v_state_next)) != 0 || 12617c478bd9Sstevel@tonic-gate (r = tx_set_value(t, t_stime, SCF_PROPERTY_STATE_TIMESTAMP, 12627c478bd9Sstevel@tonic-gate SCF_TYPE_TIME, v_stime)) != 0) { 12637c478bd9Sstevel@tonic-gate switch (r) { 12647c478bd9Sstevel@tonic-gate case ECONNABORTED: 12657c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 12667c478bd9Sstevel@tonic-gate goto out; 12677c478bd9Sstevel@tonic-gate 12687c478bd9Sstevel@tonic-gate case ECANCELED: 12697c478bd9Sstevel@tonic-gate scf_transaction_reset(t); 12707c478bd9Sstevel@tonic-gate goto add_pg; 12717c478bd9Sstevel@tonic-gate 12727c478bd9Sstevel@tonic-gate default: 12737c478bd9Sstevel@tonic-gate bad_fail("tx_set_value", r); 12747c478bd9Sstevel@tonic-gate } 12757c478bd9Sstevel@tonic-gate } 12767c478bd9Sstevel@tonic-gate 1277eb1a3463STruong Nguyen if (aux) { 1278eb1a3463STruong Nguyen if ((r = tx_set_value(t, t_aux, SCF_PROPERTY_AUX_STATE, 1279eb1a3463STruong Nguyen SCF_TYPE_ASTRING, v_aux)) != 0) { 1280eb1a3463STruong Nguyen switch (r) { 1281eb1a3463STruong Nguyen case ECONNABORTED: 1282eb1a3463STruong Nguyen ret = ECONNABORTED; 1283eb1a3463STruong Nguyen goto out; 1284eb1a3463STruong Nguyen 1285eb1a3463STruong Nguyen case ECANCELED: 1286eb1a3463STruong Nguyen scf_transaction_reset(t); 1287eb1a3463STruong Nguyen goto add_pg; 1288eb1a3463STruong Nguyen 1289eb1a3463STruong Nguyen default: 1290eb1a3463STruong Nguyen bad_fail("tx_set_value", r); 1291eb1a3463STruong Nguyen } 1292eb1a3463STruong Nguyen } 1293eb1a3463STruong Nguyen } 1294eb1a3463STruong Nguyen 12957c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(t); 12967c478bd9Sstevel@tonic-gate if (ret == 1) 12977c478bd9Sstevel@tonic-gate break; 12987c478bd9Sstevel@tonic-gate if (ret == -1) { 12997c478bd9Sstevel@tonic-gate switch (scf_error()) { 13007c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 13017c478bd9Sstevel@tonic-gate default: 13027c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 13037c478bd9Sstevel@tonic-gate goto out; 13047c478bd9Sstevel@tonic-gate 13057c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 13067c478bd9Sstevel@tonic-gate ret = EPERM; 13077c478bd9Sstevel@tonic-gate goto out; 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 13107c478bd9Sstevel@tonic-gate ret = EACCES; 13117c478bd9Sstevel@tonic-gate goto out; 13127c478bd9Sstevel@tonic-gate 13137c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 13147c478bd9Sstevel@tonic-gate ret = EROFS; 13157c478bd9Sstevel@tonic-gate goto out; 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 13187c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_commit", scf_error()); 13197c478bd9Sstevel@tonic-gate } 13207c478bd9Sstevel@tonic-gate } 13217c478bd9Sstevel@tonic-gate 13227c478bd9Sstevel@tonic-gate scf_transaction_reset(t); 13237c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 13247c478bd9Sstevel@tonic-gate switch (scf_error()) { 13257c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 13267c478bd9Sstevel@tonic-gate default: 13277c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 13287c478bd9Sstevel@tonic-gate goto out; 13297c478bd9Sstevel@tonic-gate 13307c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 13317c478bd9Sstevel@tonic-gate goto add_pg; 13327c478bd9Sstevel@tonic-gate } 13337c478bd9Sstevel@tonic-gate } 13347c478bd9Sstevel@tonic-gate } 13357c478bd9Sstevel@tonic-gate 13367c478bd9Sstevel@tonic-gate id->i_state = new_state; 13377c478bd9Sstevel@tonic-gate id->i_next_state = new_state_next; 13387c478bd9Sstevel@tonic-gate ret = 0; 13397c478bd9Sstevel@tonic-gate 13407c478bd9Sstevel@tonic-gate out: 13417c478bd9Sstevel@tonic-gate scf_transaction_destroy(t); 13427c478bd9Sstevel@tonic-gate scf_entry_destroy(t_state); 13437c478bd9Sstevel@tonic-gate scf_entry_destroy(t_state_next); 13447c478bd9Sstevel@tonic-gate scf_entry_destroy(t_stime); 13457c478bd9Sstevel@tonic-gate scf_entry_destroy(t_aux); 13467c478bd9Sstevel@tonic-gate scf_value_destroy(v_state); 13477c478bd9Sstevel@tonic-gate scf_value_destroy(v_state_next); 13487c478bd9Sstevel@tonic-gate scf_value_destroy(v_stime); 13497c478bd9Sstevel@tonic-gate scf_value_destroy(v_aux); 13507c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 13517c478bd9Sstevel@tonic-gate scf_instance_destroy(s_inst); 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate return (ret); 13547c478bd9Sstevel@tonic-gate } 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate /* 13577c478bd9Sstevel@tonic-gate * Fails with 13587c478bd9Sstevel@tonic-gate * EINVAL - type is invalid 13597c478bd9Sstevel@tonic-gate * ENOMEM 13607c478bd9Sstevel@tonic-gate * ECONNABORTED - repository connection broken 13617c478bd9Sstevel@tonic-gate * EBADF - s_inst is not set 13627c478bd9Sstevel@tonic-gate * ECANCELED - s_inst is deleted 13637c478bd9Sstevel@tonic-gate * EPERM - permission denied 13647c478bd9Sstevel@tonic-gate * EACCES - backend access denied 13657c478bd9Sstevel@tonic-gate * EROFS - backend readonly 13667c478bd9Sstevel@tonic-gate */ 13677c478bd9Sstevel@tonic-gate int 13687c478bd9Sstevel@tonic-gate restarter_remove_contract(scf_instance_t *s_inst, ctid_t contract_id, 13697c478bd9Sstevel@tonic-gate restarter_contract_type_t type) 13707c478bd9Sstevel@tonic-gate { 13717c478bd9Sstevel@tonic-gate scf_handle_t *h; 13727c478bd9Sstevel@tonic-gate scf_transaction_t *t = NULL; 13737c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_cid = NULL; 13747c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 13757c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL; 13767c478bd9Sstevel@tonic-gate scf_value_t *val; 13777c478bd9Sstevel@tonic-gate scf_iter_t *iter = NULL; 13787c478bd9Sstevel@tonic-gate const char *pname; 13797c478bd9Sstevel@tonic-gate int ret = 0, primary; 13807c478bd9Sstevel@tonic-gate uint64_t c; 13817c478bd9Sstevel@tonic-gate 13827c478bd9Sstevel@tonic-gate switch (type) { 13837c478bd9Sstevel@tonic-gate case RESTARTER_CONTRACT_PRIMARY: 13847c478bd9Sstevel@tonic-gate primary = 1; 13857c478bd9Sstevel@tonic-gate break; 13867c478bd9Sstevel@tonic-gate case RESTARTER_CONTRACT_TRANSIENT: 13877c478bd9Sstevel@tonic-gate primary = 0; 13887c478bd9Sstevel@tonic-gate break; 13897c478bd9Sstevel@tonic-gate default: 13907c478bd9Sstevel@tonic-gate return (EINVAL); 13917c478bd9Sstevel@tonic-gate } 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate h = scf_instance_handle(s_inst); 13947c478bd9Sstevel@tonic-gate 13957c478bd9Sstevel@tonic-gate pg = scf_pg_create(h); 13967c478bd9Sstevel@tonic-gate prop = scf_property_create(h); 13977c478bd9Sstevel@tonic-gate iter = scf_iter_create(h); 13987c478bd9Sstevel@tonic-gate t = scf_transaction_create(h); 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate if (pg == NULL || prop == NULL || iter == NULL || t == NULL) { 14017c478bd9Sstevel@tonic-gate ret = ENOMEM; 14027c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 14037c478bd9Sstevel@tonic-gate } 14047c478bd9Sstevel@tonic-gate 14057c478bd9Sstevel@tonic-gate add: 14067c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 14077c478bd9Sstevel@tonic-gate ret = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER, 14087c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg); 14097c478bd9Sstevel@tonic-gate if (ret != 0) 14107c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate pname = primary? SCF_PROPERTY_CONTRACT : 14137c478bd9Sstevel@tonic-gate SCF_PROPERTY_TRANSIENT_CONTRACT; 14147c478bd9Sstevel@tonic-gate 14157c478bd9Sstevel@tonic-gate for (;;) { 14167c478bd9Sstevel@tonic-gate if (scf_transaction_start(t, pg) != 0) { 14177c478bd9Sstevel@tonic-gate switch (scf_error()) { 14187c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 14197c478bd9Sstevel@tonic-gate default: 14207c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 14217c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 14227c478bd9Sstevel@tonic-gate 14237c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 14247c478bd9Sstevel@tonic-gate goto add; 14257c478bd9Sstevel@tonic-gate 14267c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 14277c478bd9Sstevel@tonic-gate ret = EPERM; 14287c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 14317c478bd9Sstevel@tonic-gate ret = EACCES; 14327c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 14357c478bd9Sstevel@tonic-gate ret = EROFS; 14367c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 14377c478bd9Sstevel@tonic-gate 14387c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 14397c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 14407c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 14417c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_start", scf_error()); 14427c478bd9Sstevel@tonic-gate } 14437c478bd9Sstevel@tonic-gate } 14447c478bd9Sstevel@tonic-gate 14457c478bd9Sstevel@tonic-gate t_cid = scf_entry_create(h); 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, pname, prop) == 0) { 14487c478bd9Sstevel@tonic-gate replace: 14497c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(t, t_cid, 14507c478bd9Sstevel@tonic-gate pname, SCF_TYPE_COUNT) != 0) { 14517c478bd9Sstevel@tonic-gate switch (scf_error()) { 14527c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 14537c478bd9Sstevel@tonic-gate default: 14547c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 14557c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 14567c478bd9Sstevel@tonic-gate 14577c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 14587c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 14597c478bd9Sstevel@tonic-gate goto add; 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 14627c478bd9Sstevel@tonic-gate goto new; 14637c478bd9Sstevel@tonic-gate 14647c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 14657c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 14667c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 14677c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 14687c478bd9Sstevel@tonic-gate bad_fail( 14697c478bd9Sstevel@tonic-gate "scf_transaction_property_changetype", 14707c478bd9Sstevel@tonic-gate scf_error()); 14717c478bd9Sstevel@tonic-gate } 14727c478bd9Sstevel@tonic-gate } 14737c478bd9Sstevel@tonic-gate 14747c478bd9Sstevel@tonic-gate if (scf_property_is_type(prop, SCF_TYPE_COUNT) == 0) { 14757c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) { 14767c478bd9Sstevel@tonic-gate switch (scf_error()) { 14777c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 14787c478bd9Sstevel@tonic-gate default: 14797c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 14807c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 14817c478bd9Sstevel@tonic-gate 14827c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 14837c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 14847c478bd9Sstevel@tonic-gate bad_fail( 14857c478bd9Sstevel@tonic-gate "scf_iter_property_values", 14867c478bd9Sstevel@tonic-gate scf_error()); 14877c478bd9Sstevel@tonic-gate } 14887c478bd9Sstevel@tonic-gate } 14897c478bd9Sstevel@tonic-gate 14907c478bd9Sstevel@tonic-gate next_val: 14917c478bd9Sstevel@tonic-gate val = scf_value_create(h); 14927c478bd9Sstevel@tonic-gate if (val == NULL) { 14937c478bd9Sstevel@tonic-gate assert(scf_error() == 14947c478bd9Sstevel@tonic-gate SCF_ERROR_NO_MEMORY); 14957c478bd9Sstevel@tonic-gate ret = ENOMEM; 14967c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 14977c478bd9Sstevel@tonic-gate } 14987c478bd9Sstevel@tonic-gate 14997c478bd9Sstevel@tonic-gate ret = scf_iter_next_value(iter, val); 15007c478bd9Sstevel@tonic-gate if (ret == -1) { 15017c478bd9Sstevel@tonic-gate switch (scf_error()) { 15027c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 15037c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 15047c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 15057c478bd9Sstevel@tonic-gate 15067c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 15077c478bd9Sstevel@tonic-gate scf_value_destroy(val); 15087c478bd9Sstevel@tonic-gate goto add; 15097c478bd9Sstevel@tonic-gate 15107c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 15117c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 15123eae19d9Swesolows case SCF_ERROR_PERMISSION_DENIED: 15137c478bd9Sstevel@tonic-gate default: 15147c478bd9Sstevel@tonic-gate bad_fail("scf_iter_next_value", 15157c478bd9Sstevel@tonic-gate scf_error()); 15167c478bd9Sstevel@tonic-gate } 15177c478bd9Sstevel@tonic-gate } 15187c478bd9Sstevel@tonic-gate 15197c478bd9Sstevel@tonic-gate if (ret == 1) { 15207c478bd9Sstevel@tonic-gate ret = scf_value_get_count(val, &c); 15217c478bd9Sstevel@tonic-gate assert(ret == 0); 15227c478bd9Sstevel@tonic-gate 15237c478bd9Sstevel@tonic-gate if (c != contract_id) { 15247c478bd9Sstevel@tonic-gate ret = scf_entry_add_value(t_cid, 15257c478bd9Sstevel@tonic-gate val); 15267c478bd9Sstevel@tonic-gate assert(ret == 0); 15277c478bd9Sstevel@tonic-gate } else { 15287c478bd9Sstevel@tonic-gate scf_value_destroy(val); 15297c478bd9Sstevel@tonic-gate } 15307c478bd9Sstevel@tonic-gate 15317c478bd9Sstevel@tonic-gate goto next_val; 15327c478bd9Sstevel@tonic-gate } 15337c478bd9Sstevel@tonic-gate 15347c478bd9Sstevel@tonic-gate scf_value_destroy(val); 15357c478bd9Sstevel@tonic-gate } else { 15367c478bd9Sstevel@tonic-gate switch (scf_error()) { 15377c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 15387c478bd9Sstevel@tonic-gate default: 15397c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 15407c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 15417c478bd9Sstevel@tonic-gate 15427c478bd9Sstevel@tonic-gate case SCF_ERROR_TYPE_MISMATCH: 15437c478bd9Sstevel@tonic-gate break; 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 15467c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 15477c478bd9Sstevel@tonic-gate bad_fail("scf_property_is_type", 15487c478bd9Sstevel@tonic-gate scf_error()); 15497c478bd9Sstevel@tonic-gate } 15507c478bd9Sstevel@tonic-gate } 15517c478bd9Sstevel@tonic-gate } else { 15527c478bd9Sstevel@tonic-gate switch (scf_error()) { 15537c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 15547c478bd9Sstevel@tonic-gate default: 15557c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 15567c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 15597c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 15607c478bd9Sstevel@tonic-gate goto add; 15617c478bd9Sstevel@tonic-gate 15627c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 15637c478bd9Sstevel@tonic-gate break; 15647c478bd9Sstevel@tonic-gate 15657c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 15667c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 15677c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 15687c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error()); 15697c478bd9Sstevel@tonic-gate } 15707c478bd9Sstevel@tonic-gate 15717c478bd9Sstevel@tonic-gate new: 15727c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(t, t_cid, pname, 15737c478bd9Sstevel@tonic-gate SCF_TYPE_COUNT) != 0) { 15747c478bd9Sstevel@tonic-gate switch (scf_error()) { 15757c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 15767c478bd9Sstevel@tonic-gate default: 15777c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 15787c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 15797c478bd9Sstevel@tonic-gate 15807c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 15817c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 15827c478bd9Sstevel@tonic-gate goto add; 15837c478bd9Sstevel@tonic-gate 15847c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 15857c478bd9Sstevel@tonic-gate goto replace; 15867c478bd9Sstevel@tonic-gate 15877c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 15887c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 15897c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 15907c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_new", 15917c478bd9Sstevel@tonic-gate scf_error()); 15927c478bd9Sstevel@tonic-gate } 15937c478bd9Sstevel@tonic-gate } 15947c478bd9Sstevel@tonic-gate } 15957c478bd9Sstevel@tonic-gate 15967c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(t); 15977c478bd9Sstevel@tonic-gate if (ret == -1) { 15987c478bd9Sstevel@tonic-gate switch (scf_error()) { 15997c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 16007c478bd9Sstevel@tonic-gate default: 16017c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 16027c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 16037c478bd9Sstevel@tonic-gate 16047c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 16057c478bd9Sstevel@tonic-gate goto add; 16067c478bd9Sstevel@tonic-gate 16077c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 16087c478bd9Sstevel@tonic-gate ret = EPERM; 16097c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 16127c478bd9Sstevel@tonic-gate ret = EACCES; 16137c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 16147c478bd9Sstevel@tonic-gate 16157c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 16167c478bd9Sstevel@tonic-gate ret = EROFS; 16177c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 16207c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_commit", scf_error()); 16217c478bd9Sstevel@tonic-gate } 16227c478bd9Sstevel@tonic-gate } 16237c478bd9Sstevel@tonic-gate if (ret == 1) { 16247c478bd9Sstevel@tonic-gate ret = 0; 16257c478bd9Sstevel@tonic-gate break; 16267c478bd9Sstevel@tonic-gate } 16277c478bd9Sstevel@tonic-gate 16287c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 16297c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 16307c478bd9Sstevel@tonic-gate switch (scf_error()) { 16317c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 16327c478bd9Sstevel@tonic-gate default: 16337c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 16347c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 16357c478bd9Sstevel@tonic-gate 16367c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 16377c478bd9Sstevel@tonic-gate goto add; 16387c478bd9Sstevel@tonic-gate 16397c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 16407c478bd9Sstevel@tonic-gate bad_fail("scf_pg_update", scf_error()); 16417c478bd9Sstevel@tonic-gate } 16427c478bd9Sstevel@tonic-gate } 16437c478bd9Sstevel@tonic-gate } 16447c478bd9Sstevel@tonic-gate 16457c478bd9Sstevel@tonic-gate remove_contract_cleanup: 16467c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 16477c478bd9Sstevel@tonic-gate scf_transaction_destroy(t); 16487c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 16497c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 16507c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 16517c478bd9Sstevel@tonic-gate 16527c478bd9Sstevel@tonic-gate return (ret); 16537c478bd9Sstevel@tonic-gate } 16547c478bd9Sstevel@tonic-gate 16557c478bd9Sstevel@tonic-gate /* 16567c478bd9Sstevel@tonic-gate * Fails with 16577c478bd9Sstevel@tonic-gate * EINVAL - type is invalid 16587c478bd9Sstevel@tonic-gate * ENOMEM 16597c478bd9Sstevel@tonic-gate * ECONNABORTED - repository disconnection 16607c478bd9Sstevel@tonic-gate * EBADF - s_inst is not set 16617c478bd9Sstevel@tonic-gate * ECANCELED - s_inst is deleted 16627c478bd9Sstevel@tonic-gate * EPERM 16637c478bd9Sstevel@tonic-gate * EACCES 16647c478bd9Sstevel@tonic-gate * EROFS 16657c478bd9Sstevel@tonic-gate */ 16667c478bd9Sstevel@tonic-gate int 16677c478bd9Sstevel@tonic-gate restarter_store_contract(scf_instance_t *s_inst, ctid_t contract_id, 16687c478bd9Sstevel@tonic-gate restarter_contract_type_t type) 16697c478bd9Sstevel@tonic-gate { 16707c478bd9Sstevel@tonic-gate scf_handle_t *h; 16717c478bd9Sstevel@tonic-gate scf_transaction_t *t = NULL; 16727c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_cid = NULL; 16737c478bd9Sstevel@tonic-gate scf_value_t *val; 16747c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 16757c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL; 16767c478bd9Sstevel@tonic-gate scf_iter_t *iter = NULL; 16777c478bd9Sstevel@tonic-gate const char *pname; 16787c478bd9Sstevel@tonic-gate int ret = 0, primary; 16797c478bd9Sstevel@tonic-gate 16807c478bd9Sstevel@tonic-gate if (type == RESTARTER_CONTRACT_PRIMARY) 16817c478bd9Sstevel@tonic-gate primary = 1; 16827c478bd9Sstevel@tonic-gate else if (type == RESTARTER_CONTRACT_TRANSIENT) 16837c478bd9Sstevel@tonic-gate primary = 0; 16847c478bd9Sstevel@tonic-gate else 16857c478bd9Sstevel@tonic-gate return (EINVAL); 16867c478bd9Sstevel@tonic-gate 16877c478bd9Sstevel@tonic-gate h = scf_instance_handle(s_inst); 16887c478bd9Sstevel@tonic-gate 16897c478bd9Sstevel@tonic-gate pg = scf_pg_create(h); 16907c478bd9Sstevel@tonic-gate prop = scf_property_create(h); 16917c478bd9Sstevel@tonic-gate iter = scf_iter_create(h); 16927c478bd9Sstevel@tonic-gate t = scf_transaction_create(h); 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate if (pg == NULL || prop == NULL || iter == NULL || t == NULL) { 16957c478bd9Sstevel@tonic-gate ret = ENOMEM; 16967c478bd9Sstevel@tonic-gate goto out; 16977c478bd9Sstevel@tonic-gate } 16987c478bd9Sstevel@tonic-gate 16997c478bd9Sstevel@tonic-gate add: 17007c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 17017c478bd9Sstevel@tonic-gate ret = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER, 17027c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg); 17037c478bd9Sstevel@tonic-gate if (ret != 0) 17047c478bd9Sstevel@tonic-gate goto out; 17057c478bd9Sstevel@tonic-gate 17067c478bd9Sstevel@tonic-gate pname = primary ? SCF_PROPERTY_CONTRACT : 17077c478bd9Sstevel@tonic-gate SCF_PROPERTY_TRANSIENT_CONTRACT; 17087c478bd9Sstevel@tonic-gate 17097c478bd9Sstevel@tonic-gate for (;;) { 17107c478bd9Sstevel@tonic-gate if (scf_transaction_start(t, pg) != 0) { 17117c478bd9Sstevel@tonic-gate switch (scf_error()) { 17127c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 17137c478bd9Sstevel@tonic-gate default: 17147c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 17157c478bd9Sstevel@tonic-gate goto out; 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 17187c478bd9Sstevel@tonic-gate goto add; 17197c478bd9Sstevel@tonic-gate 17207c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 17217c478bd9Sstevel@tonic-gate ret = EPERM; 17227c478bd9Sstevel@tonic-gate goto out; 17237c478bd9Sstevel@tonic-gate 17247c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 17257c478bd9Sstevel@tonic-gate ret = EACCES; 17267c478bd9Sstevel@tonic-gate goto out; 17277c478bd9Sstevel@tonic-gate 17287c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 17297c478bd9Sstevel@tonic-gate ret = EROFS; 17307c478bd9Sstevel@tonic-gate goto out; 17317c478bd9Sstevel@tonic-gate 17327c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 17337c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 17347c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 17357c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_start", scf_error()); 17367c478bd9Sstevel@tonic-gate } 17377c478bd9Sstevel@tonic-gate } 17387c478bd9Sstevel@tonic-gate 17397c478bd9Sstevel@tonic-gate t_cid = scf_entry_create(h); 17407c478bd9Sstevel@tonic-gate if (t_cid == NULL) { 17417c478bd9Sstevel@tonic-gate ret = ENOMEM; 17427c478bd9Sstevel@tonic-gate goto out; 17437c478bd9Sstevel@tonic-gate } 17447c478bd9Sstevel@tonic-gate 17457c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, pname, prop) == 0) { 17467c478bd9Sstevel@tonic-gate replace: 17477c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(t, t_cid, 17487c478bd9Sstevel@tonic-gate pname, SCF_TYPE_COUNT) != 0) { 17497c478bd9Sstevel@tonic-gate switch (scf_error()) { 17507c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 17517c478bd9Sstevel@tonic-gate default: 17527c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 17537c478bd9Sstevel@tonic-gate goto out; 17547c478bd9Sstevel@tonic-gate 17557c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 17567c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 17577c478bd9Sstevel@tonic-gate goto add; 17587c478bd9Sstevel@tonic-gate 17597c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 17607c478bd9Sstevel@tonic-gate goto new; 17617c478bd9Sstevel@tonic-gate 17627c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 17637c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 17647c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 17657c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 17667c478bd9Sstevel@tonic-gate bad_fail( 17677c478bd9Sstevel@tonic-gate "scf_transaction_propert_change_type", 17687c478bd9Sstevel@tonic-gate scf_error()); 17697c478bd9Sstevel@tonic-gate } 17707c478bd9Sstevel@tonic-gate } 17717c478bd9Sstevel@tonic-gate 17727c478bd9Sstevel@tonic-gate if (scf_property_is_type(prop, SCF_TYPE_COUNT) == 0) { 17737c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) { 17747c478bd9Sstevel@tonic-gate switch (scf_error()) { 17757c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 17767c478bd9Sstevel@tonic-gate default: 17777c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 17787c478bd9Sstevel@tonic-gate goto out; 17797c478bd9Sstevel@tonic-gate 17807c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 17817c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 17827c478bd9Sstevel@tonic-gate bad_fail( 17837c478bd9Sstevel@tonic-gate "scf_iter_property_values", 17847c478bd9Sstevel@tonic-gate scf_error()); 17857c478bd9Sstevel@tonic-gate } 17867c478bd9Sstevel@tonic-gate } 17877c478bd9Sstevel@tonic-gate 17887c478bd9Sstevel@tonic-gate next_val: 17897c478bd9Sstevel@tonic-gate val = scf_value_create(h); 17907c478bd9Sstevel@tonic-gate if (val == NULL) { 17917c478bd9Sstevel@tonic-gate assert(scf_error() == 17927c478bd9Sstevel@tonic-gate SCF_ERROR_NO_MEMORY); 17937c478bd9Sstevel@tonic-gate ret = ENOMEM; 17947c478bd9Sstevel@tonic-gate goto out; 17957c478bd9Sstevel@tonic-gate } 17967c478bd9Sstevel@tonic-gate 17977c478bd9Sstevel@tonic-gate ret = scf_iter_next_value(iter, val); 17987c478bd9Sstevel@tonic-gate if (ret == -1) { 17997c478bd9Sstevel@tonic-gate switch (scf_error()) { 18007c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 18017c478bd9Sstevel@tonic-gate default: 18027c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 18037c478bd9Sstevel@tonic-gate goto out; 18047c478bd9Sstevel@tonic-gate 18057c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 18067c478bd9Sstevel@tonic-gate scf_value_destroy(val); 18077c478bd9Sstevel@tonic-gate goto add; 18087c478bd9Sstevel@tonic-gate 18097c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 18107c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 18113eae19d9Swesolows case SCF_ERROR_PERMISSION_DENIED: 18127c478bd9Sstevel@tonic-gate bad_fail( 18137c478bd9Sstevel@tonic-gate "scf_iter_next_value", 18147c478bd9Sstevel@tonic-gate scf_error()); 18157c478bd9Sstevel@tonic-gate } 18167c478bd9Sstevel@tonic-gate } 18177c478bd9Sstevel@tonic-gate 18187c478bd9Sstevel@tonic-gate if (ret == 1) { 18197c478bd9Sstevel@tonic-gate ret = scf_entry_add_value(t_cid, val); 18207c478bd9Sstevel@tonic-gate assert(ret == 0); 18217c478bd9Sstevel@tonic-gate 18227c478bd9Sstevel@tonic-gate goto next_val; 18237c478bd9Sstevel@tonic-gate } 18247c478bd9Sstevel@tonic-gate 18257c478bd9Sstevel@tonic-gate scf_value_destroy(val); 18267c478bd9Sstevel@tonic-gate } else { 18277c478bd9Sstevel@tonic-gate switch (scf_error()) { 18287c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 18297c478bd9Sstevel@tonic-gate default: 18307c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 18317c478bd9Sstevel@tonic-gate goto out; 18327c478bd9Sstevel@tonic-gate 18337c478bd9Sstevel@tonic-gate case SCF_ERROR_TYPE_MISMATCH: 18347c478bd9Sstevel@tonic-gate break; 18357c478bd9Sstevel@tonic-gate 18367c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 18377c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 18387c478bd9Sstevel@tonic-gate bad_fail("scf_property_is_type", 18397c478bd9Sstevel@tonic-gate scf_error()); 18407c478bd9Sstevel@tonic-gate } 18417c478bd9Sstevel@tonic-gate } 18427c478bd9Sstevel@tonic-gate } else { 18437c478bd9Sstevel@tonic-gate switch (scf_error()) { 18447c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 18457c478bd9Sstevel@tonic-gate default: 18467c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 18477c478bd9Sstevel@tonic-gate goto out; 18487c478bd9Sstevel@tonic-gate 18497c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 18507c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 18517c478bd9Sstevel@tonic-gate goto add; 18527c478bd9Sstevel@tonic-gate 18537c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 18547c478bd9Sstevel@tonic-gate break; 18557c478bd9Sstevel@tonic-gate 18567c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 18577c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 18587c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 18597c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error()); 18607c478bd9Sstevel@tonic-gate } 18617c478bd9Sstevel@tonic-gate 18627c478bd9Sstevel@tonic-gate new: 18637c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(t, t_cid, pname, 18647c478bd9Sstevel@tonic-gate SCF_TYPE_COUNT) != 0) { 18657c478bd9Sstevel@tonic-gate switch (scf_error()) { 18667c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 18677c478bd9Sstevel@tonic-gate default: 18687c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 18697c478bd9Sstevel@tonic-gate goto out; 18707c478bd9Sstevel@tonic-gate 18717c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 18727c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 18737c478bd9Sstevel@tonic-gate goto add; 18747c478bd9Sstevel@tonic-gate 18757c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 18767c478bd9Sstevel@tonic-gate goto replace; 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 18797c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 18807c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 18817c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_new", 18827c478bd9Sstevel@tonic-gate scf_error()); 18837c478bd9Sstevel@tonic-gate } 18847c478bd9Sstevel@tonic-gate } 18857c478bd9Sstevel@tonic-gate } 18867c478bd9Sstevel@tonic-gate 18877c478bd9Sstevel@tonic-gate val = scf_value_create(h); 18887c478bd9Sstevel@tonic-gate if (val == NULL) { 18897c478bd9Sstevel@tonic-gate assert(scf_error() == SCF_ERROR_NO_MEMORY); 18907c478bd9Sstevel@tonic-gate ret = ENOMEM; 18917c478bd9Sstevel@tonic-gate goto out; 18927c478bd9Sstevel@tonic-gate } 18937c478bd9Sstevel@tonic-gate 18947c478bd9Sstevel@tonic-gate scf_value_set_count(val, contract_id); 18957c478bd9Sstevel@tonic-gate ret = scf_entry_add_value(t_cid, val); 18967c478bd9Sstevel@tonic-gate assert(ret == 0); 18977c478bd9Sstevel@tonic-gate 18987c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(t); 18997c478bd9Sstevel@tonic-gate if (ret == -1) { 19007c478bd9Sstevel@tonic-gate switch (scf_error()) { 19017c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 19027c478bd9Sstevel@tonic-gate default: 19037c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 19047c478bd9Sstevel@tonic-gate goto out; 19057c478bd9Sstevel@tonic-gate 19067c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 19077c478bd9Sstevel@tonic-gate goto add; 19087c478bd9Sstevel@tonic-gate 19097c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 19107c478bd9Sstevel@tonic-gate ret = EPERM; 19117c478bd9Sstevel@tonic-gate goto out; 19127c478bd9Sstevel@tonic-gate 19137c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 19147c478bd9Sstevel@tonic-gate ret = EACCES; 19157c478bd9Sstevel@tonic-gate goto out; 19167c478bd9Sstevel@tonic-gate 19177c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 19187c478bd9Sstevel@tonic-gate ret = EROFS; 19197c478bd9Sstevel@tonic-gate goto out; 19207c478bd9Sstevel@tonic-gate 19217c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 19227c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_commit", scf_error()); 19237c478bd9Sstevel@tonic-gate } 19247c478bd9Sstevel@tonic-gate } 19257c478bd9Sstevel@tonic-gate if (ret == 1) { 19267c478bd9Sstevel@tonic-gate ret = 0; 19277c478bd9Sstevel@tonic-gate break; 19287c478bd9Sstevel@tonic-gate } 19297c478bd9Sstevel@tonic-gate 19307c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 19317c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 19327c478bd9Sstevel@tonic-gate switch (scf_error()) { 19337c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 19347c478bd9Sstevel@tonic-gate default: 19357c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 19367c478bd9Sstevel@tonic-gate goto out; 19377c478bd9Sstevel@tonic-gate 19387c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 19397c478bd9Sstevel@tonic-gate goto add; 19407c478bd9Sstevel@tonic-gate 19417c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 19427c478bd9Sstevel@tonic-gate bad_fail("scf_pg_update", scf_error()); 19437c478bd9Sstevel@tonic-gate } 19447c478bd9Sstevel@tonic-gate } 19457c478bd9Sstevel@tonic-gate } 19467c478bd9Sstevel@tonic-gate 19477c478bd9Sstevel@tonic-gate out: 19487c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 19497c478bd9Sstevel@tonic-gate scf_transaction_destroy(t); 19507c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 19517c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 19527c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 19537c478bd9Sstevel@tonic-gate 19547c478bd9Sstevel@tonic-gate return (ret); 19557c478bd9Sstevel@tonic-gate } 19567c478bd9Sstevel@tonic-gate 19577c478bd9Sstevel@tonic-gate int 19587c478bd9Sstevel@tonic-gate restarter_rm_libs_loadable() 19597c478bd9Sstevel@tonic-gate { 19607c478bd9Sstevel@tonic-gate void *libhndl; 19617c478bd9Sstevel@tonic-gate 19627c478bd9Sstevel@tonic-gate if (method_context_safety) 19637c478bd9Sstevel@tonic-gate return (1); 19647c478bd9Sstevel@tonic-gate 19657c478bd9Sstevel@tonic-gate if ((libhndl = dlopen("libpool.so", RTLD_LAZY | RTLD_LOCAL)) == NULL) 19667c478bd9Sstevel@tonic-gate return (0); 19677c478bd9Sstevel@tonic-gate 19687c478bd9Sstevel@tonic-gate (void) dlclose(libhndl); 19697c478bd9Sstevel@tonic-gate 19707c478bd9Sstevel@tonic-gate if ((libhndl = dlopen("libproject.so", RTLD_LAZY | RTLD_LOCAL)) == NULL) 19717c478bd9Sstevel@tonic-gate return (0); 19727c478bd9Sstevel@tonic-gate 19737c478bd9Sstevel@tonic-gate (void) dlclose(libhndl); 19747c478bd9Sstevel@tonic-gate 19757c478bd9Sstevel@tonic-gate method_context_safety = 1; 19767c478bd9Sstevel@tonic-gate 19777c478bd9Sstevel@tonic-gate return (1); 19787c478bd9Sstevel@tonic-gate } 19797c478bd9Sstevel@tonic-gate 19807c478bd9Sstevel@tonic-gate static int 19817c478bd9Sstevel@tonic-gate get_astring_val(scf_propertygroup_t *pg, const char *name, char *buf, 19827c478bd9Sstevel@tonic-gate size_t bufsz, scf_property_t *prop, scf_value_t *val) 19837c478bd9Sstevel@tonic-gate { 19847c478bd9Sstevel@tonic-gate ssize_t szret; 19857c478bd9Sstevel@tonic-gate 198613d8aaa1SSean Wilcox if (pg == NULL) 198713d8aaa1SSean Wilcox return (-1); 198813d8aaa1SSean Wilcox 19897c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, name, prop) != SCF_SUCCESS) { 19907c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 19917c478bd9Sstevel@tonic-gate uu_die(rcbroken); 19927c478bd9Sstevel@tonic-gate return (-1); 19937c478bd9Sstevel@tonic-gate } 19947c478bd9Sstevel@tonic-gate 19957c478bd9Sstevel@tonic-gate if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 19967c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 19977c478bd9Sstevel@tonic-gate uu_die(rcbroken); 19987c478bd9Sstevel@tonic-gate return (-1); 19997c478bd9Sstevel@tonic-gate } 20007c478bd9Sstevel@tonic-gate 20017c478bd9Sstevel@tonic-gate szret = scf_value_get_astring(val, buf, bufsz); 20027c478bd9Sstevel@tonic-gate 20037c478bd9Sstevel@tonic-gate return (szret >= 0 ? 0 : -1); 20047c478bd9Sstevel@tonic-gate } 20057c478bd9Sstevel@tonic-gate 2006eb1a3463STruong Nguyen static int 2007eb1a3463STruong Nguyen get_boolean_val(scf_propertygroup_t *pg, const char *name, uint8_t *b, 2008eb1a3463STruong Nguyen scf_property_t *prop, scf_value_t *val) 2009eb1a3463STruong Nguyen { 2010eb1a3463STruong Nguyen if (scf_pg_get_property(pg, name, prop) != SCF_SUCCESS) { 2011eb1a3463STruong Nguyen if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 2012eb1a3463STruong Nguyen uu_die(rcbroken); 2013eb1a3463STruong Nguyen return (-1); 2014eb1a3463STruong Nguyen } 2015eb1a3463STruong Nguyen 2016eb1a3463STruong Nguyen if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 2017eb1a3463STruong Nguyen if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 2018eb1a3463STruong Nguyen uu_die(rcbroken); 2019eb1a3463STruong Nguyen return (-1); 2020eb1a3463STruong Nguyen } 2021eb1a3463STruong Nguyen 2022eb1a3463STruong Nguyen if (scf_value_get_boolean(val, b)) 2023eb1a3463STruong Nguyen return (-1); 2024eb1a3463STruong Nguyen 2025eb1a3463STruong Nguyen return (0); 2026eb1a3463STruong Nguyen } 2027eb1a3463STruong Nguyen 20287c478bd9Sstevel@tonic-gate /* 20297c478bd9Sstevel@tonic-gate * Try to load mcp->pwd, if it isn't already. 20307c478bd9Sstevel@tonic-gate * Fails with 20317c478bd9Sstevel@tonic-gate * ENOMEM - malloc() failed 20327c478bd9Sstevel@tonic-gate * ENOENT - no entry found 20337c478bd9Sstevel@tonic-gate * EIO - I/O error 20347c478bd9Sstevel@tonic-gate * EMFILE - process out of file descriptors 20357c478bd9Sstevel@tonic-gate * ENFILE - system out of file handles 20367c478bd9Sstevel@tonic-gate */ 20377c478bd9Sstevel@tonic-gate static int 20387c478bd9Sstevel@tonic-gate lookup_pwd(struct method_context *mcp) 20397c478bd9Sstevel@tonic-gate { 20407c478bd9Sstevel@tonic-gate struct passwd *pwdp; 20417c478bd9Sstevel@tonic-gate 20427c478bd9Sstevel@tonic-gate if (mcp->pwbuf != NULL && mcp->pwd.pw_uid == mcp->uid) 20437c478bd9Sstevel@tonic-gate return (0); 20447c478bd9Sstevel@tonic-gate 20457c478bd9Sstevel@tonic-gate if (mcp->pwbuf == NULL) { 20467c478bd9Sstevel@tonic-gate mcp->pwbufsz = sysconf(_SC_GETPW_R_SIZE_MAX); 20477c478bd9Sstevel@tonic-gate assert(mcp->pwbufsz >= 0); 20487c478bd9Sstevel@tonic-gate mcp->pwbuf = malloc(mcp->pwbufsz); 20497c478bd9Sstevel@tonic-gate if (mcp->pwbuf == NULL) 20507c478bd9Sstevel@tonic-gate return (ENOMEM); 20517c478bd9Sstevel@tonic-gate } 20527c478bd9Sstevel@tonic-gate 20537c478bd9Sstevel@tonic-gate do { 20547c478bd9Sstevel@tonic-gate errno = 0; 20557c478bd9Sstevel@tonic-gate pwdp = getpwuid_r(mcp->uid, &mcp->pwd, mcp->pwbuf, 20567c478bd9Sstevel@tonic-gate mcp->pwbufsz); 20577c478bd9Sstevel@tonic-gate } while (pwdp == NULL && errno == EINTR); 20587c478bd9Sstevel@tonic-gate if (pwdp != NULL) 20597c478bd9Sstevel@tonic-gate return (0); 20607c478bd9Sstevel@tonic-gate 20617c478bd9Sstevel@tonic-gate free(mcp->pwbuf); 20627c478bd9Sstevel@tonic-gate mcp->pwbuf = NULL; 20637c478bd9Sstevel@tonic-gate 20647c478bd9Sstevel@tonic-gate switch (errno) { 20657c478bd9Sstevel@tonic-gate case 0: 20667c478bd9Sstevel@tonic-gate default: 20677c478bd9Sstevel@tonic-gate /* 20687c478bd9Sstevel@tonic-gate * Until bug 5065780 is fixed, getpwuid_r() can fail with 20697c478bd9Sstevel@tonic-gate * ENOENT, particularly on the miniroot. Since the 20707c478bd9Sstevel@tonic-gate * documentation is inaccurate, we'll return ENOENT for unknown 20717c478bd9Sstevel@tonic-gate * errors. 20727c478bd9Sstevel@tonic-gate */ 20737c478bd9Sstevel@tonic-gate return (ENOENT); 20747c478bd9Sstevel@tonic-gate 20757c478bd9Sstevel@tonic-gate case EIO: 20767c478bd9Sstevel@tonic-gate case EMFILE: 20777c478bd9Sstevel@tonic-gate case ENFILE: 20787c478bd9Sstevel@tonic-gate return (errno); 20797c478bd9Sstevel@tonic-gate 20807c478bd9Sstevel@tonic-gate case ERANGE: 20817c478bd9Sstevel@tonic-gate bad_fail("getpwuid_r", errno); 20827c478bd9Sstevel@tonic-gate /* NOTREACHED */ 20837c478bd9Sstevel@tonic-gate } 20847c478bd9Sstevel@tonic-gate } 20857c478bd9Sstevel@tonic-gate 20867c478bd9Sstevel@tonic-gate /* 20877c478bd9Sstevel@tonic-gate * Get the user id for str. Returns 0 on success or 20887c478bd9Sstevel@tonic-gate * ERANGE the uid is too big 20897c478bd9Sstevel@tonic-gate * EINVAL the string starts with a digit, but is not a valid uid 20907c478bd9Sstevel@tonic-gate * ENOMEM out of memory 20917c478bd9Sstevel@tonic-gate * ENOENT no passwd entry for str 20927c478bd9Sstevel@tonic-gate * EIO an I/O error has occurred 20937c478bd9Sstevel@tonic-gate * EMFILE/ENFILE out of file descriptors 20947c478bd9Sstevel@tonic-gate */ 20957c478bd9Sstevel@tonic-gate int 20967c478bd9Sstevel@tonic-gate get_uid(const char *str, struct method_context *ci, uid_t *uidp) 20977c478bd9Sstevel@tonic-gate { 20987c478bd9Sstevel@tonic-gate if (isdigit(str[0])) { 20997c478bd9Sstevel@tonic-gate uid_t uid; 21007c478bd9Sstevel@tonic-gate char *cp; 21017c478bd9Sstevel@tonic-gate 21027c478bd9Sstevel@tonic-gate errno = 0; 21037c478bd9Sstevel@tonic-gate uid = strtol(str, &cp, 10); 21047c478bd9Sstevel@tonic-gate 21057c478bd9Sstevel@tonic-gate if (uid == 0 && errno != 0) { 21067c478bd9Sstevel@tonic-gate assert(errno != EINVAL); 21077c478bd9Sstevel@tonic-gate return (errno); 21087c478bd9Sstevel@tonic-gate } 21097c478bd9Sstevel@tonic-gate 21107c478bd9Sstevel@tonic-gate for (; *cp != '\0'; ++cp) 21117c478bd9Sstevel@tonic-gate if (*cp != ' ' || *cp != '\t') 21127c478bd9Sstevel@tonic-gate return (EINVAL); 21137c478bd9Sstevel@tonic-gate 21147c478bd9Sstevel@tonic-gate if (uid > UID_MAX) 21157c478bd9Sstevel@tonic-gate return (EINVAL); 21167c478bd9Sstevel@tonic-gate 21177c478bd9Sstevel@tonic-gate *uidp = uid; 21187c478bd9Sstevel@tonic-gate return (0); 21197c478bd9Sstevel@tonic-gate } else { 21207c478bd9Sstevel@tonic-gate struct passwd *pwdp; 21217c478bd9Sstevel@tonic-gate 21227c478bd9Sstevel@tonic-gate if (ci->pwbuf == NULL) { 21237c478bd9Sstevel@tonic-gate ci->pwbufsz = sysconf(_SC_GETPW_R_SIZE_MAX); 21247c478bd9Sstevel@tonic-gate ci->pwbuf = malloc(ci->pwbufsz); 21257c478bd9Sstevel@tonic-gate if (ci->pwbuf == NULL) 21267c478bd9Sstevel@tonic-gate return (ENOMEM); 21277c478bd9Sstevel@tonic-gate } 21287c478bd9Sstevel@tonic-gate 21297c478bd9Sstevel@tonic-gate do { 21307c478bd9Sstevel@tonic-gate errno = 0; 21317c478bd9Sstevel@tonic-gate pwdp = 21327c478bd9Sstevel@tonic-gate getpwnam_r(str, &ci->pwd, ci->pwbuf, ci->pwbufsz); 21337c478bd9Sstevel@tonic-gate } while (pwdp == NULL && errno == EINTR); 21347c478bd9Sstevel@tonic-gate 21357c478bd9Sstevel@tonic-gate if (pwdp != NULL) { 21367c478bd9Sstevel@tonic-gate *uidp = ci->pwd.pw_uid; 21377c478bd9Sstevel@tonic-gate return (0); 21387c478bd9Sstevel@tonic-gate } else { 21397c478bd9Sstevel@tonic-gate free(ci->pwbuf); 21407c478bd9Sstevel@tonic-gate ci->pwbuf = NULL; 21417c478bd9Sstevel@tonic-gate switch (errno) { 21427c478bd9Sstevel@tonic-gate case 0: 21437c478bd9Sstevel@tonic-gate return (ENOENT); 21447c478bd9Sstevel@tonic-gate 21457c478bd9Sstevel@tonic-gate case ENOENT: 21467c478bd9Sstevel@tonic-gate case EIO: 21477c478bd9Sstevel@tonic-gate case EMFILE: 21487c478bd9Sstevel@tonic-gate case ENFILE: 21497c478bd9Sstevel@tonic-gate return (errno); 21507c478bd9Sstevel@tonic-gate 21517c478bd9Sstevel@tonic-gate case ERANGE: 21527c478bd9Sstevel@tonic-gate default: 21537c478bd9Sstevel@tonic-gate bad_fail("getpwnam_r", errno); 21547c478bd9Sstevel@tonic-gate /* NOTREACHED */ 21557c478bd9Sstevel@tonic-gate } 21567c478bd9Sstevel@tonic-gate } 21577c478bd9Sstevel@tonic-gate } 21587c478bd9Sstevel@tonic-gate } 21597c478bd9Sstevel@tonic-gate 21607c478bd9Sstevel@tonic-gate gid_t 21617c478bd9Sstevel@tonic-gate get_gid(const char *str) 21627c478bd9Sstevel@tonic-gate { 21637c478bd9Sstevel@tonic-gate if (isdigit(str[0])) { 21647c478bd9Sstevel@tonic-gate gid_t gid; 21657c478bd9Sstevel@tonic-gate char *cp; 21667c478bd9Sstevel@tonic-gate 21677c478bd9Sstevel@tonic-gate errno = 0; 21687c478bd9Sstevel@tonic-gate gid = strtol(str, &cp, 10); 21697c478bd9Sstevel@tonic-gate 21707c478bd9Sstevel@tonic-gate if (gid == 0 && errno != 0) 2171f48205beScasper return ((gid_t)-1); 21727c478bd9Sstevel@tonic-gate 21737c478bd9Sstevel@tonic-gate for (; *cp != '\0'; ++cp) 21747c478bd9Sstevel@tonic-gate if (*cp != ' ' || *cp != '\t') 2175f48205beScasper return ((gid_t)-1); 21767c478bd9Sstevel@tonic-gate 21777c478bd9Sstevel@tonic-gate return (gid); 21787c478bd9Sstevel@tonic-gate } else { 21797c478bd9Sstevel@tonic-gate struct group grp, *ret; 21807c478bd9Sstevel@tonic-gate char *buffer; 21817c478bd9Sstevel@tonic-gate size_t buflen; 21827c478bd9Sstevel@tonic-gate 21837c478bd9Sstevel@tonic-gate buflen = sysconf(_SC_GETGR_R_SIZE_MAX); 21847c478bd9Sstevel@tonic-gate buffer = malloc(buflen); 21857c478bd9Sstevel@tonic-gate if (buffer == NULL) 21867c478bd9Sstevel@tonic-gate uu_die(allocfail); 21877c478bd9Sstevel@tonic-gate 21887c478bd9Sstevel@tonic-gate errno = 0; 21897c478bd9Sstevel@tonic-gate ret = getgrnam_r(str, &grp, buffer, buflen); 21907c478bd9Sstevel@tonic-gate free(buffer); 21917c478bd9Sstevel@tonic-gate 2192f48205beScasper return (ret == NULL ? (gid_t)-1 : grp.gr_gid); 21937c478bd9Sstevel@tonic-gate } 21947c478bd9Sstevel@tonic-gate } 21957c478bd9Sstevel@tonic-gate 21967c478bd9Sstevel@tonic-gate /* 21977c478bd9Sstevel@tonic-gate * Fails with 21987c478bd9Sstevel@tonic-gate * ENOMEM - out of memory 21997c478bd9Sstevel@tonic-gate * ENOENT - no passwd entry 22007c478bd9Sstevel@tonic-gate * no project entry 22017c478bd9Sstevel@tonic-gate * EIO - an I/O error occurred 22027c478bd9Sstevel@tonic-gate * EMFILE - the process is out of file descriptors 22037c478bd9Sstevel@tonic-gate * ENFILE - the system is out of file handles 22047c478bd9Sstevel@tonic-gate * ERANGE - the project id is out of range 22057c478bd9Sstevel@tonic-gate * EINVAL - str is invalid 22067c478bd9Sstevel@tonic-gate * E2BIG - the project entry was too big 22077c478bd9Sstevel@tonic-gate * -1 - the name service switch is misconfigured 22087c478bd9Sstevel@tonic-gate */ 22097c478bd9Sstevel@tonic-gate int 22107c478bd9Sstevel@tonic-gate get_projid(const char *str, struct method_context *cip) 22117c478bd9Sstevel@tonic-gate { 22127c478bd9Sstevel@tonic-gate int ret; 22137c478bd9Sstevel@tonic-gate void *buf; 22147c478bd9Sstevel@tonic-gate const size_t bufsz = PROJECT_BUFSZ; 22157c478bd9Sstevel@tonic-gate struct project proj, *pp; 22167c478bd9Sstevel@tonic-gate 22177c478bd9Sstevel@tonic-gate if (strcmp(str, ":default") == 0) { 22187c478bd9Sstevel@tonic-gate if (cip->uid == 0) { 22197c478bd9Sstevel@tonic-gate /* Don't change project for root services */ 22207c478bd9Sstevel@tonic-gate cip->project = NULL; 22217c478bd9Sstevel@tonic-gate return (0); 22227c478bd9Sstevel@tonic-gate } 22237c478bd9Sstevel@tonic-gate 22247c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 22257c478bd9Sstevel@tonic-gate case 0: 22267c478bd9Sstevel@tonic-gate break; 22277c478bd9Sstevel@tonic-gate 22287c478bd9Sstevel@tonic-gate case ENOMEM: 22297c478bd9Sstevel@tonic-gate case ENOENT: 22307c478bd9Sstevel@tonic-gate case EIO: 22317c478bd9Sstevel@tonic-gate case EMFILE: 22327c478bd9Sstevel@tonic-gate case ENFILE: 22337c478bd9Sstevel@tonic-gate return (ret); 22347c478bd9Sstevel@tonic-gate 22357c478bd9Sstevel@tonic-gate default: 22367c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 22377c478bd9Sstevel@tonic-gate } 22387c478bd9Sstevel@tonic-gate 22397c478bd9Sstevel@tonic-gate buf = malloc(bufsz); 22407c478bd9Sstevel@tonic-gate if (buf == NULL) 22417c478bd9Sstevel@tonic-gate return (ENOMEM); 22427c478bd9Sstevel@tonic-gate 22437c478bd9Sstevel@tonic-gate do { 22447c478bd9Sstevel@tonic-gate errno = 0; 22457c478bd9Sstevel@tonic-gate pp = getdefaultproj(cip->pwd.pw_name, &proj, buf, 22467c478bd9Sstevel@tonic-gate bufsz); 22477c478bd9Sstevel@tonic-gate } while (pp == NULL && errno == EINTR); 22487c478bd9Sstevel@tonic-gate 22497c478bd9Sstevel@tonic-gate /* to be continued ... */ 22507c478bd9Sstevel@tonic-gate } else { 22517c478bd9Sstevel@tonic-gate projid_t projid; 22527c478bd9Sstevel@tonic-gate char *cp; 22537c478bd9Sstevel@tonic-gate 22547c478bd9Sstevel@tonic-gate if (!isdigit(str[0])) { 22557c478bd9Sstevel@tonic-gate cip->project = strdup(str); 22567c478bd9Sstevel@tonic-gate return (cip->project != NULL ? 0 : ENOMEM); 22577c478bd9Sstevel@tonic-gate } 22587c478bd9Sstevel@tonic-gate 22597c478bd9Sstevel@tonic-gate errno = 0; 22607c478bd9Sstevel@tonic-gate projid = strtol(str, &cp, 10); 22617c478bd9Sstevel@tonic-gate 22627c478bd9Sstevel@tonic-gate if (projid == 0 && errno != 0) { 22637c478bd9Sstevel@tonic-gate assert(errno == ERANGE); 22647c478bd9Sstevel@tonic-gate return (errno); 22657c478bd9Sstevel@tonic-gate } 22667c478bd9Sstevel@tonic-gate 22677c478bd9Sstevel@tonic-gate for (; *cp != '\0'; ++cp) 22687c478bd9Sstevel@tonic-gate if (*cp != ' ' || *cp != '\t') 22697c478bd9Sstevel@tonic-gate return (EINVAL); 22707c478bd9Sstevel@tonic-gate 22717c478bd9Sstevel@tonic-gate if (projid > MAXPROJID) 22727c478bd9Sstevel@tonic-gate return (ERANGE); 22737c478bd9Sstevel@tonic-gate 22747c478bd9Sstevel@tonic-gate buf = malloc(bufsz); 22757c478bd9Sstevel@tonic-gate if (buf == NULL) 22767c478bd9Sstevel@tonic-gate return (ENOMEM); 22777c478bd9Sstevel@tonic-gate 22787c478bd9Sstevel@tonic-gate do { 22797c478bd9Sstevel@tonic-gate errno = 0; 22807c478bd9Sstevel@tonic-gate pp = getprojbyid(projid, &proj, buf, bufsz); 22817c478bd9Sstevel@tonic-gate } while (pp == NULL && errno == EINTR); 22827c478bd9Sstevel@tonic-gate } 22837c478bd9Sstevel@tonic-gate 22847c478bd9Sstevel@tonic-gate if (pp) { 22857c478bd9Sstevel@tonic-gate cip->project = strdup(pp->pj_name); 22867c478bd9Sstevel@tonic-gate free(buf); 22877c478bd9Sstevel@tonic-gate return (cip->project != NULL ? 0 : ENOMEM); 22887c478bd9Sstevel@tonic-gate } 22897c478bd9Sstevel@tonic-gate 22907c478bd9Sstevel@tonic-gate free(buf); 22917c478bd9Sstevel@tonic-gate 22927c478bd9Sstevel@tonic-gate switch (errno) { 22937c478bd9Sstevel@tonic-gate case 0: 22947c478bd9Sstevel@tonic-gate return (ENOENT); 22957c478bd9Sstevel@tonic-gate 22967c478bd9Sstevel@tonic-gate case EIO: 22977c478bd9Sstevel@tonic-gate case EMFILE: 22987c478bd9Sstevel@tonic-gate case ENFILE: 22997c478bd9Sstevel@tonic-gate return (errno); 23007c478bd9Sstevel@tonic-gate 23017c478bd9Sstevel@tonic-gate case ERANGE: 23027c478bd9Sstevel@tonic-gate return (E2BIG); 23037c478bd9Sstevel@tonic-gate 23047c478bd9Sstevel@tonic-gate default: 23057c478bd9Sstevel@tonic-gate return (-1); 23067c478bd9Sstevel@tonic-gate } 23077c478bd9Sstevel@tonic-gate } 23087c478bd9Sstevel@tonic-gate 23097c478bd9Sstevel@tonic-gate /* 23107c478bd9Sstevel@tonic-gate * Parse the supp_groups property value and populate ci->groups. Returns 23117c478bd9Sstevel@tonic-gate * EINVAL (get_gid() failed for one of the components), E2BIG (the property has 23127c478bd9Sstevel@tonic-gate * more than NGROUPS_MAX-1 groups), or 0 on success. 23137c478bd9Sstevel@tonic-gate */ 23147c478bd9Sstevel@tonic-gate int 23157c478bd9Sstevel@tonic-gate get_groups(char *str, struct method_context *ci) 23167c478bd9Sstevel@tonic-gate { 23177c478bd9Sstevel@tonic-gate char *cp, *end, *next; 23187c478bd9Sstevel@tonic-gate uint_t i; 23197c478bd9Sstevel@tonic-gate 23207c478bd9Sstevel@tonic-gate const char * const whitespace = " \t"; 23217c478bd9Sstevel@tonic-gate const char * const illegal = ", \t"; 23227c478bd9Sstevel@tonic-gate 23237c478bd9Sstevel@tonic-gate if (str[0] == '\0') { 23247c478bd9Sstevel@tonic-gate ci->ngroups = 0; 23257c478bd9Sstevel@tonic-gate return (0); 23267c478bd9Sstevel@tonic-gate } 23277c478bd9Sstevel@tonic-gate 23287c478bd9Sstevel@tonic-gate for (cp = str, i = 0; *cp != '\0'; ) { 23297c478bd9Sstevel@tonic-gate /* skip whitespace */ 23307c478bd9Sstevel@tonic-gate cp += strspn(cp, whitespace); 23317c478bd9Sstevel@tonic-gate 23327c478bd9Sstevel@tonic-gate /* find the end */ 23337c478bd9Sstevel@tonic-gate end = cp + strcspn(cp, illegal); 23347c478bd9Sstevel@tonic-gate 23357c478bd9Sstevel@tonic-gate /* skip whitespace after end */ 23367c478bd9Sstevel@tonic-gate next = end + strspn(end, whitespace); 23377c478bd9Sstevel@tonic-gate 23387c478bd9Sstevel@tonic-gate /* if there's a comma, it separates the fields */ 23397c478bd9Sstevel@tonic-gate if (*next == ',') 23407c478bd9Sstevel@tonic-gate ++next; 23417c478bd9Sstevel@tonic-gate 23427c478bd9Sstevel@tonic-gate *end = '\0'; 23437c478bd9Sstevel@tonic-gate 2344f48205beScasper if ((ci->groups[i] = get_gid(cp)) == (gid_t)-1) { 23457c478bd9Sstevel@tonic-gate ci->ngroups = 0; 23467c478bd9Sstevel@tonic-gate return (EINVAL); 23477c478bd9Sstevel@tonic-gate } 23487c478bd9Sstevel@tonic-gate 23497c478bd9Sstevel@tonic-gate ++i; 23507c478bd9Sstevel@tonic-gate if (i > NGROUPS_MAX - 1) { 23517c478bd9Sstevel@tonic-gate ci->ngroups = 0; 23527c478bd9Sstevel@tonic-gate return (E2BIG); 23537c478bd9Sstevel@tonic-gate } 23547c478bd9Sstevel@tonic-gate 23557c478bd9Sstevel@tonic-gate cp = next; 23567c478bd9Sstevel@tonic-gate } 23577c478bd9Sstevel@tonic-gate 23587c478bd9Sstevel@tonic-gate ci->ngroups = i; 23597c478bd9Sstevel@tonic-gate return (0); 23607c478bd9Sstevel@tonic-gate } 23617c478bd9Sstevel@tonic-gate 2362870ad75aSSean Wilcox 23637c478bd9Sstevel@tonic-gate /* 2364870ad75aSSean Wilcox * Return an error message structure containing the error message 2365870ad75aSSean Wilcox * with context, and the error so the caller can make a decision 2366870ad75aSSean Wilcox * on what to do next. 2367870ad75aSSean Wilcox * 2368870ad75aSSean Wilcox * Because get_ids uses the mc_error_create() function which can 2369870ad75aSSean Wilcox * reallocate the merr, this function must return the merr pointer 2370870ad75aSSean Wilcox * in case it was reallocated. 23717c478bd9Sstevel@tonic-gate */ 2372870ad75aSSean Wilcox static mc_error_t * 237313d8aaa1SSean Wilcox get_profile(scf_propertygroup_t *methpg, scf_propertygroup_t *instpg, 237413d8aaa1SSean Wilcox scf_property_t *prop, scf_value_t *val, const char *cmdline, 2375870ad75aSSean Wilcox struct method_context *ci, mc_error_t *merr) 23767c478bd9Sstevel@tonic-gate { 23777c478bd9Sstevel@tonic-gate char *buf = ci->vbuf; 23787c478bd9Sstevel@tonic-gate ssize_t buf_sz = ci->vbuf_sz; 23797c478bd9Sstevel@tonic-gate char cmd[PATH_MAX]; 23807c478bd9Sstevel@tonic-gate char *cp, *value; 23817c478bd9Sstevel@tonic-gate const char *cmdp; 23827c478bd9Sstevel@tonic-gate execattr_t *eap; 2383870ad75aSSean Wilcox mc_error_t *err = merr; 2384870ad75aSSean Wilcox int r; 23857c478bd9Sstevel@tonic-gate 238613d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_PROFILE, buf, buf_sz, prop, 238713d8aaa1SSean Wilcox val) == 0 || get_astring_val(instpg, SCF_PROPERTY_PROFILE, buf, 238813d8aaa1SSean Wilcox buf_sz, prop, val) == 0)) 2389870ad75aSSean Wilcox return (mc_error_create(merr, scf_error(), 2390870ad75aSSean Wilcox "Method context requires a profile, but the \"%s\" " 2391870ad75aSSean Wilcox "property could not be read. scf_error is %s", 2392870ad75aSSean Wilcox SCF_PROPERTY_PROFILE, scf_strerror(scf_error()))); 23937c478bd9Sstevel@tonic-gate 23947c478bd9Sstevel@tonic-gate /* Extract the command from the command line. */ 23957c478bd9Sstevel@tonic-gate cp = strpbrk(cmdline, " \t"); 23967c478bd9Sstevel@tonic-gate 23977c478bd9Sstevel@tonic-gate if (cp == NULL) { 23987c478bd9Sstevel@tonic-gate cmdp = cmdline; 23997c478bd9Sstevel@tonic-gate } else { 24007c478bd9Sstevel@tonic-gate (void) strncpy(cmd, cmdline, cp - cmdline); 24017c478bd9Sstevel@tonic-gate cmd[cp - cmdline] = '\0'; 24027c478bd9Sstevel@tonic-gate cmdp = cmd; 24037c478bd9Sstevel@tonic-gate } 24047c478bd9Sstevel@tonic-gate 24057c478bd9Sstevel@tonic-gate /* Require that cmdp[0] == '/'? */ 24067c478bd9Sstevel@tonic-gate 24077c478bd9Sstevel@tonic-gate eap = getexecprof(buf, KV_COMMAND, cmdp, GET_ONE); 24087c478bd9Sstevel@tonic-gate if (eap == NULL) 2409870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT, 2410870ad75aSSean Wilcox "Could not find the execution profile \"%s\", " 2411870ad75aSSean Wilcox "command %s.", buf, cmdp)); 24127c478bd9Sstevel@tonic-gate 24137c478bd9Sstevel@tonic-gate /* Based on pfexec.c */ 24147c478bd9Sstevel@tonic-gate 24157c478bd9Sstevel@tonic-gate /* Get the euid first so we don't override ci->pwd for the uid. */ 24167c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_EUID_KW)) != NULL) { 2417870ad75aSSean Wilcox if ((r = get_uid(value, ci, &ci->euid)) != 0) { 2418f48205beScasper ci->euid = (uid_t)-1; 2419870ad75aSSean Wilcox err = mc_error_create(merr, r, 2420870ad75aSSean Wilcox "Could not interpret profile euid value \"%s\", " 2421870ad75aSSean Wilcox "from the execution profile \"%s\", error %d.", 2422870ad75aSSean Wilcox value, buf, r); 24237c478bd9Sstevel@tonic-gate goto out; 24247c478bd9Sstevel@tonic-gate } 24257c478bd9Sstevel@tonic-gate } 24267c478bd9Sstevel@tonic-gate 24277c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_UID_KW)) != NULL) { 2428870ad75aSSean Wilcox if ((r = get_uid(value, ci, &ci->uid)) != 0) { 2429f48205beScasper ci->euid = ci->uid = (uid_t)-1; 2430870ad75aSSean Wilcox err = mc_error_create(merr, r, 2431870ad75aSSean Wilcox "Could not interpret profile uid value \"%s\", " 2432870ad75aSSean Wilcox "from the execution profile \"%s\", error %d.", 2433870ad75aSSean Wilcox value, buf, r); 24347c478bd9Sstevel@tonic-gate goto out; 24357c478bd9Sstevel@tonic-gate } 24367c478bd9Sstevel@tonic-gate ci->euid = ci->uid; 24377c478bd9Sstevel@tonic-gate } 24387c478bd9Sstevel@tonic-gate 24397c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_GID_KW)) != NULL) { 24407c478bd9Sstevel@tonic-gate ci->egid = ci->gid = get_gid(value); 2441f48205beScasper if (ci->gid == (gid_t)-1) { 2442870ad75aSSean Wilcox err = mc_error_create(merr, EINVAL, 2443870ad75aSSean Wilcox "Could not interpret profile gid value \"%s\", " 2444870ad75aSSean Wilcox "from the execution profile \"%s\".", value, buf); 24457c478bd9Sstevel@tonic-gate goto out; 24467c478bd9Sstevel@tonic-gate } 24477c478bd9Sstevel@tonic-gate } 24487c478bd9Sstevel@tonic-gate 24497c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_EGID_KW)) != NULL) { 24507c478bd9Sstevel@tonic-gate ci->egid = get_gid(value); 2451f48205beScasper if (ci->egid == (gid_t)-1) { 2452870ad75aSSean Wilcox err = mc_error_create(merr, EINVAL, 2453870ad75aSSean Wilcox "Could not interpret profile egid value \"%s\", " 2454870ad75aSSean Wilcox "from the execution profile \"%s\".", value, buf); 24557c478bd9Sstevel@tonic-gate goto out; 24567c478bd9Sstevel@tonic-gate } 24577c478bd9Sstevel@tonic-gate } 24587c478bd9Sstevel@tonic-gate 24597c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_LPRIV_KW)) != NULL) { 24607c478bd9Sstevel@tonic-gate ci->lpriv_set = priv_str_to_set(value, ",", NULL); 24617c478bd9Sstevel@tonic-gate if (ci->lpriv_set == NULL) { 24627c478bd9Sstevel@tonic-gate if (errno != EINVAL) 2463870ad75aSSean Wilcox err = mc_error_create(merr, ENOMEM, 2464870ad75aSSean Wilcox ALLOCFAIL); 24657c478bd9Sstevel@tonic-gate else 2466870ad75aSSean Wilcox err = mc_error_create(merr, EINVAL, 2467870ad75aSSean Wilcox "Could not interpret profile " 2468870ad75aSSean Wilcox "limitprivs value \"%s\", from " 2469870ad75aSSean Wilcox "the execution profile \"%s\".", 2470870ad75aSSean Wilcox value, buf); 24717c478bd9Sstevel@tonic-gate goto out; 24727c478bd9Sstevel@tonic-gate } 24737c478bd9Sstevel@tonic-gate } 24747c478bd9Sstevel@tonic-gate 24757c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_IPRIV_KW)) != NULL) { 24767c478bd9Sstevel@tonic-gate ci->priv_set = priv_str_to_set(value, ",", NULL); 24777c478bd9Sstevel@tonic-gate if (ci->priv_set == NULL) { 24787c478bd9Sstevel@tonic-gate if (errno != EINVAL) 2479870ad75aSSean Wilcox err = mc_error_create(merr, ENOMEM, 2480870ad75aSSean Wilcox ALLOCFAIL); 24817c478bd9Sstevel@tonic-gate else 2482870ad75aSSean Wilcox err = mc_error_create(merr, EINVAL, 2483870ad75aSSean Wilcox "Could not interpret profile privs value " 2484870ad75aSSean Wilcox "\"%s\", from the execution profile " 2485870ad75aSSean Wilcox "\"%s\".", value, buf); 24867c478bd9Sstevel@tonic-gate goto out; 24877c478bd9Sstevel@tonic-gate } 24887c478bd9Sstevel@tonic-gate } 24897c478bd9Sstevel@tonic-gate 24907c478bd9Sstevel@tonic-gate out: 24917c478bd9Sstevel@tonic-gate free_execattr(eap); 24927c478bd9Sstevel@tonic-gate 2493870ad75aSSean Wilcox return (err); 24947c478bd9Sstevel@tonic-gate } 24957c478bd9Sstevel@tonic-gate 24967c478bd9Sstevel@tonic-gate /* 2497870ad75aSSean Wilcox * Return an error message structure containing the error message 2498870ad75aSSean Wilcox * with context, and the error so the caller can make a decision 2499870ad75aSSean Wilcox * on what to do next. 2500870ad75aSSean Wilcox * 2501870ad75aSSean Wilcox * Because get_ids uses the mc_error_create() function which can 2502870ad75aSSean Wilcox * reallocate the merr, this function must return the merr pointer 2503870ad75aSSean Wilcox * in case it was reallocated. 25047c478bd9Sstevel@tonic-gate */ 2505870ad75aSSean Wilcox static mc_error_t * 250613d8aaa1SSean Wilcox get_ids(scf_propertygroup_t *methpg, scf_propertygroup_t *instpg, 2507870ad75aSSean Wilcox scf_property_t *prop, scf_value_t *val, struct method_context *ci, 2508870ad75aSSean Wilcox mc_error_t *merr) 25097c478bd9Sstevel@tonic-gate { 25107c478bd9Sstevel@tonic-gate char *vbuf = ci->vbuf; 25117c478bd9Sstevel@tonic-gate ssize_t vbuf_sz = ci->vbuf_sz; 25127c478bd9Sstevel@tonic-gate int r; 25137c478bd9Sstevel@tonic-gate 251413d8aaa1SSean Wilcox /* 251513d8aaa1SSean Wilcox * This should never happen because the caller should fall through 251613d8aaa1SSean Wilcox * another path of just setting the ids to defaults, instead of 251713d8aaa1SSean Wilcox * attempting to get the ids here. 251813d8aaa1SSean Wilcox */ 2519870ad75aSSean Wilcox if (methpg == NULL && instpg == NULL) 2520870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT, 2521870ad75aSSean Wilcox "No property groups to get ids from.")); 252213d8aaa1SSean Wilcox 252313d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_USER, 252413d8aaa1SSean Wilcox vbuf, vbuf_sz, prop, val) == 0 || get_astring_val(instpg, 252513d8aaa1SSean Wilcox SCF_PROPERTY_USER, vbuf, vbuf_sz, prop, 2526870ad75aSSean Wilcox val) == 0)) 2527870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT, 2528870ad75aSSean Wilcox "Could not get \"%s\" property.", SCF_PROPERTY_USER)); 25297c478bd9Sstevel@tonic-gate 2530870ad75aSSean Wilcox if ((r = get_uid(vbuf, ci, &ci->uid)) != 0) { 2531f48205beScasper ci->uid = (uid_t)-1; 2532870ad75aSSean Wilcox return (mc_error_create(merr, r, 2533870ad75aSSean Wilcox "Could not interpret \"%s\" property value \"%s\", " 2534870ad75aSSean Wilcox "error %d.", SCF_PROPERTY_USER, vbuf, r)); 25357c478bd9Sstevel@tonic-gate } 25367c478bd9Sstevel@tonic-gate 253713d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_GROUP, vbuf, vbuf_sz, prop, 253813d8aaa1SSean Wilcox val) == 0 || get_astring_val(instpg, SCF_PROPERTY_GROUP, vbuf, 253913d8aaa1SSean Wilcox vbuf_sz, prop, val) == 0)) { 254013d8aaa1SSean Wilcox if (scf_error() == SCF_ERROR_NOT_FOUND) { 254113d8aaa1SSean Wilcox (void) strcpy(vbuf, ":default"); 254213d8aaa1SSean Wilcox } else { 2543870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT, 2544870ad75aSSean Wilcox "Could not get \"%s\" property.", 2545870ad75aSSean Wilcox SCF_PROPERTY_GROUP)); 25467c478bd9Sstevel@tonic-gate } 254713d8aaa1SSean Wilcox } 25487c478bd9Sstevel@tonic-gate 25497c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") != 0) { 25507c478bd9Sstevel@tonic-gate ci->gid = get_gid(vbuf); 2551f48205beScasper if (ci->gid == (gid_t)-1) { 2552870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT, 2553870ad75aSSean Wilcox "Could not interpret \"%s\" property value \"%s\".", 2554870ad75aSSean Wilcox SCF_PROPERTY_GROUP, vbuf)); 25557c478bd9Sstevel@tonic-gate } 25567c478bd9Sstevel@tonic-gate } else { 25577c478bd9Sstevel@tonic-gate switch (r = lookup_pwd(ci)) { 25587c478bd9Sstevel@tonic-gate case 0: 25597c478bd9Sstevel@tonic-gate ci->gid = ci->pwd.pw_gid; 25607c478bd9Sstevel@tonic-gate break; 25617c478bd9Sstevel@tonic-gate 25627c478bd9Sstevel@tonic-gate case ENOENT: 2563f48205beScasper ci->gid = (gid_t)-1; 2564870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT, 2565870ad75aSSean Wilcox "No passwd entry for uid \"%d\".", ci->uid)); 25667c478bd9Sstevel@tonic-gate 25677c478bd9Sstevel@tonic-gate case ENOMEM: 2568870ad75aSSean Wilcox return (mc_error_create(merr, ENOMEM, 2569870ad75aSSean Wilcox "Out of memory.")); 25707c478bd9Sstevel@tonic-gate 25717c478bd9Sstevel@tonic-gate case EIO: 25727c478bd9Sstevel@tonic-gate case EMFILE: 25737c478bd9Sstevel@tonic-gate case ENFILE: 2574870ad75aSSean Wilcox return (mc_error_create(merr, ENFILE, 2575870ad75aSSean Wilcox "getpwuid_r() failed, error %d.", r)); 25767c478bd9Sstevel@tonic-gate 25777c478bd9Sstevel@tonic-gate default: 25787c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", r); 25797c478bd9Sstevel@tonic-gate } 25807c478bd9Sstevel@tonic-gate } 25817c478bd9Sstevel@tonic-gate 258213d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_SUPP_GROUPS, vbuf, vbuf_sz, 258313d8aaa1SSean Wilcox prop, val) == 0 || get_astring_val(instpg, 258413d8aaa1SSean Wilcox SCF_PROPERTY_SUPP_GROUPS, vbuf, vbuf_sz, prop, val) == 0)) { 258513d8aaa1SSean Wilcox if (scf_error() == SCF_ERROR_NOT_FOUND) { 258613d8aaa1SSean Wilcox (void) strcpy(vbuf, ":default"); 258713d8aaa1SSean Wilcox } else { 2588870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT, 2589870ad75aSSean Wilcox "Could not get supplemental groups (\"%s\") " 2590870ad75aSSean Wilcox "property.", SCF_PROPERTY_SUPP_GROUPS)); 25917c478bd9Sstevel@tonic-gate } 259213d8aaa1SSean Wilcox } 25937c478bd9Sstevel@tonic-gate 25947c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") != 0) { 25957c478bd9Sstevel@tonic-gate switch (r = get_groups(vbuf, ci)) { 25967c478bd9Sstevel@tonic-gate case 0: 25977c478bd9Sstevel@tonic-gate break; 25987c478bd9Sstevel@tonic-gate 25997c478bd9Sstevel@tonic-gate case EINVAL: 2600870ad75aSSean Wilcox return (mc_error_create(merr, EINVAL, 2601870ad75aSSean Wilcox "Could not interpret supplemental groups (\"%s\") " 2602870ad75aSSean Wilcox "property value \"%s\".", SCF_PROPERTY_SUPP_GROUPS, 2603870ad75aSSean Wilcox vbuf)); 26047c478bd9Sstevel@tonic-gate 26057c478bd9Sstevel@tonic-gate case E2BIG: 2606870ad75aSSean Wilcox return (mc_error_create(merr, E2BIG, 2607870ad75aSSean Wilcox "Too many supplemental groups values in \"%s\".", 2608870ad75aSSean Wilcox vbuf)); 26097c478bd9Sstevel@tonic-gate 26107c478bd9Sstevel@tonic-gate default: 26117c478bd9Sstevel@tonic-gate bad_fail("get_groups", r); 26127c478bd9Sstevel@tonic-gate } 26137c478bd9Sstevel@tonic-gate } else { 26147c478bd9Sstevel@tonic-gate ci->ngroups = -1; 26157c478bd9Sstevel@tonic-gate } 26167c478bd9Sstevel@tonic-gate 261713d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_PRIVILEGES, vbuf, vbuf_sz, 261813d8aaa1SSean Wilcox prop, val) == 0 || get_astring_val(instpg, SCF_PROPERTY_PRIVILEGES, 261913d8aaa1SSean Wilcox vbuf, vbuf_sz, prop, val) == 0)) { 262013d8aaa1SSean Wilcox if (scf_error() == SCF_ERROR_NOT_FOUND) { 262113d8aaa1SSean Wilcox (void) strcpy(vbuf, ":default"); 262213d8aaa1SSean Wilcox } else { 2623870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT, 2624870ad75aSSean Wilcox "Could not get \"%s\" property.", 2625870ad75aSSean Wilcox SCF_PROPERTY_PRIVILEGES)); 26267c478bd9Sstevel@tonic-gate } 262713d8aaa1SSean Wilcox } 26287c478bd9Sstevel@tonic-gate 26297c478bd9Sstevel@tonic-gate /* 26307c478bd9Sstevel@tonic-gate * For default privs, we need to keep priv_set == NULL, as 26317c478bd9Sstevel@tonic-gate * we use this test elsewhere. 26327c478bd9Sstevel@tonic-gate */ 26337c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") != 0) { 26347c478bd9Sstevel@tonic-gate ci->priv_set = priv_str_to_set(vbuf, ",", NULL); 26357c478bd9Sstevel@tonic-gate if (ci->priv_set == NULL) { 26367c478bd9Sstevel@tonic-gate if (errno != EINVAL) { 2637870ad75aSSean Wilcox return (mc_error_create(merr, ENOMEM, 2638870ad75aSSean Wilcox ALLOCFAIL)); 26397c478bd9Sstevel@tonic-gate } else { 2640870ad75aSSean Wilcox return (mc_error_create(merr, EINVAL, 2641870ad75aSSean Wilcox "Could not interpret \"%s\" " 2642870ad75aSSean Wilcox "property value \"%s\".", 2643870ad75aSSean Wilcox SCF_PROPERTY_PRIVILEGES, vbuf)); 26447c478bd9Sstevel@tonic-gate } 26457c478bd9Sstevel@tonic-gate } 26467c478bd9Sstevel@tonic-gate } 26477c478bd9Sstevel@tonic-gate 264813d8aaa1SSean Wilcox if (!(get_astring_val(methpg, SCF_PROPERTY_LIMIT_PRIVILEGES, vbuf, 264913d8aaa1SSean Wilcox vbuf_sz, prop, val) == 0 || get_astring_val(instpg, 265013d8aaa1SSean Wilcox SCF_PROPERTY_LIMIT_PRIVILEGES, vbuf, vbuf_sz, prop, val) == 0)) { 265113d8aaa1SSean Wilcox if (scf_error() == SCF_ERROR_NOT_FOUND) { 265213d8aaa1SSean Wilcox (void) strcpy(vbuf, ":default"); 265313d8aaa1SSean Wilcox } else { 2654870ad75aSSean Wilcox return (mc_error_create(merr, ENOENT, 2655870ad75aSSean Wilcox "Could not get \"%s\" property.", 2656870ad75aSSean Wilcox SCF_PROPERTY_LIMIT_PRIVILEGES)); 26577c478bd9Sstevel@tonic-gate } 265813d8aaa1SSean Wilcox } 26597c478bd9Sstevel@tonic-gate 26607c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") == 0) 26617c478bd9Sstevel@tonic-gate /* 26627c478bd9Sstevel@tonic-gate * L must default to all privileges so root NPA services see 26637c478bd9Sstevel@tonic-gate * iE = all. "zone" is all privileges available in the current 26647c478bd9Sstevel@tonic-gate * zone, equivalent to "all" in the global zone. 26657c478bd9Sstevel@tonic-gate */ 26667c478bd9Sstevel@tonic-gate (void) strcpy(vbuf, "zone"); 26677c478bd9Sstevel@tonic-gate 26687c478bd9Sstevel@tonic-gate ci->lpriv_set = priv_str_to_set(vbuf, ",", NULL); 26697c478bd9Sstevel@tonic-gate if (ci->lpriv_set == NULL) { 2670870ad75aSSean Wilcox if (errno != EINVAL) { 2671870ad75aSSean Wilcox return (mc_error_create(merr, ENOMEM, ALLOCFAIL)); 2672870ad75aSSean Wilcox } else { 2673870ad75aSSean Wilcox return (mc_error_create(merr, EINVAL, 2674870ad75aSSean Wilcox "Could not interpret \"%s\" property value \"%s\".", 2675870ad75aSSean Wilcox SCF_PROPERTY_LIMIT_PRIVILEGES, vbuf)); 26767c478bd9Sstevel@tonic-gate } 26777c478bd9Sstevel@tonic-gate } 26787c478bd9Sstevel@tonic-gate 2679870ad75aSSean Wilcox return (merr); 26807c478bd9Sstevel@tonic-gate } 26817c478bd9Sstevel@tonic-gate 26827c478bd9Sstevel@tonic-gate static int 26837c478bd9Sstevel@tonic-gate get_environment(scf_handle_t *h, scf_propertygroup_t *pg, 26847c478bd9Sstevel@tonic-gate struct method_context *mcp, scf_property_t *prop, scf_value_t *val) 26857c478bd9Sstevel@tonic-gate { 26867c478bd9Sstevel@tonic-gate scf_iter_t *iter; 26877c478bd9Sstevel@tonic-gate scf_type_t type; 26887c478bd9Sstevel@tonic-gate size_t i = 0; 26897c478bd9Sstevel@tonic-gate int ret; 26907c478bd9Sstevel@tonic-gate 26917c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_ENVIRONMENT, prop) != 0) { 26927c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_NOT_FOUND) 26937c478bd9Sstevel@tonic-gate return (ENOENT); 26947c478bd9Sstevel@tonic-gate return (scf_error()); 26957c478bd9Sstevel@tonic-gate } 26967c478bd9Sstevel@tonic-gate if (scf_property_type(prop, &type) != 0) 26977c478bd9Sstevel@tonic-gate return (scf_error()); 26987c478bd9Sstevel@tonic-gate if (type != SCF_TYPE_ASTRING) 26997c478bd9Sstevel@tonic-gate return (EINVAL); 27007c478bd9Sstevel@tonic-gate if ((iter = scf_iter_create(h)) == NULL) 27017c478bd9Sstevel@tonic-gate return (scf_error()); 27027c478bd9Sstevel@tonic-gate 27037c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) { 27047c478bd9Sstevel@tonic-gate ret = scf_error(); 27057c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 27067c478bd9Sstevel@tonic-gate return (ret); 27077c478bd9Sstevel@tonic-gate } 27087c478bd9Sstevel@tonic-gate 27097c478bd9Sstevel@tonic-gate mcp->env_sz = 10; 27107c478bd9Sstevel@tonic-gate 27117c478bd9Sstevel@tonic-gate if ((mcp->env = uu_zalloc(sizeof (*mcp->env) * mcp->env_sz)) == NULL) { 27127c478bd9Sstevel@tonic-gate ret = ENOMEM; 27137c478bd9Sstevel@tonic-gate goto out; 27147c478bd9Sstevel@tonic-gate } 27157c478bd9Sstevel@tonic-gate 27167c478bd9Sstevel@tonic-gate while ((ret = scf_iter_next_value(iter, val)) == 1) { 27177c478bd9Sstevel@tonic-gate ret = scf_value_get_as_string(val, mcp->vbuf, mcp->vbuf_sz); 27187c478bd9Sstevel@tonic-gate if (ret == -1) { 27197c478bd9Sstevel@tonic-gate ret = scf_error(); 27207c478bd9Sstevel@tonic-gate goto out; 27217c478bd9Sstevel@tonic-gate } 27227c478bd9Sstevel@tonic-gate 27237c478bd9Sstevel@tonic-gate if ((mcp->env[i] = strdup(mcp->vbuf)) == NULL) { 27247c478bd9Sstevel@tonic-gate ret = ENOMEM; 27257c478bd9Sstevel@tonic-gate goto out; 27267c478bd9Sstevel@tonic-gate } 27277c478bd9Sstevel@tonic-gate 27287c478bd9Sstevel@tonic-gate if (++i == mcp->env_sz) { 27297c478bd9Sstevel@tonic-gate char **env; 27307c478bd9Sstevel@tonic-gate mcp->env_sz *= 2; 27317c478bd9Sstevel@tonic-gate env = uu_zalloc(sizeof (*mcp->env) * mcp->env_sz); 27327c478bd9Sstevel@tonic-gate if (env == NULL) { 27337c478bd9Sstevel@tonic-gate ret = ENOMEM; 27347c478bd9Sstevel@tonic-gate goto out; 27357c478bd9Sstevel@tonic-gate } 27367c478bd9Sstevel@tonic-gate (void) memcpy(env, mcp->env, 27377c478bd9Sstevel@tonic-gate sizeof (*mcp->env) * (mcp->env_sz / 2)); 27387c478bd9Sstevel@tonic-gate free(mcp->env); 27397c478bd9Sstevel@tonic-gate mcp->env = env; 27407c478bd9Sstevel@tonic-gate } 27417c478bd9Sstevel@tonic-gate } 27427c478bd9Sstevel@tonic-gate 27437c478bd9Sstevel@tonic-gate if (ret == -1) 27447c478bd9Sstevel@tonic-gate ret = scf_error(); 27457c478bd9Sstevel@tonic-gate 27467c478bd9Sstevel@tonic-gate out: 27477c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 27487c478bd9Sstevel@tonic-gate return (ret); 27497c478bd9Sstevel@tonic-gate } 27507c478bd9Sstevel@tonic-gate 27517c478bd9Sstevel@tonic-gate /* 27527c478bd9Sstevel@tonic-gate * Fetch method context information from the repository, allocate and fill 2753870ad75aSSean Wilcox * a method_context structure, return it in *mcpp, and return NULL. 27547c478bd9Sstevel@tonic-gate * 275513d8aaa1SSean Wilcox * If no method_context is defined, original init context is provided, where 275613d8aaa1SSean Wilcox * the working directory is '/', and uid/gid are 0/0. But if a method_context 275713d8aaa1SSean Wilcox * is defined at any level the smf_method(5) method_context defaults are used. 275813d8aaa1SSean Wilcox * 2759870ad75aSSean Wilcox * Return an error message structure containing the error message 2760870ad75aSSean Wilcox * with context, and the error so the caller can make a decision 2761870ad75aSSean Wilcox * on what to do next. 2762870ad75aSSean Wilcox * 2763870ad75aSSean Wilcox * Error Types : 2764870ad75aSSean Wilcox * E2BIG Too many values or entry is too big 2765870ad75aSSean Wilcox * EINVAL Invalid value 2766870ad75aSSean Wilcox * EIO an I/O error has occured 2767870ad75aSSean Wilcox * ENOENT no entry for value 2768870ad75aSSean Wilcox * ENOMEM out of memory 2769870ad75aSSean Wilcox * ENOTSUP Version mismatch 2770870ad75aSSean Wilcox * ERANGE value is out of range 2771870ad75aSSean Wilcox * EMFILE/ENFILE out of file descriptors 2772870ad75aSSean Wilcox * 2773870ad75aSSean Wilcox * SCF_ERROR_BACKEND_ACCESS 2774870ad75aSSean Wilcox * SCF_ERROR_CONNECTION_BROKEN 2775870ad75aSSean Wilcox * SCF_ERROR_DELETED 2776870ad75aSSean Wilcox * SCF_ERROR_CONSTRAINT_VIOLATED 2777870ad75aSSean Wilcox * SCF_ERROR_HANDLE_DESTROYED 2778870ad75aSSean Wilcox * SCF_ERROR_INTERNAL 2779870ad75aSSean Wilcox * SCF_ERROR_INVALID_ARGUMENT 2780870ad75aSSean Wilcox * SCF_ERROR_NO_MEMORY 2781870ad75aSSean Wilcox * SCF_ERROR_NO_RESOURCES 2782870ad75aSSean Wilcox * SCF_ERROR_NOT_BOUND 2783870ad75aSSean Wilcox * SCF_ERROR_NOT_FOUND 2784870ad75aSSean Wilcox * SCF_ERROR_NOT_SET 2785870ad75aSSean Wilcox * SCF_ERROR_TYPE_MISMATCH 2786870ad75aSSean Wilcox * 27877c478bd9Sstevel@tonic-gate */ 2788870ad75aSSean Wilcox mc_error_t * 27897c478bd9Sstevel@tonic-gate restarter_get_method_context(uint_t version, scf_instance_t *inst, 27907c478bd9Sstevel@tonic-gate scf_snapshot_t *snap, const char *mname, const char *cmdline, 27917c478bd9Sstevel@tonic-gate struct method_context **mcpp) 27927c478bd9Sstevel@tonic-gate { 27937c478bd9Sstevel@tonic-gate scf_handle_t *h; 27947c478bd9Sstevel@tonic-gate scf_propertygroup_t *methpg = NULL; 27957c478bd9Sstevel@tonic-gate scf_propertygroup_t *instpg = NULL; 27967c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 27977c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL; 27987c478bd9Sstevel@tonic-gate scf_value_t *val = NULL; 27997c478bd9Sstevel@tonic-gate scf_type_t ty; 28007c478bd9Sstevel@tonic-gate uint8_t use_profile; 2801870ad75aSSean Wilcox int ret = 0; 280213d8aaa1SSean Wilcox int mc_used = 0; 2803870ad75aSSean Wilcox mc_error_t *err = NULL; 28047c478bd9Sstevel@tonic-gate struct method_context *cip; 28057c478bd9Sstevel@tonic-gate 2806870ad75aSSean Wilcox if ((err = malloc(sizeof (mc_error_t))) == NULL) 2807870ad75aSSean Wilcox return (mc_error_create(NULL, ENOMEM, NULL)); 2808870ad75aSSean Wilcox 2809870ad75aSSean Wilcox /* Set the type to zero to track if an error occured. */ 2810870ad75aSSean Wilcox err->type = 0; 2811870ad75aSSean Wilcox 28127c478bd9Sstevel@tonic-gate if (version != RESTARTER_METHOD_CONTEXT_VERSION) 2813870ad75aSSean Wilcox return (mc_error_create(err, ENOTSUP, 2814870ad75aSSean Wilcox "Invalid client version %d. (Expected %d)", 2815870ad75aSSean Wilcox version, RESTARTER_METHOD_CONTEXT_VERSION)); 28167c478bd9Sstevel@tonic-gate 28177c478bd9Sstevel@tonic-gate /* Get the handle before we allocate anything. */ 28187c478bd9Sstevel@tonic-gate h = scf_instance_handle(inst); 28197c478bd9Sstevel@tonic-gate if (h == NULL) 2820870ad75aSSean Wilcox return (mc_error_create(err, scf_error(), 2821870ad75aSSean Wilcox scf_strerror(scf_error()))); 28227c478bd9Sstevel@tonic-gate 28237c478bd9Sstevel@tonic-gate cip = malloc(sizeof (*cip)); 28247c478bd9Sstevel@tonic-gate if (cip == NULL) 2825870ad75aSSean Wilcox return (mc_error_create(err, ENOMEM, ALLOCFAIL)); 28267c478bd9Sstevel@tonic-gate 28277c478bd9Sstevel@tonic-gate (void) memset(cip, 0, sizeof (*cip)); 2828f48205beScasper cip->uid = (uid_t)-1; 2829f48205beScasper cip->euid = (uid_t)-1; 2830f48205beScasper cip->gid = (gid_t)-1; 2831f48205beScasper cip->egid = (gid_t)-1; 28327c478bd9Sstevel@tonic-gate 28337c478bd9Sstevel@tonic-gate cip->vbuf_sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 28347c478bd9Sstevel@tonic-gate assert(cip->vbuf_sz >= 0); 28357c478bd9Sstevel@tonic-gate cip->vbuf = malloc(cip->vbuf_sz); 28367c478bd9Sstevel@tonic-gate if (cip->vbuf == NULL) { 28377c478bd9Sstevel@tonic-gate free(cip); 2838870ad75aSSean Wilcox return (mc_error_create(err, ENOMEM, ALLOCFAIL)); 28397c478bd9Sstevel@tonic-gate } 28407c478bd9Sstevel@tonic-gate 28417c478bd9Sstevel@tonic-gate if ((instpg = scf_pg_create(h)) == NULL || 28427c478bd9Sstevel@tonic-gate (methpg = scf_pg_create(h)) == NULL || 28437c478bd9Sstevel@tonic-gate (prop = scf_property_create(h)) == NULL || 28447c478bd9Sstevel@tonic-gate (val = scf_value_create(h)) == NULL) { 2845870ad75aSSean Wilcox err = mc_error_create(err, scf_error(), 2846870ad75aSSean Wilcox "Failed to create repository object: %s\n", 2847870ad75aSSean Wilcox scf_strerror(scf_error())); 28487c478bd9Sstevel@tonic-gate goto out; 28497c478bd9Sstevel@tonic-gate } 28507c478bd9Sstevel@tonic-gate 28517c478bd9Sstevel@tonic-gate /* 28527c478bd9Sstevel@tonic-gate * The method environment, and the credentials/profile data, 28537c478bd9Sstevel@tonic-gate * may be found either in the pg for the method (methpg), 28547c478bd9Sstevel@tonic-gate * or in the instance/service SCF_PG_METHOD_CONTEXT pg (named 28557c478bd9Sstevel@tonic-gate * instpg below). 28567c478bd9Sstevel@tonic-gate */ 28577c478bd9Sstevel@tonic-gate 28587c478bd9Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, snap, mname, methpg) != 28597c478bd9Sstevel@tonic-gate SCF_SUCCESS) { 2860870ad75aSSean Wilcox err = mc_error_create(err, scf_error(), "Unable to get the " 2861870ad75aSSean Wilcox "\"%s\" method, %s", mname, scf_strerror(scf_error())); 28627c478bd9Sstevel@tonic-gate goto out; 28637c478bd9Sstevel@tonic-gate } 28647c478bd9Sstevel@tonic-gate 28657c478bd9Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, snap, SCF_PG_METHOD_CONTEXT, 28667c478bd9Sstevel@tonic-gate instpg) != SCF_SUCCESS) { 28677c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) { 2868870ad75aSSean Wilcox err = mc_error_create(err, scf_error(), 2869870ad75aSSean Wilcox "Unable to retrieve the \"%s\" property group, %s", 2870870ad75aSSean Wilcox SCF_PG_METHOD_CONTEXT, scf_strerror(scf_error())); 28717c478bd9Sstevel@tonic-gate goto out; 28727c478bd9Sstevel@tonic-gate } 28737c478bd9Sstevel@tonic-gate scf_pg_destroy(instpg); 28747c478bd9Sstevel@tonic-gate instpg = NULL; 287513d8aaa1SSean Wilcox } else { 287613d8aaa1SSean Wilcox mc_used++; 28777c478bd9Sstevel@tonic-gate } 28787c478bd9Sstevel@tonic-gate 28797c478bd9Sstevel@tonic-gate ret = get_environment(h, methpg, cip, prop, val); 28807c478bd9Sstevel@tonic-gate if (ret == ENOENT && instpg != NULL) { 28817c478bd9Sstevel@tonic-gate ret = get_environment(h, instpg, cip, prop, val); 28827c478bd9Sstevel@tonic-gate } 28837c478bd9Sstevel@tonic-gate 28847c478bd9Sstevel@tonic-gate switch (ret) { 28857c478bd9Sstevel@tonic-gate case 0: 288613d8aaa1SSean Wilcox mc_used++; 288713d8aaa1SSean Wilcox break; 28887c478bd9Sstevel@tonic-gate case ENOENT: 28897c478bd9Sstevel@tonic-gate break; 28907c478bd9Sstevel@tonic-gate case ENOMEM: 2891870ad75aSSean Wilcox err = mc_error_create(err, ret, "Out of memory."); 28927c478bd9Sstevel@tonic-gate goto out; 28937c478bd9Sstevel@tonic-gate case EINVAL: 2894870ad75aSSean Wilcox err = mc_error_create(err, ret, "Invalid method environment."); 28957c478bd9Sstevel@tonic-gate goto out; 28967c478bd9Sstevel@tonic-gate default: 2897870ad75aSSean Wilcox err = mc_error_create(err, ret, 2898870ad75aSSean Wilcox "Get method environment failed : %s\n", scf_strerror(ret)); 28997c478bd9Sstevel@tonic-gate goto out; 29007c478bd9Sstevel@tonic-gate } 29017c478bd9Sstevel@tonic-gate 29027c478bd9Sstevel@tonic-gate pg = methpg; 29037c478bd9Sstevel@tonic-gate 29047c478bd9Sstevel@tonic-gate ret = scf_pg_get_property(pg, SCF_PROPERTY_USE_PROFILE, prop); 29057c478bd9Sstevel@tonic-gate if (ret && scf_error() == SCF_ERROR_NOT_FOUND && instpg != NULL) { 290613d8aaa1SSean Wilcox pg = NULL; 290713d8aaa1SSean Wilcox ret = scf_pg_get_property(instpg, SCF_PROPERTY_USE_PROFILE, 290813d8aaa1SSean Wilcox prop); 29097c478bd9Sstevel@tonic-gate } 29107c478bd9Sstevel@tonic-gate 29117c478bd9Sstevel@tonic-gate if (ret) { 29127c478bd9Sstevel@tonic-gate switch (scf_error()) { 29137c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 291413d8aaa1SSean Wilcox /* No profile context: use default credentials */ 29157c478bd9Sstevel@tonic-gate cip->uid = 0; 29167c478bd9Sstevel@tonic-gate cip->gid = 0; 291713d8aaa1SSean Wilcox break; 29187c478bd9Sstevel@tonic-gate 29197c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2920870ad75aSSean Wilcox err = mc_error_create(err, SCF_ERROR_CONNECTION_BROKEN, 2921870ad75aSSean Wilcox RCBROKEN); 29227c478bd9Sstevel@tonic-gate goto out; 29237c478bd9Sstevel@tonic-gate 29247c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 2925870ad75aSSean Wilcox err = mc_error_create(err, SCF_ERROR_NOT_FOUND, 2926870ad75aSSean Wilcox "Could not find property group \"%s\"", 2927870ad75aSSean Wilcox pg == NULL ? SCF_PG_METHOD_CONTEXT : mname); 29287c478bd9Sstevel@tonic-gate goto out; 29297c478bd9Sstevel@tonic-gate 29307c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 29317c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 29327c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 29337c478bd9Sstevel@tonic-gate default: 29347c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error()); 29357c478bd9Sstevel@tonic-gate } 293613d8aaa1SSean Wilcox } else { 29377c478bd9Sstevel@tonic-gate if (scf_property_type(prop, &ty) != SCF_SUCCESS) { 2938870ad75aSSean Wilcox ret = scf_error(); 2939870ad75aSSean Wilcox switch (ret) { 29407c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2941870ad75aSSean Wilcox err = mc_error_create(err, 2942870ad75aSSean Wilcox SCF_ERROR_CONNECTION_BROKEN, RCBROKEN); 29437c478bd9Sstevel@tonic-gate break; 29447c478bd9Sstevel@tonic-gate 29457c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 2946870ad75aSSean Wilcox err = mc_error_create(err, 2947870ad75aSSean Wilcox SCF_ERROR_NOT_FOUND, 2948870ad75aSSean Wilcox "Could not find property group \"%s\"", 2949870ad75aSSean Wilcox pg == NULL ? SCF_PG_METHOD_CONTEXT : mname); 29507c478bd9Sstevel@tonic-gate break; 29517c478bd9Sstevel@tonic-gate 29527c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 29537c478bd9Sstevel@tonic-gate default: 2954870ad75aSSean Wilcox bad_fail("scf_property_type", ret); 29557c478bd9Sstevel@tonic-gate } 29567c478bd9Sstevel@tonic-gate 29577c478bd9Sstevel@tonic-gate goto out; 29587c478bd9Sstevel@tonic-gate } 29597c478bd9Sstevel@tonic-gate 29607c478bd9Sstevel@tonic-gate if (ty != SCF_TYPE_BOOLEAN) { 2961870ad75aSSean Wilcox err = mc_error_create(err, 2962870ad75aSSean Wilcox SCF_ERROR_TYPE_MISMATCH, 2963870ad75aSSean Wilcox "\"%s\" property is not boolean in property group " 2964870ad75aSSean Wilcox "\"%s\".", SCF_PROPERTY_USE_PROFILE, 2965870ad75aSSean Wilcox pg == NULL ? SCF_PG_METHOD_CONTEXT : mname); 29667c478bd9Sstevel@tonic-gate goto out; 29677c478bd9Sstevel@tonic-gate } 29687c478bd9Sstevel@tonic-gate 29697c478bd9Sstevel@tonic-gate if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 2970870ad75aSSean Wilcox ret = scf_error(); 2971870ad75aSSean Wilcox switch (ret) { 29727c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2973870ad75aSSean Wilcox err = mc_error_create(err, 2974870ad75aSSean Wilcox SCF_ERROR_CONNECTION_BROKEN, RCBROKEN); 29757c478bd9Sstevel@tonic-gate break; 29767c478bd9Sstevel@tonic-gate 29777c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 2978870ad75aSSean Wilcox err = mc_error_create(err, 2979870ad75aSSean Wilcox SCF_ERROR_CONSTRAINT_VIOLATED, 2980870ad75aSSean Wilcox "\"%s\" property has multiple values.", 2981870ad75aSSean Wilcox SCF_PROPERTY_USE_PROFILE); 29827c478bd9Sstevel@tonic-gate break; 29837c478bd9Sstevel@tonic-gate 29847c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 2985870ad75aSSean Wilcox err = mc_error_create(err, 2986870ad75aSSean Wilcox SCF_ERROR_NOT_FOUND, 2987870ad75aSSean Wilcox "\"%s\" property has no values.", 2988870ad75aSSean Wilcox SCF_PROPERTY_USE_PROFILE); 29897c478bd9Sstevel@tonic-gate break; 29907c478bd9Sstevel@tonic-gate default: 2991870ad75aSSean Wilcox bad_fail("scf_property_get_value", ret); 29927c478bd9Sstevel@tonic-gate } 29937c478bd9Sstevel@tonic-gate 29947c478bd9Sstevel@tonic-gate goto out; 29957c478bd9Sstevel@tonic-gate } 29967c478bd9Sstevel@tonic-gate 299713d8aaa1SSean Wilcox mc_used++; 29987c478bd9Sstevel@tonic-gate ret = scf_value_get_boolean(val, &use_profile); 29997c478bd9Sstevel@tonic-gate assert(ret == SCF_SUCCESS); 30007c478bd9Sstevel@tonic-gate 30017c478bd9Sstevel@tonic-gate /* get ids & privileges */ 30027c478bd9Sstevel@tonic-gate if (use_profile) 3003870ad75aSSean Wilcox err = get_profile(pg, instpg, prop, val, cmdline, 3004870ad75aSSean Wilcox cip, err); 30057c478bd9Sstevel@tonic-gate else 3006870ad75aSSean Wilcox err = get_ids(pg, instpg, prop, val, cip, err); 300713d8aaa1SSean Wilcox 3008870ad75aSSean Wilcox if (err->type != 0) 30097c478bd9Sstevel@tonic-gate goto out; 301013d8aaa1SSean Wilcox } 30117c478bd9Sstevel@tonic-gate 30127c478bd9Sstevel@tonic-gate /* get working directory */ 301313d8aaa1SSean Wilcox if ((methpg != NULL && scf_pg_get_property(methpg, 301413d8aaa1SSean Wilcox SCF_PROPERTY_WORKING_DIRECTORY, prop) == SCF_SUCCESS) || 301513d8aaa1SSean Wilcox (instpg != NULL && scf_pg_get_property(instpg, 301613d8aaa1SSean Wilcox SCF_PROPERTY_WORKING_DIRECTORY, prop) == SCF_SUCCESS)) { 301713d8aaa1SSean Wilcox if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 3018870ad75aSSean Wilcox ret = scf_error(); 3019870ad75aSSean Wilcox switch (ret) { 302013d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN: 3021870ad75aSSean Wilcox err = mc_error_create(err, ret, RCBROKEN); 302213d8aaa1SSean Wilcox break; 302313d8aaa1SSean Wilcox 302413d8aaa1SSean Wilcox case SCF_ERROR_CONSTRAINT_VIOLATED: 3025870ad75aSSean Wilcox err = mc_error_create(err, ret, 3026870ad75aSSean Wilcox "\"%s\" property has multiple values.", 3027870ad75aSSean Wilcox SCF_PROPERTY_WORKING_DIRECTORY); 302813d8aaa1SSean Wilcox break; 302913d8aaa1SSean Wilcox 303013d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND: 3031870ad75aSSean Wilcox err = mc_error_create(err, ret, 3032870ad75aSSean Wilcox "\"%s\" property has no values.", 3033870ad75aSSean Wilcox SCF_PROPERTY_WORKING_DIRECTORY); 303413d8aaa1SSean Wilcox break; 303513d8aaa1SSean Wilcox 303613d8aaa1SSean Wilcox default: 3037870ad75aSSean Wilcox bad_fail("scf_property_get_value", ret); 303813d8aaa1SSean Wilcox } 303913d8aaa1SSean Wilcox 30407c478bd9Sstevel@tonic-gate goto out; 30417c478bd9Sstevel@tonic-gate } 30427c478bd9Sstevel@tonic-gate 304313d8aaa1SSean Wilcox mc_used++; 304413d8aaa1SSean Wilcox ret = scf_value_get_astring(val, cip->vbuf, cip->vbuf_sz); 304513d8aaa1SSean Wilcox assert(ret != -1); 304613d8aaa1SSean Wilcox } else { 3047870ad75aSSean Wilcox ret = scf_error(); 3048870ad75aSSean Wilcox switch (ret) { 304913d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND: 305013d8aaa1SSean Wilcox /* okay if missing. */ 305113d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default"); 305213d8aaa1SSean Wilcox break; 305313d8aaa1SSean Wilcox 305413d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN: 3055870ad75aSSean Wilcox err = mc_error_create(err, ret, RCBROKEN); 305613d8aaa1SSean Wilcox goto out; 305713d8aaa1SSean Wilcox 305813d8aaa1SSean Wilcox case SCF_ERROR_DELETED: 3059870ad75aSSean Wilcox err = mc_error_create(err, ret, 3060870ad75aSSean Wilcox "Property group could not be found"); 306113d8aaa1SSean Wilcox goto out; 306213d8aaa1SSean Wilcox 306313d8aaa1SSean Wilcox case SCF_ERROR_HANDLE_MISMATCH: 306413d8aaa1SSean Wilcox case SCF_ERROR_INVALID_ARGUMENT: 306513d8aaa1SSean Wilcox case SCF_ERROR_NOT_SET: 306613d8aaa1SSean Wilcox default: 3067870ad75aSSean Wilcox bad_fail("scf_pg_get_property", ret); 306813d8aaa1SSean Wilcox } 306913d8aaa1SSean Wilcox } 307013d8aaa1SSean Wilcox 30717c478bd9Sstevel@tonic-gate if (strcmp(cip->vbuf, ":default") == 0 || 30727c478bd9Sstevel@tonic-gate strcmp(cip->vbuf, ":home") == 0) { 30737c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 30747c478bd9Sstevel@tonic-gate case 0: 30757c478bd9Sstevel@tonic-gate break; 30767c478bd9Sstevel@tonic-gate 30777c478bd9Sstevel@tonic-gate case ENOMEM: 3078870ad75aSSean Wilcox err = mc_error_create(err, ret, "Out of memory."); 30797c478bd9Sstevel@tonic-gate goto out; 30807c478bd9Sstevel@tonic-gate 30817c478bd9Sstevel@tonic-gate case ENOENT: 30827c478bd9Sstevel@tonic-gate case EIO: 30837c478bd9Sstevel@tonic-gate case EMFILE: 30847c478bd9Sstevel@tonic-gate case ENFILE: 3085870ad75aSSean Wilcox err = mc_error_create(err, ret, 3086870ad75aSSean Wilcox "Could not get passwd entry."); 30877c478bd9Sstevel@tonic-gate goto out; 30887c478bd9Sstevel@tonic-gate 30897c478bd9Sstevel@tonic-gate default: 30907c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 30917c478bd9Sstevel@tonic-gate } 30927c478bd9Sstevel@tonic-gate 30937c478bd9Sstevel@tonic-gate cip->working_dir = strdup(cip->pwd.pw_dir); 30947c478bd9Sstevel@tonic-gate if (cip->working_dir == NULL) { 3095870ad75aSSean Wilcox err = mc_error_create(err, ENOMEM, ALLOCFAIL); 30967c478bd9Sstevel@tonic-gate goto out; 30977c478bd9Sstevel@tonic-gate } 30987c478bd9Sstevel@tonic-gate } else { 30997c478bd9Sstevel@tonic-gate cip->working_dir = strdup(cip->vbuf); 31007c478bd9Sstevel@tonic-gate if (cip->working_dir == NULL) { 3101870ad75aSSean Wilcox err = mc_error_create(err, ENOMEM, ALLOCFAIL); 31027c478bd9Sstevel@tonic-gate goto out; 31037c478bd9Sstevel@tonic-gate } 31047c478bd9Sstevel@tonic-gate } 31057c478bd9Sstevel@tonic-gate 31067c478bd9Sstevel@tonic-gate /* get (optional) corefile pattern */ 310713d8aaa1SSean Wilcox if ((methpg != NULL && scf_pg_get_property(methpg, 310813d8aaa1SSean Wilcox SCF_PROPERTY_COREFILE_PATTERN, prop) == SCF_SUCCESS) || 310913d8aaa1SSean Wilcox (instpg != NULL && scf_pg_get_property(instpg, 311013d8aaa1SSean Wilcox SCF_PROPERTY_COREFILE_PATTERN, prop) == SCF_SUCCESS)) { 311113d8aaa1SSean Wilcox if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 3112870ad75aSSean Wilcox ret = scf_error(); 3113870ad75aSSean Wilcox switch (ret) { 311413d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN: 3115870ad75aSSean Wilcox err = mc_error_create(err, ret, RCBROKEN); 311613d8aaa1SSean Wilcox break; 311713d8aaa1SSean Wilcox 311813d8aaa1SSean Wilcox case SCF_ERROR_CONSTRAINT_VIOLATED: 3119870ad75aSSean Wilcox err = mc_error_create(err, ret, 3120870ad75aSSean Wilcox "\"%s\" property has multiple values.", 3121870ad75aSSean Wilcox SCF_PROPERTY_COREFILE_PATTERN); 312213d8aaa1SSean Wilcox break; 312313d8aaa1SSean Wilcox 312413d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND: 3125870ad75aSSean Wilcox err = mc_error_create(err, ret, 3126870ad75aSSean Wilcox "\"%s\" property has no values.", 3127870ad75aSSean Wilcox SCF_PROPERTY_COREFILE_PATTERN); 312813d8aaa1SSean Wilcox break; 312913d8aaa1SSean Wilcox 313013d8aaa1SSean Wilcox default: 3131870ad75aSSean Wilcox bad_fail("scf_property_get_value", ret); 31327c478bd9Sstevel@tonic-gate } 31337c478bd9Sstevel@tonic-gate 313413d8aaa1SSean Wilcox } else { 313513d8aaa1SSean Wilcox 313613d8aaa1SSean Wilcox ret = scf_value_get_astring(val, cip->vbuf, 313713d8aaa1SSean Wilcox cip->vbuf_sz); 313813d8aaa1SSean Wilcox assert(ret != -1); 313913d8aaa1SSean Wilcox 31407c478bd9Sstevel@tonic-gate cip->corefile_pattern = strdup(cip->vbuf); 31417c478bd9Sstevel@tonic-gate if (cip->corefile_pattern == NULL) { 3142870ad75aSSean Wilcox err = mc_error_create(err, ENOMEM, ALLOCFAIL); 31437c478bd9Sstevel@tonic-gate goto out; 31447c478bd9Sstevel@tonic-gate } 314513d8aaa1SSean Wilcox } 314613d8aaa1SSean Wilcox 314713d8aaa1SSean Wilcox mc_used++; 31487c478bd9Sstevel@tonic-gate } else { 3149870ad75aSSean Wilcox ret = scf_error(); 3150870ad75aSSean Wilcox switch (ret) { 31517c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 31527c478bd9Sstevel@tonic-gate /* okay if missing. */ 31537c478bd9Sstevel@tonic-gate break; 31547c478bd9Sstevel@tonic-gate 31557c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 3156870ad75aSSean Wilcox err = mc_error_create(err, ret, RCBROKEN); 31577c478bd9Sstevel@tonic-gate goto out; 31587c478bd9Sstevel@tonic-gate 31597c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 3160870ad75aSSean Wilcox err = mc_error_create(err, ret, 3161870ad75aSSean Wilcox "Property group could not be found"); 31627c478bd9Sstevel@tonic-gate goto out; 31637c478bd9Sstevel@tonic-gate 31647c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 31657c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 31667c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 31677c478bd9Sstevel@tonic-gate default: 3168870ad75aSSean Wilcox bad_fail("scf_pg_get_property", ret); 31697c478bd9Sstevel@tonic-gate } 31707c478bd9Sstevel@tonic-gate } 31717c478bd9Sstevel@tonic-gate 31727c478bd9Sstevel@tonic-gate if (restarter_rm_libs_loadable()) { 31737c478bd9Sstevel@tonic-gate /* get project */ 317413d8aaa1SSean Wilcox if ((methpg != NULL && scf_pg_get_property(methpg, 317513d8aaa1SSean Wilcox SCF_PROPERTY_PROJECT, prop) == SCF_SUCCESS) || 317613d8aaa1SSean Wilcox (instpg != NULL && scf_pg_get_property(instpg, 317713d8aaa1SSean Wilcox SCF_PROPERTY_PROJECT, prop) == SCF_SUCCESS)) { 317813d8aaa1SSean Wilcox if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 3179870ad75aSSean Wilcox ret = scf_error(); 3180870ad75aSSean Wilcox switch (ret) { 318113d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN: 3182870ad75aSSean Wilcox err = mc_error_create(err, ret, 3183870ad75aSSean Wilcox RCBROKEN); 318413d8aaa1SSean Wilcox break; 318513d8aaa1SSean Wilcox 318613d8aaa1SSean Wilcox case SCF_ERROR_CONSTRAINT_VIOLATED: 3187870ad75aSSean Wilcox err = mc_error_create(err, ret, 3188870ad75aSSean Wilcox "\"%s\" property has multiple " 3189870ad75aSSean Wilcox "values.", SCF_PROPERTY_PROJECT); 319013d8aaa1SSean Wilcox break; 319113d8aaa1SSean Wilcox 319213d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND: 3193870ad75aSSean Wilcox err = mc_error_create(err, ret, 3194870ad75aSSean Wilcox "\"%s\" property has no values.", 3195870ad75aSSean Wilcox SCF_PROPERTY_PROJECT); 319613d8aaa1SSean Wilcox break; 319713d8aaa1SSean Wilcox 319813d8aaa1SSean Wilcox default: 3199870ad75aSSean Wilcox bad_fail("scf_property_get_value", ret); 320013d8aaa1SSean Wilcox } 320113d8aaa1SSean Wilcox 320213d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default"); 320313d8aaa1SSean Wilcox } else { 320413d8aaa1SSean Wilcox ret = scf_value_get_astring(val, cip->vbuf, 320513d8aaa1SSean Wilcox cip->vbuf_sz); 320613d8aaa1SSean Wilcox assert(ret != -1); 320713d8aaa1SSean Wilcox } 320813d8aaa1SSean Wilcox 320913d8aaa1SSean Wilcox mc_used++; 321013d8aaa1SSean Wilcox } else { 321113d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default"); 32127c478bd9Sstevel@tonic-gate } 32137c478bd9Sstevel@tonic-gate 32147c478bd9Sstevel@tonic-gate switch (ret = get_projid(cip->vbuf, cip)) { 32157c478bd9Sstevel@tonic-gate case 0: 32167c478bd9Sstevel@tonic-gate break; 32177c478bd9Sstevel@tonic-gate 32187c478bd9Sstevel@tonic-gate case ENOMEM: 3219870ad75aSSean Wilcox err = mc_error_create(err, ret, "Out of memory."); 32207c478bd9Sstevel@tonic-gate goto out; 32217c478bd9Sstevel@tonic-gate 32227c478bd9Sstevel@tonic-gate case ENOENT: 3223870ad75aSSean Wilcox err = mc_error_create(err, ret, 3224870ad75aSSean Wilcox "Missing passwd or project entry for \"%s\".", 3225870ad75aSSean Wilcox cip->vbuf); 32267c478bd9Sstevel@tonic-gate goto out; 32277c478bd9Sstevel@tonic-gate 32287c478bd9Sstevel@tonic-gate case EIO: 3229870ad75aSSean Wilcox err = mc_error_create(err, ret, "I/O error."); 32307c478bd9Sstevel@tonic-gate goto out; 32317c478bd9Sstevel@tonic-gate 32327c478bd9Sstevel@tonic-gate case EMFILE: 32337c478bd9Sstevel@tonic-gate case ENFILE: 3234870ad75aSSean Wilcox err = mc_error_create(err, ret, 3235870ad75aSSean Wilcox "Out of file descriptors."); 32367c478bd9Sstevel@tonic-gate goto out; 32377c478bd9Sstevel@tonic-gate 32387c478bd9Sstevel@tonic-gate case -1: 3239870ad75aSSean Wilcox err = mc_error_create(err, ret, 3240870ad75aSSean Wilcox "Name service switch is misconfigured."); 32417c478bd9Sstevel@tonic-gate goto out; 32427c478bd9Sstevel@tonic-gate 32437c478bd9Sstevel@tonic-gate case ERANGE: 3244870ad75aSSean Wilcox case E2BIG: 3245870ad75aSSean Wilcox err = mc_error_create(err, ret, 3246870ad75aSSean Wilcox "Project ID \"%s\" too big.", cip->vbuf); 32477c478bd9Sstevel@tonic-gate goto out; 32487c478bd9Sstevel@tonic-gate 32497c478bd9Sstevel@tonic-gate case EINVAL: 3250870ad75aSSean Wilcox err = mc_error_create(err, ret, 3251870ad75aSSean Wilcox "Project ID \"%s\" is invalid.", cip->vbuf); 32527c478bd9Sstevel@tonic-gate goto out; 32537c478bd9Sstevel@tonic-gate 32547c478bd9Sstevel@tonic-gate default: 32557c478bd9Sstevel@tonic-gate bad_fail("get_projid", ret); 32567c478bd9Sstevel@tonic-gate } 32577c478bd9Sstevel@tonic-gate 32587c478bd9Sstevel@tonic-gate /* get resource pool */ 325913d8aaa1SSean Wilcox if ((methpg != NULL && scf_pg_get_property(methpg, 326013d8aaa1SSean Wilcox SCF_PROPERTY_RESOURCE_POOL, prop) == SCF_SUCCESS) || 326113d8aaa1SSean Wilcox (instpg != NULL && scf_pg_get_property(instpg, 326213d8aaa1SSean Wilcox SCF_PROPERTY_RESOURCE_POOL, prop) == SCF_SUCCESS)) { 326313d8aaa1SSean Wilcox if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 3264870ad75aSSean Wilcox ret = scf_error(); 3265870ad75aSSean Wilcox switch (ret) { 326613d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN: 3267870ad75aSSean Wilcox err = mc_error_create(err, ret, 3268870ad75aSSean Wilcox RCBROKEN); 326913d8aaa1SSean Wilcox break; 327013d8aaa1SSean Wilcox 327113d8aaa1SSean Wilcox case SCF_ERROR_CONSTRAINT_VIOLATED: 3272870ad75aSSean Wilcox err = mc_error_create(err, ret, 3273870ad75aSSean Wilcox "\"%s\" property has multiple " 3274870ad75aSSean Wilcox "values.", 3275870ad75aSSean Wilcox SCF_PROPERTY_RESOURCE_POOL); 327613d8aaa1SSean Wilcox break; 327713d8aaa1SSean Wilcox 327813d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND: 3279870ad75aSSean Wilcox err = mc_error_create(err, ret, 3280870ad75aSSean Wilcox "\"%s\" property has no " 3281870ad75aSSean Wilcox "values.", 3282870ad75aSSean Wilcox SCF_PROPERTY_RESOURCE_POOL); 328313d8aaa1SSean Wilcox break; 328413d8aaa1SSean Wilcox 328513d8aaa1SSean Wilcox default: 3286870ad75aSSean Wilcox bad_fail("scf_property_get_value", ret); 328713d8aaa1SSean Wilcox } 328813d8aaa1SSean Wilcox 328913d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default"); 329013d8aaa1SSean Wilcox } else { 329113d8aaa1SSean Wilcox ret = scf_value_get_astring(val, cip->vbuf, 329213d8aaa1SSean Wilcox cip->vbuf_sz); 329313d8aaa1SSean Wilcox assert(ret != -1); 329413d8aaa1SSean Wilcox } 329513d8aaa1SSean Wilcox 329613d8aaa1SSean Wilcox mc_used++; 329713d8aaa1SSean Wilcox } else { 3298870ad75aSSean Wilcox ret = scf_error(); 3299870ad75aSSean Wilcox switch (ret) { 330013d8aaa1SSean Wilcox case SCF_ERROR_NOT_FOUND: 330113d8aaa1SSean Wilcox /* okay if missing. */ 330213d8aaa1SSean Wilcox (void) strcpy(cip->vbuf, ":default"); 330313d8aaa1SSean Wilcox break; 330413d8aaa1SSean Wilcox 330513d8aaa1SSean Wilcox case SCF_ERROR_CONNECTION_BROKEN: 3306870ad75aSSean Wilcox err = mc_error_create(err, ret, RCBROKEN); 33077c478bd9Sstevel@tonic-gate goto out; 330813d8aaa1SSean Wilcox 330913d8aaa1SSean Wilcox case SCF_ERROR_DELETED: 3310870ad75aSSean Wilcox err = mc_error_create(err, ret, 3311870ad75aSSean Wilcox "property group could not be found."); 331213d8aaa1SSean Wilcox goto out; 331313d8aaa1SSean Wilcox 331413d8aaa1SSean Wilcox case SCF_ERROR_HANDLE_MISMATCH: 331513d8aaa1SSean Wilcox case SCF_ERROR_INVALID_ARGUMENT: 331613d8aaa1SSean Wilcox case SCF_ERROR_NOT_SET: 331713d8aaa1SSean Wilcox default: 3318870ad75aSSean Wilcox bad_fail("scf_pg_get_property", ret); 331913d8aaa1SSean Wilcox } 33207c478bd9Sstevel@tonic-gate } 33217c478bd9Sstevel@tonic-gate 33227c478bd9Sstevel@tonic-gate if (strcmp(cip->vbuf, ":default") != 0) { 33237c478bd9Sstevel@tonic-gate cip->resource_pool = strdup(cip->vbuf); 33247c478bd9Sstevel@tonic-gate if (cip->resource_pool == NULL) { 3325870ad75aSSean Wilcox err = mc_error_create(err, ENOMEM, ALLOCFAIL); 33267c478bd9Sstevel@tonic-gate goto out; 33277c478bd9Sstevel@tonic-gate } 33287c478bd9Sstevel@tonic-gate } 33297c478bd9Sstevel@tonic-gate } 33307c478bd9Sstevel@tonic-gate 333113d8aaa1SSean Wilcox /* 333213d8aaa1SSean Wilcox * A method_context was not used for any configurable 333313d8aaa1SSean Wilcox * elements or attributes, so reset and use the simple 333413d8aaa1SSean Wilcox * defaults that provide historic init behavior. 333513d8aaa1SSean Wilcox */ 333613d8aaa1SSean Wilcox if (mc_used == 0) { 33373dd94f79SBryan Cantrill free(cip->pwbuf); 33383dd94f79SBryan Cantrill free(cip->vbuf); 33393dd94f79SBryan Cantrill free(cip->working_dir); 33403dd94f79SBryan Cantrill 334113d8aaa1SSean Wilcox (void) memset(cip, 0, sizeof (*cip)); 334213d8aaa1SSean Wilcox cip->uid = 0; 334313d8aaa1SSean Wilcox cip->gid = 0; 334413d8aaa1SSean Wilcox cip->euid = (uid_t)-1; 334513d8aaa1SSean Wilcox cip->egid = (gid_t)-1; 334613d8aaa1SSean Wilcox } 334713d8aaa1SSean Wilcox 33487c478bd9Sstevel@tonic-gate *mcpp = cip; 33497c478bd9Sstevel@tonic-gate 33507c478bd9Sstevel@tonic-gate out: 33517c478bd9Sstevel@tonic-gate (void) scf_value_destroy(val); 33527c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 33537c478bd9Sstevel@tonic-gate scf_pg_destroy(instpg); 33547c478bd9Sstevel@tonic-gate scf_pg_destroy(methpg); 33557c478bd9Sstevel@tonic-gate 33563dd94f79SBryan Cantrill if (cip->pwbuf != NULL) { 33577c478bd9Sstevel@tonic-gate free(cip->pwbuf); 33583dd94f79SBryan Cantrill cip->pwbuf = NULL; 33593dd94f79SBryan Cantrill } 33603dd94f79SBryan Cantrill 33617c478bd9Sstevel@tonic-gate free(cip->vbuf); 33627c478bd9Sstevel@tonic-gate 3363870ad75aSSean Wilcox if (err->type != 0) { 33647c478bd9Sstevel@tonic-gate restarter_free_method_context(cip); 3365870ad75aSSean Wilcox } else { 3366870ad75aSSean Wilcox restarter_mc_error_destroy(err); 3367870ad75aSSean Wilcox err = NULL; 3368870ad75aSSean Wilcox } 33697c478bd9Sstevel@tonic-gate 3370870ad75aSSean Wilcox return (err); 33717c478bd9Sstevel@tonic-gate } 33727c478bd9Sstevel@tonic-gate 33737c478bd9Sstevel@tonic-gate /* 33747c478bd9Sstevel@tonic-gate * Modify the current process per the given method_context. On success, returns 33757c478bd9Sstevel@tonic-gate * 0. Note that the environment is not modified by this function to include the 33767c478bd9Sstevel@tonic-gate * environment variables in cip->env. 33777c478bd9Sstevel@tonic-gate * 33787c478bd9Sstevel@tonic-gate * On failure, sets *fp to NULL or the name of the function which failed, 33797c478bd9Sstevel@tonic-gate * and returns one of the following error codes. The words in parentheses are 33807c478bd9Sstevel@tonic-gate * the values to which *fp may be set for the error case. 33817c478bd9Sstevel@tonic-gate * ENOMEM - malloc() failed 33827c478bd9Sstevel@tonic-gate * EIO - an I/O error occurred (getpwuid_r, chdir) 33837c478bd9Sstevel@tonic-gate * EMFILE - process is out of file descriptors (getpwuid_r) 33847c478bd9Sstevel@tonic-gate * ENFILE - system is out of file handles (getpwuid_r) 33857c478bd9Sstevel@tonic-gate * EINVAL - gid or egid is out of range (setregid) 33867c478bd9Sstevel@tonic-gate * ngroups is too big (setgroups) 33877c478bd9Sstevel@tonic-gate * project's project id is bad (setproject) 33887c478bd9Sstevel@tonic-gate * uid or euid is out of range (setreuid) 33893ad28c1eSrm88369 * poolname is invalid (pool_set_binding) 33907c478bd9Sstevel@tonic-gate * EPERM - insufficient privilege (setregid, initgroups, setgroups, setppriv, 33917c478bd9Sstevel@tonic-gate * setproject, setreuid, settaskid) 33927c478bd9Sstevel@tonic-gate * ENOENT - uid has a passwd entry but no shadow entry 33937c478bd9Sstevel@tonic-gate * working_dir does not exist (chdir) 33947c478bd9Sstevel@tonic-gate * uid has no passwd entry 33957c478bd9Sstevel@tonic-gate * the pool could not be found (pool_set_binding) 33967c478bd9Sstevel@tonic-gate * EFAULT - lpriv_set or priv_set has a bad address (setppriv) 33977c478bd9Sstevel@tonic-gate * working_dir has a bad address (chdir) 33987c478bd9Sstevel@tonic-gate * EACCES - could not access working_dir (chdir) 33997c478bd9Sstevel@tonic-gate * in a TASK_FINAL task (setproject, settaskid) 34007c478bd9Sstevel@tonic-gate * no resource pool accepting default binding exists (setproject) 34017c478bd9Sstevel@tonic-gate * ELOOP - too many symbolic links in working_dir (chdir) 34027c478bd9Sstevel@tonic-gate * ENAMETOOLONG - working_dir is too long (chdir) 34037c478bd9Sstevel@tonic-gate * ENOLINK - working_dir is on an inaccessible remote machine (chdir) 34047c478bd9Sstevel@tonic-gate * ENOTDIR - working_dir is not a directory (chdir) 34057c478bd9Sstevel@tonic-gate * ESRCH - uid is not a user of project (setproject) 34067c478bd9Sstevel@tonic-gate * project is invalid (setproject) 34077c478bd9Sstevel@tonic-gate * the resource pool specified for project is unknown (setproject) 34087c478bd9Sstevel@tonic-gate * EBADF - the configuration for the pool is invalid (pool_set_binding) 34097c478bd9Sstevel@tonic-gate * -1 - core_set_process_path() failed (core_set_process_path) 34107c478bd9Sstevel@tonic-gate * a resource control assignment failed (setproject) 34117c478bd9Sstevel@tonic-gate * a system error occurred during pool_set_binding (pool_set_binding) 34127c478bd9Sstevel@tonic-gate */ 34137c478bd9Sstevel@tonic-gate int 34147c478bd9Sstevel@tonic-gate restarter_set_method_context(struct method_context *cip, const char **fp) 34157c478bd9Sstevel@tonic-gate { 34167c478bd9Sstevel@tonic-gate pid_t mypid = -1; 34177c478bd9Sstevel@tonic-gate int r, ret; 34187c478bd9Sstevel@tonic-gate 34197c478bd9Sstevel@tonic-gate cip->pwbuf = NULL; 34207c478bd9Sstevel@tonic-gate *fp = NULL; 34217c478bd9Sstevel@tonic-gate 3422f48205beScasper if (cip->gid != (gid_t)-1) { 34237c478bd9Sstevel@tonic-gate if (setregid(cip->gid, 3424f48205beScasper cip->egid != (gid_t)-1 ? cip->egid : cip->gid) != 0) { 34257c478bd9Sstevel@tonic-gate *fp = "setregid"; 34267c478bd9Sstevel@tonic-gate 34277c478bd9Sstevel@tonic-gate ret = errno; 34287c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 34297c478bd9Sstevel@tonic-gate goto out; 34307c478bd9Sstevel@tonic-gate } 34317c478bd9Sstevel@tonic-gate } else { 34327c478bd9Sstevel@tonic-gate if (cip->pwbuf == NULL) { 34337c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 34347c478bd9Sstevel@tonic-gate case 0: 34357c478bd9Sstevel@tonic-gate break; 34367c478bd9Sstevel@tonic-gate 34377c478bd9Sstevel@tonic-gate case ENOMEM: 34387c478bd9Sstevel@tonic-gate case ENOENT: 34397c478bd9Sstevel@tonic-gate *fp = NULL; 34407c478bd9Sstevel@tonic-gate goto out; 34417c478bd9Sstevel@tonic-gate 34427c478bd9Sstevel@tonic-gate case EIO: 34437c478bd9Sstevel@tonic-gate case EMFILE: 34447c478bd9Sstevel@tonic-gate case ENFILE: 34457c478bd9Sstevel@tonic-gate *fp = "getpwuid_r"; 34467c478bd9Sstevel@tonic-gate goto out; 34477c478bd9Sstevel@tonic-gate 34487c478bd9Sstevel@tonic-gate default: 34497c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 34507c478bd9Sstevel@tonic-gate } 34517c478bd9Sstevel@tonic-gate } 34527c478bd9Sstevel@tonic-gate 34537c478bd9Sstevel@tonic-gate if (setregid(cip->pwd.pw_gid, 3454f48205beScasper cip->egid != (gid_t)-1 ? 3455f48205beScasper cip->egid : cip->pwd.pw_gid) != 0) { 34567c478bd9Sstevel@tonic-gate *fp = "setregid"; 34577c478bd9Sstevel@tonic-gate 34587c478bd9Sstevel@tonic-gate ret = errno; 34597c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 34607c478bd9Sstevel@tonic-gate goto out; 34617c478bd9Sstevel@tonic-gate } 34627c478bd9Sstevel@tonic-gate } 34637c478bd9Sstevel@tonic-gate 34647c478bd9Sstevel@tonic-gate if (cip->ngroups == -1) { 34657c478bd9Sstevel@tonic-gate if (cip->pwbuf == NULL) { 34667c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 34677c478bd9Sstevel@tonic-gate case 0: 34687c478bd9Sstevel@tonic-gate break; 34697c478bd9Sstevel@tonic-gate 34707c478bd9Sstevel@tonic-gate case ENOMEM: 34717c478bd9Sstevel@tonic-gate case ENOENT: 34727c478bd9Sstevel@tonic-gate *fp = NULL; 34737c478bd9Sstevel@tonic-gate goto out; 34747c478bd9Sstevel@tonic-gate 34757c478bd9Sstevel@tonic-gate case EIO: 34767c478bd9Sstevel@tonic-gate case EMFILE: 34777c478bd9Sstevel@tonic-gate case ENFILE: 34787c478bd9Sstevel@tonic-gate *fp = "getpwuid_r"; 34797c478bd9Sstevel@tonic-gate goto out; 34807c478bd9Sstevel@tonic-gate 34817c478bd9Sstevel@tonic-gate default: 34827c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 34837c478bd9Sstevel@tonic-gate } 34847c478bd9Sstevel@tonic-gate } 34857c478bd9Sstevel@tonic-gate 34867c478bd9Sstevel@tonic-gate /* Ok if cip->gid == -1 */ 34877c478bd9Sstevel@tonic-gate if (initgroups(cip->pwd.pw_name, cip->gid) != 0) { 34887c478bd9Sstevel@tonic-gate *fp = "initgroups"; 34897c478bd9Sstevel@tonic-gate ret = errno; 34907c478bd9Sstevel@tonic-gate assert(ret == EPERM); 34917c478bd9Sstevel@tonic-gate goto out; 34927c478bd9Sstevel@tonic-gate } 34937c478bd9Sstevel@tonic-gate } else if (cip->ngroups > 0 && 34947c478bd9Sstevel@tonic-gate setgroups(cip->ngroups, cip->groups) != 0) { 34957c478bd9Sstevel@tonic-gate *fp = "setgroups"; 34967c478bd9Sstevel@tonic-gate 34977c478bd9Sstevel@tonic-gate ret = errno; 34987c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 34997c478bd9Sstevel@tonic-gate goto out; 35007c478bd9Sstevel@tonic-gate } 35017c478bd9Sstevel@tonic-gate 35027c478bd9Sstevel@tonic-gate if (cip->corefile_pattern != NULL) { 35037c478bd9Sstevel@tonic-gate mypid = getpid(); 35047c478bd9Sstevel@tonic-gate 35057c478bd9Sstevel@tonic-gate if (core_set_process_path(cip->corefile_pattern, 35067c478bd9Sstevel@tonic-gate strlen(cip->corefile_pattern) + 1, mypid) != 0) { 35077c478bd9Sstevel@tonic-gate *fp = "core_set_process_path"; 35087c478bd9Sstevel@tonic-gate ret = -1; 35097c478bd9Sstevel@tonic-gate goto out; 35107c478bd9Sstevel@tonic-gate } 35117c478bd9Sstevel@tonic-gate } 35127c478bd9Sstevel@tonic-gate 35137c478bd9Sstevel@tonic-gate if (restarter_rm_libs_loadable()) { 35147c478bd9Sstevel@tonic-gate if (cip->project == NULL) { 35157c478bd9Sstevel@tonic-gate if (settaskid(getprojid(), TASK_NORMAL) == -1) { 35167c478bd9Sstevel@tonic-gate switch (errno) { 35177c478bd9Sstevel@tonic-gate case EACCES: 35187c478bd9Sstevel@tonic-gate case EPERM: 35197c478bd9Sstevel@tonic-gate *fp = "settaskid"; 35207c478bd9Sstevel@tonic-gate ret = errno; 35217c478bd9Sstevel@tonic-gate goto out; 35227c478bd9Sstevel@tonic-gate 35237c478bd9Sstevel@tonic-gate case EINVAL: 35247c478bd9Sstevel@tonic-gate default: 35257c478bd9Sstevel@tonic-gate bad_fail("settaskid", errno); 35267c478bd9Sstevel@tonic-gate } 35277c478bd9Sstevel@tonic-gate } 35287c478bd9Sstevel@tonic-gate } else { 35297c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 35307c478bd9Sstevel@tonic-gate case 0: 35317c478bd9Sstevel@tonic-gate break; 35327c478bd9Sstevel@tonic-gate 35337c478bd9Sstevel@tonic-gate case ENOMEM: 35347c478bd9Sstevel@tonic-gate case ENOENT: 35357c478bd9Sstevel@tonic-gate *fp = NULL; 35367c478bd9Sstevel@tonic-gate goto out; 35377c478bd9Sstevel@tonic-gate 35387c478bd9Sstevel@tonic-gate case EIO: 35397c478bd9Sstevel@tonic-gate case EMFILE: 35407c478bd9Sstevel@tonic-gate case ENFILE: 35417c478bd9Sstevel@tonic-gate *fp = "getpwuid_r"; 35427c478bd9Sstevel@tonic-gate goto out; 35437c478bd9Sstevel@tonic-gate 35447c478bd9Sstevel@tonic-gate default: 35457c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 35467c478bd9Sstevel@tonic-gate } 35477c478bd9Sstevel@tonic-gate 35487c478bd9Sstevel@tonic-gate *fp = "setproject"; 35497c478bd9Sstevel@tonic-gate 35507c478bd9Sstevel@tonic-gate switch (setproject(cip->project, cip->pwd.pw_name, 35517c478bd9Sstevel@tonic-gate TASK_NORMAL)) { 35527c478bd9Sstevel@tonic-gate case 0: 35537c478bd9Sstevel@tonic-gate break; 35547c478bd9Sstevel@tonic-gate 35557c478bd9Sstevel@tonic-gate case SETPROJ_ERR_TASK: 35567c478bd9Sstevel@tonic-gate case SETPROJ_ERR_POOL: 35577c478bd9Sstevel@tonic-gate ret = errno; 35587c478bd9Sstevel@tonic-gate goto out; 35597c478bd9Sstevel@tonic-gate 35607c478bd9Sstevel@tonic-gate default: 35617c478bd9Sstevel@tonic-gate ret = -1; 35627c478bd9Sstevel@tonic-gate goto out; 35637c478bd9Sstevel@tonic-gate } 35647c478bd9Sstevel@tonic-gate } 35657c478bd9Sstevel@tonic-gate 35667c478bd9Sstevel@tonic-gate if (cip->resource_pool != NULL) { 35677c478bd9Sstevel@tonic-gate if (mypid == -1) 35687c478bd9Sstevel@tonic-gate mypid = getpid(); 35697c478bd9Sstevel@tonic-gate 35707c478bd9Sstevel@tonic-gate *fp = "pool_set_binding"; 35717c478bd9Sstevel@tonic-gate 35727c478bd9Sstevel@tonic-gate if (pool_set_binding(cip->resource_pool, P_PID, 35737c478bd9Sstevel@tonic-gate mypid) != PO_SUCCESS) { 35747c478bd9Sstevel@tonic-gate switch (pool_error()) { 35753ad28c1eSrm88369 case POE_INVALID_SEARCH: 35767c478bd9Sstevel@tonic-gate ret = ENOENT; 35777c478bd9Sstevel@tonic-gate break; 35787c478bd9Sstevel@tonic-gate 35793ad28c1eSrm88369 case POE_BADPARAM: 35803ad28c1eSrm88369 ret = EINVAL; 35813ad28c1eSrm88369 break; 35823ad28c1eSrm88369 35837c478bd9Sstevel@tonic-gate case POE_INVALID_CONF: 35847c478bd9Sstevel@tonic-gate ret = EBADF; 35857c478bd9Sstevel@tonic-gate break; 35867c478bd9Sstevel@tonic-gate 35877c478bd9Sstevel@tonic-gate case POE_SYSTEM: 35887c478bd9Sstevel@tonic-gate ret = -1; 35897c478bd9Sstevel@tonic-gate break; 35907c478bd9Sstevel@tonic-gate 35917c478bd9Sstevel@tonic-gate default: 35927c478bd9Sstevel@tonic-gate bad_fail("pool_set_binding", 35937c478bd9Sstevel@tonic-gate pool_error()); 35947c478bd9Sstevel@tonic-gate } 35957c478bd9Sstevel@tonic-gate 35967c478bd9Sstevel@tonic-gate goto out; 35977c478bd9Sstevel@tonic-gate } 35987c478bd9Sstevel@tonic-gate } 35997c478bd9Sstevel@tonic-gate } 36007c478bd9Sstevel@tonic-gate 36017c478bd9Sstevel@tonic-gate /* 36022a3221a4Svp157776 * Now, we have to assume our ID. If the UID is 0, we want it to be 36032a3221a4Svp157776 * privilege-aware, otherwise the limit set gets used instead of E/P. 36047c478bd9Sstevel@tonic-gate * We can do this by setting P as well, which keeps 36057c478bd9Sstevel@tonic-gate * PA status (see priv_can_clear_PA()). 36067c478bd9Sstevel@tonic-gate */ 36077c478bd9Sstevel@tonic-gate 360813d8aaa1SSean Wilcox *fp = "setppriv"; 360913d8aaa1SSean Wilcox 361013d8aaa1SSean Wilcox if (cip->lpriv_set != NULL) { 361113d8aaa1SSean Wilcox if (setppriv(PRIV_SET, PRIV_LIMIT, cip->lpriv_set) != 0) { 361213d8aaa1SSean Wilcox ret = errno; 361313d8aaa1SSean Wilcox assert(ret == EFAULT || ret == EPERM); 361413d8aaa1SSean Wilcox goto out; 361513d8aaa1SSean Wilcox } 361613d8aaa1SSean Wilcox } 361713d8aaa1SSean Wilcox if (cip->priv_set != NULL) { 361813d8aaa1SSean Wilcox if (setppriv(PRIV_SET, PRIV_INHERITABLE, cip->priv_set) != 0) { 361913d8aaa1SSean Wilcox ret = errno; 362013d8aaa1SSean Wilcox assert(ret == EFAULT || ret == EPERM); 362113d8aaa1SSean Wilcox goto out; 362213d8aaa1SSean Wilcox } 362313d8aaa1SSean Wilcox } 362413d8aaa1SSean Wilcox 362513d8aaa1SSean Wilcox /* 362613d8aaa1SSean Wilcox * If the limit privset is already set, then must be privilege 362713d8aaa1SSean Wilcox * aware. Otherwise, don't assume anything, and force privilege 362813d8aaa1SSean Wilcox * aware status. 362913d8aaa1SSean Wilcox */ 363013d8aaa1SSean Wilcox 363113d8aaa1SSean Wilcox if (cip->lpriv_set == NULL && cip->priv_set != NULL) { 363213d8aaa1SSean Wilcox ret = setpflags(PRIV_AWARE, 1); 363313d8aaa1SSean Wilcox assert(ret == 0); 363413d8aaa1SSean Wilcox } 363513d8aaa1SSean Wilcox 36367c478bd9Sstevel@tonic-gate *fp = "setreuid"; 3637f48205beScasper if (setreuid(cip->uid, 3638f48205beScasper cip->euid != (uid_t)-1 ? cip->euid : cip->uid) != 0) { 36397c478bd9Sstevel@tonic-gate ret = errno; 36407c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 36417c478bd9Sstevel@tonic-gate goto out; 36427c478bd9Sstevel@tonic-gate } 36437c478bd9Sstevel@tonic-gate 36447c478bd9Sstevel@tonic-gate *fp = "setppriv"; 36457c478bd9Sstevel@tonic-gate if (cip->priv_set != NULL) { 36467c478bd9Sstevel@tonic-gate if (setppriv(PRIV_SET, PRIV_PERMITTED, cip->priv_set) != 0) { 36477c478bd9Sstevel@tonic-gate ret = errno; 36487c478bd9Sstevel@tonic-gate assert(ret == EFAULT || ret == EPERM); 36497c478bd9Sstevel@tonic-gate goto out; 36507c478bd9Sstevel@tonic-gate } 36517c478bd9Sstevel@tonic-gate } 36527c478bd9Sstevel@tonic-gate 36532a3221a4Svp157776 /* 36542a3221a4Svp157776 * The last thing to do is chdir to the specified working directory. 36552a3221a4Svp157776 * This should come after the uid switching as only the user might 36562a3221a4Svp157776 * have access to the specified directory. 36572a3221a4Svp157776 */ 36582a3221a4Svp157776 if (cip->working_dir != NULL) { 36593eae19d9Swesolows do { 36602a3221a4Svp157776 r = chdir(cip->working_dir); 36613eae19d9Swesolows } while (r != 0 && errno == EINTR); 36622a3221a4Svp157776 if (r != 0) { 36632a3221a4Svp157776 *fp = "chdir"; 36642a3221a4Svp157776 ret = errno; 36652a3221a4Svp157776 goto out; 36662a3221a4Svp157776 } 36672a3221a4Svp157776 } 36682a3221a4Svp157776 36697c478bd9Sstevel@tonic-gate ret = 0; 36707c478bd9Sstevel@tonic-gate out: 36717c478bd9Sstevel@tonic-gate free(cip->pwbuf); 36727c478bd9Sstevel@tonic-gate cip->pwbuf = NULL; 36737c478bd9Sstevel@tonic-gate return (ret); 36747c478bd9Sstevel@tonic-gate } 36757c478bd9Sstevel@tonic-gate 36767c478bd9Sstevel@tonic-gate void 36777c478bd9Sstevel@tonic-gate restarter_free_method_context(struct method_context *mcp) 36787c478bd9Sstevel@tonic-gate { 36797c478bd9Sstevel@tonic-gate size_t i; 36807c478bd9Sstevel@tonic-gate 36817c478bd9Sstevel@tonic-gate if (mcp->lpriv_set != NULL) 36827c478bd9Sstevel@tonic-gate priv_freeset(mcp->lpriv_set); 36837c478bd9Sstevel@tonic-gate if (mcp->priv_set != NULL) 36847c478bd9Sstevel@tonic-gate priv_freeset(mcp->priv_set); 36857c478bd9Sstevel@tonic-gate 36867c478bd9Sstevel@tonic-gate if (mcp->env != NULL) { 36877c478bd9Sstevel@tonic-gate for (i = 0; i < mcp->env_sz; i++) 36887c478bd9Sstevel@tonic-gate free(mcp->env[i]); 36897c478bd9Sstevel@tonic-gate free(mcp->env); 36907c478bd9Sstevel@tonic-gate } 36917c478bd9Sstevel@tonic-gate 36927c478bd9Sstevel@tonic-gate free(mcp->working_dir); 36937c478bd9Sstevel@tonic-gate free(mcp->corefile_pattern); 36947c478bd9Sstevel@tonic-gate free(mcp->project); 36957c478bd9Sstevel@tonic-gate free(mcp->resource_pool); 36967c478bd9Sstevel@tonic-gate free(mcp); 36977c478bd9Sstevel@tonic-gate } 36987c478bd9Sstevel@tonic-gate 36997c478bd9Sstevel@tonic-gate /* 37007c478bd9Sstevel@tonic-gate * Method keyword functions 37017c478bd9Sstevel@tonic-gate */ 37027c478bd9Sstevel@tonic-gate 37037c478bd9Sstevel@tonic-gate int 37047c478bd9Sstevel@tonic-gate restarter_is_null_method(const char *meth) 37057c478bd9Sstevel@tonic-gate { 37067c478bd9Sstevel@tonic-gate return (strcmp(meth, MKW_TRUE) == 0); 37077c478bd9Sstevel@tonic-gate } 37087c478bd9Sstevel@tonic-gate 37097c478bd9Sstevel@tonic-gate static int 37107c478bd9Sstevel@tonic-gate is_kill_method(const char *method, const char *kill_str, 37117c478bd9Sstevel@tonic-gate size_t kill_str_len) 37127c478bd9Sstevel@tonic-gate { 37137c478bd9Sstevel@tonic-gate const char *cp; 37147c478bd9Sstevel@tonic-gate int sig; 37157c478bd9Sstevel@tonic-gate 37167c478bd9Sstevel@tonic-gate if (strncmp(method, kill_str, kill_str_len) != 0 || 37177c478bd9Sstevel@tonic-gate (method[kill_str_len] != '\0' && 37187c478bd9Sstevel@tonic-gate !isspace(method[kill_str_len]))) 37197c478bd9Sstevel@tonic-gate return (-1); 37207c478bd9Sstevel@tonic-gate 37217c478bd9Sstevel@tonic-gate cp = method + kill_str_len; 37227c478bd9Sstevel@tonic-gate while (*cp != '\0' && isspace(*cp)) 37237c478bd9Sstevel@tonic-gate ++cp; 37247c478bd9Sstevel@tonic-gate 37257c478bd9Sstevel@tonic-gate if (*cp == '\0') 37267c478bd9Sstevel@tonic-gate return (SIGTERM); 37277c478bd9Sstevel@tonic-gate 37287c478bd9Sstevel@tonic-gate if (*cp != '-') 37297c478bd9Sstevel@tonic-gate return (-1); 37307c478bd9Sstevel@tonic-gate 37317c478bd9Sstevel@tonic-gate return (str2sig(cp + 1, &sig) == 0 ? sig : -1); 37327c478bd9Sstevel@tonic-gate } 37337c478bd9Sstevel@tonic-gate 37347c478bd9Sstevel@tonic-gate int 37357c478bd9Sstevel@tonic-gate restarter_is_kill_proc_method(const char *method) 37367c478bd9Sstevel@tonic-gate { 37377c478bd9Sstevel@tonic-gate return (is_kill_method(method, MKW_KILL_PROC, 37387c478bd9Sstevel@tonic-gate sizeof (MKW_KILL_PROC) - 1)); 37397c478bd9Sstevel@tonic-gate } 37407c478bd9Sstevel@tonic-gate 37417c478bd9Sstevel@tonic-gate int 37427c478bd9Sstevel@tonic-gate restarter_is_kill_method(const char *method) 37437c478bd9Sstevel@tonic-gate { 37447c478bd9Sstevel@tonic-gate return (is_kill_method(method, MKW_KILL, sizeof (MKW_KILL) - 1)); 37457c478bd9Sstevel@tonic-gate } 37467c478bd9Sstevel@tonic-gate 37477c478bd9Sstevel@tonic-gate /* 37487c478bd9Sstevel@tonic-gate * Stubs for now. 37497c478bd9Sstevel@tonic-gate */ 37507c478bd9Sstevel@tonic-gate 37517c478bd9Sstevel@tonic-gate /* ARGSUSED */ 37527c478bd9Sstevel@tonic-gate int 37537c478bd9Sstevel@tonic-gate restarter_event_get_enabled(restarter_event_t *e) 37547c478bd9Sstevel@tonic-gate { 37557c478bd9Sstevel@tonic-gate return (-1); 37567c478bd9Sstevel@tonic-gate } 37577c478bd9Sstevel@tonic-gate 37587c478bd9Sstevel@tonic-gate /* ARGSUSED */ 37597c478bd9Sstevel@tonic-gate uint64_t 37607c478bd9Sstevel@tonic-gate restarter_event_get_seq(restarter_event_t *e) 37617c478bd9Sstevel@tonic-gate { 37627c478bd9Sstevel@tonic-gate return (-1); 37637c478bd9Sstevel@tonic-gate } 37647c478bd9Sstevel@tonic-gate 37657c478bd9Sstevel@tonic-gate /* ARGSUSED */ 37667c478bd9Sstevel@tonic-gate void 37677c478bd9Sstevel@tonic-gate restarter_event_get_time(restarter_event_t *e, hrtime_t *time) 37687c478bd9Sstevel@tonic-gate { 37697c478bd9Sstevel@tonic-gate } 3770eb1a3463STruong Nguyen 3771eb1a3463STruong Nguyen /* 3772eb1a3463STruong Nguyen * Check for and validate fmri specified in restarter_actions/auxiliary_fmri 3773eb1a3463STruong Nguyen * 0 - Success 3774eb1a3463STruong Nguyen * 1 - Failure 3775eb1a3463STruong Nguyen */ 3776eb1a3463STruong Nguyen int 3777eb1a3463STruong Nguyen restarter_inst_validate_ractions_aux_fmri(scf_instance_t *inst) 3778eb1a3463STruong Nguyen { 3779eb1a3463STruong Nguyen scf_handle_t *h; 3780eb1a3463STruong Nguyen scf_propertygroup_t *pg; 3781eb1a3463STruong Nguyen scf_property_t *prop; 3782eb1a3463STruong Nguyen scf_value_t *val; 3783eb1a3463STruong Nguyen char *aux_fmri; 3784eb1a3463STruong Nguyen size_t size = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 3785eb1a3463STruong Nguyen int ret = 1; 3786eb1a3463STruong Nguyen 3787eb1a3463STruong Nguyen if ((aux_fmri = malloc(size)) == NULL) 3788eb1a3463STruong Nguyen return (1); 3789eb1a3463STruong Nguyen 3790eb1a3463STruong Nguyen h = scf_instance_handle(inst); 3791eb1a3463STruong Nguyen 3792eb1a3463STruong Nguyen pg = scf_pg_create(h); 3793eb1a3463STruong Nguyen prop = scf_property_create(h); 3794eb1a3463STruong Nguyen val = scf_value_create(h); 3795eb1a3463STruong Nguyen if (pg == NULL || prop == NULL || val == NULL) 3796eb1a3463STruong Nguyen goto out; 3797eb1a3463STruong Nguyen 3798eb1a3463STruong Nguyen if (instance_get_or_add_pg(inst, SCF_PG_RESTARTER_ACTIONS, 3799eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS_TYPE, SCF_PG_RESTARTER_ACTIONS_FLAGS, 3800eb1a3463STruong Nguyen pg) != SCF_SUCCESS) 3801eb1a3463STruong Nguyen goto out; 3802eb1a3463STruong Nguyen 3803eb1a3463STruong Nguyen if (get_astring_val(pg, SCF_PROPERTY_AUX_FMRI, aux_fmri, size, 3804eb1a3463STruong Nguyen prop, val) != SCF_SUCCESS) 3805eb1a3463STruong Nguyen goto out; 3806eb1a3463STruong Nguyen 3807eb1a3463STruong Nguyen if (scf_parse_fmri(aux_fmri, NULL, NULL, NULL, NULL, NULL, 3808eb1a3463STruong Nguyen NULL) != SCF_SUCCESS) 3809eb1a3463STruong Nguyen goto out; 3810eb1a3463STruong Nguyen 3811eb1a3463STruong Nguyen ret = 0; 3812eb1a3463STruong Nguyen 3813eb1a3463STruong Nguyen out: 3814eb1a3463STruong Nguyen free(aux_fmri); 3815eb1a3463STruong Nguyen scf_value_destroy(val); 3816eb1a3463STruong Nguyen scf_property_destroy(prop); 3817eb1a3463STruong Nguyen scf_pg_destroy(pg); 3818eb1a3463STruong Nguyen return (ret); 3819eb1a3463STruong Nguyen } 3820eb1a3463STruong Nguyen 3821eb1a3463STruong Nguyen /* 3822eb1a3463STruong Nguyen * Get instance's boolean value in restarter_actions/auxiliary_tty 3823eb1a3463STruong Nguyen * Return -1 on failure 3824eb1a3463STruong Nguyen */ 3825eb1a3463STruong Nguyen int 3826eb1a3463STruong Nguyen restarter_inst_ractions_from_tty(scf_instance_t *inst) 3827eb1a3463STruong Nguyen { 3828eb1a3463STruong Nguyen scf_handle_t *h; 3829eb1a3463STruong Nguyen scf_propertygroup_t *pg; 3830eb1a3463STruong Nguyen scf_property_t *prop; 3831eb1a3463STruong Nguyen scf_value_t *val; 3832eb1a3463STruong Nguyen uint8_t has_tty; 3833eb1a3463STruong Nguyen int ret = -1; 3834eb1a3463STruong Nguyen 3835eb1a3463STruong Nguyen h = scf_instance_handle(inst); 3836eb1a3463STruong Nguyen pg = scf_pg_create(h); 3837eb1a3463STruong Nguyen prop = scf_property_create(h); 3838eb1a3463STruong Nguyen val = scf_value_create(h); 3839eb1a3463STruong Nguyen if (pg == NULL || prop == NULL || val == NULL) 3840eb1a3463STruong Nguyen goto out; 3841eb1a3463STruong Nguyen 3842eb1a3463STruong Nguyen if (instance_get_or_add_pg(inst, SCF_PG_RESTARTER_ACTIONS, 3843eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS_TYPE, SCF_PG_RESTARTER_ACTIONS_FLAGS, 3844eb1a3463STruong Nguyen pg) != SCF_SUCCESS) 3845eb1a3463STruong Nguyen goto out; 3846eb1a3463STruong Nguyen 3847eb1a3463STruong Nguyen if (get_boolean_val(pg, SCF_PROPERTY_AUX_TTY, &has_tty, prop, 3848eb1a3463STruong Nguyen val) != SCF_SUCCESS) 3849eb1a3463STruong Nguyen goto out; 3850eb1a3463STruong Nguyen 3851eb1a3463STruong Nguyen ret = has_tty; 3852eb1a3463STruong Nguyen 3853eb1a3463STruong Nguyen out: 3854eb1a3463STruong Nguyen scf_value_destroy(val); 3855eb1a3463STruong Nguyen scf_property_destroy(prop); 3856eb1a3463STruong Nguyen scf_pg_destroy(pg); 3857eb1a3463STruong Nguyen return (ret); 3858eb1a3463STruong Nguyen } 3859eb1a3463STruong Nguyen 3860*ac0324d2SJerry Jelinek /* 3861*ac0324d2SJerry Jelinek * If the instance's dump-on-restart property exists, remove it and return true, 3862*ac0324d2SJerry Jelinek * otherwise return false. 3863*ac0324d2SJerry Jelinek */ 3864*ac0324d2SJerry Jelinek int 3865*ac0324d2SJerry Jelinek restarter_inst_dump(scf_instance_t *inst) 3866*ac0324d2SJerry Jelinek { 3867*ac0324d2SJerry Jelinek scf_handle_t *h; 3868*ac0324d2SJerry Jelinek scf_propertygroup_t *pg; 3869*ac0324d2SJerry Jelinek scf_property_t *prop; 3870*ac0324d2SJerry Jelinek scf_value_t *val; 3871*ac0324d2SJerry Jelinek int ret = 0; 3872*ac0324d2SJerry Jelinek 3873*ac0324d2SJerry Jelinek h = scf_instance_handle(inst); 3874*ac0324d2SJerry Jelinek pg = scf_pg_create(h); 3875*ac0324d2SJerry Jelinek prop = scf_property_create(h); 3876*ac0324d2SJerry Jelinek val = scf_value_create(h); 3877*ac0324d2SJerry Jelinek if (pg == NULL || prop == NULL || val == NULL) 3878*ac0324d2SJerry Jelinek goto out; 3879*ac0324d2SJerry Jelinek 3880*ac0324d2SJerry Jelinek if (scf_instance_get_pg(inst, SCF_PG_RESTARTER_ACTIONS, pg) != 3881*ac0324d2SJerry Jelinek SCF_SUCCESS) { 3882*ac0324d2SJerry Jelinek if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 3883*ac0324d2SJerry Jelinek uu_die(rcbroken); 3884*ac0324d2SJerry Jelinek goto out; 3885*ac0324d2SJerry Jelinek } 3886*ac0324d2SJerry Jelinek 3887*ac0324d2SJerry Jelinek if (scf_pg_get_property(pg, SCF_PROPERTY_DODUMP, prop) != SCF_SUCCESS) { 3888*ac0324d2SJerry Jelinek if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 3889*ac0324d2SJerry Jelinek uu_die(rcbroken); 3890*ac0324d2SJerry Jelinek goto out; 3891*ac0324d2SJerry Jelinek } 3892*ac0324d2SJerry Jelinek 3893*ac0324d2SJerry Jelinek ret = 1; 3894*ac0324d2SJerry Jelinek 3895*ac0324d2SJerry Jelinek if (scf_instance_delete_prop(inst, SCF_PG_RESTARTER_ACTIONS, 3896*ac0324d2SJerry Jelinek SCF_PROPERTY_DODUMP) != SCF_SUCCESS) { 3897*ac0324d2SJerry Jelinek if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 3898*ac0324d2SJerry Jelinek uu_die(rcbroken); 3899*ac0324d2SJerry Jelinek goto out; 3900*ac0324d2SJerry Jelinek } 3901*ac0324d2SJerry Jelinek 3902*ac0324d2SJerry Jelinek out: 3903*ac0324d2SJerry Jelinek scf_value_destroy(val); 3904*ac0324d2SJerry Jelinek scf_property_destroy(prop); 3905*ac0324d2SJerry Jelinek scf_pg_destroy(pg); 3906*ac0324d2SJerry Jelinek return (ret); 3907*ac0324d2SJerry Jelinek } 3908*ac0324d2SJerry Jelinek 3909eb1a3463STruong Nguyen static int 3910eb1a3463STruong Nguyen restarter_inst_set_astring_prop(scf_instance_t *inst, const char *pgname, 3911eb1a3463STruong Nguyen const char *pgtype, uint32_t pgflags, const char *pname, const char *str) 3912eb1a3463STruong Nguyen { 3913eb1a3463STruong Nguyen scf_handle_t *h; 3914eb1a3463STruong Nguyen scf_propertygroup_t *pg; 3915eb1a3463STruong Nguyen scf_transaction_t *t; 3916eb1a3463STruong Nguyen scf_transaction_entry_t *e; 3917eb1a3463STruong Nguyen scf_value_t *v; 3918eb1a3463STruong Nguyen int ret = 1, r; 3919eb1a3463STruong Nguyen 3920eb1a3463STruong Nguyen h = scf_instance_handle(inst); 3921eb1a3463STruong Nguyen 3922eb1a3463STruong Nguyen pg = scf_pg_create(h); 3923eb1a3463STruong Nguyen t = scf_transaction_create(h); 3924eb1a3463STruong Nguyen e = scf_entry_create(h); 3925eb1a3463STruong Nguyen v = scf_value_create(h); 3926eb1a3463STruong Nguyen if (pg == NULL || t == NULL || e == NULL || v == NULL) 3927eb1a3463STruong Nguyen goto out; 3928eb1a3463STruong Nguyen 3929eb1a3463STruong Nguyen if (instance_get_or_add_pg(inst, pgname, pgtype, pgflags, pg)) 3930eb1a3463STruong Nguyen goto out; 3931eb1a3463STruong Nguyen 3932eb1a3463STruong Nguyen if (scf_value_set_astring(v, str) != SCF_SUCCESS) 3933eb1a3463STruong Nguyen goto out; 3934eb1a3463STruong Nguyen 3935eb1a3463STruong Nguyen for (;;) { 3936eb1a3463STruong Nguyen if (scf_transaction_start(t, pg) != 0) 3937eb1a3463STruong Nguyen goto out; 3938eb1a3463STruong Nguyen 3939eb1a3463STruong Nguyen if (tx_set_value(t, e, pname, SCF_TYPE_ASTRING, v) != 0) 3940eb1a3463STruong Nguyen goto out; 3941eb1a3463STruong Nguyen 3942eb1a3463STruong Nguyen if ((r = scf_transaction_commit(t)) == 1) 3943eb1a3463STruong Nguyen break; 3944eb1a3463STruong Nguyen 3945eb1a3463STruong Nguyen if (r == -1) 3946eb1a3463STruong Nguyen goto out; 3947eb1a3463STruong Nguyen 3948eb1a3463STruong Nguyen scf_transaction_reset(t); 3949eb1a3463STruong Nguyen if (scf_pg_update(pg) == -1) 3950eb1a3463STruong Nguyen goto out; 3951eb1a3463STruong Nguyen } 3952eb1a3463STruong Nguyen ret = 0; 3953eb1a3463STruong Nguyen 3954eb1a3463STruong Nguyen out: 3955eb1a3463STruong Nguyen scf_transaction_destroy(t); 3956eb1a3463STruong Nguyen scf_entry_destroy(e); 3957eb1a3463STruong Nguyen scf_value_destroy(v); 3958eb1a3463STruong Nguyen scf_pg_destroy(pg); 3959eb1a3463STruong Nguyen 3960eb1a3463STruong Nguyen return (ret); 3961eb1a3463STruong Nguyen } 3962eb1a3463STruong Nguyen 3963eb1a3463STruong Nguyen int 3964eb1a3463STruong Nguyen restarter_inst_set_aux_fmri(scf_instance_t *inst) 3965eb1a3463STruong Nguyen { 3966eb1a3463STruong Nguyen scf_handle_t *h; 3967eb1a3463STruong Nguyen scf_propertygroup_t *pg; 3968eb1a3463STruong Nguyen scf_property_t *prop; 3969eb1a3463STruong Nguyen scf_value_t *val; 3970eb1a3463STruong Nguyen char *aux_fmri; 3971eb1a3463STruong Nguyen size_t size = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 3972eb1a3463STruong Nguyen int ret = 1; 3973eb1a3463STruong Nguyen 3974eb1a3463STruong Nguyen if ((aux_fmri = malloc(size)) == NULL) 3975eb1a3463STruong Nguyen return (1); 3976eb1a3463STruong Nguyen 3977eb1a3463STruong Nguyen h = scf_instance_handle(inst); 3978eb1a3463STruong Nguyen 3979eb1a3463STruong Nguyen pg = scf_pg_create(h); 3980eb1a3463STruong Nguyen prop = scf_property_create(h); 3981eb1a3463STruong Nguyen val = scf_value_create(h); 3982eb1a3463STruong Nguyen if (pg == NULL || prop == NULL || val == NULL) 3983eb1a3463STruong Nguyen goto out; 3984eb1a3463STruong Nguyen 3985eb1a3463STruong Nguyen /* 3986eb1a3463STruong Nguyen * Get auxiliary_fmri value from restarter_actions pg 3987eb1a3463STruong Nguyen */ 3988eb1a3463STruong Nguyen if (instance_get_or_add_pg(inst, SCF_PG_RESTARTER_ACTIONS, 3989eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS_TYPE, SCF_PG_RESTARTER_ACTIONS_FLAGS, 3990eb1a3463STruong Nguyen pg) != SCF_SUCCESS) 3991eb1a3463STruong Nguyen goto out; 3992eb1a3463STruong Nguyen 3993eb1a3463STruong Nguyen if (get_astring_val(pg, SCF_PROPERTY_AUX_FMRI, aux_fmri, size, 3994eb1a3463STruong Nguyen prop, val) != SCF_SUCCESS) 3995eb1a3463STruong Nguyen goto out; 3996eb1a3463STruong Nguyen 3997eb1a3463STruong Nguyen /* 3998eb1a3463STruong Nguyen * Populate restarter/auxiliary_fmri with the obtained fmri. 3999eb1a3463STruong Nguyen */ 4000eb1a3463STruong Nguyen ret = restarter_inst_set_astring_prop(inst, SCF_PG_RESTARTER, 4001eb1a3463STruong Nguyen SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, 4002eb1a3463STruong Nguyen SCF_PROPERTY_AUX_FMRI, aux_fmri); 4003eb1a3463STruong Nguyen 4004eb1a3463STruong Nguyen out: 4005eb1a3463STruong Nguyen free(aux_fmri); 4006eb1a3463STruong Nguyen scf_value_destroy(val); 4007eb1a3463STruong Nguyen scf_property_destroy(prop); 4008eb1a3463STruong Nguyen scf_pg_destroy(pg); 4009eb1a3463STruong Nguyen return (ret); 4010eb1a3463STruong Nguyen } 4011eb1a3463STruong Nguyen 4012eb1a3463STruong Nguyen int 4013eb1a3463STruong Nguyen restarter_inst_reset_aux_fmri(scf_instance_t *inst) 4014eb1a3463STruong Nguyen { 4015eb1a3463STruong Nguyen return (scf_instance_delete_prop(inst, 4016eb1a3463STruong Nguyen SCF_PG_RESTARTER, SCF_PROPERTY_AUX_FMRI)); 4017eb1a3463STruong Nguyen } 4018eb1a3463STruong Nguyen 4019eb1a3463STruong Nguyen int 4020eb1a3463STruong Nguyen restarter_inst_reset_ractions_aux_fmri(scf_instance_t *inst) 4021eb1a3463STruong Nguyen { 4022eb1a3463STruong Nguyen return (scf_instance_delete_prop(inst, 4023eb1a3463STruong Nguyen SCF_PG_RESTARTER_ACTIONS, SCF_PROPERTY_AUX_FMRI)); 4024eb1a3463STruong Nguyen } 4025