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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt