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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt