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