1 /* 2 * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org> 3 * Copyright (C) 2013 John Crispin <blogic@openwrt.org> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU Lesser General Public License version 2.1 7 * as published by the Free Software Foundation 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14 15 #define _GNU_SOURCE 16 #include <sys/resource.h> 17 #include <sys/types.h> 18 #include <sys/socket.h> 19 #include <sys/stat.h> 20 #include <grp.h> 21 #include <net/if.h> 22 #include <unistd.h> 23 #include <stdint.h> 24 #include <stdio.h> 25 #include <fcntl.h> 26 #include <pwd.h> 27 #include <libgen.h> 28 #include <unistd.h> 29 #define SYSLOG_NAMES 30 #include <syslog.h> 31 32 #include <libubox/md5.h> 33 #include <libubox/utils.h> 34 35 #include "../procd.h" 36 #include "../rcS.h" 37 38 #include "service.h" 39 #include "instance.h" 40 41 #define UJAIL_BIN_PATH "/sbin/ujail" 42 #define CGROUP_BASEDIR "/sys/fs/cgroup/services" 43 44 enum { 45 INSTANCE_ATTR_COMMAND, 46 INSTANCE_ATTR_ENV, 47 INSTANCE_ATTR_DATA, 48 INSTANCE_ATTR_NETDEV, 49 INSTANCE_ATTR_FILE, 50 INSTANCE_ATTR_TRIGGER, 51 INSTANCE_ATTR_RESPAWN, 52 INSTANCE_ATTR_NICE, 53 INSTANCE_ATTR_LIMITS, 54 INSTANCE_ATTR_WATCH, 55 INSTANCE_ATTR_ERROR, 56 INSTANCE_ATTR_USER, 57 INSTANCE_ATTR_GROUP, 58 INSTANCE_ATTR_STDOUT, 59 INSTANCE_ATTR_STDERR, 60 INSTANCE_ATTR_NO_NEW_PRIVS, 61 INSTANCE_ATTR_JAIL, 62 INSTANCE_ATTR_TRACE, 63 INSTANCE_ATTR_SECCOMP, 64 INSTANCE_ATTR_CAPABILITIES, 65 INSTANCE_ATTR_PIDFILE, 66 INSTANCE_ATTR_RELOADSIG, 67 INSTANCE_ATTR_TERMTIMEOUT, 68 INSTANCE_ATTR_FACILITY, 69 INSTANCE_ATTR_EXTROOT, 70 INSTANCE_ATTR_OVERLAYDIR, 71 INSTANCE_ATTR_TMPOVERLAYSIZE, 72 INSTANCE_ATTR_BUNDLE, 73 INSTANCE_ATTR_WATCHDOG, 74 __INSTANCE_ATTR_MAX 75 }; 76 77 static const struct blobmsg_policy instance_attr[__INSTANCE_ATTR_MAX] = { 78 [INSTANCE_ATTR_COMMAND] = { "command", BLOBMSG_TYPE_ARRAY }, 79 [INSTANCE_ATTR_ENV] = { "env", BLOBMSG_TYPE_TABLE }, 80 [INSTANCE_ATTR_DATA] = { "data", BLOBMSG_TYPE_TABLE }, 81 [INSTANCE_ATTR_NETDEV] = { "netdev", BLOBMSG_TYPE_ARRAY }, 82 [INSTANCE_ATTR_FILE] = { "file", BLOBMSG_TYPE_ARRAY }, 83 [INSTANCE_ATTR_TRIGGER] = { "triggers", BLOBMSG_TYPE_ARRAY }, 84 [INSTANCE_ATTR_RESPAWN] = { "respawn", BLOBMSG_TYPE_ARRAY }, 85 [INSTANCE_ATTR_NICE] = { "nice", BLOBMSG_TYPE_INT32 }, 86 [INSTANCE_ATTR_LIMITS] = { "limits", BLOBMSG_TYPE_TABLE }, 87 [INSTANCE_ATTR_WATCH] = { "watch", BLOBMSG_TYPE_ARRAY }, 88 [INSTANCE_ATTR_ERROR] = { "error", BLOBMSG_TYPE_ARRAY }, 89 [INSTANCE_ATTR_USER] = { "user", BLOBMSG_TYPE_STRING }, 90 [INSTANCE_ATTR_GROUP] = { "group", BLOBMSG_TYPE_STRING }, 91 [INSTANCE_ATTR_STDOUT] = { "stdout", BLOBMSG_TYPE_BOOL }, 92 [INSTANCE_ATTR_STDERR] = { "stderr", BLOBMSG_TYPE_BOOL }, 93 [INSTANCE_ATTR_NO_NEW_PRIVS] = { "no_new_privs", BLOBMSG_TYPE_BOOL }, 94 [INSTANCE_ATTR_JAIL] = { "jail", BLOBMSG_TYPE_TABLE }, 95 [INSTANCE_ATTR_TRACE] = { "trace", BLOBMSG_TYPE_BOOL }, 96 [INSTANCE_ATTR_SECCOMP] = { "seccomp", BLOBMSG_TYPE_STRING }, 97 [INSTANCE_ATTR_CAPABILITIES] = { "capabilities", BLOBMSG_TYPE_STRING }, 98 [INSTANCE_ATTR_PIDFILE] = { "pidfile", BLOBMSG_TYPE_STRING }, 99 [INSTANCE_ATTR_RELOADSIG] = { "reload_signal", BLOBMSG_TYPE_INT32 }, 100 [INSTANCE_ATTR_TERMTIMEOUT] = { "term_timeout", BLOBMSG_TYPE_INT32 }, 101 [INSTANCE_ATTR_FACILITY] = { "facility", BLOBMSG_TYPE_STRING }, 102 [INSTANCE_ATTR_EXTROOT] = { "extroot", BLOBMSG_TYPE_STRING }, 103 [INSTANCE_ATTR_OVERLAYDIR] = { "overlaydir", BLOBMSG_TYPE_STRING }, 104 [INSTANCE_ATTR_TMPOVERLAYSIZE] = { "tmpoverlaysize", BLOBMSG_TYPE_STRING }, 105 [INSTANCE_ATTR_BUNDLE] = { "bundle", BLOBMSG_TYPE_STRING }, 106 [INSTANCE_ATTR_WATCHDOG] = { "watchdog", BLOBMSG_TYPE_ARRAY }, 107 }; 108 109 enum { 110 JAIL_ATTR_NAME, 111 JAIL_ATTR_HOSTNAME, 112 JAIL_ATTR_PROCFS, 113 JAIL_ATTR_SYSFS, 114 JAIL_ATTR_UBUS, 115 JAIL_ATTR_UDEBUG, 116 JAIL_ATTR_LOG, 117 JAIL_ATTR_RONLY, 118 JAIL_ATTR_MOUNT, 119 JAIL_ATTR_NETNS, 120 JAIL_ATTR_USERNS, 121 JAIL_ATTR_CGROUPSNS, 122 JAIL_ATTR_CONSOLE, 123 JAIL_ATTR_REQUIREJAIL, 124 JAIL_ATTR_IMMEDIATELY, 125 JAIL_ATTR_PIDFILE, 126 JAIL_ATTR_SETNS, 127 __JAIL_ATTR_MAX, 128 }; 129 130 static const struct blobmsg_policy jail_attr[__JAIL_ATTR_MAX] = { 131 [JAIL_ATTR_NAME] = { "name", BLOBMSG_TYPE_STRING }, 132 [JAIL_ATTR_HOSTNAME] = { "hostname", BLOBMSG_TYPE_STRING }, 133 [JAIL_ATTR_PROCFS] = { "procfs", BLOBMSG_TYPE_BOOL }, 134 [JAIL_ATTR_SYSFS] = { "sysfs", BLOBMSG_TYPE_BOOL }, 135 [JAIL_ATTR_UBUS] = { "ubus", BLOBMSG_TYPE_BOOL }, 136 [JAIL_ATTR_UDEBUG] = { "udebug", BLOBMSG_TYPE_BOOL }, 137 [JAIL_ATTR_LOG] = { "log", BLOBMSG_TYPE_BOOL }, 138 [JAIL_ATTR_RONLY] = { "ronly", BLOBMSG_TYPE_BOOL }, 139 [JAIL_ATTR_MOUNT] = { "mount", BLOBMSG_TYPE_TABLE }, 140 [JAIL_ATTR_NETNS] = { "netns", BLOBMSG_TYPE_BOOL }, 141 [JAIL_ATTR_USERNS] = { "userns", BLOBMSG_TYPE_BOOL }, 142 [JAIL_ATTR_CGROUPSNS] = { "cgroupsns", BLOBMSG_TYPE_BOOL }, 143 [JAIL_ATTR_CONSOLE] = { "console", BLOBMSG_TYPE_BOOL }, 144 [JAIL_ATTR_REQUIREJAIL] = { "requirejail", BLOBMSG_TYPE_BOOL }, 145 [JAIL_ATTR_IMMEDIATELY] = { "immediately", BLOBMSG_TYPE_BOOL }, 146 [JAIL_ATTR_PIDFILE] = { "pidfile", BLOBMSG_TYPE_STRING }, 147 [JAIL_ATTR_SETNS] = { "setns", BLOBMSG_TYPE_ARRAY }, 148 }; 149 150 enum { 151 JAIL_SETNS_ATTR_PID, 152 JAIL_SETNS_ATTR_NS, 153 __JAIL_SETNS_ATTR_MAX, 154 }; 155 156 static const struct blobmsg_policy jail_setns_attr[__JAIL_SETNS_ATTR_MAX] = { 157 [JAIL_SETNS_ATTR_PID] = { "pid", BLOBMSG_TYPE_INT32 }, 158 [JAIL_SETNS_ATTR_NS] = { "namespaces", BLOBMSG_TYPE_ARRAY }, 159 }; 160 161 struct instance_netdev { 162 struct blobmsg_list_node node; 163 int ifindex; 164 }; 165 166 struct instance_file { 167 struct blobmsg_list_node node; 168 uint32_t md5[4]; 169 }; 170 171 struct rlimit_name { 172 const char *name; 173 int resource; 174 }; 175 176 static const struct rlimit_name rlimit_names[] = { 177 { "as", RLIMIT_AS }, 178 { "core", RLIMIT_CORE }, 179 { "cpu", RLIMIT_CPU }, 180 { "data", RLIMIT_DATA }, 181 { "fsize", RLIMIT_FSIZE }, 182 { "memlock", RLIMIT_MEMLOCK }, 183 { "nofile", RLIMIT_NOFILE }, 184 { "nproc", RLIMIT_NPROC }, 185 { "rss", RLIMIT_RSS }, 186 { "stack", RLIMIT_STACK }, 187 #ifdef linux 188 { "nice", RLIMIT_NICE }, 189 { "rtprio", RLIMIT_RTPRIO }, 190 { "msgqueue", RLIMIT_MSGQUEUE }, 191 { "sigpending", RLIMIT_SIGPENDING }, 192 #endif 193 { NULL, 0 } 194 }; 195 196 static void closefd(int fd) 197 { 198 if (fd > STDERR_FILENO) 199 close(fd); 200 } 201 202 /* convert a string into numeric syslog facility or return -1 if no match found */ 203 static int 204 syslog_facility_str_to_int(const char *facility) 205 { 206 CODE *p = facilitynames; 207 208 while (p->c_name && strcasecmp(p->c_name, facility)) 209 p++; 210 211 return p->c_val; 212 } 213 214 static void 215 instance_limits(const char *limit, const char *value) 216 { 217 int i; 218 struct rlimit rlim; 219 unsigned long cur, max; 220 221 for (i = 0; rlimit_names[i].name != NULL; i++) { 222 if (strcmp(rlimit_names[i].name, limit)) 223 continue; 224 if (!strcmp(value, "unlimited")) { 225 rlim.rlim_cur = RLIM_INFINITY; 226 rlim.rlim_max = RLIM_INFINITY; 227 } else { 228 if (getrlimit(rlimit_names[i].resource, &rlim)) 229 return; 230 231 cur = rlim.rlim_cur; 232 max = rlim.rlim_max; 233 234 if (sscanf(value, "%lu %lu", &cur, &max) < 1) 235 return; 236 237 rlim.rlim_cur = cur; 238 rlim.rlim_max = max; 239 } 240 241 setrlimit(rlimit_names[i].resource, &rlim); 242 return; 243 } 244 } 245 246 static char * 247 instance_gen_setns_argstr(struct blob_attr *attr) 248 { 249 struct blob_attr *tb[__JAIL_SETNS_ATTR_MAX]; 250 struct blob_attr *cur; 251 int rem, len, total; 252 char *ret; 253 254 blobmsg_parse(jail_setns_attr, __JAIL_SETNS_ATTR_MAX, tb, 255 blobmsg_data(attr), blobmsg_data_len(attr)); 256 257 if (!tb[JAIL_SETNS_ATTR_PID] || !tb[JAIL_SETNS_ATTR_NS]) 258 return NULL; 259 260 len = snprintf(NULL, 0, "%d:", blobmsg_get_u32(tb[JAIL_SETNS_ATTR_PID])); 261 262 blobmsg_for_each_attr(cur, tb[JAIL_SETNS_ATTR_NS], rem) { 263 char *tmp; 264 265 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) 266 return NULL; 267 268 tmp = blobmsg_get_string(cur); 269 if (!tmp) 270 return NULL; 271 272 len += strlen(tmp) + 1; 273 } 274 275 total = len; 276 ret = malloc(total); 277 if (!ret) 278 return NULL; 279 280 len = snprintf(ret, total, "%d:", blobmsg_get_u32(tb[JAIL_SETNS_ATTR_PID])); 281 282 blobmsg_for_each_attr(cur, tb[JAIL_SETNS_ATTR_NS], rem) { 283 strncpy(&ret[len], blobmsg_get_string(cur), total - len); 284 len += strlen(blobmsg_get_string(cur)); 285 ret[len++] = ','; 286 } 287 ret[total - 1] = '\0'; 288 289 return ret; 290 } 291 292 static inline int 293 jail_run(struct service_instance *in, char **argv) 294 { 295 char *term_timeout_str; 296 struct blobmsg_list_node *var; 297 struct jail *jail = &in->jail; 298 int argc = 0; 299 300 argv[argc++] = UJAIL_BIN_PATH; 301 302 if (asprintf(&term_timeout_str, "%d", in->term_timeout) == -1) 303 exit(ENOMEM); 304 305 argv[argc++] = "-t"; 306 argv[argc++] = term_timeout_str; 307 308 if (jail->name) { 309 argv[argc++] = "-n"; 310 argv[argc++] = jail->name; 311 } 312 313 if (jail->hostname) { 314 argv[argc++] = "-h"; 315 argv[argc++] = jail->hostname; 316 } 317 318 if (in->seccomp) { 319 argv[argc++] = "-S"; 320 argv[argc++] = in->seccomp; 321 } 322 323 if (in->user) { 324 argv[argc++] = "-U"; 325 argv[argc++] = in->user; 326 } 327 328 if (in->group) { 329 argv[argc++] = "-G"; 330 argv[argc++] = in->group; 331 } 332 333 if (in->capabilities) { 334 argv[argc++] = "-C"; 335 argv[argc++] = in->capabilities; 336 } 337 338 if (in->no_new_privs) 339 argv[argc++] = "-c"; 340 341 if (jail->procfs) 342 argv[argc++] = "-p"; 343 344 if (jail->sysfs) 345 argv[argc++] = "-s"; 346 347 if (jail->ubus) 348 argv[argc++] = "-u"; 349 350 if (jail->udebug) 351 argv[argc++] = "-D"; 352 353 if (jail->log) 354 argv[argc++] = "-l"; 355 356 if (jail->ronly) 357 argv[argc++] = "-o"; 358 359 if (jail->netns) 360 argv[argc++] = "-N"; 361 362 if (jail->userns) 363 argv[argc++] = "-f"; 364 365 if (jail->cgroupsns) 366 argv[argc++] = "-F"; 367 368 if (jail->console) 369 argv[argc++] = "-y"; 370 371 if (in->extroot) { 372 argv[argc++] = "-R"; 373 argv[argc++] = in->extroot; 374 } 375 376 if (in->overlaydir) { 377 argv[argc++] = "-O"; 378 argv[argc++] = in->overlaydir; 379 } 380 381 if (in->tmpoverlaysize) { 382 argv[argc++] = "-T"; 383 argv[argc++] = in->tmpoverlaysize; 384 } 385 386 if (in->immediately) 387 argv[argc++] = "-i"; 388 389 if (jail->pidfile) { 390 argv[argc++] = "-P"; 391 argv[argc++] = jail->pidfile; 392 } 393 394 if (in->bundle) { 395 argv[argc++] = "-J"; 396 argv[argc++] = in->bundle; 397 } 398 399 if (in->require_jail) 400 argv[argc++] = "-E"; 401 402 blobmsg_list_for_each(&in->env, var) { 403 argv[argc++] = "-e"; 404 argv[argc++] = (char *) blobmsg_name(var->data); 405 } 406 407 blobmsg_list_for_each(&jail->mount, var) { 408 const char *type = blobmsg_data(var->data); 409 410 if (*type == '1') 411 argv[argc++] = "-w"; 412 else 413 argv[argc++] = "-r"; 414 argv[argc++] = (char *) blobmsg_name(var->data); 415 } 416 417 blobmsg_list_for_each(&jail->setns, var) { 418 char *setns_arg = instance_gen_setns_argstr(var->data); 419 420 if (setns_arg) { 421 argv[argc++] = "-j"; 422 argv[argc++] = setns_arg; 423 } 424 } 425 426 argv[argc++] = "--"; 427 428 return argc; 429 } 430 431 static int 432 instance_removepid(struct service_instance *in) { 433 if (!in->pidfile) 434 return 0; 435 if (unlink(in->pidfile)) { 436 ERROR("Failed to remove pidfile: %s: %m\n", in->pidfile); 437 return 1; 438 } 439 return 0; 440 } 441 442 static int 443 instance_writepid(struct service_instance *in) 444 { 445 FILE *_pidfile; 446 447 if (!in->pidfile) { 448 return 0; 449 } 450 _pidfile = fopen(in->pidfile, "w"); 451 if (_pidfile == NULL) { 452 ERROR("failed to open pidfile for writing: %s: %m", in->pidfile); 453 return 1; 454 } 455 if (fprintf(_pidfile, "%d\n", in->proc.pid) < 0) { 456 ERROR("failed to write pidfile: %s: %m", in->pidfile); 457 fclose(_pidfile); 458 return 2; 459 } 460 if (fclose(_pidfile)) { 461 ERROR("failed to close pidfile: %s: %m", in->pidfile); 462 return 3; 463 } 464 465 return 0; 466 } 467 468 static void 469 instance_run(struct service_instance *in, int _stdout, int _stderr) 470 { 471 struct blobmsg_list_node *var; 472 struct blob_attr *cur; 473 char **argv; 474 int argc = 1; /* NULL terminated */ 475 int rem, _stdin; 476 bool seccomp = !in->trace && !in->has_jail && in->seccomp; 477 bool setlbf = _stdout >= 0; 478 479 if (in->nice) 480 setpriority(PRIO_PROCESS, 0, in->nice); 481 482 blobmsg_for_each_attr(cur, in->command, rem) 483 argc++; 484 485 blobmsg_list_for_each(&in->env, var) 486 setenv(blobmsg_name(var->data), blobmsg_data(var->data), 1); 487 488 if (seccomp) 489 setenv("SECCOMP_FILE", in->seccomp, 1); 490 491 if (setlbf) 492 setenv("LD_PRELOAD", "/lib/libsetlbf.so", 1); 493 494 blobmsg_list_for_each(&in->limits, var) 495 instance_limits(blobmsg_name(var->data), blobmsg_data(var->data)); 496 497 if (in->trace || seccomp) 498 argc += 1; 499 500 argv = alloca(sizeof(char *) * (argc + in->jail.argc)); 501 argc = 0; 502 503 #ifdef SECCOMP_SUPPORT 504 if (in->trace) 505 argv[argc++] = "/sbin/utrace"; 506 else if (seccomp) 507 argv[argc++] = "/sbin/seccomp-trace"; 508 #else 509 if (in->trace || seccomp) 510 ULOG_WARN("Seccomp support for %s::%s not available\n", in->srv->name, in->name); 511 #endif 512 513 if (in->has_jail) { 514 argc = jail_run(in, argv); 515 if (argc != in->jail.argc) 516 ULOG_WARN("expected %i jail params, used %i for %s::%s\n", 517 in->jail.argc, argc, in->srv->name, in->name); 518 } 519 520 blobmsg_for_each_attr(cur, in->command, rem) 521 argv[argc++] = blobmsg_data(cur); 522 523 argv[argc] = NULL; 524 525 _stdin = open("/dev/null", O_RDONLY); 526 527 if (_stdout == -1) 528 _stdout = open("/dev/null", O_WRONLY); 529 530 if (_stderr == -1) 531 _stderr = open("/dev/null", O_WRONLY); 532 533 if (_stdin > -1) { 534 dup2(_stdin, STDIN_FILENO); 535 closefd(_stdin); 536 } 537 if (_stdout > -1) { 538 dup2(_stdout, STDOUT_FILENO); 539 closefd(_stdout); 540 } 541 if (_stderr > -1) { 542 dup2(_stderr, STDERR_FILENO); 543 closefd(_stderr); 544 } 545 546 if (!in->has_jail && in->user && in->pw_gid && initgroups(in->user, in->pw_gid)) { 547 ERROR("failed to initgroups() for user %s: %m\n", in->user); 548 exit(127); 549 } 550 if (!in->has_jail && in->gr_gid && setgid(in->gr_gid)) { 551 ERROR("failed to set group id %d: %m\n", in->gr_gid); 552 exit(127); 553 } 554 if (!in->has_jail && in->uid && setuid(in->uid)) { 555 ERROR("failed to set user id %d: %m\n", in->uid); 556 exit(127); 557 } 558 559 execvp(argv[0], argv); 560 exit(127); 561 } 562 563 static int 564 instance_add_cgroup(const char *service, const char *instance) 565 { 566 const char *cgroup_procs = "/cgroup.procs"; 567 char cgnamebuf[256]; 568 struct stat sb; 569 int fd, ret; 570 571 if (stat("/sys/fs/cgroup/cgroup.subtree_control", &sb)) 572 return 0; 573 574 ret = snprintf(cgnamebuf, sizeof(cgnamebuf), "%s/%s/%s", CGROUP_BASEDIR, 575 service, instance); 576 if (ret >= sizeof(cgnamebuf)) 577 return -ENAMETOOLONG; 578 579 if (mkdir_p(cgnamebuf, 0700)) 580 return -EPERM; 581 582 if (strlen(cgnamebuf) + strlen(cgroup_procs) >= sizeof(cgnamebuf)) 583 return -ENAMETOOLONG; 584 585 strcat(cgnamebuf, cgroup_procs); 586 587 fd = open(cgnamebuf, O_WRONLY); 588 if (fd == -1) 589 return -EIO; 590 591 dprintf(fd, "%d", getpid()); 592 close(fd); 593 594 return 0; 595 } 596 597 static void 598 instance_free_stdio(struct service_instance *in) 599 { 600 if (in->_stdout.fd.fd > -1) { 601 ustream_free(&in->_stdout.stream); 602 close(in->_stdout.fd.fd); 603 in->_stdout.fd.fd = -1; 604 } 605 606 if (in->_stderr.fd.fd > -1) { 607 ustream_free(&in->_stderr.stream); 608 close(in->_stderr.fd.fd); 609 in->_stderr.fd.fd = -1; 610 } 611 612 if (in->console.fd.fd > -1) { 613 ustream_free(&in->console.stream); 614 close(in->console.fd.fd); 615 in->console.fd.fd = -1; 616 } 617 618 if (in->console_client.fd.fd > -1) { 619 ustream_free(&in->console_client.stream); 620 close(in->console_client.fd.fd); 621 in->console_client.fd.fd = -1; 622 } 623 } 624 625 void 626 instance_start(struct service_instance *in) 627 { 628 int pid, ret; 629 int opipe[2] = { -1, -1 }; 630 int epipe[2] = { -1, -1 }; 631 632 if (!avl_is_empty(&in->errors.avl)) { 633 LOG("Not starting instance %s::%s, an error was indicated\n", in->srv->name, in->name); 634 return; 635 } 636 637 if (!in->bundle && !in->command) { 638 LOG("Not starting instance %s::%s, command not set\n", in->srv->name, in->name); 639 return; 640 } 641 642 if (in->proc.pending) { 643 if (in->halt) 644 in->restart = true; 645 return; 646 } 647 648 instance_free_stdio(in); 649 if (in->_stdout.fd.fd > -2) { 650 if (pipe(opipe)) { 651 ULOG_WARN("pipe() failed: %m\n"); 652 opipe[0] = opipe[1] = -1; 653 } 654 } 655 656 if (in->_stderr.fd.fd > -2) { 657 if (pipe(epipe)) { 658 ULOG_WARN("pipe() failed: %m\n"); 659 epipe[0] = epipe[1] = -1; 660 } 661 } 662 663 in->restart = false; 664 in->halt = false; 665 666 if (!in->valid) 667 return; 668 669 pid = fork(); 670 if (pid < 0) 671 return; 672 673 if (!pid) { 674 uloop_done(); 675 closefd(opipe[0]); 676 closefd(epipe[0]); 677 ret = instance_add_cgroup(in->srv->name, in->name); 678 if (ret) 679 ULOG_WARN("failed adding instance cgroup for %s: %s\n", 680 in->srv->name, strerror(-ret)); 681 682 instance_run(in, opipe[1], epipe[1]); 683 return; 684 } 685 686 P_DEBUG(2, "Started instance %s::%s[%d]\n", in->srv->name, in->name, pid); 687 in->proc.pid = pid; 688 instance_writepid(in); 689 clock_gettime(CLOCK_MONOTONIC, &in->start); 690 uloop_process_add(&in->proc); 691 692 if (opipe[0] > -1) { 693 ustream_fd_init(&in->_stdout, opipe[0]); 694 closefd(opipe[1]); 695 fcntl(opipe[0], F_SETFD, FD_CLOEXEC); 696 } 697 698 if (epipe[0] > -1) { 699 ustream_fd_init(&in->_stderr, epipe[0]); 700 closefd(epipe[1]); 701 fcntl(epipe[0], F_SETFD, FD_CLOEXEC); 702 } 703 704 if (in->watchdog.mode != INSTANCE_WATCHDOG_MODE_DISABLED) { 705 uloop_timeout_set(&in->watchdog.timeout, in->watchdog.freq * 1000); 706 P_DEBUG(2, "Started instance %s::%s watchdog timer : timeout = %d\n", in->srv->name, in->name, in->watchdog.freq); 707 } 708 709 service_event("instance.start", in->srv->name, in->name); 710 } 711 712 static void 713 instance_stdio(struct ustream *s, int prio, struct service_instance *in) 714 { 715 char *newline, *str, *arg0, ident[32]; 716 int len; 717 718 arg0 = basename(blobmsg_data(blobmsg_data(in->command))); 719 snprintf(ident, sizeof(ident), "%s[%d]", arg0, in->proc.pid); 720 ulog_open(ULOG_SYSLOG, in->syslog_facility, ident); 721 722 do { 723 str = ustream_get_read_buf(s, &len); 724 if (!str) 725 break; 726 727 newline = memchr(str, '\n', len); 728 if (!newline && (s->r.buffer_len != len)) 729 break; 730 731 if (newline) { 732 *newline = 0; 733 len = newline + 1 - str; 734 } 735 ulog(prio, "%s\n", str); 736 737 ustream_consume(s, len); 738 } while (1); 739 740 ulog_open(ULOG_SYSLOG, LOG_DAEMON, "procd"); 741 } 742 743 static void 744 instance_stdout(struct ustream *s, int bytes) 745 { 746 instance_stdio(s, LOG_INFO, 747 container_of(s, struct service_instance, _stdout.stream)); 748 } 749 750 static void 751 instance_console(struct ustream *s, int bytes) 752 { 753 struct service_instance *in = container_of(s, struct service_instance, console.stream); 754 char *buf; 755 int len; 756 757 do { 758 buf = ustream_get_read_buf(s, &len); 759 if (!buf) 760 break; 761 762 ulog(LOG_INFO, "out: %s\n", buf); 763 764 /* test if console client is attached */ 765 if (in->console_client.fd.fd > -1) 766 ustream_write(&in->console_client.stream, buf, len, false); 767 768 ustream_consume(s, len); 769 } while (1); 770 } 771 772 static void 773 instance_console_client(struct ustream *s, int bytes) 774 { 775 struct service_instance *in = container_of(s, struct service_instance, console_client.stream); 776 char *buf; 777 int len; 778 779 do { 780 buf = ustream_get_read_buf(s, &len); 781 if (!buf) 782 break; 783 784 ulog(LOG_INFO, "in: %s\n", buf); 785 ustream_write(&in->console.stream, buf, len, false); 786 ustream_consume(s, len); 787 } while (1); 788 } 789 790 static void 791 instance_stderr(struct ustream *s, int bytes) 792 { 793 instance_stdio(s, LOG_ERR, 794 container_of(s, struct service_instance, _stderr.stream)); 795 } 796 797 static void 798 instance_timeout(struct uloop_timeout *t) 799 { 800 struct service_instance *in; 801 802 in = container_of(t, struct service_instance, timeout); 803 804 if (in->halt) { 805 LOG("Instance %s::%s pid %d not stopped on SIGTERM, sending SIGKILL instead\n", 806 in->srv->name, in->name, in->proc.pid); 807 kill(in->proc.pid, SIGKILL); 808 } else if (in->restart || in->respawn) { 809 instance_start(in); 810 rc(in->srv->name, "running"); 811 } 812 } 813 814 static void 815 instance_delete(struct service_instance *in) 816 { 817 struct service *s = in->srv; 818 819 avl_delete(&s->instances.avl, &in->node.avl); 820 instance_free(in); 821 service_stopped(s); 822 } 823 824 static int 825 instance_exit_code(int ret) 826 { 827 if (WIFEXITED(ret)) { 828 return WEXITSTATUS(ret); 829 } 830 831 if (WIFSIGNALED(ret)) { 832 return SIGNALLED_OFFSET + WTERMSIG(ret); 833 } 834 835 if (WIFSTOPPED(ret)) { 836 return WSTOPSIG(ret); 837 } 838 839 return 1; 840 } 841 842 static void 843 instance_exit(struct uloop_process *p, int ret) 844 { 845 struct service_instance *in; 846 bool restart = false; 847 struct timespec tp; 848 long runtime; 849 850 in = container_of(p, struct service_instance, proc); 851 852 clock_gettime(CLOCK_MONOTONIC, &tp); 853 runtime = tp.tv_sec - in->start.tv_sec; 854 855 P_DEBUG(2, "Instance %s::%s exit with error code %d after %ld seconds\n", in->srv->name, in->name, ret, runtime); 856 857 in->exit_code = instance_exit_code(ret); 858 uloop_timeout_cancel(&in->timeout); 859 uloop_timeout_cancel(&in->watchdog.timeout); 860 service_event("instance.stop", in->srv->name, in->name); 861 862 if (in->halt) { 863 instance_removepid(in); 864 if (in->restart) 865 restart = true; 866 else 867 instance_delete(in); 868 } else if (in->restart) { 869 restart = true; 870 } else if (in->respawn) { 871 if (runtime < in->respawn_threshold) 872 in->respawn_count++; 873 else 874 in->respawn_count = 0; 875 if (in->respawn_count > in->respawn_retry && in->respawn_retry > 0 ) { 876 LOG("Instance %s::%s s in a crash loop %d crashes, %ld seconds since last crash\n", 877 in->srv->name, in->name, in->respawn_count, runtime); 878 in->restart = in->respawn = 0; 879 in->halt = 1; 880 service_event("instance.fail", in->srv->name, in->name); 881 } else { 882 service_event("instance.respawn", in->srv->name, in->name); 883 uloop_timeout_set(&in->timeout, in->respawn_timeout * 1000); 884 } 885 } 886 887 if (restart) { 888 instance_start(in); 889 rc(in->srv->name, "running"); 890 } 891 } 892 893 void 894 instance_stop(struct service_instance *in, bool halt) 895 { 896 if (!in->proc.pending) { 897 if (halt) 898 instance_delete(in); 899 return; 900 } 901 in->halt = halt; 902 in->restart = in->respawn = false; 903 kill(in->proc.pid, SIGTERM); 904 if (!in->has_jail) 905 uloop_timeout_set(&in->timeout, in->term_timeout * 1000); 906 } 907 908 static void 909 instance_restart(struct service_instance *in) 910 { 911 if (!in->proc.pending) 912 return; 913 914 if (in->reload_signal) { 915 kill(in->proc.pid, in->reload_signal); 916 return; 917 } 918 919 in->halt = true; 920 in->restart = true; 921 kill(in->proc.pid, SIGTERM); 922 if (!in->has_jail) 923 uloop_timeout_set(&in->timeout, in->term_timeout * 1000); 924 } 925 926 static void 927 instance_watchdog(struct uloop_timeout *t) 928 { 929 struct service_instance *in = container_of(t, struct service_instance, watchdog.timeout); 930 931 P_DEBUG(3, "instance %s::%s watchdog timer expired\n", in->srv->name, in->name); 932 933 if (in->respawn) 934 instance_restart(in); 935 else 936 instance_stop(in, true); 937 } 938 939 static bool string_changed(const char *a, const char *b) 940 { 941 return !((!a && !b) || (a && b && !strcmp(a, b))); 942 } 943 944 static bool 945 instance_config_changed(struct service_instance *in, struct service_instance *in_new) 946 { 947 if (!in->valid) 948 return true; 949 950 if (!blob_attr_equal(in->command, in_new->command)) 951 return true; 952 953 if (string_changed(in->bundle, in_new->bundle)) 954 return true; 955 956 if (string_changed(in->extroot, in_new->extroot)) 957 return true; 958 959 if (string_changed(in->overlaydir, in_new->overlaydir)) 960 return true; 961 962 if (string_changed(in->tmpoverlaysize, in_new->tmpoverlaysize)) 963 return true; 964 965 if (!blobmsg_list_equal(&in->env, &in_new->env)) 966 return true; 967 968 if (!blobmsg_list_equal(&in->netdev, &in_new->netdev)) 969 return true; 970 971 if (!blobmsg_list_equal(&in->file, &in_new->file)) 972 return true; 973 974 if (in->nice != in_new->nice) 975 return true; 976 977 if (in->syslog_facility != in_new->syslog_facility) 978 return true; 979 980 if (string_changed(in->user, in_new->user)) 981 return true; 982 983 if (string_changed(in->group, in_new->group)) 984 return true; 985 986 if (in->uid != in_new->uid) 987 return true; 988 989 if (in->pw_gid != in_new->pw_gid) 990 return true; 991 992 if (in->gr_gid != in_new->gr_gid) 993 return true; 994 995 if (string_changed(in->pidfile, in_new->pidfile)) 996 return true; 997 998 if (in->respawn_retry != in_new->respawn_retry) 999 return true; 1000 if (in->respawn_threshold != in_new->respawn_threshold) 1001 return true; 1002 if (in->respawn_timeout != in_new->respawn_timeout) 1003 return true; 1004 1005 if (in->reload_signal != in_new->reload_signal) 1006 return true; 1007 1008 if (in->term_timeout != in_new->term_timeout) 1009 return true; 1010 1011 if (string_changed(in->seccomp, in_new->seccomp)) 1012 return true; 1013 1014 if (string_changed(in->capabilities, in_new->capabilities)) 1015 return true; 1016 1017 if (!blobmsg_list_equal(&in->limits, &in_new->limits)) 1018 return true; 1019 1020 if (!blobmsg_list_equal(&in->jail.mount, &in_new->jail.mount)) 1021 return true; 1022 1023 if (!blobmsg_list_equal(&in->jail.setns, &in_new->jail.setns)) 1024 return true; 1025 1026 if (!blobmsg_list_equal(&in->errors, &in_new->errors)) 1027 return true; 1028 1029 if (in->has_jail != in_new->has_jail) 1030 return true; 1031 1032 if (in->trace != in_new->trace) 1033 return true; 1034 1035 if (in->require_jail != in_new->require_jail) 1036 return true; 1037 1038 if (in->immediately != in_new->immediately) 1039 return true; 1040 1041 if (in->no_new_privs != in_new->no_new_privs) 1042 return true; 1043 1044 if (string_changed(in->jail.name, in_new->jail.name)) 1045 return true; 1046 1047 if (string_changed(in->jail.hostname, in_new->jail.hostname)) 1048 return true; 1049 1050 if (string_changed(in->jail.pidfile, in_new->jail.pidfile)) 1051 return true; 1052 1053 if (in->jail.flags != in_new->jail.flags) 1054 return true; 1055 1056 if (!in->watchdog.self_managed && in->watchdog.mode != in_new->watchdog.mode) 1057 return true; 1058 1059 if (!in->watchdog.self_managed && in->watchdog.freq != in_new->watchdog.freq) 1060 return true; 1061 1062 return false; 1063 } 1064 1065 static bool 1066 instance_netdev_cmp(struct blobmsg_list_node *l1, struct blobmsg_list_node *l2) 1067 { 1068 struct instance_netdev *n1 = container_of(l1, struct instance_netdev, node); 1069 struct instance_netdev *n2 = container_of(l2, struct instance_netdev, node); 1070 1071 return n1->ifindex == n2->ifindex; 1072 } 1073 1074 static void 1075 instance_netdev_update(struct blobmsg_list_node *l) 1076 { 1077 struct instance_netdev *n = container_of(l, struct instance_netdev, node); 1078 1079 n->ifindex = if_nametoindex(n->node.avl.key); 1080 } 1081 1082 static bool 1083 instance_file_cmp(struct blobmsg_list_node *l1, struct blobmsg_list_node *l2) 1084 { 1085 struct instance_file *f1 = container_of(l1, struct instance_file, node); 1086 struct instance_file *f2 = container_of(l2, struct instance_file, node); 1087 1088 return !memcmp(f1->md5, f2->md5, sizeof(f1->md5)); 1089 } 1090 1091 static void 1092 instance_file_update(struct blobmsg_list_node *l) 1093 { 1094 struct instance_file *f = container_of(l, struct instance_file, node); 1095 md5_ctx_t md5; 1096 char buf[256]; 1097 int len, fd; 1098 1099 memset(f->md5, 0, sizeof(f->md5)); 1100 1101 fd = open(l->avl.key, O_RDONLY); 1102 if (fd < 0) 1103 return; 1104 1105 md5_begin(&md5); 1106 do { 1107 len = read(fd, buf, sizeof(buf)); 1108 if (len < 0) { 1109 if (errno == EINTR) 1110 continue; 1111 1112 break; 1113 } 1114 if (!len) 1115 break; 1116 1117 md5_hash(buf, len, &md5); 1118 } while(1); 1119 1120 md5_end(f->md5, &md5); 1121 close(fd); 1122 } 1123 1124 static void 1125 instance_fill_any(struct blobmsg_list *l, struct blob_attr *cur) 1126 { 1127 if (!cur) 1128 return; 1129 1130 blobmsg_list_fill(l, blobmsg_data(cur), blobmsg_data_len(cur), false); 1131 } 1132 1133 static bool 1134 instance_fill_array(struct blobmsg_list *l, struct blob_attr *cur, blobmsg_update_cb cb, bool array) 1135 { 1136 struct blobmsg_list_node *node; 1137 1138 if (!cur) 1139 return true; 1140 1141 if (!blobmsg_check_attr_list(cur, BLOBMSG_TYPE_STRING)) 1142 return false; 1143 1144 blobmsg_list_fill(l, blobmsg_data(cur), blobmsg_data_len(cur), array); 1145 if (cb) { 1146 blobmsg_list_for_each(l, node) 1147 cb(node); 1148 } 1149 return true; 1150 } 1151 1152 static int 1153 instance_jail_parse(struct service_instance *in, struct blob_attr *attr) 1154 { 1155 struct blob_attr *tb[__JAIL_ATTR_MAX]; 1156 struct jail *jail = &in->jail; 1157 struct blobmsg_list_node *var; 1158 1159 blobmsg_parse(jail_attr, __JAIL_ATTR_MAX, tb, 1160 blobmsg_data(attr), blobmsg_data_len(attr)); 1161 1162 jail->argc = 4; 1163 1164 if (tb[JAIL_ATTR_REQUIREJAIL] && blobmsg_get_bool(tb[JAIL_ATTR_REQUIREJAIL])) { 1165 in->require_jail = true; 1166 jail->argc++; 1167 } 1168 if (tb[JAIL_ATTR_IMMEDIATELY] && blobmsg_get_bool(tb[JAIL_ATTR_IMMEDIATELY])) { 1169 in->immediately = true; 1170 jail->argc++; 1171 } 1172 if (tb[JAIL_ATTR_NAME]) { 1173 jail->name = strdup(blobmsg_get_string(tb[JAIL_ATTR_NAME])); 1174 jail->argc += 2; 1175 } 1176 if (tb[JAIL_ATTR_HOSTNAME]) { 1177 jail->hostname = strdup(blobmsg_get_string(tb[JAIL_ATTR_HOSTNAME])); 1178 jail->argc += 2; 1179 } 1180 if (tb[JAIL_ATTR_PROCFS] && blobmsg_get_bool(tb[JAIL_ATTR_PROCFS])) { 1181 jail->procfs = true; 1182 jail->argc++; 1183 } 1184 if (tb[JAIL_ATTR_SYSFS] && blobmsg_get_bool(tb[JAIL_ATTR_SYSFS])) { 1185 jail->sysfs = true; 1186 jail->argc++; 1187 } 1188 if (tb[JAIL_ATTR_UBUS] && blobmsg_get_bool(tb[JAIL_ATTR_UBUS])) { 1189 jail->ubus = true; 1190 jail->argc++; 1191 } 1192 if (tb[JAIL_ATTR_UDEBUG] && blobmsg_get_bool(tb[JAIL_ATTR_UDEBUG])) { 1193 jail->udebug = true; 1194 jail->argc++; 1195 } 1196 if (tb[JAIL_ATTR_LOG] && blobmsg_get_bool(tb[JAIL_ATTR_LOG])) { 1197 jail->log = true; 1198 jail->argc++; 1199 } 1200 if (tb[JAIL_ATTR_RONLY] && blobmsg_get_bool(tb[JAIL_ATTR_RONLY])) { 1201 jail->ronly = true; 1202 jail->argc++; 1203 } 1204 if (tb[JAIL_ATTR_NETNS] && blobmsg_get_bool(tb[JAIL_ATTR_NETNS])) { 1205 jail->netns = true; 1206 jail->argc++; 1207 } 1208 if (tb[JAIL_ATTR_USERNS] && blobmsg_get_bool(tb[JAIL_ATTR_USERNS])) { 1209 jail->userns = true; 1210 jail->argc++; 1211 } 1212 if (tb[JAIL_ATTR_CGROUPSNS] && blobmsg_get_bool(tb[JAIL_ATTR_CGROUPSNS])) { 1213 jail->cgroupsns = true; 1214 jail->argc++; 1215 } 1216 if (tb[JAIL_ATTR_CONSOLE] && blobmsg_get_bool(tb[JAIL_ATTR_CONSOLE])) { 1217 jail->console = true; 1218 jail->argc++; 1219 } 1220 if (tb[JAIL_ATTR_PIDFILE]) { 1221 jail->pidfile = strdup(blobmsg_get_string(tb[JAIL_ATTR_PIDFILE])); 1222 jail->argc += 2; 1223 } 1224 1225 if (tb[JAIL_ATTR_SETNS]) { 1226 struct blob_attr *cur; 1227 int rem; 1228 1229 blobmsg_for_each_attr(cur, tb[JAIL_ATTR_SETNS], rem) 1230 jail->argc += 2; 1231 blobmsg_list_fill(&jail->setns, blobmsg_data(tb[JAIL_ATTR_SETNS]), 1232 blobmsg_data_len(tb[JAIL_ATTR_SETNS]), true); 1233 } 1234 1235 if (tb[JAIL_ATTR_MOUNT]) { 1236 struct blob_attr *cur; 1237 int rem; 1238 1239 blobmsg_for_each_attr(cur, tb[JAIL_ATTR_MOUNT], rem) 1240 jail->argc += 2; 1241 instance_fill_array(&jail->mount, tb[JAIL_ATTR_MOUNT], NULL, false); 1242 } 1243 1244 blobmsg_list_for_each(&in->env, var) 1245 jail->argc += 2; 1246 1247 if (in->seccomp) 1248 jail->argc += 2; 1249 1250 if (in->capabilities) 1251 jail->argc += 2; 1252 1253 if (in->user) 1254 jail->argc += 2; 1255 1256 if (in->group) 1257 jail->argc += 2; 1258 1259 if (in->extroot) 1260 jail->argc += 2; 1261 1262 if (in->overlaydir) 1263 jail->argc += 2; 1264 1265 if (in->tmpoverlaysize) 1266 jail->argc += 2; 1267 1268 if (in->no_new_privs) 1269 jail->argc++; 1270 1271 if (in->bundle) 1272 jail->argc += 2; 1273 1274 return true; 1275 } 1276 1277 static bool 1278 instance_config_parse_command(struct service_instance *in, struct blob_attr **tb) 1279 { 1280 struct blob_attr *cur, *cur2; 1281 bool ret = false; 1282 int rem; 1283 1284 cur = tb[INSTANCE_ATTR_COMMAND]; 1285 if (!cur) { 1286 in->command = NULL; 1287 return true; 1288 } 1289 1290 if (!blobmsg_check_attr_list(cur, BLOBMSG_TYPE_STRING)) 1291 return false; 1292 1293 blobmsg_for_each_attr(cur2, cur, rem) { 1294 ret = true; 1295 break; 1296 } 1297 1298 in->command = cur; 1299 return ret; 1300 } 1301 1302 static bool 1303 instance_config_parse(struct service_instance *in) 1304 { 1305 struct blob_attr *tb[__INSTANCE_ATTR_MAX]; 1306 struct blob_attr *cur, *cur2; 1307 struct stat s; 1308 int rem, r; 1309 1310 blobmsg_parse(instance_attr, __INSTANCE_ATTR_MAX, tb, 1311 blobmsg_data(in->config), blobmsg_data_len(in->config)); 1312 1313 if (!tb[INSTANCE_ATTR_BUNDLE] && !instance_config_parse_command(in, tb)) 1314 return false; 1315 1316 if (tb[INSTANCE_ATTR_TERMTIMEOUT]) 1317 in->term_timeout = blobmsg_get_u32(tb[INSTANCE_ATTR_TERMTIMEOUT]); 1318 if (tb[INSTANCE_ATTR_RESPAWN]) { 1319 int i = 0; 1320 uint32_t vals[3] = { 3600, 5, 5}; 1321 1322 blobmsg_for_each_attr(cur2, tb[INSTANCE_ATTR_RESPAWN], rem) { 1323 if ((i >= 3) && (blobmsg_type(cur2) == BLOBMSG_TYPE_STRING)) 1324 continue; 1325 vals[i] = atoi(blobmsg_get_string(cur2)); 1326 i++; 1327 } 1328 in->respawn = true; 1329 in->respawn_count = 0; 1330 in->respawn_threshold = vals[0]; 1331 in->respawn_timeout = vals[1]; 1332 in->respawn_retry = vals[2]; 1333 } 1334 if (tb[INSTANCE_ATTR_TRIGGER]) { 1335 in->trigger = tb[INSTANCE_ATTR_TRIGGER]; 1336 trigger_add(in->trigger, in); 1337 } 1338 1339 if (tb[INSTANCE_ATTR_WATCH]) { 1340 blobmsg_for_each_attr(cur2, tb[INSTANCE_ATTR_WATCH], rem) { 1341 if (blobmsg_type(cur2) != BLOBMSG_TYPE_STRING) 1342 continue; 1343 P_DEBUG(3, "watch for %s\n", blobmsg_get_string(cur2)); 1344 watch_add(blobmsg_get_string(cur2), in); 1345 } 1346 } 1347 1348 if ((cur = tb[INSTANCE_ATTR_NICE])) { 1349 in->nice = (int8_t) blobmsg_get_u32(cur); 1350 if (in->nice < -20 || in->nice > 20) 1351 return false; 1352 } 1353 1354 if (tb[INSTANCE_ATTR_USER]) { 1355 const char *user = blobmsg_get_string(tb[INSTANCE_ATTR_USER]); 1356 struct passwd *p = getpwnam(user); 1357 if (p) { 1358 in->user = strdup(user); 1359 in->uid = p->pw_uid; 1360 in->gr_gid = in->pw_gid = p->pw_gid; 1361 } 1362 } 1363 1364 if (tb[INSTANCE_ATTR_GROUP]) { 1365 const char *group = blobmsg_get_string(tb[INSTANCE_ATTR_GROUP]); 1366 struct group *p = getgrnam(group); 1367 if (p) { 1368 in->group = strdup(group); 1369 in->gr_gid = p->gr_gid; 1370 } 1371 } 1372 1373 if (tb[INSTANCE_ATTR_TRACE]) 1374 in->trace = blobmsg_get_bool(tb[INSTANCE_ATTR_TRACE]); 1375 1376 if (tb[INSTANCE_ATTR_NO_NEW_PRIVS]) 1377 in->no_new_privs = blobmsg_get_bool(tb[INSTANCE_ATTR_NO_NEW_PRIVS]); 1378 1379 if (!in->trace && tb[INSTANCE_ATTR_SECCOMP]) 1380 in->seccomp = strdup(blobmsg_get_string(tb[INSTANCE_ATTR_SECCOMP])); 1381 1382 if (tb[INSTANCE_ATTR_CAPABILITIES]) 1383 in->capabilities = strdup(blobmsg_get_string(tb[INSTANCE_ATTR_CAPABILITIES])); 1384 1385 if (tb[INSTANCE_ATTR_EXTROOT]) 1386 in->extroot = strdup(blobmsg_get_string(tb[INSTANCE_ATTR_EXTROOT])); 1387 1388 if (tb[INSTANCE_ATTR_OVERLAYDIR]) 1389 in->overlaydir = strdup(blobmsg_get_string(tb[INSTANCE_ATTR_OVERLAYDIR])); 1390 1391 if (tb[INSTANCE_ATTR_TMPOVERLAYSIZE]) 1392 in->tmpoverlaysize = strdup(blobmsg_get_string(tb[INSTANCE_ATTR_TMPOVERLAYSIZE])); 1393 1394 if (tb[INSTANCE_ATTR_BUNDLE]) 1395 in->bundle = strdup(blobmsg_get_string(tb[INSTANCE_ATTR_BUNDLE])); 1396 1397 if (tb[INSTANCE_ATTR_PIDFILE]) { 1398 char *pidfile = blobmsg_get_string(tb[INSTANCE_ATTR_PIDFILE]); 1399 if (pidfile) 1400 in->pidfile = strdup(pidfile); 1401 } 1402 1403 if (tb[INSTANCE_ATTR_RELOADSIG]) 1404 in->reload_signal = blobmsg_get_u32(tb[INSTANCE_ATTR_RELOADSIG]); 1405 1406 if (tb[INSTANCE_ATTR_STDOUT] && blobmsg_get_bool(tb[INSTANCE_ATTR_STDOUT])) 1407 in->_stdout.fd.fd = -1; 1408 1409 if (tb[INSTANCE_ATTR_STDERR] && blobmsg_get_bool(tb[INSTANCE_ATTR_STDERR])) 1410 in->_stderr.fd.fd = -1; 1411 1412 instance_fill_any(&in->data, tb[INSTANCE_ATTR_DATA]); 1413 1414 if (!instance_fill_array(&in->env, tb[INSTANCE_ATTR_ENV], NULL, false)) 1415 return false; 1416 1417 if (!instance_fill_array(&in->netdev, tb[INSTANCE_ATTR_NETDEV], instance_netdev_update, true)) 1418 return false; 1419 1420 if (!instance_fill_array(&in->file, tb[INSTANCE_ATTR_FILE], instance_file_update, true)) 1421 return false; 1422 1423 if (!instance_fill_array(&in->limits, tb[INSTANCE_ATTR_LIMITS], NULL, false)) 1424 return false; 1425 1426 if (!instance_fill_array(&in->errors, tb[INSTANCE_ATTR_ERROR], NULL, true)) 1427 return false; 1428 1429 if (tb[INSTANCE_ATTR_FACILITY]) { 1430 int facility = syslog_facility_str_to_int(blobmsg_get_string(tb[INSTANCE_ATTR_FACILITY])); 1431 if (facility != -1) { 1432 in->syslog_facility = facility; 1433 P_DEBUG(3, "setting facility '%s'\n", blobmsg_get_string(tb[INSTANCE_ATTR_FACILITY])); 1434 } else 1435 P_DEBUG(3, "unknown syslog facility '%s' given, using default (LOG_DAEMON)\n", blobmsg_get_string(tb[INSTANCE_ATTR_FACILITY])); 1436 } 1437 1438 if (tb[INSTANCE_ATTR_WATCHDOG]) { 1439 int i = 0; 1440 uint32_t vals[2] = { 0, 30 }; 1441 1442 blobmsg_for_each_attr(cur2, tb[INSTANCE_ATTR_WATCHDOG], rem) { 1443 if (i >= 2) 1444 break; 1445 1446 vals[i] = atoi(blobmsg_get_string(cur2)); 1447 i++; 1448 } 1449 1450 if (vals[0] >= 0 && vals[0] < __INSTANCE_WATCHDOG_MODE_MAX) { 1451 in->watchdog.mode = vals[0]; 1452 P_DEBUG(3, "setting watchdog mode (%d)\n", vals[0]); 1453 } else { 1454 in->watchdog.mode = 0; 1455 P_DEBUG(3, "unknown watchdog mode (%d) given, using default (0)\n", vals[0]); 1456 } 1457 1458 if (vals[1] > 0) { 1459 in->watchdog.freq = vals[1]; 1460 P_DEBUG(3, "setting watchdog timeout (%d)\n", vals[0]); 1461 } else { 1462 in->watchdog.freq = 30; 1463 P_DEBUG(3, "invalid watchdog timeout (%d) given, using default (30)\n", vals[1]); 1464 } 1465 } 1466 1467 if (!in->trace && tb[INSTANCE_ATTR_JAIL]) 1468 in->has_jail = instance_jail_parse(in, tb[INSTANCE_ATTR_JAIL]); 1469 1470 if (in->has_jail) { 1471 r = stat(UJAIL_BIN_PATH, &s); 1472 if (r < 0) { 1473 if (in->require_jail) { 1474 ERROR("Cannot jail service %s::%s. %s: %m (%d)\n", 1475 in->srv->name, in->name, UJAIL_BIN_PATH, r); 1476 return false; 1477 } 1478 P_DEBUG(2, "unable to find %s: %m (%d)\n", UJAIL_BIN_PATH, r); 1479 in->has_jail = false; 1480 } 1481 } 1482 1483 return true; 1484 } 1485 1486 static void 1487 instance_config_cleanup(struct service_instance *in) 1488 { 1489 blobmsg_list_free(&in->env); 1490 blobmsg_list_free(&in->data); 1491 blobmsg_list_free(&in->netdev); 1492 blobmsg_list_free(&in->file); 1493 blobmsg_list_free(&in->limits); 1494 blobmsg_list_free(&in->errors); 1495 blobmsg_list_free(&in->jail.mount); 1496 blobmsg_list_free(&in->jail.setns); 1497 } 1498 1499 static void 1500 instance_config_move_strdup(char **dst, char *src) 1501 { 1502 if (*dst) { 1503 free(*dst); 1504 *dst = NULL; 1505 } 1506 1507 if (!src) 1508 return; 1509 1510 *dst = strdup(src); 1511 } 1512 1513 static void 1514 instance_config_move(struct service_instance *in, struct service_instance *in_src) 1515 { 1516 instance_config_cleanup(in); 1517 blobmsg_list_move(&in->env, &in_src->env); 1518 blobmsg_list_move(&in->data, &in_src->data); 1519 blobmsg_list_move(&in->netdev, &in_src->netdev); 1520 blobmsg_list_move(&in->file, &in_src->file); 1521 blobmsg_list_move(&in->limits, &in_src->limits); 1522 blobmsg_list_move(&in->errors, &in_src->errors); 1523 blobmsg_list_move(&in->jail.mount, &in_src->jail.mount); 1524 blobmsg_list_move(&in->jail.setns, &in_src->jail.setns); 1525 in->trigger = in_src->trigger; 1526 in->command = in_src->command; 1527 in->respawn = in_src->respawn; 1528 in->respawn_retry = in_src->respawn_retry; 1529 in->respawn_threshold = in_src->respawn_threshold; 1530 in->respawn_timeout = in_src->respawn_timeout; 1531 in->reload_signal = in_src->reload_signal; 1532 in->term_timeout = in_src->term_timeout; 1533 if (!in->watchdog.self_managed) { 1534 // Note: in->watchdog.timeout is in a linked list; do not copy 1535 in->watchdog.mode = in_src->watchdog.mode; 1536 in->watchdog.freq = in_src->watchdog.freq; 1537 } 1538 in->name = in_src->name; 1539 in->nice = in_src->nice; 1540 in->trace = in_src->trace; 1541 in->node.avl.key = in_src->node.avl.key; 1542 in->syslog_facility = in_src->syslog_facility; 1543 in->require_jail = in_src->require_jail; 1544 in->no_new_privs = in_src->no_new_privs; 1545 in->immediately = in_src->immediately; 1546 in->uid = in_src->uid; 1547 in->pw_gid = in_src->pw_gid; 1548 in->gr_gid = in_src->gr_gid; 1549 1550 in->has_jail = in_src->has_jail; 1551 in->jail.flags = in_src->jail.flags; 1552 in->jail.argc = in_src->jail.argc; 1553 1554 instance_config_move_strdup(&in->pidfile, in_src->pidfile); 1555 instance_config_move_strdup(&in->seccomp, in_src->seccomp); 1556 instance_config_move_strdup(&in->capabilities, in_src->capabilities); 1557 instance_config_move_strdup(&in->bundle, in_src->bundle); 1558 instance_config_move_strdup(&in->extroot, in_src->extroot); 1559 instance_config_move_strdup(&in->overlaydir, in_src->overlaydir); 1560 instance_config_move_strdup(&in->tmpoverlaysize, in_src->tmpoverlaysize); 1561 instance_config_move_strdup(&in->user, in_src->user); 1562 instance_config_move_strdup(&in->group, in_src->group); 1563 instance_config_move_strdup(&in->jail.name, in_src->jail.name); 1564 instance_config_move_strdup(&in->jail.hostname, in_src->jail.hostname); 1565 instance_config_move_strdup(&in->jail.pidfile, in_src->jail.pidfile); 1566 1567 free(in->config); 1568 in->config = in_src->config; 1569 in_src->config = NULL; 1570 } 1571 1572 void 1573 instance_update(struct service_instance *in, struct service_instance *in_new) 1574 { 1575 bool changed = instance_config_changed(in, in_new); 1576 bool running = in->proc.pending; 1577 bool stopping = in->halt; 1578 1579 if (!running || stopping) { 1580 instance_config_move(in, in_new); 1581 instance_start(in); 1582 } else { 1583 if (changed) 1584 instance_restart(in); 1585 else if (!blobmsg_list_equal(&in->data, &in_new->data)) { 1586 service_data_trigger(&in->data); 1587 service_data_trigger(&in_new->data); 1588 } 1589 instance_config_move(in, in_new); 1590 /* restart happens in the child callback handler */ 1591 } 1592 } 1593 1594 void 1595 instance_free(struct service_instance *in) 1596 { 1597 service_data_trigger(&in->data); 1598 instance_free_stdio(in); 1599 uloop_process_delete(&in->proc); 1600 uloop_timeout_cancel(&in->timeout); 1601 uloop_timeout_cancel(&in->watchdog.timeout); 1602 trigger_del(in); 1603 watch_del(in); 1604 instance_config_cleanup(in); 1605 free(in->config); 1606 free(in->data_blob); 1607 free(in->user); 1608 free(in->group); 1609 free(in->extroot); 1610 free(in->overlaydir); 1611 free(in->tmpoverlaysize); 1612 free(in->bundle); 1613 free(in->jail.name); 1614 free(in->jail.hostname); 1615 free(in->jail.pidfile); 1616 free(in->seccomp); 1617 free(in->capabilities); 1618 free(in->pidfile); 1619 free(in); 1620 } 1621 1622 void 1623 instance_init(struct service_instance *in, struct service *s, struct blob_attr *config) 1624 { 1625 config = blob_memdup(config); 1626 in->srv = s; 1627 in->name = blobmsg_name(config); 1628 in->config = config; 1629 in->timeout.cb = instance_timeout; 1630 in->proc.cb = instance_exit; 1631 in->term_timeout = 5; 1632 in->syslog_facility = LOG_DAEMON; 1633 in->exit_code = 0; 1634 in->require_jail = false; 1635 in->immediately = false; 1636 1637 in->_stdout.fd.fd = -2; 1638 in->_stdout.stream.string_data = true; 1639 in->_stdout.stream.notify_read = instance_stdout; 1640 1641 in->_stderr.fd.fd = -2; 1642 in->_stderr.stream.string_data = true; 1643 in->_stderr.stream.notify_read = instance_stderr; 1644 1645 in->console.fd.fd = -2; 1646 in->console.stream.string_data = true; 1647 in->console.stream.notify_read = instance_console; 1648 1649 in->console_client.fd.fd = -2; 1650 in->console_client.stream.string_data = true; 1651 in->console_client.stream.notify_read = instance_console_client; 1652 1653 blobmsg_list_init(&in->netdev, struct instance_netdev, node, instance_netdev_cmp); 1654 blobmsg_list_init(&in->file, struct instance_file, node, instance_file_cmp); 1655 blobmsg_list_simple_init(&in->env); 1656 blobmsg_list_simple_init(&in->data); 1657 blobmsg_list_simple_init(&in->limits); 1658 blobmsg_list_simple_init(&in->errors); 1659 blobmsg_list_simple_init(&in->jail.mount); 1660 blobmsg_list_simple_init(&in->jail.setns); 1661 1662 in->watchdog.timeout.cb = instance_watchdog; 1663 1664 in->valid = instance_config_parse(in); 1665 service_data_trigger(&in->data); 1666 } 1667 1668 void instance_dump(struct blob_buf *b, struct service_instance *in, int verbose) 1669 { 1670 void *i; 1671 1672 if (!in->valid) 1673 return; 1674 1675 i = blobmsg_open_table(b, in->name); 1676 blobmsg_add_u8(b, "running", in->proc.pending); 1677 if (in->proc.pending) 1678 blobmsg_add_u32(b, "pid", in->proc.pid); 1679 if (in->command) 1680 blobmsg_add_blob(b, in->command); 1681 if (in->bundle) 1682 blobmsg_add_string(b, "bundle", in->bundle); 1683 blobmsg_add_u32(b, "term_timeout", in->term_timeout); 1684 if (!in->proc.pending) 1685 blobmsg_add_u32(b, "exit_code", in->exit_code); 1686 1687 if (!avl_is_empty(&in->errors.avl)) { 1688 struct blobmsg_list_node *var; 1689 void *e = blobmsg_open_array(b, "errors"); 1690 blobmsg_list_for_each(&in->errors, var) 1691 blobmsg_add_string(b, NULL, blobmsg_data(var->data)); 1692 blobmsg_close_table(b, e); 1693 } 1694 1695 if (!avl_is_empty(&in->env.avl)) { 1696 struct blobmsg_list_node *var; 1697 void *e = blobmsg_open_table(b, "env"); 1698 blobmsg_list_for_each(&in->env, var) 1699 blobmsg_add_string(b, blobmsg_name(var->data), blobmsg_data(var->data)); 1700 blobmsg_close_table(b, e); 1701 } 1702 1703 if (!avl_is_empty(&in->data.avl)) { 1704 struct blobmsg_list_node *var; 1705 void *e = blobmsg_open_table(b, "data"); 1706 blobmsg_list_for_each(&in->data, var) 1707 blobmsg_add_blob(b, var->data); 1708 blobmsg_close_table(b, e); 1709 } 1710 1711 if (!avl_is_empty(&in->limits.avl)) { 1712 struct blobmsg_list_node *var; 1713 void *e = blobmsg_open_table(b, "limits"); 1714 blobmsg_list_for_each(&in->limits, var) 1715 blobmsg_add_string(b, blobmsg_name(var->data), blobmsg_data(var->data)); 1716 blobmsg_close_table(b, e); 1717 } 1718 1719 if (!avl_is_empty(&in->netdev.avl)) { 1720 struct blobmsg_list_node *var; 1721 void *n = blobmsg_open_array(b, "netdev"); 1722 1723 blobmsg_list_for_each(&in->netdev, var) 1724 blobmsg_add_string(b, NULL, blobmsg_data(var->data)); 1725 blobmsg_close_array(b, n); 1726 } 1727 1728 if (in->reload_signal) 1729 blobmsg_add_u32(b, "reload_signal", in->reload_signal); 1730 1731 if (in->respawn) { 1732 void *r = blobmsg_open_table(b, "respawn"); 1733 blobmsg_add_u32(b, "threshold", in->respawn_threshold); 1734 blobmsg_add_u32(b, "timeout", in->respawn_timeout); 1735 blobmsg_add_u32(b, "retry", in->respawn_retry); 1736 blobmsg_close_table(b, r); 1737 } 1738 1739 if (in->trace) 1740 blobmsg_add_u8(b, "trace", true); 1741 1742 if (in->no_new_privs) 1743 blobmsg_add_u8(b, "no_new_privs", true); 1744 1745 if (in->seccomp) 1746 blobmsg_add_string(b, "seccomp", in->seccomp); 1747 1748 if (in->capabilities) 1749 blobmsg_add_string(b, "capabilities", in->capabilities); 1750 1751 if (in->pidfile) 1752 blobmsg_add_string(b, "pidfile", in->pidfile); 1753 1754 if (in->user) 1755 blobmsg_add_string(b, "user", in->user); 1756 1757 if (in->group) 1758 blobmsg_add_string(b, "group", in->group); 1759 1760 if (in->has_jail) { 1761 void *r = blobmsg_open_table(b, "jail"); 1762 if (in->jail.name) 1763 blobmsg_add_string(b, "name", in->jail.name); 1764 if (!in->bundle) { 1765 if (in->jail.hostname) 1766 blobmsg_add_string(b, "hostname", in->jail.hostname); 1767 1768 blobmsg_add_u8(b, "procfs", in->jail.procfs); 1769 blobmsg_add_u8(b, "sysfs", in->jail.sysfs); 1770 blobmsg_add_u8(b, "ubus", in->jail.ubus); 1771 blobmsg_add_u8(b, "log", in->jail.log); 1772 blobmsg_add_u8(b, "ronly", in->jail.ronly); 1773 blobmsg_add_u8(b, "netns", in->jail.netns); 1774 blobmsg_add_u8(b, "userns", in->jail.userns); 1775 blobmsg_add_u8(b, "cgroupsns", in->jail.cgroupsns); 1776 } else { 1777 if (in->jail.pidfile) 1778 blobmsg_add_string(b, "pidfile", in->jail.pidfile); 1779 1780 blobmsg_add_u8(b, "immediately", in->immediately); 1781 } 1782 blobmsg_add_u8(b, "console", (in->console.fd.fd > -1)); 1783 blobmsg_close_table(b, r); 1784 if (!avl_is_empty(&in->jail.mount.avl)) { 1785 struct blobmsg_list_node *var; 1786 void *e = blobmsg_open_table(b, "mount"); 1787 blobmsg_list_for_each(&in->jail.mount, var) 1788 blobmsg_add_string(b, blobmsg_name(var->data), blobmsg_data(var->data)); 1789 blobmsg_close_table(b, e); 1790 } 1791 1792 if (!avl_is_empty(&in->jail.setns.avl)) { 1793 struct blobmsg_list_node *var; 1794 void *s = blobmsg_open_array(b, "setns"); 1795 blobmsg_list_for_each(&in->jail.setns, var) 1796 blobmsg_add_blob(b, var->data); 1797 blobmsg_close_array(b, s); 1798 } 1799 } 1800 1801 if (in->extroot) 1802 blobmsg_add_string(b, "extroot", in->extroot); 1803 if (in->overlaydir) 1804 blobmsg_add_string(b, "overlaydir", in->overlaydir); 1805 if (in->tmpoverlaysize) 1806 blobmsg_add_string(b, "tmpoverlaysize", in->tmpoverlaysize); 1807 1808 if (verbose && in->trigger) 1809 blobmsg_add_blob(b, in->trigger); 1810 1811 if (in->watchdog.mode != INSTANCE_WATCHDOG_MODE_DISABLED) { 1812 void *r = blobmsg_open_table(b, "watchdog"); 1813 blobmsg_add_u32(b, "mode", in->watchdog.mode); 1814 blobmsg_add_u32(b, "timeout", in->watchdog.freq); 1815 blobmsg_close_table(b, r); 1816 } 1817 1818 blobmsg_close_table(b, i); 1819 } 1820
This page was automatically generated by LXR 0.3.1. • OpenWrt