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

Sources/procd/service/instance.c

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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt