Exemple #1
0
static bool test_strv_single(struct torture_context *tctx)
{
	const char *data = "foo";
	char *strv = NULL;
	char *t;
	int ret;

	/* Add an item */
	ret = strv_add(tctx, &strv, data);
	torture_assert(tctx, ret == 0, "strv_add() failed");

	/* Is there 1 item? */
	torture_assert_int_equal(tctx,
				 strv_count(strv), 1,
				 "strv_count() failed");

	/* Is the expected item the first one? */
	t = strv_next(strv, NULL);
	torture_assert(tctx,
		       strcmp(t, data) == 0,
		       "strv_next() failed");

	/* Can the expected item be found? */
	t = strv_find(strv, data);
	torture_assert(tctx,
		       strcmp(t, data) == 0,
		       "strv_next() failed");

	/* Delete it */
	strv_delete(&strv, t);

	/* Should have no items */
	torture_assert_int_equal(tctx,
				 strv_count(strv), 0,
				 "strv_count() failed");
	return true;
}
Exemple #2
0
static void test_strv_find(void) {
        assert_se(strv_find((char **)input_table_multiple, "three"));
        assert_se(!strv_find((char **)input_table_multiple, "four"));
}
Exemple #3
0
int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        int r;

        assert(bus);
        assert(path);

        r = sd_bus_call_method(bus,
                        dest,
                        path,
                        "org.freedesktop.DBus.Properties",
                        "GetAll",
                        &error,
                        &reply,
                        "s", "");
        if (r < 0)
                return r;

        r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
        if (r < 0)
                return r;

        while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
                const char *name;
                const char *contents;

                r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
                if (r < 0)
                        return r;

                if (!filter || strv_find(filter, name)) {
                        r = sd_bus_message_peek_type(reply, NULL, &contents);
                        if (r < 0)
                                return r;

                        r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
                        if (r < 0)
                                return r;

                        r = bus_print_property(name, reply, all);
                        if (r < 0)
                                return r;
                        if (r == 0) {
                                if (all)
                                        printf("%s=[unprintable]\n", name);
                                /* skip what we didn't read */
                                r = sd_bus_message_skip(reply, contents);
                                if (r < 0)
                                        return r;
                        }

                        r = sd_bus_message_exit_container(reply);
                        if (r < 0)
                                return r;
                } else {
                        r = sd_bus_message_skip(reply, "v");
                        if (r < 0)
                                return r;
                }

                r = sd_bus_message_exit_container(reply);
                if (r < 0)
                        return r;
        }
        if (r < 0)
                return r;

        r = sd_bus_message_exit_container(reply);
        if (r < 0)
                return r;

        return 0;
}
Exemple #4
0
int mount_cgroup_controllers(char ***join_controllers) {
        int r;
        FILE *f;
        char buf[LINE_MAX];
        Set *controllers;

        /* Mount all available cgroup controllers that are built into the kernel. */

        f = fopen("/proc/cgroups", "re");
        if (!f) {
                log_error("Failed to enumerate cgroup controllers: %m");
                return 0;
        }

        controllers = set_new(string_hash_func, string_compare_func);
        if (!controllers) {
                r = log_oom();
                goto finish;
        }

        /* Ignore the header line */
        (void) fgets(buf, sizeof(buf), f);

        for (;;) {
                char *controller;
                int enabled = 0;

                if (fscanf(f, "%ms %*i %*i %i", &controller, &enabled) != 2) {

                        if (feof(f))
                                break;

                        log_error("Failed to parse /proc/cgroups.");
                        r = -EIO;
                        goto finish;
                }

                if (!enabled) {
                        free(controller);
                        continue;
                }

                r = set_put(controllers, controller);
                if (r < 0) {
                        log_error("Failed to add controller to set.");
                        free(controller);
                        goto finish;
                }
        }

        for (;;) {
                MountPoint p;
                char *controller, *where, *options;
                char ***k = NULL;

                controller = set_steal_first(controllers);
                if (!controller)
                        break;

                if (join_controllers)
                        for (k = join_controllers; *k; k++)
                                if (strv_find(*k, controller))
                                        break;

                if (k && *k) {
                        char **i, **j;

                        for (i = *k, j = *k; *i; i++) {

                                if (!streq(*i, controller)) {
                                        char *t;

                                        t = set_remove(controllers, *i);
                                        if (!t) {
                                                free(*i);
                                                continue;
                                        }
                                        free(t);
                                }

                                *(j++) = *i;
                        }

                        *j = NULL;

                        options = strv_join(*k, ",");
                        if (!options) {
                                free(controller);
                                r = log_oom();
                                goto finish;
                        }

                } else {
                        options = controller;
                        controller = NULL;
                }

                where = strappend("/sys/fs/cgroup/", options);
                if (!where) {
                        free(options);
                        r = log_oom();
                        goto finish;
                }

                zero(p);
                p.what = "cgroup";
                p.where = where;
                p.type = "cgroup";
                p.options = options;
                p.flags = MS_NOSUID|MS_NOEXEC|MS_NODEV;
                p.mode = MNT_IN_CONTAINER;

                r = mount_one(&p, true);
                free(controller);
                free(where);

                if (r < 0) {
                        free(options);
                        goto finish;
                }

                if (r > 0 && k && *k) {
                        char **i;

                        for (i = *k; *i; i++) {
                                char *t;

                                t = strappend("/sys/fs/cgroup/", *i);
                                if (!t) {
                                        r = log_oom();
                                        free(options);
                                        goto finish;
                                }

                                r = symlink(options, t);
                                free(t);

                                if (r < 0 && errno != EEXIST) {
                                        log_error("Failed to create symlink: %m");
                                        r = -errno;
                                        free(options);
                                        goto finish;
                                }
                        }
                }

                free(options);
        }

        r = 0;

finish:
        set_free_free(controllers);

        fclose(f);

        return r;
}
Exemple #5
0
int mount_cgroup_controllers(char ***join_controllers) {
        _cleanup_set_free_free_ Set *controllers = NULL;
        int r;

        if (!cg_is_legacy_wanted())
                return 0;

        /* Mount all available cgroup controllers that are built into the kernel. */

        controllers = set_new(&string_hash_ops);
        if (!controllers)
                return log_oom();

        r = cg_kernel_controllers(controllers);
        if (r < 0)
                return log_error_errno(r, "Failed to enumerate cgroup controllers: %m");

        for (;;) {
                _cleanup_free_ char *options = NULL, *controller = NULL, *where = NULL;
                MountPoint p = {
                        .what = "cgroup",
                        .type = "cgroup",
                        .flags = MS_NOSUID|MS_NOEXEC|MS_NODEV,
                        .mode = MNT_IN_CONTAINER,
                };
                char ***k = NULL;

                controller = set_steal_first(controllers);
                if (!controller)
                        break;

                if (join_controllers)
                        for (k = join_controllers; *k; k++)
                                if (strv_find(*k, controller))
                                        break;

                if (k && *k) {
                        char **i, **j;

                        for (i = *k, j = *k; *i; i++) {

                                if (!streq(*i, controller)) {
                                        _cleanup_free_ char *t;

                                        t = set_remove(controllers, *i);
                                        if (!t) {
                                                free(*i);
                                                continue;
                                        }
                                }

                                *(j++) = *i;
                        }

                        *j = NULL;

                        options = strv_join(*k, ",");
                        if (!options)
                                return log_oom();
                } else {
                        options = controller;
                        controller = NULL;
                }

                where = strappend("/sys/fs/cgroup/", options);
                if (!where)
                        return log_oom();

                p.where = where;
                p.options = options;

                r = mount_one(&p, true);
                if (r < 0)
                        return r;

                if (r > 0 && k && *k) {
                        char **i;

                        for (i = *k; *i; i++) {
                                _cleanup_free_ char *t = NULL;

                                t = strappend("/sys/fs/cgroup/", *i);
                                if (!t)
                                        return log_oom();

                                r = symlink(options, t);
                                if (r < 0 && errno != EEXIST)
                                        return log_error_errno(errno, "Failed to create symlink %s: %m", t);
#ifdef SMACK_RUN_LABEL
                                r = mac_smack_copy(t, options);
                                if (r < 0 && r != -EOPNOTSUPP)
                                        return log_error_errno(r, "Failed to copy smack label from %s to %s: %m", options, t);
#endif
                        }
                }
        }

        /* Now that we mounted everything, let's make the tmpfs the
         * cgroup file systems are mounted into read-only. */
        (void) mount("tmpfs", "/sys/fs/cgroup", "tmpfs", MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755");

        return 0;
}

#if defined(HAVE_SELINUX) || defined(HAVE_SMACK)
static int nftw_cb(
                const char *fpath,
                const struct stat *sb,
                int tflag,
                struct FTW *ftwbuf) {

        /* No need to label /dev twice in a row... */
        if (_unlikely_(ftwbuf->level == 0))
                return FTW_CONTINUE;

        label_fix(fpath, false, false);

        /* /run/initramfs is static data and big, no need to
         * dynamically relabel its contents at boot... */
        if (_unlikely_(ftwbuf->level == 1 &&
                      tflag == FTW_D &&
                      streq(fpath, "/run/initramfs")))
                return FTW_SKIP_SUBTREE;

        return FTW_CONTINUE;
};
#endif

int mount_setup(bool loaded_policy) {
        unsigned i;
        int r = 0;

        for (i = 0; i < ELEMENTSOF(mount_table); i ++) {
                int j;

                j = mount_one(mount_table + i, loaded_policy);
                if (j != 0 && r >= 0)
                        r = j;
        }

        if (r < 0)
                return r;

#if defined(HAVE_SELINUX) || defined(HAVE_SMACK)
        /* Nodes in devtmpfs and /run need to be manually updated for
         * the appropriate labels, after mounting. The other virtual
         * API file systems like /sys and /proc do not need that, they
         * use the same label for all their files. */
        if (loaded_policy) {
                usec_t before_relabel, after_relabel;
                char timespan[FORMAT_TIMESPAN_MAX];

                before_relabel = now(CLOCK_MONOTONIC);

                nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
                nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);

                after_relabel = now(CLOCK_MONOTONIC);

                log_info("Relabelled /dev and /run in %s.",
                         format_timespan(timespan, sizeof(timespan), after_relabel - before_relabel, 0));
        }
#endif

        /* Create a few default symlinks, which are normally created
         * by udevd, but some scripts might need them before we start
         * udevd. */
        dev_setup(NULL, UID_INVALID, GID_INVALID);

        /* Mark the root directory as shared in regards to mount
         * propagation. The kernel defaults to "private", but we think
         * it makes more sense to have a default of "shared" so that
         * nspawn and the container tools work out of the box. If
         * specific setups need other settings they can reset the
         * propagation mode to private if needed. */
        if (detect_container() <= 0)
                if (mount(NULL, "/", NULL, MS_REC|MS_SHARED, NULL) < 0)
                        log_warning_errno(errno, "Failed to set up the root directory for shared mount propagation: %m");

        /* Create a few directories we always want around, Note that
         * sd_booted() checks for /run/systemd/system, so this mkdir
         * really needs to stay for good, otherwise software that
         * copied sd-daemon.c into their sources will misdetect
         * systemd. */
        mkdir_label("/run/systemd", 0755);
        mkdir_label("/run/systemd/system", 0755);
        mkdir_label("/run/systemd/inaccessible", 0000);

        return 0;
}
Exemple #6
0
int mount_cgroup_controllers(char ***join_controllers) {
    int r;
    char buf[LINE_MAX];
    _cleanup_set_free_free_ Set *controllers = NULL;
    _cleanup_fclose_ FILE *f;

    /* Mount all available cgroup controllers that are built into the kernel. */

    f = fopen("/proc/cgroups", "re");
    if (!f) {
        log_error("Failed to enumerate cgroup controllers: %m");
        return 0;
    }

    controllers = set_new(string_hash_func, string_compare_func);
    if (!controllers)
        return log_oom();

    /* Ignore the header line */
    (void) fgets(buf, sizeof(buf), f);

    for (;;) {
        char *controller;
        int enabled = 0;

        if (fscanf(f, "%ms %*i %*i %i", &controller, &enabled) != 2) {

            if (feof(f))
                break;

            log_error("Failed to parse /proc/cgroups.");
            return -EIO;
        }

        if (!enabled) {
            free(controller);
            continue;
        }

        r = set_consume(controllers, controller);
        if (r < 0) {
            log_error("Failed to add controller to set.");
            return r;
        }
    }

    for (;;) {
        MountPoint p = {
            .what = "cgroup",
            .type = "cgroup",
            .flags = MS_NOSUID|MS_NOEXEC|MS_NODEV,
            .mode = MNT_IN_CONTAINER,
        };
        char ***k = NULL;
        _cleanup_free_ char *options = NULL, *controller;

        controller = set_steal_first(controllers);
        if (!controller)
            break;

        if (join_controllers)
            for (k = join_controllers; *k; k++)
                if (strv_find(*k, controller))
                    break;

        if (k && *k) {
            char **i, **j;

            for (i = *k, j = *k; *i; i++) {

                if (!streq(*i, controller)) {
                    char _cleanup_free_ *t;

                    t = set_remove(controllers, *i);
                    if (!t) {
                        free(*i);
                        continue;
                    }
                }

                *(j++) = *i;
            }

            *j = NULL;

            options = strv_join(*k, ",");
            if (!options)
                return log_oom();
        } else {
            options = controller;
            controller = NULL;
        }

        p.where = strappenda("/sys/fs/cgroup/", options);
        p.options = options;

        r = mount_one(&p, true);
        if (r < 0)
            return r;

        if (r > 0 && k && *k) {
            char **i;

            for (i = *k; *i; i++) {
                char *t = strappenda("/sys/fs/cgroup/", *i);

                r = symlink(options, t);
                if (r < 0 && errno != EEXIST) {
                    log_error("Failed to create symlink %s: %m", t);
                    return -errno;
                }
            }
        }
    }

    return 0;
}

