1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2015, Joyent, Inc.
  25  */
  26 
  27 /*
  28  * startd.c - the master restarter
  29  *
  30  * svc.startd comprises two halves.  The graph engine is based in graph.c and
  31  * maintains the service dependency graph based on the information in the
  32  * repository.  For each service it also tracks the current state and the
  33  * restarter responsible for the service.  Based on the graph, events from the
  34  * repository (mostly administrative requests from svcadm), and messages from
  35  * the restarters, the graph engine makes decisions about how the services
  36  * should be manipulated and sends commands to the appropriate restarters.
  37  * Communication between the graph engine and the restarters is embodied in
  38  * protocol.c.
  39  *
  40  * The second half of svc.startd is the restarter for services managed by
  41  * svc.startd and is primarily contained in restarter.c.  It responds to graph
  42  * engine commands by executing methods, updating the repository, and sending
  43  * feedback (mostly state updates) to the graph engine.
  44  *
  45  * Overview of the SMF Architecture
  46  *
  47  * There are a few different components that make up SMF and are responsible
  48  * for different pieces of functionality that are used:
  49  *
  50  * svc.startd(1M): A daemon that is in charge of starting, stopping, and
  51  *     restarting services and instances.
  52  * svc.configd(1M): A daemon that manages the repository that stores
  53  *     information, property groups, and state of the different services and
  54  *     instances.
  55  * libscf(3LIB): A C library that provides the glue for communicating,
  56  *     accessing, and updating information about services and instances.
  57  * svccfg(1M): A utility to add and remove services as well as change the
  58  *     properties associated with different services and instances.
  59  * svcadm(1M): A utility to control the different instance of a service. You
  60  *     can use this to enable and disable them among some other useful things.
  61  * svcs(1): A utility that reports on the status of various services on the
  62  *     system.
  63  *
  64  * The following block diagram explains how these components communicate:
  65  *
  66  * The SMF Block Diagram
  67  *                                                       Repository
  68  *   This attempts to show       +---------+             +--------+
  69  *   the relations between       |         |     SQL     |        |
  70  *   the different pieces        | configd |<----------->| SQLite |
  71  *   that make SMF work and      |         | Transaction |        |
  72  *   users/administrators        +---------+             +--------+
  73  *   call into.                   ^      ^
  74  *                                |      |
  75  *                   door_call(3C)|      | door_call(3C)
  76  *                                |      |
  77  *                                v      v
  78  *      +----------+     +--------+      +--------+      +----------+
  79  *      |          |     |        |      |        |      |  svccfg  |
  80  *      |  startd  |<--->| libscf |      | libscf |<---->|  svcadm  |
  81  *      |          |     | (3LIB) |      | (3LIB) |      |   svcs   |
  82  *      +----------+     +--------+      +--------+      +----------+
  83  *        ^      ^
  84  *        |      | fork(2)/exec(2)
  85  *        |      | libcontract(3LIB)
  86  *        v      v                           Various System/User services
  87  *       +-------------------------------------------------------------------+
  88  *       | system/filesystem/local:default      system/coreadm:default       |
  89  *       | network/loopback:default             system/zones:default         |
  90  *       | milestone/multi-user:default         system/cron:default          |
  91  *       | system/console-login:default         network/ssh:default          |
  92  *       | system/pfexec:default                system/svc/restarter:default |
  93  *       +-------------------------------------------------------------------+
  94  *
  95  * Chatting with Configd and Sharing Repository Information
  96  *
  97  * As you run commands with svcs, svccfg, and svcadm, they are all creating a
  98  * libscf handle to communicate with configd. As calls are made via libscf they
  99  * ultimately go and talk to configd to get information. However, how we
 100  * actually are talking to configd is not as straightforward as it appears.
 101  *
 102  * When configd starts up it creates a door located at
 103  * /etc/svc/volatile/repository_door. This door runs the routine called
 104  * main_switcher() from usr/src/cmd/svc/configd/maindoor.c. When you first
 105  * invoke svc(cfg|s|adm), one of the first things that occurs is creating a
 106  * scf_handle_t and binding it to configd by calling scf_handle_bind(). This
 107  * function makes a door call to configd and gets returned a new file
 108  * descriptor. This file descriptor is itself another door which calls into
 109  * configd's client_switcher(). This is the door that is actually used when
 110  * getting and fetching properties, and many other useful things.
 111  *
 112  * svc.startd needs a way to notice the changes that occur to the repository.
 113  * For example, if you enabled a service that was not previously running, it's
 114  * up to startd to notice that this has happened, check dependencies, and
 115  * eventually start up the service. The way it gets these notifications is via
 116  * a thread who's sole purpose in life is to call _scf_notify_wait(). This
 117  * function acts like poll(2) but for changes that occur in the repository.
 118  * Once this thread gets the event, it dispatches the event appropriately.
 119  *
 120  * The Events of svc.startd
 121  *
 122  * svc.startd has to handle a lot of complexity. Understanding how you go from
 123  * getting the notification that a service was enabled to actually enabling it
 124  * is not obvious from a cursory glance. The first thing to keep in mind is
 125  * that startd maintains a graph of all the related services and instances so
 126  * it can keep track of what is enabled, what dependencies exist, etc. all so
 127  * that it can answer the question of what is affected by a change. Internally
 128  * there are a lot of different queues for events, threads to process these
 129  * queues, and different paths to have events enter these queues. What follows
 130  * is a diagram that attempts to explain some of those paths, though it's
 131  * important to note that for some of these pieces, such as the graph and
 132  * vertex events, there are many additional ways and code paths these threads
 133  * and functions can take. And yes, restarter_event_enqueue() is not the same
 134  * thing as restarter_queue_event().
 135  *
 136  *   Threads/Functions                 Queues                  Threads/Functions
 137  *
 138  * called by various
 139  *     +----------------+             +-------+                  +-------------+
 140  * --->| graph_protocol | graph_event | graph |   graph_event_   | graph_event |
 141  * --->| _send_event()  |------------>| event |----------------->| _thread     |
 142  *     +----------------+ _enqueue()  | queue |   dequeue()      +-------------+
 143  *                                    +-------+                         |
 144  *  _scf_notify_wait()                               vertex_send_event()|
 145  *  |                                                                   v
 146  *  |  +------------------+                              +--------------------+
 147  *  +->| repository_event | vertex_send_event()          | restarter_protocol |
 148  *     | _thread          |----------------------------->| _send_event()      |
 149  *     +------------------+                              +--------------------+
 150  *                                                          |    | out to other
 151  *                restarter_                     restarter_ |    | restarters
 152  *                event_dequeue() +-----------+  event_     |    | not startd
 153  *               +----------------| restarter |<------------+    +------------->
 154  *               v                |   event   |  enqueue()
 155  *      +-----------------+       |   queue   |             +------------------>
 156  *      | restarter_event |       +-----------+             |+----------------->
 157  *      | _thread         |                                 ||+---------------->
 158  *      +-----------------+                                 ||| start/stop inst
 159  *               |               +--------------+       +--------------------+
 160  *               |               |   instance   |       | restarter_process_ |
 161  *               +-------------->|    event     |------>| events             |
 162  *                restarter_     |    queue     |       | per-instance lwp   |
 163  *                queue_event()  +--------------+       +--------------------+
 164  *                                                          ||| various funcs
 165  *                                                          ||| controlling
 166  *                                                          ||| instance state
 167  *                                                          ||+--------------->
 168  *                                                          |+---------------->
 169  *                                                          +----------------->
 170  *
 171  * What's important to take away is that there is a queue for each instance on
 172  * the system that handles events related to dealing directly with that
 173  * instance and that events can be added to it because of changes to properties
 174  * that are made to configd and acted upon asynchronously by startd.
 175  *
 176  * Error handling
 177  *
 178  * In general, when svc.startd runs out of memory it reattempts a few times,
 179  * sleeping inbetween, before giving up and exiting (see startd_alloc_retry()).
 180  * When a repository connection is broken (libscf calls fail with
 181  * SCF_ERROR_CONNECTION_BROKEN, librestart and internal functions return
 182  * ECONNABORTED), svc.startd calls libscf_rebind_handle(), which coordinates
 183  * with the svc.configd-restarting thread, fork_configd_thread(), via
 184  * st->st_configd_live_cv, and rebinds the repository handle.  Doing so resets
 185  * all libscf state associated with that handle, so functions which do this
 186  * should communicate the event to their callers (usually by returning
 187  * ECONNRESET) so they may reset their state appropriately.
 188  *
 189  * External references
 190  *
 191  * svc.configd generates special security audit events for changes to some
 192  * restarter related properties.  See the special_props_list array in
 193  * usr/src/cmd/svc/configd/rc_node.c for the properties that cause these audit
 194  * events.  If you change the semantics of these propereties within startd, you
 195  * will probably need to update rc_node.c
 196  */
 197 
 198 #include <stdio.h>
 199 #include <stdio_ext.h>
 200 #include <sys/mnttab.h>           /* uses FILE * without including stdio.h */
 201 #include <alloca.h>
 202 #include <sys/mount.h>
 203 #include <sys/stat.h>
 204 #include <sys/types.h>
 205 #include <sys/wait.h>
 206 #include <sys/proc.h>
 207 #include <assert.h>
 208 #include <errno.h>
 209 #include <fcntl.h>
 210 #include <ftw.h>
 211 #include <libintl.h>
 212 #include <libscf.h>
 213 #include <libscf_priv.h>
 214 #include <libuutil.h>
 215 #include <locale.h>
 216 #include <poll.h>
 217 #include <pthread.h>
 218 #include <signal.h>
 219 #include <stdarg.h>
 220 #include <stdlib.h>
 221 #include <string.h>
 222 #include <strings.h>
 223 #include <unistd.h>
 224 
 225 #include "startd.h"
 226 #include "protocol.h"
 227 
 228 extern int psecflags(idtype_t, id_t, psecflags_cmd_t, uint_t);
 229 
 230 ssize_t max_scf_name_size;
 231 ssize_t max_scf_fmri_size;
 232 ssize_t max_scf_value_size;
 233 
 234 mode_t fmask;
 235 mode_t dmask;
 236 
 237 graph_update_t *gu;
 238 restarter_update_t *ru;
 239 
 240 startd_state_t *st;
 241 
 242 boolean_t booting_to_single_user = B_FALSE;
 243 
 244 const char * const admin_actions[] = {
 245     SCF_PROPERTY_DEGRADED,
 246     SCF_PROPERTY_MAINT_OFF,
 247     SCF_PROPERTY_MAINT_ON,
 248     SCF_PROPERTY_MAINT_ON_IMMEDIATE,
 249     SCF_PROPERTY_REFRESH,
 250     SCF_PROPERTY_RESTART
 251 };
 252 
 253 const int admin_events[NACTIONS] = {
 254     RESTARTER_EVENT_TYPE_ADMIN_DEGRADED,
 255     RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF,
 256     RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON,
 257     RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON_IMMEDIATE,
 258     RESTARTER_EVENT_TYPE_ADMIN_REFRESH,
 259     RESTARTER_EVENT_TYPE_ADMIN_RESTART
 260 };
 261 
 262 const char * const instance_state_str[] = {
 263         "none",
 264         "uninitialized",
 265         "maintenance",
 266         "offline",
 267         "disabled",
 268         "online",
 269         "degraded"
 270 };
 271 
 272 static int finished = 0;
 273 static int opt_reconfig = 0;
 274 static uint8_t prop_reconfig = 0;
 275 
 276 #define INITIAL_REBIND_ATTEMPTS 5
 277 #define INITIAL_REBIND_DELAY    3
 278 
 279 pthread_mutexattr_t mutex_attrs;
 280 
 281 #ifdef DEBUG
 282 const char *
 283 _umem_debug_init(void)
 284 {
 285         return ("default,verbose");     /* UMEM_DEBUG setting */
 286 }
 287 
 288 const char *
 289 _umem_logging_init(void)
 290 {
 291         return ("fail,contents");       /* UMEM_LOGGING setting */
 292 }
 293 #endif
 294 
 295 const char *
 296 _umem_options_init(void)
 297 {
 298         /*
 299          * To reduce our memory footprint, we set our UMEM_OPTIONS to indicate
 300          * that we do not wish to have per-CPU magazines -- if svc.startd is so
 301          * hot on CPU such that this becomes a scalability problem, there are
 302          * likely deeper things amiss...
 303          */
 304         return ("nomagazines");         /* UMEM_OPTIONS setting */
 305 }
 306 
 307 /*
 308  * startd_alloc_retry()
 309  *   Wrapper for allocation functions.  Retries with a decaying time
 310  *   value on failure to allocate, and aborts startd if failure is
 311  *   persistent.
 312  */
 313 void *
 314 startd_alloc_retry(void *f(size_t, int), size_t sz)
 315 {
 316         void *p;
 317         uint_t try, msecs;
 318 
 319         p = f(sz, UMEM_DEFAULT);
 320         if (p != NULL || sz == 0)
 321                 return (p);
 322 
 323         msecs = ALLOC_DELAY;
 324 
 325         for (try = 0; p == NULL && try < ALLOC_RETRY; ++try) {
 326                 (void) poll(NULL, 0, msecs);
 327                 msecs *= ALLOC_DELAY_MULT;
 328                 p = f(sz, UMEM_DEFAULT);
 329                 if (p != NULL)
 330                         return (p);
 331         }
 332 
 333         uu_die("Insufficient memory.\n");
 334         /* NOTREACHED */
 335 }
 336 
 337 void *
 338 safe_realloc(void *p, size_t sz)
 339 {
 340         uint_t try, msecs;
 341 
 342         p = realloc(p, sz);
 343         if (p != NULL || sz == 0)
 344                 return (p);
 345 
 346         msecs = ALLOC_DELAY;
 347 
 348         for (try = 0; errno == EAGAIN && try < ALLOC_RETRY; ++try) {
 349                 (void) poll(NULL, 0, msecs);
 350                 p = realloc(p, sz);
 351                 if (p != NULL)
 352                         return (p);
 353                 msecs *= ALLOC_DELAY_MULT;
 354         }
 355 
 356         uu_die("Insufficient memory.\n");
 357         /* NOTREACHED */
 358 }
 359 
 360 char *
 361 safe_strdup(const char *s)
 362 {
 363         uint_t try, msecs;
 364         char *d;
 365 
 366         d = strdup(s);
 367         if (d != NULL)
 368                 return (d);
 369 
 370         msecs = ALLOC_DELAY;
 371 
 372         for (try = 0;
 373             (errno == EAGAIN || errno == ENOMEM) && try < ALLOC_RETRY;
 374             ++try) {
 375                 (void) poll(NULL, 0, msecs);
 376                 d = strdup(s);
 377                 if (d != NULL)
 378                         return (d);
 379                 msecs *= ALLOC_DELAY_MULT;
 380         }
 381 
 382         uu_die("Insufficient memory.\n");
 383         /* NOTREACHED */
 384 }
 385 
 386 
 387 void
 388 startd_free(void *p, size_t sz)
 389 {
 390         umem_free(p, sz);
 391 }
 392 
 393 /*
 394  * Creates a uu_list_pool_t with the same retry policy as startd_alloc().
 395  * Only returns NULL for UU_ERROR_UNKNOWN_FLAG and UU_ERROR_NOT_SUPPORTED.
 396  */
 397 uu_list_pool_t *
 398 startd_list_pool_create(const char *name, size_t e, size_t o,
 399     uu_compare_fn_t *f, uint32_t flags)
 400 {
 401         uu_list_pool_t *pool;
 402         uint_t try, msecs;
 403 
 404         pool = uu_list_pool_create(name, e, o, f, flags);
 405         if (pool != NULL)
 406                 return (pool);
 407 
 408         msecs = ALLOC_DELAY;
 409 
 410         for (try = 0; uu_error() == UU_ERROR_NO_MEMORY && try < ALLOC_RETRY;
 411             ++try) {
 412                 (void) poll(NULL, 0, msecs);
 413                 pool = uu_list_pool_create(name, e, o, f, flags);
 414                 if (pool != NULL)
 415                         return (pool);
 416                 msecs *= ALLOC_DELAY_MULT;
 417         }
 418 
 419         if (try < ALLOC_RETRY)
 420                 return (NULL);
 421 
 422         uu_die("Insufficient memory.\n");
 423         /* NOTREACHED */
 424 }
 425 
 426 /*
 427  * Creates a uu_list_t with the same retry policy as startd_alloc().  Only
 428  * returns NULL for UU_ERROR_UNKNOWN_FLAG and UU_ERROR_NOT_SUPPORTED.
 429  */
 430 uu_list_t *
 431 startd_list_create(uu_list_pool_t *pool, void *parent, uint32_t flags)
 432 {
 433         uu_list_t *list;
 434         uint_t try, msecs;
 435 
 436         list = uu_list_create(pool, parent, flags);
 437         if (list != NULL)
 438                 return (list);
 439 
 440         msecs = ALLOC_DELAY;
 441 
 442         for (try = 0; uu_error() == UU_ERROR_NO_MEMORY && try < ALLOC_RETRY;
 443             ++try) {
 444                 (void) poll(NULL, 0, msecs);
 445                 list = uu_list_create(pool, parent, flags);
 446                 if (list != NULL)
 447                         return (list);
 448                 msecs *= ALLOC_DELAY_MULT;
 449         }
 450 
 451         if (try < ALLOC_RETRY)
 452                 return (NULL);
 453 
 454         uu_die("Insufficient memory.\n");
 455         /* NOTREACHED */
 456 }
 457 
 458 pthread_t
 459 startd_thread_create(void *(*func)(void *), void *ptr)
 460 {
 461         int err;
 462         pthread_t tid;
 463 
 464         err = pthread_create(&tid, NULL, func, ptr);
 465         if (err != 0) {
 466                 assert(err == EAGAIN);
 467                 uu_die("Could not create thread.\n");
 468         }
 469 
 470         err = pthread_detach(tid);
 471         assert(err == 0);
 472 
 473         return (tid);
 474 }
 475 
 476 extern int info_events_all;
 477 
 478 struct psf_desc {
 479         char *name;
 480         uint_t flag;
 481 } procsec_flag_tbl[] = {
 482         { "aslr",       PROC_SEC_ASLR },
 483         { NULL, NULL }
 484 };
 485 
 486 static void
 487 init_secflags(scf_handle_t *hndl)
 488 {
 489         scf_property_t *prop;
 490         scf_value_t *val;
 491         struct psf_desc *psfd = NULL;
 492         char *proc_sec_fmri = "svc:/system/process-security/"
 493             ":properties/secflags";
 494 
 495         for (psfd = procsec_flag_tbl; psfd->name != NULL; psfd++) {
 496                 char *pfmri;
 497                 uint8_t flag;
 498 
 499                 prop = safe_scf_property_create(hndl);
 500                 val = safe_scf_value_create(hndl);
 501 
 502                 if ((pfmri = uu_msprintf("%s/%s", proc_sec_fmri, psfd->name)) == NULL)
 503                         uu_die("Allocation failure\n");
 504 
 505                 if (scf_handle_decode_fmri(hndl, pfmri,
 506                     NULL, NULL, NULL, NULL, prop, NULL) != 0)
 507                         goto next;
 508 
 509                 if (scf_property_get_value(prop, val) != 0)
 510                         goto next;
 511 
 512                 (void) scf_value_get_boolean(val, &flag);
 513 
 514                 /*
 515                  * XXX: This will fail if the zone had PRIV_PROC_SECFLAGS
 516                  * removed.
 517                  *
 518                  * I'm not sure what we should do in that case -- I'd still
 519                  * like this to be settable based on a zonecfg setting, too.
 520                  *
 521                  * We only set things explicitly _on_ here, rather than
 522                  * explicitly _off_ such that a zone's settings do not
 523                  * permanently override those from the GZ.
 524                  *
 525                  * XXX: This might be a bit crap, we sorta want a tri-state
 526                  */
 527                 if (flag != 0) {
 528                         if (psecflags(P_PID, P_MYID,
 529                             PSECFLAGS_ENABLE, psfd->flag) != 0) {
 530                                 uu_warn("couldn't set security flags: %s\n",
 531                                     strerror(errno));
 532                         }
 533                 }
 534 next:
 535                 uu_free(pfmri);
 536                 scf_value_destroy(val);
 537                 scf_property_destroy(prop);
 538         }
 539 }
 540 
 541 static int
 542 read_startd_config(void)
 543 {
 544         scf_handle_t *hndl;
 545         scf_instance_t *inst;
 546         scf_propertygroup_t *pg;
 547         scf_property_t *prop;
 548         scf_value_t *val;
 549         scf_iter_t *iter, *piter;
 550         instance_data_t idata;
 551         char *buf, *vbuf;
 552         char *startd_options_fmri = uu_msprintf("%s/:properties/options",
 553             SCF_SERVICE_STARTD);
 554         char *startd_reconfigure_fmri = uu_msprintf(
 555             "%s/:properties/system/reconfigure", SCF_SERVICE_STARTD);
 556         char *env_opts, *lasts, *cp;
 557         int bind_fails = 0;
 558         int ret = 0, r;
 559         uint_t count = 0, msecs = ALLOC_DELAY;
 560         size_t sz;
 561         ctid_t ctid;
 562         uint64_t uint64;
 563 
 564         buf = startd_alloc(max_scf_fmri_size);
 565 
 566         if (startd_options_fmri == NULL || startd_reconfigure_fmri == NULL)
 567                 uu_die("Allocation failure\n");
 568 
 569         st->st_log_prefix = LOG_PREFIX_EARLY;
 570 
 571         if ((st->st_log_file = getenv("STARTD_DEFAULT_LOG")) == NULL) {
 572                 st->st_log_file = startd_alloc(strlen(STARTD_DEFAULT_LOG) + 1);
 573 
 574                 (void) strcpy(st->st_log_file, STARTD_DEFAULT_LOG);
 575         }
 576 
 577         st->st_door_path = getenv("STARTD_ALT_DOOR");
 578 
 579         /*
 580          * Read "options" property group.
 581          */
 582         for (hndl = libscf_handle_create_bound(SCF_VERSION); hndl == NULL;
 583             hndl = libscf_handle_create_bound(SCF_VERSION), bind_fails++) {
 584                 (void) sleep(INITIAL_REBIND_DELAY);
 585 
 586                 if (bind_fails > INITIAL_REBIND_ATTEMPTS) {
 587                         /*
 588                          * In the case that we can't bind to the repository
 589                          * (which should have been started), we need to allow
 590                          * the user into maintenance mode to determine what's
 591                          * failed.
 592                          */
 593                         log_framework(LOG_INFO, "Couldn't fetch "
 594                             "default settings: %s\n",
 595                             scf_strerror(scf_error()));
 596 
 597                         ret = -1;
 598 
 599                         goto noscfout;
 600                 }
 601         }
 602 
 603         idata.i_fmri = SCF_SERVICE_STARTD;
 604         idata.i_state = RESTARTER_STATE_NONE;
 605         idata.i_next_state = RESTARTER_STATE_NONE;
 606 timestamp:
 607         switch (r = _restarter_commit_states(hndl, &idata,
 608             RESTARTER_STATE_ONLINE, RESTARTER_STATE_NONE,
 609             restarter_get_str_short(restarter_str_insert_in_graph))) {
 610         case 0:
 611                 break;
 612 
 613         case ENOMEM:
 614                 ++count;
 615                 if (count < ALLOC_RETRY) {
 616                         (void) poll(NULL, 0, msecs);
 617                         msecs *= ALLOC_DELAY_MULT;
 618                         goto timestamp;
 619                 }
 620 
 621                 uu_die("Insufficient memory.\n");
 622                 /* NOTREACHED */
 623 
 624         case ECONNABORTED:
 625                 libscf_handle_rebind(hndl);
 626                 goto timestamp;
 627 
 628         case ENOENT:
 629         case EPERM:
 630         case EACCES:
 631         case EROFS:
 632                 log_error(LOG_INFO, "Could set state of %s: %s.\n",
 633                     idata.i_fmri, strerror(r));
 634                 break;
 635 
 636         case EINVAL:
 637         default:
 638                 bad_error("_restarter_commit_states", r);
 639         }
 640 
 641         pg = safe_scf_pg_create(hndl);
 642         prop = safe_scf_property_create(hndl);
 643         val = safe_scf_value_create(hndl);
 644         inst = safe_scf_instance_create(hndl);
 645 
 646         /* set startd's restarter properties */
 647         if (scf_handle_decode_fmri(hndl, SCF_SERVICE_STARTD, NULL, NULL, inst,
 648             NULL, NULL, SCF_DECODE_FMRI_EXACT) == 0) {
 649                 (void) libscf_write_start_pid(inst, getpid());
 650                 ctid = proc_get_ctid();
 651                 if (ctid != -1) {
 652                         uint64 = (uint64_t)ctid;
 653                         (void) libscf_inst_set_count_prop(inst,
 654                             SCF_PG_RESTARTER, SCF_PG_RESTARTER_TYPE,
 655                             SCF_PG_RESTARTER_FLAGS, SCF_PROPERTY_CONTRACT,
 656                             uint64);
 657                 }
 658                 (void) libscf_note_method_log(inst, LOG_PREFIX_EARLY,
 659                     STARTD_DEFAULT_LOG);
 660                 (void) libscf_note_method_log(inst, LOG_PREFIX_NORMAL,
 661                     STARTD_DEFAULT_LOG);
 662         }
 663 
 664         /* Read reconfigure property for recovery. */
 665         if (scf_handle_decode_fmri(hndl, startd_reconfigure_fmri, NULL, NULL,
 666             NULL, NULL, prop, NULL) != -1 &&
 667             scf_property_get_value(prop, val) == 0)
 668                 (void) scf_value_get_boolean(val, &prop_reconfig);
 669 
 670         /*
 671          * Set up the initial process secflags.  We do this super early, and
 672          * in svc.startd, so that it's inherited by as much stuff as possible
 673          * upon boot.
 674          */
 675         init_secflags(hndl);
 676 
 677         if (scf_handle_decode_fmri(hndl, startd_options_fmri, NULL, NULL, NULL,
 678             pg, NULL, SCF_DECODE_FMRI_TRUNCATE) == -1) {
 679                 /*
 680                  * No configuration options defined.
 681                  */
 682                 if (scf_error() != SCF_ERROR_NOT_FOUND)
 683                         uu_warn("Couldn't read configuration from 'options' "
 684                             "group: %s\n", scf_strerror(scf_error()));
 685                 goto scfout;
 686         }
 687 
 688         /*
 689          * If there is no "options" group defined, then our defaults are fine.
 690          */
 691         if (scf_pg_get_name(pg, NULL, 0) < 0)
 692                 goto scfout;
 693 
 694         /* get info_events_all */
 695         info_events_all = libscf_get_info_events_all(pg);
 696 
 697         /* Iterate through. */
 698         iter = safe_scf_iter_create(hndl);
 699 
 700         (void) scf_iter_pg_properties(iter, pg);
 701 
 702         piter = safe_scf_iter_create(hndl);
 703         vbuf = startd_alloc(max_scf_value_size);
 704 
 705         while ((scf_iter_next_property(iter, prop) == 1)) {
 706                 scf_type_t ty;
 707 
 708                 if (scf_property_get_name(prop, buf, max_scf_fmri_size) < 0)
 709                         continue;
 710 
 711                 if (strcmp(buf, "logging") != 0 &&
 712                     strcmp(buf, "boot_messages") != 0)
 713                         continue;
 714 
 715                 if (scf_property_type(prop, &ty) != 0) {
 716                         switch (scf_error()) {
 717                         case SCF_ERROR_CONNECTION_BROKEN:
 718                         default:
 719                                 libscf_handle_rebind(hndl);
 720                                 continue;
 721 
 722                         case SCF_ERROR_DELETED:
 723                                 continue;
 724 
 725                         case SCF_ERROR_NOT_BOUND:
 726                         case SCF_ERROR_NOT_SET:
 727                                 bad_error("scf_property_type", scf_error());
 728                         }
 729                 }
 730 
 731                 if (ty != SCF_TYPE_ASTRING) {
 732                         uu_warn("property \"options/%s\" is not of type "
 733                             "astring; ignored.\n", buf);
 734                         continue;
 735                 }
 736 
 737                 if (scf_property_get_value(prop, val) != 0) {
 738                         switch (scf_error()) {
 739                         case SCF_ERROR_CONNECTION_BROKEN:
 740                         default:
 741                                 return (ECONNABORTED);
 742 
 743                         case SCF_ERROR_DELETED:
 744                         case SCF_ERROR_NOT_FOUND:
 745                                 return (0);
 746 
 747                         case SCF_ERROR_CONSTRAINT_VIOLATED:
 748                                 uu_warn("property \"options/%s\" has multiple "
 749                                     "values; ignored.\n", buf);
 750                                 continue;
 751 
 752                         case SCF_ERROR_PERMISSION_DENIED:
 753                                 uu_warn("property \"options/%s\" cannot be "
 754                                     "read because startd has insufficient "
 755                                     "permission; ignored.\n", buf);
 756                                 continue;
 757 
 758                         case SCF_ERROR_HANDLE_MISMATCH:
 759                         case SCF_ERROR_NOT_BOUND:
 760                         case SCF_ERROR_NOT_SET:
 761                                 bad_error("scf_property_get_value",
 762                                     scf_error());
 763                         }
 764                 }
 765 
 766                 if (scf_value_get_astring(val, vbuf, max_scf_value_size) < 0)
 767                         bad_error("scf_value_get_astring", scf_error());
 768 
 769                 if (strcmp("logging", buf) == 0) {
 770                         if (strcmp("verbose", vbuf) == 0) {
 771                                 st->st_boot_flags = STARTD_BOOT_VERBOSE;
 772                                 st->st_log_level_min = LOG_INFO;
 773                         } else if (strcmp("debug", vbuf) == 0) {
 774                                 st->st_boot_flags = STARTD_BOOT_VERBOSE;
 775                                 st->st_log_level_min = LOG_DEBUG;
 776                         } else if (strcmp("quiet", vbuf) == 0) {
 777                                 st->st_log_level_min = LOG_NOTICE;
 778                         } else {
 779                                 uu_warn("unknown options/logging "
 780                                     "value '%s' ignored\n", vbuf);
 781                         }
 782 
 783                 } else if (strcmp("boot_messages", buf) == 0) {
 784                         if (strcmp("quiet", vbuf) == 0) {
 785                                 st->st_boot_flags = STARTD_BOOT_QUIET;
 786                         } else if (strcmp("verbose", vbuf) == 0) {
 787                                 st->st_boot_flags = STARTD_BOOT_VERBOSE;
 788                         } else {
 789                                 log_framework(LOG_NOTICE, "unknown "
 790                                     "options/boot_messages value '%s' "
 791                                     "ignored\n", vbuf);
 792                         }
 793 
 794                 }
 795         }
 796 
 797         startd_free(vbuf, max_scf_value_size);
 798         scf_iter_destroy(piter);
 799 
 800         scf_iter_destroy(iter);
 801 
 802 scfout:
 803         scf_value_destroy(val);
 804         scf_pg_destroy(pg);
 805         scf_property_destroy(prop);
 806         scf_instance_destroy(inst);
 807         (void) scf_handle_unbind(hndl);
 808         scf_handle_destroy(hndl);
 809 
 810 noscfout:
 811         startd_free(buf, max_scf_fmri_size);
 812         uu_free(startd_options_fmri);
 813         uu_free(startd_reconfigure_fmri);
 814 
 815         if (booting_to_single_user) {
 816                 st->st_subgraph = startd_alloc(max_scf_fmri_size);
 817                 sz = strlcpy(st->st_subgraph, "milestone/single-user:default",
 818                     max_scf_fmri_size);
 819                 assert(sz < max_scf_fmri_size);
 820         }
 821 
 822         /*
 823          * Options passed in as boot arguments override repository defaults.
 824          */
 825         env_opts = getenv("SMF_OPTIONS");
 826         if (env_opts == NULL)
 827                 return (ret);
 828 
 829         for (cp = strtok_r(env_opts, ",", &lasts); cp != NULL;
 830             cp = strtok_r(NULL, ",", &lasts)) {
 831                 if (strcmp(cp, "debug") == 0) {
 832                         st->st_boot_flags = STARTD_BOOT_VERBOSE;
 833                         st->st_log_level_min = LOG_DEBUG;
 834 
 835                         /* -m debug should send messages to console */
 836                         st->st_log_flags =
 837                             st->st_log_flags | STARTD_LOG_TERMINAL;
 838                 } else if (strcmp(cp, "verbose") == 0) {
 839                         st->st_boot_flags = STARTD_BOOT_VERBOSE;
 840                         st->st_log_level_min = LOG_INFO;
 841                 } else if (strcmp(cp, "seed") == 0) {
 842                         uu_warn("SMF option \"%s\" unimplemented.\n", cp);
 843                 } else if (strcmp(cp, "quiet") == 0) {
 844                         st->st_log_level_min = LOG_NOTICE;
 845                 } else if (strncmp(cp, "milestone=",
 846                     sizeof ("milestone=") - 1) == 0) {
 847                         char *mp = cp + sizeof ("milestone=") - 1;
 848 
 849                         if (booting_to_single_user)
 850                                 continue;
 851 
 852                         if (st->st_subgraph == NULL) {
 853                                 st->st_subgraph =
 854                                     startd_alloc(max_scf_fmri_size);
 855                                 st->st_subgraph[0] = '\0';
 856                         }
 857 
 858                         if (mp[0] == '\0' || strcmp(mp, "all") == 0) {
 859                                 (void) strcpy(st->st_subgraph, "all");
 860                         } else if (strcmp(mp, "su") == 0 ||
 861                             strcmp(mp, "single-user") == 0) {
 862                                 (void) strcpy(st->st_subgraph,
 863                                     "milestone/single-user:default");
 864                         } else if (strcmp(mp, "mu") == 0 ||
 865                             strcmp(mp, "multi-user") == 0) {
 866                                 (void) strcpy(st->st_subgraph,
 867                                     "milestone/multi-user:default");
 868                         } else if (strcmp(mp, "mus") == 0 ||
 869                             strcmp(mp, "multi-user-server") == 0) {
 870                                 (void) strcpy(st->st_subgraph,
 871                                     "milestone/multi-user-server:default");
 872                         } else if (strcmp(mp, "none") == 0) {
 873                                 (void) strcpy(st->st_subgraph, "none");
 874                         } else {
 875                                 log_framework(LOG_NOTICE,
 876                                     "invalid milestone option value "
 877                                     "'%s' ignored\n", mp);
 878                         }
 879                 } else {
 880                         uu_warn("Unknown SMF option \"%s\".\n", cp);
 881                 }
 882         }
 883 
 884         return (ret);
 885 }
 886 
 887 /*
 888  * void set_boot_env()
 889  *
 890  * If -r was passed or /reconfigure exists, this is a reconfig
 891  * reboot.  We need to make sure that this information is given
 892  * to the appropriate services the first time they're started
 893  * by setting the system/reconfigure repository property,
 894  * as well as pass the _INIT_RECONFIG variable on to the rcS
 895  * start method so that legacy services can continue to use it.
 896  *
 897  * This function must never be called before contract_init(), as
 898  * it sets st_initial.  get_startd_config() sets prop_reconfig from
 899  * pre-existing repository state.
 900  */
 901 static void
 902 set_boot_env()
 903 {
 904         struct stat sb;
 905         int r;
 906 
 907         /*
 908          * Check if property still is set -- indicates we didn't get
 909          * far enough previously to unset it.  Otherwise, if this isn't
 910          * the first startup, don't re-process /reconfigure or the
 911          * boot flag.
 912          */
 913         if (prop_reconfig != 1 && st->st_initial != 1)
 914                 return;
 915 
 916         /* If /reconfigure exists, also set opt_reconfig. */
 917         if (stat("/reconfigure", &sb) != -1)
 918                 opt_reconfig = 1;
 919 
 920         /* Nothing to do.  Just return. */
 921         if (opt_reconfig == 0 && prop_reconfig == 0)
 922                 return;
 923 
 924         /*
 925          * Set startd's reconfigure property.  This property is
 926          * then cleared by successful completion of the single-user
 927          * milestone.
 928          */
 929         if (prop_reconfig != 1) {
 930                 r = libscf_set_reconfig(1);
 931                 switch (r) {
 932                 case 0:
 933                         break;
 934 
 935                 case ENOENT:
 936                 case EPERM:
 937                 case EACCES:
 938                 case EROFS:
 939                         log_error(LOG_WARNING, "Could not set reconfiguration "
 940                             "property: %s\n", strerror(r));
 941                         break;
 942 
 943                 default:
 944                         bad_error("libscf_set_reconfig", r);
 945                 }
 946         }
 947 }
 948 
 949 static void
 950 startup(void)
 951 {
 952         ctid_t configd_ctid;
 953         int err;
 954 
 955         /*
 956          * Initialize data structures.
 957          */
 958         gu = startd_zalloc(sizeof (graph_update_t));
 959         ru = startd_zalloc(sizeof (restarter_update_t));
 960 
 961         (void) pthread_cond_init(&st->st_load_cv, NULL);
 962         (void) pthread_cond_init(&st->st_configd_live_cv, NULL);
 963         (void) pthread_cond_init(&gu->gu_cv, NULL);
 964         (void) pthread_cond_init(&gu->gu_freeze_cv, NULL);
 965         (void) pthread_cond_init(&ru->restarter_update_cv, NULL);
 966         (void) pthread_mutex_init(&st->st_load_lock, &mutex_attrs);
 967         (void) pthread_mutex_init(&st->st_configd_live_lock, &mutex_attrs);
 968         (void) pthread_mutex_init(&gu->gu_lock, &mutex_attrs);
 969         (void) pthread_mutex_init(&gu->gu_freeze_lock, &mutex_attrs);
 970         (void) pthread_mutex_init(&ru->restarter_update_lock, &mutex_attrs);
 971 
 972         configd_ctid = contract_init();
 973 
 974         if (configd_ctid != -1)
 975                 log_framework(LOG_DEBUG, "Existing configd contract %ld; not "
 976                     "starting svc.configd\n", configd_ctid);
 977 
 978         /*
 979          * Call utmpx_init() before creating the fork_configd() thread.
 980          */
 981         utmpx_init();
 982 
 983         (void) startd_thread_create(fork_configd_thread, (void *)configd_ctid);
 984 
 985         /*
 986          * Await, if necessary, configd's initial arrival.
 987          */
 988         MUTEX_LOCK(&st->st_configd_live_lock);
 989         while (!st->st_configd_lives) {
 990                 log_framework(LOG_DEBUG, "Awaiting cv signal on "
 991                     "configd_live_cv\n");
 992                 err = pthread_cond_wait(&st->st_configd_live_cv,
 993                     &st->st_configd_live_lock);
 994                 assert(err == 0);
 995         }
 996         MUTEX_UNLOCK(&st->st_configd_live_lock);
 997 
 998         wait_init();
 999 
1000         if (read_startd_config())
1001                 log_framework(LOG_INFO, "svc.configd unable to provide startd "
1002                     "optional settings\n");
1003 
1004         log_init();
1005         dict_init();
1006         timeout_init();
1007         restarter_protocol_init();
1008         restarter_init();
1009 
1010         /*
1011          * svc.configd is started by fork_configd_thread so repository access is
1012          * available, run early manifest import before continuing with starting
1013          * graph engine and the rest of startd.
1014          */
1015         log_framework(LOG_DEBUG, "Calling fork_emi...\n");
1016         fork_emi();
1017 
1018         graph_protocol_init();
1019         graph_init();
1020 
1021         init_env();
1022 
1023         set_boot_env();
1024         restarter_start();
1025         graph_engine_start();
1026 }
1027 
1028 static void
1029 usage(const char *name)
1030 {
1031         uu_warn(gettext("usage: %s [-n]\n"), name);
1032         exit(UU_EXIT_USAGE);
1033 }
1034 
1035 static int
1036 daemonize_start(void)
1037 {
1038         pid_t pid;
1039         int fd;
1040 
1041         if ((pid = fork1()) < 0)
1042                 return (-1);
1043 
1044         if (pid != 0)
1045                 exit(0);
1046 
1047         (void) close(STDIN_FILENO);
1048 
1049         if ((fd = open("/dev/null", O_RDONLY)) == -1) {
1050                 uu_warn(gettext("can't connect stdin to /dev/null"));
1051         } else if (fd != STDIN_FILENO) {
1052                 (void) dup2(fd, STDIN_FILENO);
1053                 startd_close(fd);
1054         }
1055 
1056         closefrom(3);
1057         (void) dup2(STDERR_FILENO, STDOUT_FILENO);
1058 
1059         (void) setsid();
1060         (void) chdir("/");
1061 
1062         /* Use default umask that init handed us, but 022 to create files. */
1063         dmask = umask(022);
1064         fmask = umask(dmask);
1065 
1066         return (0);
1067 }
1068 
1069 /*ARGSUSED*/
1070 static void
1071 die_handler(int sig, siginfo_t *info, void *data)
1072 {
1073         finished = 1;
1074 }
1075 
1076 int
1077 main(int argc, char *argv[])
1078 {
1079         int opt;
1080         int daemonize = 1;
1081         struct sigaction act;
1082         sigset_t nullset;
1083         struct stat sb;
1084 
1085         (void) uu_setpname(argv[0]);
1086 
1087         st = startd_zalloc(sizeof (startd_state_t));
1088 
1089         (void) pthread_mutexattr_init(&mutex_attrs);
1090 #ifndef NDEBUG
1091         (void) pthread_mutexattr_settype(&mutex_attrs,
1092             PTHREAD_MUTEX_ERRORCHECK);
1093 #endif
1094 
1095         max_scf_name_size = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH);
1096         max_scf_value_size = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
1097         max_scf_fmri_size = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
1098 
1099         if (max_scf_name_size == -1 || max_scf_value_size == -1 ||
1100             max_scf_value_size == -1)
1101                 uu_die("Can't determine repository maximum lengths.\n");
1102 
1103         max_scf_name_size++;
1104         max_scf_value_size++;
1105         max_scf_fmri_size++;
1106 
1107         st->st_log_flags = STARTD_LOG_FILE | STARTD_LOG_SYSLOG;
1108         st->st_log_level_min = LOG_NOTICE;
1109 
1110         while ((opt = getopt(argc, argv, "nrs")) != EOF) {
1111                 switch (opt) {
1112                 case 'n':
1113                         daemonize = 0;
1114                         break;
1115                 case 'r':                       /* reconfiguration boot */
1116                         opt_reconfig = 1;
1117                         break;
1118                 case 's':                       /* single-user mode */
1119                         booting_to_single_user = B_TRUE;
1120                         break;
1121                 default:
1122                         usage(argv[0]);         /* exits */
1123                 }
1124         }
1125 
1126         if (optind != argc)
1127                 usage(argv[0]);
1128 
1129         (void) enable_extended_FILE_stdio(-1, -1);
1130 
1131         if (daemonize)
1132                 if (daemonize_start() < 0)
1133                         uu_die("Can't daemonize\n");
1134 
1135         log_init();
1136 
1137         if (stat("/etc/svc/volatile/resetting", &sb) != -1) {
1138                 log_framework(LOG_NOTICE, "Restarter quiesced.\n");
1139 
1140                 for (;;)
1141                         (void) pause();
1142         }
1143 
1144         act.sa_sigaction = &die_handler;
1145         (void) sigfillset(&act.sa_mask);
1146         act.sa_flags = SA_SIGINFO;
1147         (void) sigaction(SIGINT, &act, NULL);
1148         (void) sigaction(SIGTERM, &act, NULL);
1149 
1150         startup();
1151 
1152         (void) sigemptyset(&nullset);
1153         while (!finished) {
1154                 log_framework(LOG_DEBUG, "Main thread paused\n");
1155                 (void) sigsuspend(&nullset);
1156         }
1157 
1158         (void) log_framework(LOG_DEBUG, "Restarter exiting.\n");
1159         return (0);
1160 }