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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt