jail: allow passing environment variable to procd jailed process
[project/procd.git] / system.c
index ffd8f7175594338c5274f11d8c789446fe770bae..c208e3ee47434d3433aaa6ead4d3f75df803c6fc 100644 (file)
--- a/system.c
+++ b/system.c
@@ -36,6 +36,7 @@
 static struct blob_buf b;
 static int notify;
 static struct ubus_context *_ctx;
+static int initramfs;
 
 enum vjson_state {
        VJSON_ERROR,
@@ -43,6 +44,78 @@ enum vjson_state {
        VJSON_SUCCESS,
 };
 
+static const char *system_rootfs_type(void) {
+       const char proc_mounts[] = "/proc/self/mounts";
+       static char fstype[16] = { 0 };
+       char *mountstr = NULL, *mp = "/", *pos, *tmp;
+       FILE *mounts;
+       ssize_t nread;
+       size_t len = 0;
+       bool found;
+
+       if (initramfs)
+               return "initramfs";
+
+       if (fstype[0])
+               return fstype;
+
+       mounts = fopen(proc_mounts, "r");
+       if (!mounts)
+               return NULL;
+
+       while ((nread = getline(&mountstr, &len, mounts)) != -1) {
+               found = false;
+
+               pos = strchr(mountstr, ' ');
+               if (!pos)
+                       continue;
+
+               tmp = pos + 1;
+               pos = strchr(tmp, ' ');
+               if (!pos)
+                       continue;
+
+               *pos = '\0';
+               if (strcmp(tmp, mp))
+                       continue;
+
+               tmp = pos + 1;
+               pos = strchr(tmp, ' ');
+               if (!pos)
+                       continue;
+
+               *pos = '\0';
+
+               if (!strcmp(tmp, "overlay")) {
+                       /*
+                        * there is no point in parsing overlay option string for
+                        * lowerdir, as that can point to "/" being a previous
+                        * overlay mount (after firstboot or sysuprade config
+                        * restore). Hence just assume the lowerdir is "/rom" and
+                        * restart searching for that instead.
+                        */
+                       mp = "/rom";
+                       fseek(mounts, 0, SEEK_SET);
+                       continue;
+               }
+
+               found = true;
+               break;
+       }
+
+       if (found)
+               strncpy(fstype, tmp, sizeof(fstype) - 1);
+
+       fstype[sizeof(fstype) - 1]= '\0';
+       free(mountstr);
+       fclose(mounts);
+
+       if (found)
+               return fstype;
+       else
+               return NULL;
+}
+
 static int system_board(struct ubus_context *ctx, struct ubus_object *obj,
                  struct ubus_request_data *req, const char *method,
                  struct blob_attr *msg)
@@ -50,6 +123,7 @@ static int system_board(struct ubus_context *ctx, struct ubus_object *obj,
        void *c;
        char line[256];
        char *key, *val, *next;
+       const char *rootfs_type = system_rootfs_type();
        struct utsname utsname;
        FILE *f;
 
@@ -71,6 +145,13 @@ static int system_board(struct ubus_context *ctx, struct ubus_object *obj,
                        if (!key || !val)
                                continue;
 
+#ifdef __aarch64__
+                       if (!strcasecmp(key, "CPU revision")) {
+                               snprintf(line, sizeof(line), "ARMv8 Processor rev %lu", strtoul(val + 2, NULL, 16));
+                               blobmsg_add_string(&b, "system", line);
+                               break;
+                       }
+#else
                        if (!strcasecmp(key, "system type") ||
                            !strcasecmp(key, "processor") ||
                            !strcasecmp(key, "cpu") ||
@@ -84,6 +165,7 @@ static int system_board(struct ubus_context *ctx, struct ubus_object *obj,
                                        break;
                                }
                        }
+#endif
                }
 
                fclose(f);
@@ -157,6 +239,9 @@ static int system_board(struct ubus_context *ctx, struct ubus_object *obj,
                fclose(f);
        }
 
+       if (rootfs_type)
+               blobmsg_add_string(&b, "rootfs_type", rootfs_type);
+
        if ((f = fopen("/etc/openwrt_release", "r")) != NULL)
        {
                c = blobmsg_open_table(&b, "release");
@@ -364,7 +449,7 @@ static int watchdog_set(struct ubus_context *ctx, struct ubus_object *obj,
 
                if (timeout <= frequency)
                        timeout = frequency * 2;
-                watchdog_timeout(timeout);
+               watchdog_timeout(timeout);
        }
 
        if (tb[WDT_MAGICCLOSE])
@@ -672,6 +757,12 @@ static int sysupgrade(struct ubus_context *ctx, struct ubus_object *obj,
 
        blobmsg_parse(validation_policy, __VALIDATION_MAX, validation, blob_data(b.head), blob_len(b.head));
 
+       if (!validation[VALIDATION_VALID] || !validation[VALIDATION_FORCEABLE] ||
+           !validation[VALIDATION_ALLOW_BACKUP]) {
+               sysupgrade_error(ctx, req, "Validation script provided invalid input");
+               return UBUS_STATUS_INVALID_ARGUMENT;
+       }
+
        valid = validation[VALIDATION_VALID] && blobmsg_get_bool(validation[VALIDATION_VALID]);
        forceable = validation[VALIDATION_FORCEABLE] && blobmsg_get_bool(validation[VALIDATION_FORCEABLE]);
        allow_backup = validation[VALIDATION_ALLOW_BACKUP] && blobmsg_get_bool(validation[VALIDATION_ALLOW_BACKUP]);
@@ -745,6 +836,11 @@ void ubus_init_system(struct ubus_context *ctx)
        int ret;
 
        _ctx = ctx;
+
+       initramfs = !!getenv("INITRAMFS");
+       if (initramfs)
+               unsetenv("INITRAMFS");
+
        ret = ubus_add_object(ctx, &system_object);
        if (ret)
                ERROR("Failed to add object: %s\n", ubus_strerror(ret));