• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/procd/service/instance.c

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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt