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