ujail: stop using extern in elf.h
[project/procd.git] / service / instance.c
index 4ace40b..40ff021 100644 (file)
@@ -12,6 +12,7 @@
  * GNU General Public License for more details.
  */
 
+#define _GNU_SOURCE
 #include <sys/resource.h>
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -19,6 +20,7 @@
 #include <net/if.h>
 #include <unistd.h>
 #include <stdint.h>
+#include <stdio.h>
 #include <fcntl.h>
 #include <pwd.h>
 #include <libgen.h>
@@ -224,8 +226,11 @@ instance_run(struct service_instance *in, int _stdout, int _stderr)
        struct blobmsg_list_node *var;
        struct blob_attr *cur;
        char **argv;
+       char *ld_preload;
        int argc = 1; /* NULL terminated */
        int rem, _stdin;
+       bool seccomp = !in->trace && !in->has_jail && in->seccomp;
+       bool setlbf = _stdout >= 0;
 
        if (in->nice)
                setpriority(PRIO_PROCESS, 0, in->nice);
@@ -236,10 +241,14 @@ instance_run(struct service_instance *in, int _stdout, int _stderr)
        blobmsg_list_for_each(&in->env, var)
                setenv(blobmsg_name(var->data), blobmsg_data(var->data), 1);
 
-       if (!in->trace && !in->has_jail && in->seccomp) {
+       if (seccomp)
                setenv("SECCOMP_FILE", in->seccomp, 1);
-               setenv("LD_PRELOAD", "/lib/libpreload-seccomp.so", 1);
-       }
+
+       if ((seccomp || setlbf) && asprintf(&ld_preload, "LD_PRELOAD=%s%s%s",
+                       seccomp ? "/lib/libpreload-seccomp.so" : "",
+                       seccomp && setlbf ? ":" : "",
+                       setlbf ? "/lib/libsetlbf.so" : "") > 0)
+               putenv(ld_preload);
 
        blobmsg_list_for_each(&in->limits, var)
                instance_limits(blobmsg_name(var->data), blobmsg_data(var->data));
@@ -295,6 +304,22 @@ instance_run(struct service_instance *in, int _stdout, int _stderr)
        exit(127);
 }
 
+static void
+instance_free_stdio(struct service_instance *in)
+{
+       if (in->_stdout.fd.fd > -1) {
+               ustream_free(&in->_stdout.stream);
+               close(in->_stdout.fd.fd);
+               in->_stdout.fd.fd = -1;
+       }
+
+       if (in->_stderr.fd.fd > -1) {
+               ustream_free(&in->_stderr.stream);
+               close(in->_stderr.fd.fd);
+               in->_stderr.fd.fd = -1;
+       }
+}
+
 void
 instance_start(struct service_instance *in)
 {
@@ -310,6 +335,7 @@ instance_start(struct service_instance *in)
        if (in->proc.pending)
                return;
 
+       instance_free_stdio(in);
        if (in->_stdout.fd.fd > -2) {
                if (pipe(opipe)) {
                        ULOG_WARN("pipe() failed: %d (%s)\n", errno, strerror(errno));
@@ -823,16 +849,7 @@ instance_update(struct service_instance *in, struct service_instance *in_new)
 void
 instance_free(struct service_instance *in)
 {
-       if (in->_stdout.fd.fd > -1) {
-               ustream_free(&in->_stdout.stream);
-               close(in->_stdout.fd.fd);
-       }
-
-       if (in->_stderr.fd.fd > -1) {
-               ustream_free(&in->_stderr.stream);
-               close(in->_stderr.fd.fd);
-       }
-
+       instance_free_stdio(in);
        uloop_process_delete(&in->proc);
        uloop_timeout_cancel(&in->timeout);
        trigger_del(in);
@@ -917,8 +934,8 @@ void instance_dump(struct blob_buf *b, struct service_instance *in, int verbose)
 
        if (in->respawn) {
                void *r = blobmsg_open_table(b, "respawn");
-               blobmsg_add_u32(b, "timeout", in->respawn_timeout);
                blobmsg_add_u32(b, "threshold", in->respawn_threshold);
+               blobmsg_add_u32(b, "timeout", in->respawn_timeout);
                blobmsg_add_u32(b, "retry", in->respawn_retry);
                blobmsg_close_table(b, r);
        }