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 }