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