static int nftw_cb(
    const char *fpath,
    const struct stat *sb,
    int tflag,
    struct FTW *ftwbuf) {

    /* No need to label /dev twice in a row... */
    if (_unlikely_(ftwbuf->level == 0))
        return FTW_CONTINUE;

    label_fix(fpath, false, false);

    /* /run/initramfs is static data and big, no need to
     * dynamically relabel its contents at boot... */
    if (_unlikely_(ftwbuf->level == 1 &&
                   tflag == FTW_D &&
                   streq(fpath, "/run/initramfs")))
        return FTW_SKIP_SUBTREE;

    return FTW_CONTINUE;
};

int mount_setup(bool loaded_policy) {
    int r;
    unsigned i;

    for (i = 0; i < ELEMENTSOF(mount_table); i ++) {
        r = mount_one(mount_table + i, true);

        if (r < 0)
            return r;
    }

    /* Nodes in devtmpfs and /run need to be manually updated for
     * the appropriate labels, after mounting. The other virtual
     * API file systems like /sys and /proc do not need that, they
     * use the same label for all their files. */
    if (loaded_policy) {
        usec_t before_relabel, after_relabel;
        char timespan[FORMAT_TIMESPAN_MAX];

        before_relabel = now(CLOCK_MONOTONIC);

        nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
        nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);

        after_relabel = now(CLOCK_MONOTONIC);

        log_info("Relabelled /dev and /run in %s.",
                 format_timespan(timespan, sizeof(timespan), after_relabel - before_relabel, 0));
    }

    /* Create a few default symlinks, which are normally created
     * by udevd, but some scripts might need them before we start
     * udevd. */
    dev_setup(NULL);

    /* Mark the root directory as shared in regards to mount
     * propagation. The kernel defaults to "private", but we think
     * it makes more sense to have a default of "shared" so that
     * nspawn and the container tools work out of the box. If
     * specific setups need other settings they can reset the
     * propagation mode to private if needed. */
    if (detect_container(NULL) <= 0)
        if (mount(NULL, "/", NULL, MS_REC|MS_SHARED, NULL) < 0)
            log_warning("Failed to set up the root directory for shared mount propagation: %m");

    /* Create a few directories we always want around, Note that
     * sd_booted() checks for /run/systemd/system, so this mkdir
     * really needs to stay for good, otherwise software that
     * copied sd-daemon.c into their sources will misdetect
     * systemd. */
    mkdir_label("/run/systemd", 0755);
    mkdir_label("/run/systemd/system", 0755);
    mkdir_label("/run/systemd/inaccessible", 0000);

    return 0;
}
Exemple #7
0
static bool test_strv_multi(struct torture_context *tctx)
{
	const char *data[] = { "foo", "bar", "", "samba", "x"};
	char *strv = NULL;
	char *t;
	int i, ret;
	const int num = ARRAY_SIZE(data);

	/* Add items */
	for (i = 0; i < num; i++) {
		ret = strv_add(tctx, &strv, data[i]);
		torture_assert(tctx, ret == 0, "strv_add() failed");
	}

	torture_assert_int_equal(tctx,
				 strv_count(strv), num,
				 "strv_count() failed");

	/* Check that strv_next() finds the expected values */
	t = NULL;
	for (i = 0; i < num; i++) {
		t = strv_next(strv, t);
		torture_assert(tctx,
			       strcmp(t, data[i]) == 0,
			       "strv_next() failed");
	}


	/* Check that strv_next() finds the expected values */
	t = NULL;
	for (i = 0; i < num; i++) {
		t = strv_next(strv, t);
		torture_assert(tctx,
			       strcmp(t, data[i]) == 0,
			       "strv_next() failed");
	}

	/* Find each item, delete it, check count */
	for (i = 0; i < num; i++) {
		t = strv_find(strv, data[i]);
		torture_assert(tctx,
			       strcmp(t, data[i]) == 0,
			       "strv_next() failed");
		strv_delete(&strv, t);
		torture_assert_int_equal(tctx,
					 strv_count(strv), num - i - 1,
					 "strv_delete() failed");
	}

	/* Add items */
	for (i = 0; i < num; i++) {
		ret = strv_add(tctx, &strv, data[i]);
		torture_assert(tctx, ret == 0, "strv_add() failed");
	}

	torture_assert_int_equal(tctx,
				 strv_count(strv), num,
				 "strv_count() failed");

	/* Find items in reverse, delete, check count */
	for (i = num - 1; i >= 0; i--) {
		t = strv_find(strv, data[i]);
		torture_assert(tctx,
			       strcmp(t, data[i]) == 0,
			       "strv_next() failed");
		strv_delete(&strv, t);
		torture_assert_int_equal(tctx,
					 strv_count(strv), i,
					 "strv_delete() failed");
	}

	return true;
}