instance: add 'requirejail' attribute
[oweals/procd.git] / service / instance.c
index e872ba0228026d46f3cc0f07d5ee8ca0612e2bab..ffaaaa172491b776a92481cebd341363792ea0c3 100644 (file)
@@ -101,6 +101,7 @@ enum {
        JAIL_ATTR_RONLY,
        JAIL_ATTR_MOUNT,
        JAIL_ATTR_NETNS,
+       JAIL_ATTR_REQUIREJAIL,
        __JAIL_ATTR_MAX,
 };
 
@@ -114,6 +115,7 @@ static const struct blobmsg_policy jail_attr[__JAIL_ATTR_MAX] = {
        [JAIL_ATTR_RONLY] = { "ronly", BLOBMSG_TYPE_BOOL },
        [JAIL_ATTR_MOUNT] = { "mount", BLOBMSG_TYPE_TABLE },
        [JAIL_ATTR_NETNS] = { "netns", BLOBMSG_TYPE_BOOL },
+       [JAIL_ATTR_REQUIREJAIL] = { "requirejail", BLOBMSG_TYPE_BOOL },
 };
 
 struct instance_netdev {
@@ -819,20 +821,16 @@ instance_jail_parse(struct service_instance *in, struct blob_attr *attr)
 {
        struct blob_attr *tb[__JAIL_ATTR_MAX];
        struct jail *jail = &in->jail;
-       struct stat s;
-       int r;
-
-       r = stat(UJAIL_BIN_PATH, &s);
-       if (r < 0) {
-               ERROR("unable to find %s: %m (%d)\n", UJAIL_BIN_PATH, r);
-               return 0;
-       }
 
        blobmsg_parse(jail_attr, __JAIL_ATTR_MAX, tb,
                blobmsg_data(attr), blobmsg_data_len(attr));
 
        jail->argc = 2;
 
+       if (tb[JAIL_ATTR_REQUIREJAIL]) {
+               in->require_jail = true;
+               jail->argc++;
+       }
        if (tb[JAIL_ATTR_NAME]) {
                jail->name = strdup(blobmsg_get_string(tb[JAIL_ATTR_NAME]));
                jail->argc += 2;
@@ -885,7 +883,7 @@ instance_jail_parse(struct service_instance *in, struct blob_attr *attr)
        if (in->no_new_privs)
                jail->argc++;
 
-       return 1;
+       return true;
 }
 
 static bool
@@ -918,7 +916,8 @@ instance_config_parse(struct service_instance *in)
 {
        struct blob_attr *tb[__INSTANCE_ATTR_MAX];
        struct blob_attr *cur, *cur2;
-       int rem;
+       struct stat s;
+       int rem, r;
 
        blobmsg_parse(instance_attr, __INSTANCE_ATTR_MAX, tb,
                blobmsg_data(in->config), blobmsg_data_len(in->config));
@@ -1004,6 +1003,19 @@ instance_config_parse(struct service_instance *in)
        if (!in->trace && tb[INSTANCE_ATTR_JAIL])
                in->has_jail = instance_jail_parse(in, tb[INSTANCE_ATTR_JAIL]);
 
+       if (in->has_jail) {
+               r = stat(UJAIL_BIN_PATH, &s);
+               if (r < 0) {
+                       if (in->require_jail) {
+                               ERROR("Cannot jail service %s::%s. %s: %m (%d)\n",
+                                               in->srv->name, in->name, UJAIL_BIN_PATH, r);
+                               return false;
+                       }
+                       DEBUG(2, "unable to find %s: %m (%d)\n", UJAIL_BIN_PATH, r);
+                       in->has_jail = false;
+               }
+       }
+
        if (tb[INSTANCE_ATTR_STDOUT] && blobmsg_get_bool(tb[INSTANCE_ATTR_STDOUT]))
                in->_stdout.fd.fd = -1;
 
@@ -1146,6 +1158,7 @@ instance_init(struct service_instance *in, struct service *s, struct blob_attr *
        in->term_timeout = 5;
        in->syslog_facility = LOG_DAEMON;
        in->exit_code = 0;
+       in->require_jail = false;
 
        in->_stdout.fd.fd = -2;
        in->_stdout.stream.string_data = true;