52f5cf29bb38a19387e9f8f5d90673f97664e079
[project/procd.git] / 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 <net/if.h>
21 #include <unistd.h>
22 #include <stdint.h>
23 #include <stdio.h>
24 #include <fcntl.h>
25 #include <pwd.h>
26 #include <libgen.h>
27 #include <unistd.h>
28
29 #include <libubox/md5.h>
30
31 #include "../procd.h"
32
33 #include "service.h"
34 #include "instance.h"
35
36
37 enum {
38         INSTANCE_ATTR_COMMAND,
39         INSTANCE_ATTR_ENV,
40         INSTANCE_ATTR_DATA,
41         INSTANCE_ATTR_NETDEV,
42         INSTANCE_ATTR_FILE,
43         INSTANCE_ATTR_TRIGGER,
44         INSTANCE_ATTR_RESPAWN,
45         INSTANCE_ATTR_NICE,
46         INSTANCE_ATTR_LIMITS,
47         INSTANCE_ATTR_WATCH,
48         INSTANCE_ATTR_ERROR,
49         INSTANCE_ATTR_USER,
50         INSTANCE_ATTR_STDOUT,
51         INSTANCE_ATTR_STDERR,
52         INSTANCE_ATTR_NO_NEW_PRIVS,
53         INSTANCE_ATTR_JAIL,
54         INSTANCE_ATTR_TRACE,
55         INSTANCE_ATTR_SECCOMP,
56         __INSTANCE_ATTR_MAX
57 };
58
59 static const struct blobmsg_policy instance_attr[__INSTANCE_ATTR_MAX] = {
60         [INSTANCE_ATTR_COMMAND] = { "command", BLOBMSG_TYPE_ARRAY },
61         [INSTANCE_ATTR_ENV] = { "env", BLOBMSG_TYPE_TABLE },
62         [INSTANCE_ATTR_DATA] = { "data", BLOBMSG_TYPE_TABLE },
63         [INSTANCE_ATTR_NETDEV] = { "netdev", BLOBMSG_TYPE_ARRAY },
64         [INSTANCE_ATTR_FILE] = { "file", BLOBMSG_TYPE_ARRAY },
65         [INSTANCE_ATTR_TRIGGER] = { "triggers", BLOBMSG_TYPE_ARRAY },
66         [INSTANCE_ATTR_RESPAWN] = { "respawn", BLOBMSG_TYPE_ARRAY },
67         [INSTANCE_ATTR_NICE] = { "nice", BLOBMSG_TYPE_INT32 },
68         [INSTANCE_ATTR_LIMITS] = { "limits", BLOBMSG_TYPE_TABLE },
69         [INSTANCE_ATTR_WATCH] = { "watch", BLOBMSG_TYPE_ARRAY },
70         [INSTANCE_ATTR_ERROR] = { "error", BLOBMSG_TYPE_ARRAY },
71         [INSTANCE_ATTR_USER] = { "user", BLOBMSG_TYPE_STRING },
72         [INSTANCE_ATTR_STDOUT] = { "stdout", BLOBMSG_TYPE_BOOL },
73         [INSTANCE_ATTR_STDERR] = { "stderr", BLOBMSG_TYPE_BOOL },
74         [INSTANCE_ATTR_NO_NEW_PRIVS] = { "no_new_privs", BLOBMSG_TYPE_BOOL },
75         [INSTANCE_ATTR_JAIL] = { "jail", BLOBMSG_TYPE_TABLE },
76         [INSTANCE_ATTR_TRACE] = { "trace", BLOBMSG_TYPE_BOOL },
77         [INSTANCE_ATTR_SECCOMP] = { "seccomp", BLOBMSG_TYPE_STRING },
78 };
79
80 enum {
81         JAIL_ATTR_NAME,
82         JAIL_ATTR_PROCFS,
83         JAIL_ATTR_SYSFS,
84         JAIL_ATTR_UBUS,
85         JAIL_ATTR_LOG,
86         JAIL_ATTR_RONLY,
87         JAIL_ATTR_MOUNT,
88         __JAIL_ATTR_MAX,
89 };
90
91 static const struct blobmsg_policy jail_attr[__JAIL_ATTR_MAX] = {
92         [JAIL_ATTR_NAME] = { "name", BLOBMSG_TYPE_STRING },
93         [JAIL_ATTR_PROCFS] = { "procfs", BLOBMSG_TYPE_BOOL },
94         [JAIL_ATTR_SYSFS] = { "sysfs", BLOBMSG_TYPE_BOOL },
95         [JAIL_ATTR_UBUS] = { "ubus", BLOBMSG_TYPE_BOOL },
96         [JAIL_ATTR_LOG] = { "log", BLOBMSG_TYPE_BOOL },
97         [JAIL_ATTR_RONLY] = { "ronly", BLOBMSG_TYPE_BOOL },
98         [JAIL_ATTR_MOUNT] = { "mount", BLOBMSG_TYPE_TABLE },
99 };
100
101 struct instance_netdev {
102         struct blobmsg_list_node node;
103         int ifindex;
104 };
105
106 struct instance_file {
107         struct blobmsg_list_node node;
108         uint32_t md5[4];
109 };
110
111 struct rlimit_name {
112         const char *name;
113         int resource;
114 };
115
116 static const struct rlimit_name rlimit_names[] = {
117         { "as", RLIMIT_AS },
118         { "core", RLIMIT_CORE },
119         { "cpu", RLIMIT_CPU },
120         { "data", RLIMIT_DATA },
121         { "fsize", RLIMIT_FSIZE },
122         { "memlock", RLIMIT_MEMLOCK },
123         { "msgqueue", RLIMIT_MSGQUEUE },
124         { "nice", RLIMIT_NICE },
125         { "nofile", RLIMIT_NOFILE },
126         { "nproc", RLIMIT_NPROC },
127         { "rss", RLIMIT_RSS },
128         { "rtprio", RLIMIT_RTPRIO },
129         { "sigpending", RLIMIT_SIGPENDING },
130         { "stack", RLIMIT_STACK },
131         { NULL, 0 }
132 };
133
134 static char trace[] = "/sbin/utrace";
135
136 static void closefd(int fd)
137 {
138         if (fd > STDERR_FILENO)
139                 close(fd);
140 }
141
142 static void
143 instance_limits(const char *limit, const char *value)
144 {
145         int i;
146         struct rlimit rlim;
147         unsigned long cur, max;
148
149         for (i = 0; rlimit_names[i].name != NULL; i++) {
150                 if (strcmp(rlimit_names[i].name, limit))
151                         continue;
152                 if (!strcmp(value, "unlimited")) {
153                         rlim.rlim_cur = RLIM_INFINITY;
154                         rlim.rlim_max = RLIM_INFINITY;
155                 } else {
156                         if (getrlimit(rlimit_names[i].resource, &rlim))
157                                 return;
158
159                         cur = rlim.rlim_cur;
160                         max = rlim.rlim_max;
161
162                         if (sscanf(value, "%lu %lu", &cur, &max) < 1)
163                                 return;
164
165                         rlim.rlim_cur = cur;
166                         rlim.rlim_max = max;
167                 }
168
169                 setrlimit(rlimit_names[i].resource, &rlim);
170                 return;
171         }
172 }
173
174 static inline int
175 jail_run(struct service_instance *in, char **argv)
176 {
177         struct blobmsg_list_node *var;
178         struct jail *jail = &in->jail;
179         int argc = 0;
180
181         argv[argc++] = "/sbin/ujail";
182
183         if (jail->name) {
184                 argv[argc++] = "-n";
185                 argv[argc++] = jail->name;
186         }
187
188         if (in->seccomp) {
189                 argv[argc++] = "-S";
190                 argv[argc++] = in->seccomp;
191         }
192
193         if (in->no_new_privs)
194                 argv[argc++] = "-c";
195
196         if (jail->procfs)
197                 argv[argc++] = "-p";
198
199         if (jail->sysfs)
200                 argv[argc++] = "-s";
201
202         if (jail->ubus)
203                 argv[argc++] = "-u";
204
205         if (jail->log)
206                 argv[argc++] = "-l";
207
208         if (jail->ronly)
209                 argv[argc++] = "-o";
210
211         blobmsg_list_for_each(&jail->mount, var) {
212                 const char *type = blobmsg_data(var->data);
213
214                 if (*type == '1')
215                         argv[argc++] = "-w";
216                 else
217                         argv[argc++] = "-r";
218                 argv[argc++] = (char *) blobmsg_name(var->data);
219         }
220
221         argv[argc++] = "--";
222
223         return argc;
224 }
225
226 static void
227 instance_run(struct service_instance *in, int _stdout, int _stderr)
228 {
229         struct blobmsg_list_node *var;
230         struct blob_attr *cur;
231         char **argv;
232         char *ld_preload;
233         int argc = 1; /* NULL terminated */
234         int rem, _stdin;
235         bool seccomp = !in->trace && !in->has_jail && in->seccomp;
236         bool setlbf = _stdout >= 0;
237
238         if (in->nice)
239                 setpriority(PRIO_PROCESS, 0, in->nice);
240
241         blobmsg_for_each_attr(cur, in->command, rem)
242                 argc++;
243
244         blobmsg_list_for_each(&in->env, var)
245                 setenv(blobmsg_name(var->data), blobmsg_data(var->data), 1);
246
247         if (seccomp)
248                 setenv("SECCOMP_FILE", in->seccomp, 1);
249
250         if ((seccomp || setlbf) && asprintf(&ld_preload, "LD_PRELOAD=%s%s%s",
251                         seccomp ? "/lib/libpreload-seccomp.so" : "",
252                         seccomp && setlbf ? ":" : "",
253                         setlbf ? "/lib/libsetlbf.so" : "") > 0)
254                 putenv(ld_preload);
255
256         blobmsg_list_for_each(&in->limits, var)
257                 instance_limits(blobmsg_name(var->data), blobmsg_data(var->data));
258
259         if (in->trace)
260                 argc += 1;
261
262         argv = alloca(sizeof(char *) * (argc + in->jail.argc));
263         argc = 0;
264
265         if (in->trace)
266                 argv[argc++] = trace;
267
268         if (in->has_jail)
269                 argc = jail_run(in, argv);
270
271         blobmsg_for_each_attr(cur, in->command, rem)
272                 argv[argc++] = blobmsg_data(cur);
273
274         argv[argc] = NULL;
275
276         _stdin = open("/dev/null", O_RDONLY);
277
278         if (_stdout == -1)
279                 _stdout = open("/dev/null", O_WRONLY);
280
281         if (_stderr == -1)
282                 _stderr = open("/dev/null", O_WRONLY);
283
284         if (_stdin > -1) {
285                 dup2(_stdin, STDIN_FILENO);
286                 closefd(_stdin);
287         }
288         if (_stdout > -1) {
289                 dup2(_stdout, STDOUT_FILENO);
290                 closefd(_stdout);
291         }
292         if (_stderr > -1) {
293                 dup2(_stderr, STDERR_FILENO);
294                 closefd(_stderr);
295         }
296
297         if (in->gid && setgid(in->gid)) {
298                 ERROR("failed to set group id %d: %d (%s)\n", in->gid, errno, strerror(errno));
299                 exit(127);
300         }
301         if (in->uid && setuid(in->uid)) {
302                 ERROR("failed to set user id %d: %d (%s)\n", in->uid, errno, strerror(errno));
303                 exit(127);
304         }
305
306         execvp(argv[0], argv);
307         exit(127);
308 }
309
310 static void
311 instance_free_stdio(struct service_instance *in)
312 {
313         if (in->_stdout.fd.fd > -1) {
314                 ustream_free(&in->_stdout.stream);
315                 close(in->_stdout.fd.fd);
316                 in->_stdout.fd.fd = -1;
317         }
318
319         if (in->_stderr.fd.fd > -1) {
320                 ustream_free(&in->_stderr.stream);
321                 close(in->_stderr.fd.fd);
322                 in->_stderr.fd.fd = -1;
323         }
324 }
325
326 void
327 instance_start(struct service_instance *in)
328 {
329         int pid;
330         int opipe[2] = { -1, -1 };
331         int epipe[2] = { -1, -1 };
332
333         if (!avl_is_empty(&in->errors.avl)) {
334                 LOG("Not starting instance %s::%s, an error was indicated\n", in->srv->name, in->name);
335                 return;
336         }
337
338         if (in->proc.pending)
339                 return;
340
341         instance_free_stdio(in);
342         if (in->_stdout.fd.fd > -2) {
343                 if (pipe(opipe)) {
344                         ULOG_WARN("pipe() failed: %d (%s)\n", errno, strerror(errno));
345                         opipe[0] = opipe[1] = -1;
346                 }
347         }
348
349         if (in->_stderr.fd.fd > -2) {
350                 if (pipe(epipe)) {
351                         ULOG_WARN("pipe() failed: %d (%s)\n", errno, strerror(errno));
352                         epipe[0] = epipe[1] = -1;
353                 }
354         }
355
356         in->restart = false;
357         in->halt = !in->respawn;
358
359         if (!in->valid)
360                 return;
361
362         pid = fork();
363         if (pid < 0)
364                 return;
365
366         if (!pid) {
367                 uloop_done();
368                 closefd(opipe[0]);
369                 closefd(epipe[0]);
370                 instance_run(in, opipe[1], epipe[1]);
371                 return;
372         }
373
374         DEBUG(2, "Started instance %s::%s\n", in->srv->name, in->name);
375         in->proc.pid = pid;
376         clock_gettime(CLOCK_MONOTONIC, &in->start);
377         uloop_process_add(&in->proc);
378
379         if (opipe[0] > -1) {
380                 ustream_fd_init(&in->_stdout, opipe[0]);
381                 closefd(opipe[1]);
382         }
383
384         if (epipe[0] > -1) {
385                 ustream_fd_init(&in->_stderr, epipe[0]);
386                 closefd(epipe[1]);
387         }
388
389         service_event("instance.start", in->srv->name, in->name);
390 }
391
392 static void
393 instance_stdio(struct ustream *s, int prio, struct service_instance *in)
394 {
395         char *newline, *str, *arg0, ident[32];
396         int len;
397
398         arg0 = basename(blobmsg_data(blobmsg_data(in->command)));
399         snprintf(ident, sizeof(ident), "%s[%d]", arg0, in->proc.pid);
400         ulog_open(ULOG_SYSLOG, LOG_DAEMON, ident);
401
402         do {
403                 str = ustream_get_read_buf(s, NULL);
404                 if (!str)
405                         break;
406
407                 newline = strchr(str, '\n');
408                 if (!newline)
409                         break;
410
411                 *newline = 0;
412                 ulog(prio, "%s\n", str);
413
414                 len = newline + 1 - str;
415                 ustream_consume(s, len);
416         } while (1);
417
418         ulog_open(ULOG_SYSLOG, LOG_DAEMON, "procd");
419 }
420
421 static void
422 instance_stdout(struct ustream *s, int bytes)
423 {
424         instance_stdio(s, LOG_INFO,
425                        container_of(s, struct service_instance, _stdout.stream));
426 }
427
428 static void
429 instance_stderr(struct ustream *s, int bytes)
430 {
431         instance_stdio(s, LOG_ERR,
432                        container_of(s, struct service_instance, _stderr.stream));
433 }
434
435 static void
436 instance_timeout(struct uloop_timeout *t)
437 {
438         struct service_instance *in;
439
440         in = container_of(t, struct service_instance, timeout);
441
442         if (!in->halt && (in->restart || in->respawn))
443                 instance_start(in);
444 }
445
446 static void
447 instance_exit(struct uloop_process *p, int ret)
448 {
449         struct service_instance *in;
450         struct timespec tp;
451         long runtime;
452
453         in = container_of(p, struct service_instance, proc);
454
455         clock_gettime(CLOCK_MONOTONIC, &tp);
456         runtime = tp.tv_sec - in->start.tv_sec;
457
458         DEBUG(2, "Instance %s::%s exit with error code %d after %ld seconds\n", in->srv->name, in->name, ret, runtime);
459         if (upgrade_running)
460                 return;
461
462         uloop_timeout_cancel(&in->timeout);
463         if (in->halt) {
464                 /* no action */
465         } else if (in->restart) {
466                 instance_start(in);
467         } else if (in->respawn) {
468                 if (runtime < in->respawn_threshold)
469                         in->respawn_count++;
470                 else
471                         in->respawn_count = 0;
472                 if (in->respawn_count > in->respawn_retry && in->respawn_retry > 0 ) {
473                         LOG("Instance %s::%s s in a crash loop %d crashes, %ld seconds since last crash\n",
474                                                                 in->srv->name, in->name, in->respawn_count, runtime);
475                         in->restart = in->respawn = 0;
476                         in->halt = 1;
477                 } else {
478                         uloop_timeout_set(&in->timeout, in->respawn_timeout * 1000);
479                 }
480         }
481         service_event("instance.stop", in->srv->name, in->name);
482 }
483
484 void
485 instance_stop(struct service_instance *in)
486 {
487         if (!in->proc.pending)
488                 return;
489         in->halt = true;
490         in->restart = in->respawn = false;
491         kill(in->proc.pid, SIGTERM);
492 }
493
494 static void
495 instance_restart(struct service_instance *in)
496 {
497         if (!in->proc.pending)
498                 return;
499         in->halt = false;
500         in->restart = true;
501         kill(in->proc.pid, SIGTERM);
502 }
503
504 static bool
505 instance_config_changed(struct service_instance *in, struct service_instance *in_new)
506 {
507         if (!in->valid)
508                 return true;
509
510         if (!blob_attr_equal(in->command, in_new->command))
511                 return true;
512
513         if (!blobmsg_list_equal(&in->env, &in_new->env))
514                 return true;
515
516         if (!blobmsg_list_equal(&in->data, &in_new->data))
517                 return true;
518
519         if (!blobmsg_list_equal(&in->netdev, &in_new->netdev))
520                 return true;
521
522         if (!blobmsg_list_equal(&in->file, &in_new->file))
523                 return true;
524
525         if (in->nice != in_new->nice)
526                 return true;
527
528         if (in->uid != in_new->uid)
529                 return true;
530
531         if (in->gid != in_new->gid)
532                 return true;
533
534         if (!blobmsg_list_equal(&in->limits, &in_new->limits))
535                 return true;
536
537         if (!blobmsg_list_equal(&in->jail.mount, &in_new->jail.mount))
538                 return true;
539
540         if (!blobmsg_list_equal(&in->errors, &in_new->errors))
541                 return true;
542
543         return false;
544 }
545
546 static bool
547 instance_netdev_cmp(struct blobmsg_list_node *l1, struct blobmsg_list_node *l2)
548 {
549         struct instance_netdev *n1 = container_of(l1, struct instance_netdev, node);
550         struct instance_netdev *n2 = container_of(l2, struct instance_netdev, node);
551
552         return n1->ifindex == n2->ifindex;
553 }
554
555 static void
556 instance_netdev_update(struct blobmsg_list_node *l)
557 {
558         struct instance_netdev *n = container_of(l, struct instance_netdev, node);
559
560         n->ifindex = if_nametoindex(n->node.avl.key);
561 }
562
563 static bool
564 instance_file_cmp(struct blobmsg_list_node *l1, struct blobmsg_list_node *l2)
565 {
566         struct instance_file *f1 = container_of(l1, struct instance_file, node);
567         struct instance_file *f2 = container_of(l2, struct instance_file, node);
568
569         return !memcmp(f1->md5, f2->md5, sizeof(f1->md5));
570 }
571
572 static void
573 instance_file_update(struct blobmsg_list_node *l)
574 {
575         struct instance_file *f = container_of(l, struct instance_file, node);
576         md5_ctx_t md5;
577         char buf[256];
578         int len, fd;
579
580         memset(f->md5, 0, sizeof(f->md5));
581
582         fd = open(l->avl.key, O_RDONLY);
583         if (fd < 0)
584                 return;
585
586         md5_begin(&md5);
587         do {
588                 len = read(fd, buf, sizeof(buf));
589                 if (len < 0) {
590                         if (errno == EINTR)
591                                 continue;
592
593                         break;
594                 }
595                 if (!len)
596                         break;
597
598                 md5_hash(buf, len, &md5);
599         } while(1);
600
601         md5_end(f->md5, &md5);
602         close(fd);
603 }
604
605 static void
606 instance_fill_any(struct blobmsg_list *l, struct blob_attr *cur)
607 {
608         if (!cur)
609                 return;
610
611         blobmsg_list_fill(l, blobmsg_data(cur), blobmsg_data_len(cur), false);
612 }
613
614 static bool
615 instance_fill_array(struct blobmsg_list *l, struct blob_attr *cur, blobmsg_update_cb cb, bool array)
616 {
617         struct blobmsg_list_node *node;
618
619         if (!cur)
620                 return true;
621
622         if (!blobmsg_check_attr_list(cur, BLOBMSG_TYPE_STRING))
623                 return false;
624
625         blobmsg_list_fill(l, blobmsg_data(cur), blobmsg_data_len(cur), array);
626         if (cb) {
627                 blobmsg_list_for_each(l, node)
628                         cb(node);
629         }
630         return true;
631 }
632
633 static int
634 instance_jail_parse(struct service_instance *in, struct blob_attr *attr)
635 {
636         struct blob_attr *tb[__JAIL_ATTR_MAX];
637         struct jail *jail = &in->jail;
638         struct stat s;
639
640         if (stat("/sbin/ujail", &s))
641                 return 0;
642
643         blobmsg_parse(jail_attr, __JAIL_ATTR_MAX, tb,
644                 blobmsg_data(attr), blobmsg_data_len(attr));
645
646         jail->argc = 2;
647
648         if (tb[JAIL_ATTR_NAME]) {
649                 jail->name = blobmsg_get_string(tb[JAIL_ATTR_NAME]);
650                 jail->argc += 2;
651         }
652         if (tb[JAIL_ATTR_PROCFS]) {
653                 jail->procfs = blobmsg_get_bool(tb[JAIL_ATTR_PROCFS]);
654                 jail->argc++;
655         }
656         if (tb[JAIL_ATTR_SYSFS]) {
657                 jail->sysfs = blobmsg_get_bool(tb[JAIL_ATTR_SYSFS]);
658                 jail->argc++;
659         }
660         if (tb[JAIL_ATTR_UBUS]) {
661                 jail->ubus = blobmsg_get_bool(tb[JAIL_ATTR_UBUS]);
662                 jail->argc++;
663         }
664         if (tb[JAIL_ATTR_LOG]) {
665                 jail->log = blobmsg_get_bool(tb[JAIL_ATTR_LOG]);
666                 jail->argc++;
667         }
668         if (tb[JAIL_ATTR_RONLY]) {
669                 jail->ronly = blobmsg_get_bool(tb[JAIL_ATTR_RONLY]);
670                 jail->argc++;
671         }
672         if (tb[JAIL_ATTR_MOUNT]) {
673                 struct blob_attr *cur;
674                 int rem;
675
676                 blobmsg_for_each_attr(cur, tb[JAIL_ATTR_MOUNT], rem)
677                         jail->argc += 2;
678                 instance_fill_array(&jail->mount, tb[JAIL_ATTR_MOUNT], NULL, false);
679         }
680         if (in->seccomp)
681                 jail->argc += 2;
682
683         return 1;
684 }
685
686 static bool
687 instance_config_parse(struct service_instance *in)
688 {
689         struct blob_attr *tb[__INSTANCE_ATTR_MAX];
690         struct blob_attr *cur, *cur2;
691         int argc = 0;
692         int rem;
693
694         blobmsg_parse(instance_attr, __INSTANCE_ATTR_MAX, tb,
695                 blobmsg_data(in->config), blobmsg_data_len(in->config));
696
697         cur = tb[INSTANCE_ATTR_COMMAND];
698         if (!cur)
699                 return false;
700
701         if (!blobmsg_check_attr_list(cur, BLOBMSG_TYPE_STRING))
702                 return false;
703
704         blobmsg_for_each_attr(cur2, cur, rem) {
705                 argc++;
706                 break;
707         }
708         if (!argc)
709                 return false;
710
711         in->command = cur;
712
713         if (tb[INSTANCE_ATTR_RESPAWN]) {
714                 int i = 0;
715                 uint32_t vals[3] = { 3600, 5, 5};
716
717                 blobmsg_for_each_attr(cur2, tb[INSTANCE_ATTR_RESPAWN], rem) {
718                         if ((i >= 3) && (blobmsg_type(cur2) == BLOBMSG_TYPE_STRING))
719                                 continue;
720                         vals[i] = atoi(blobmsg_get_string(cur2));
721                         i++;
722                 }
723                 in->respawn = true;
724                 in->respawn_count = 0;
725                 in->respawn_threshold = vals[0];
726                 in->respawn_timeout = vals[1];
727                 in->respawn_retry = vals[2];
728         }
729         if (tb[INSTANCE_ATTR_TRIGGER]) {
730                 in->trigger = tb[INSTANCE_ATTR_TRIGGER];
731                 trigger_add(in->trigger, in);
732         }
733
734         if (tb[INSTANCE_ATTR_WATCH]) {
735                 blobmsg_for_each_attr(cur2, tb[INSTANCE_ATTR_WATCH], rem) {
736                         if (blobmsg_type(cur2) != BLOBMSG_TYPE_STRING)
737                                 continue;
738                         DEBUG(3, "watch for %s\n", blobmsg_get_string(cur2));
739                         watch_add(blobmsg_get_string(cur2), in);
740                 }
741         }
742
743         if ((cur = tb[INSTANCE_ATTR_NICE])) {
744                 in->nice = (int8_t) blobmsg_get_u32(cur);
745                 if (in->nice < -20 || in->nice > 20)
746                         return false;
747         }
748
749         if (tb[INSTANCE_ATTR_USER]) {
750                 struct passwd *p = getpwnam(blobmsg_get_string(tb[INSTANCE_ATTR_USER]));
751                 if (p) {
752                         in->uid = p->pw_uid;
753                         in->gid = p->pw_gid;
754                 }
755         }
756
757         if (tb[INSTANCE_ATTR_TRACE])
758                 in->trace = blobmsg_get_bool(tb[INSTANCE_ATTR_TRACE]);
759
760         if (tb[INSTANCE_ATTR_NO_NEW_PRIVS])
761                 in->no_new_privs = blobmsg_get_bool(tb[INSTANCE_ATTR_NO_NEW_PRIVS]);
762
763         if (!in->trace && tb[INSTANCE_ATTR_SECCOMP]) {
764                 char *seccomp = blobmsg_get_string(tb[INSTANCE_ATTR_SECCOMP]);
765                 struct stat s;
766
767                 if (stat(seccomp, &s))
768                         ERROR("%s: not starting seccomp as %s is missing\n", in->name, seccomp);
769                 else
770                         in->seccomp = seccomp;
771         }
772         if (!in->trace && tb[INSTANCE_ATTR_JAIL])
773                 in->has_jail = instance_jail_parse(in, tb[INSTANCE_ATTR_JAIL]);
774
775         if (tb[INSTANCE_ATTR_STDOUT] && blobmsg_get_bool(tb[INSTANCE_ATTR_STDOUT]))
776                 in->_stdout.fd.fd = -1;
777
778         if (tb[INSTANCE_ATTR_STDERR] && blobmsg_get_bool(tb[INSTANCE_ATTR_STDERR]))
779                 in->_stderr.fd.fd = -1;
780
781         instance_fill_any(&in->data, tb[INSTANCE_ATTR_DATA]);
782
783         if (!instance_fill_array(&in->env, tb[INSTANCE_ATTR_ENV], NULL, false))
784                 return false;
785
786         if (!instance_fill_array(&in->netdev, tb[INSTANCE_ATTR_NETDEV], instance_netdev_update, true))
787                 return false;
788
789         if (!instance_fill_array(&in->file, tb[INSTANCE_ATTR_FILE], instance_file_update, true))
790                 return false;
791
792         if (!instance_fill_array(&in->limits, tb[INSTANCE_ATTR_LIMITS], NULL, false))
793                 return false;
794
795         if (!instance_fill_array(&in->errors, tb[INSTANCE_ATTR_ERROR], NULL, true))
796                 return false;
797
798         return true;
799 }
800
801 static void
802 instance_config_cleanup(struct service_instance *in)
803 {
804         blobmsg_list_free(&in->env);
805         blobmsg_list_free(&in->data);
806         blobmsg_list_free(&in->netdev);
807         blobmsg_list_free(&in->file);
808         blobmsg_list_free(&in->limits);
809         blobmsg_list_free(&in->errors);
810         blobmsg_list_free(&in->jail.mount);
811 }
812
813 static void
814 instance_config_move(struct service_instance *in, struct service_instance *in_src)
815 {
816         instance_config_cleanup(in);
817         blobmsg_list_move(&in->env, &in_src->env);
818         blobmsg_list_move(&in->data, &in_src->data);
819         blobmsg_list_move(&in->netdev, &in_src->netdev);
820         blobmsg_list_move(&in->file, &in_src->file);
821         blobmsg_list_move(&in->limits, &in_src->limits);
822         blobmsg_list_move(&in->errors, &in_src->errors);
823         blobmsg_list_move(&in->jail.mount, &in_src->jail.mount);
824         in->trigger = in_src->trigger;
825         in->command = in_src->command;
826         in->name = in_src->name;
827         in->node.avl.key = in_src->node.avl.key;
828
829         free(in->config);
830         in->config = in_src->config;
831         in_src->config = NULL;
832 }
833
834 bool
835 instance_update(struct service_instance *in, struct service_instance *in_new)
836 {
837         bool changed = instance_config_changed(in, in_new);
838         bool running = in->proc.pending;
839
840         if (!changed && running)
841                 return false;
842
843         if (!running) {
844                 if (changed)
845                         instance_config_move(in, in_new);
846                 instance_start(in);
847         } else {
848                 instance_restart(in);
849                 instance_config_move(in, in_new);
850                 /* restart happens in the child callback handler */
851         }
852         return true;
853 }
854
855 void
856 instance_free(struct service_instance *in)
857 {
858         instance_free_stdio(in);
859         uloop_process_delete(&in->proc);
860         uloop_timeout_cancel(&in->timeout);
861         trigger_del(in);
862         watch_del(in);
863         instance_config_cleanup(in);
864         free(in->config);
865         free(in);
866 }
867
868 void
869 instance_init(struct service_instance *in, struct service *s, struct blob_attr *config)
870 {
871         config = blob_memdup(config);
872         in->srv = s;
873         in->name = blobmsg_name(config);
874         in->config = config;
875         in->timeout.cb = instance_timeout;
876         in->proc.cb = instance_exit;
877
878         in->_stdout.fd.fd = -2;
879         in->_stdout.stream.string_data = true;
880         in->_stdout.stream.notify_read = instance_stdout;
881
882         in->_stderr.fd.fd = -2;
883         in->_stderr.stream.string_data = true;
884         in->_stderr.stream.notify_read = instance_stderr;
885
886         blobmsg_list_init(&in->netdev, struct instance_netdev, node, instance_netdev_cmp);
887         blobmsg_list_init(&in->file, struct instance_file, node, instance_file_cmp);
888         blobmsg_list_simple_init(&in->env);
889         blobmsg_list_simple_init(&in->data);
890         blobmsg_list_simple_init(&in->limits);
891         blobmsg_list_simple_init(&in->errors);
892         blobmsg_list_simple_init(&in->jail.mount);
893         in->valid = instance_config_parse(in);
894 }
895
896 void instance_dump(struct blob_buf *b, struct service_instance *in, int verbose)
897 {
898         void *i;
899
900         if (!in->valid)
901                 return;
902
903         i = blobmsg_open_table(b, in->name);
904         blobmsg_add_u8(b, "running", in->proc.pending);
905         if (in->proc.pending)
906                 blobmsg_add_u32(b, "pid", in->proc.pid);
907         blobmsg_add_blob(b, in->command);
908
909         if (!avl_is_empty(&in->errors.avl)) {
910                 struct blobmsg_list_node *var;
911                 void *e = blobmsg_open_array(b, "errors");
912                 blobmsg_list_for_each(&in->errors, var)
913                         blobmsg_add_string(b, NULL, blobmsg_data(var->data));
914                 blobmsg_close_table(b, e);
915         }
916
917         if (!avl_is_empty(&in->env.avl)) {
918                 struct blobmsg_list_node *var;
919                 void *e = blobmsg_open_table(b, "env");
920                 blobmsg_list_for_each(&in->env, var)
921                         blobmsg_add_string(b, blobmsg_name(var->data), blobmsg_data(var->data));
922                 blobmsg_close_table(b, e);
923         }
924
925         if (!avl_is_empty(&in->data.avl)) {
926                 struct blobmsg_list_node *var;
927                 void *e = blobmsg_open_table(b, "data");
928                 blobmsg_list_for_each(&in->data, var)
929                         blobmsg_add_blob(b, var->data);
930                 blobmsg_close_table(b, e);
931         }
932
933         if (!avl_is_empty(&in->limits.avl)) {
934                 struct blobmsg_list_node *var;
935                 void *e = blobmsg_open_table(b, "limits");
936                 blobmsg_list_for_each(&in->limits, var)
937                         blobmsg_add_string(b, blobmsg_name(var->data), blobmsg_data(var->data));
938                 blobmsg_close_table(b, e);
939         }
940
941         if (in->respawn) {
942                 void *r = blobmsg_open_table(b, "respawn");
943                 blobmsg_add_u32(b, "threshold", in->respawn_threshold);
944                 blobmsg_add_u32(b, "timeout", in->respawn_timeout);
945                 blobmsg_add_u32(b, "retry", in->respawn_retry);
946                 blobmsg_close_table(b, r);
947         }
948
949         if (in->trace)
950                 blobmsg_add_u8(b, "trace", true);
951
952         if (in->no_new_privs)
953                 blobmsg_add_u8(b, "no_new_privs", true);
954
955         if (in->seccomp)
956                 blobmsg_add_string(b, "seccomp", in->seccomp);
957
958         if (in->has_jail) {
959                 void *r = blobmsg_open_table(b, "jail");
960                 if (in->jail.name)
961                         blobmsg_add_string(b, "name", in->jail.name);
962                 blobmsg_add_u8(b, "procfs", in->jail.procfs);
963                 blobmsg_add_u8(b, "sysfs", in->jail.sysfs);
964                 blobmsg_add_u8(b, "ubus", in->jail.ubus);
965                 blobmsg_add_u8(b, "log", in->jail.log);
966                 blobmsg_add_u8(b, "ronly", in->jail.ronly);
967                 blobmsg_close_table(b, r);
968                 if (!avl_is_empty(&in->jail.mount.avl)) {
969                         struct blobmsg_list_node *var;
970                         void *e = blobmsg_open_table(b, "mount");
971                         blobmsg_list_for_each(&in->jail.mount, var)
972                                 blobmsg_add_string(b, blobmsg_name(var->data), blobmsg_data(var->data));
973                         blobmsg_close_table(b, e);
974                 }
975         }
976
977         if (verbose && in->trigger)
978                 blobmsg_add_blob(b, in->trigger);
979
980         blobmsg_close_table(b, i);
981 }