예제 #1
0
END_TEST

START_TEST(test_filename_is_valid)
{
  filename_t *file = NULL;
  ck_assert_msg(0 == filename_is_valid(file), "A NULL file is never valid.");

  file = (filename_t *)malloc(sizeof(filename_t));
  file->name = NULL;
  ck_assert_msg(0 == filename_is_valid(file), "A file with a NULL name is"
    " never valid");
  free(file);
  file = NULL;

  // +2 for the `\0` character.
  char buf[PATH_MAX + 2];
  memset(buf, 'a', sizeof(buf));
  buf[PATH_MAX + 1] = '\0'; // +1 because indexes start at 0.
  file = filename_ptr_create(&buf[0]);
  ck_assert_msg(0 == filename_is_valid(file), "A file over PATH_MAX is never"
    " valid.");
  filename_ptr_free(&file);

  file = filename_ptr_create("fr/og");
  ck_assert_str_eq("fr/og", file->name);
  ck_assert_msg(0 == filename_is_valid(file), "A filename with a / is never"
    " valid.");
  filename_ptr_free(&file);

  file = filename_ptr_create("frog");
  ck_assert_str_eq("frog", file->name);
  ck_assert_int_eq(1, filename_is_valid(file));
  filename_ptr_free(&file);
}
예제 #2
0
int drop_in_file(const char *dir, const char *unit, unsigned level,
                 const char *name, char **_p, char **_q) {

        char prefix[DECIMAL_STR_MAX(unsigned)];
        _cleanup_free_ char *b = NULL;
        char *p, *q;

        assert(unit);
        assert(name);
        assert(_p);
        assert(_q);

        sprintf(prefix, "%u", level);

        b = xescape(name, "/.");
        if (!b)
                return -ENOMEM;

        if (!filename_is_valid(b))
                return -EINVAL;

        p = strjoin(dir, "/", unit, ".d");
        if (!p)
                return -ENOMEM;

        q = strjoin(p, "/", prefix, "-", b, ".conf");
        if (!q) {
                free(p);
                return -ENOMEM;
        }

        *_p = p;
        *_q = q;
        return 0;
}
예제 #3
0
static int file_of_seat(const char *seat, char **_p) {
        char *p;
        int r;

        assert(_p);

        if (seat) {
                if (!filename_is_valid(seat))
                        return -EINVAL;

                p = strappend("/run/systemd/seats/", seat);
        } else {
                _cleanup_free_ char *buf = NULL;

                r = sd_session_get_seat(NULL, &buf);
                if (r < 0)
                        return r;

                p = strappend("/run/systemd/seats/", buf);
        }

        if (!p)
                return -ENOMEM;

        *_p = TAKE_PTR(p);
        return 0;
}
예제 #4
0
bool locale_is_valid(const char *name) {

        if (isempty(name))
                return false;

        if (strlen(name) >= 128)
                return false;

        if (!utf8_is_valid(name))
                return false;

        if (!filename_is_valid(name))
                return false;

        if (!string_is_safe(name))
                return false;

        return true;
}
예제 #5
0
static int extract_prefix(const char *path, char **ret) {
        _cleanup_free_ char *name = NULL;
        const char *bn, *underscore;
        size_t m;

        bn = basename(path);

        underscore = strchr(bn, '_');
        if (underscore)
                m = underscore - bn;
        else {
                const char *e;

                e = endswith(bn, ".raw");
                if (!e)
                        e = strchr(bn, 0);

                m = e - bn;
        }

        name = strndup(bn, m);
        if (!name)
                return -ENOMEM;

        /*  A slightly reduced version of what's permitted in unit names. With ':' and '\' are removed, as well as '_'
         *  which we use as delimiter for the second part of the image string, which we ignore for now. */
        if (!in_charset(name, DIGITS LETTERS "-."))
                return -EINVAL;

        if (!filename_is_valid(name))
                return -EINVAL;

        *ret = TAKE_PTR(name);

        return 0;
}
예제 #6
0
static int set_machine_info(Context *c, sd_bus_message *m, int prop, sd_bus_message_handler_t cb, sd_bus_error *error) {
    int interactive;
    const char *name;
    int r;

    assert(c);
    assert(m);

    r = sd_bus_message_read(m, "sb", &name, &interactive);
    if (r < 0)
        return r;

    if (isempty(name))
        name = NULL;

    if (streq_ptr(name, c->data[prop]))
        return sd_bus_reply_method_return(m, NULL);

    /* Since the pretty hostname should always be changed at the
     * same time as the static one, use the same policy action for
     * both... */

    r = bus_verify_polkit_async(
            m,
            CAP_SYS_ADMIN,
            prop == PROP_PRETTY_HOSTNAME ? "org.freedesktop.hostname1.set-static-hostname" : "org.freedesktop.hostname1.set-machine-info",
            NULL,
            interactive,
            UID_INVALID,
            &c->polkit_registry,
            error);
    if (r < 0)
        return r;
    if (r == 0)
        return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */

    if (isempty(name)) {
        c->data[prop] = mfree(c->data[prop]);
    } else {
        char *h;

        /* The icon name might ultimately be used as file
         * name, so better be safe than sorry */

        if (prop == PROP_ICON_NAME && !filename_is_valid(name))
            return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid icon name '%s'", name);
        if (prop == PROP_PRETTY_HOSTNAME && string_has_cc(name, NULL))
            return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid pretty host name '%s'", name);
        if (prop == PROP_CHASSIS && !valid_chassis(name))
            return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid chassis '%s'", name);
        if (prop == PROP_DEPLOYMENT && !valid_deployment(name))
            return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid deployment '%s'", name);
        if (prop == PROP_LOCATION && string_has_cc(name, NULL))
            return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid location '%s'", name);

        h = strdup(name);
        if (!h)
            return -ENOMEM;

        free(c->data[prop]);
        c->data[prop] = h;
    }

    r = context_write_data_machine_info(c);
    if (r < 0) {
        log_error_errno(r, "Failed to write machine info: %m");
        return sd_bus_error_set_errnof(error, r, "Failed to write machine info: %s", strerror(-r));
    }

    log_info("Changed %s to '%s'",
             prop == PROP_PRETTY_HOSTNAME ? "pretty host name" :
             prop == PROP_DEPLOYMENT ? "deployment" :
             prop == PROP_LOCATION ? "location" :
             prop == PROP_CHASSIS ? "chassis" : "icon name", strna(c->data[prop]));

    (void) sd_bus_emit_properties_changed(
        sd_bus_message_get_bus(m),
        "/org/freedesktop/hostname1",
        "org.freedesktop.hostname1",
        prop == PROP_PRETTY_HOSTNAME ? "PrettyHostname" :
        prop == PROP_DEPLOYMENT ? "Deployment" :
        prop == PROP_LOCATION ? "Location" :
        prop == PROP_CHASSIS ? "Chassis" : "IconName" , NULL);

    return sd_bus_reply_method_return(m, NULL);
}
예제 #7
0
void server_process_native_file(
                Server *s,
                int fd,
                const struct ucred *ucred,
                const struct timeval *tv,
                const char *label, size_t label_len) {

        struct stat st;
        bool sealed;
        int r;

        /* Data is in the passed fd, since it didn't fit in a
         * datagram. */

        assert(s);
        assert(fd >= 0);

        /* If it's a memfd, check if it is sealed. If so, we can just
         * use map it and use it, and do not need to copy the data
         * out. */
        sealed = memfd_get_sealed(fd) > 0;

        if (!sealed && (!ucred || ucred->uid != 0)) {
                _cleanup_free_ char *sl = NULL, *k = NULL;
                const char *e;

                /* If this is not a sealed memfd, and the peer is unknown or
                 * unprivileged, then verify the path. */

                if (asprintf(&sl, "/proc/self/fd/%i", fd) < 0) {
                        log_oom();
                        return;
                }

                r = readlink_malloc(sl, &k);
                if (r < 0) {
                        log_error_errno(r, "readlink(%s) failed: %m", sl);
                        return;
                }

                e = path_startswith(k, "/dev/shm/");
                if (!e)
                        e = path_startswith(k, "/tmp/");
                if (!e)
                        e = path_startswith(k, "/var/tmp/");
                if (!e) {
                        log_error("Received file outside of allowed directories. Refusing.");
                        return;
                }

                if (!filename_is_valid(e)) {
                        log_error("Received file in subdirectory of allowed directories. Refusing.");
                        return;
                }
        }

        if (fstat(fd, &st) < 0) {
                log_error_errno(errno, "Failed to stat passed file, ignoring: %m");
                return;
        }

        if (!S_ISREG(st.st_mode)) {
                log_error("File passed is not regular. Ignoring.");
                return;
        }

        if (st.st_size <= 0)
                return;

        if (st.st_size > ENTRY_SIZE_MAX) {
                log_error("File passed too large. Ignoring.");
                return;
        }

        if (sealed) {
                void *p;
                size_t ps;

                /* The file is sealed, we can just map it and use it. */

                ps = PAGE_ALIGN(st.st_size);
                p = mmap(NULL, ps, PROT_READ, MAP_PRIVATE, fd, 0);
                if (p == MAP_FAILED) {
                        log_error_errno(errno, "Failed to map memfd, ignoring: %m");
                        return;
                }

                server_process_native_message(s, p, st.st_size, ucred, tv, label, label_len);
                assert_se(munmap(p, ps) >= 0);
        } else {
                _cleanup_free_ void *p = NULL;
                struct statvfs vfs;
                ssize_t n;

                if (fstatvfs(fd, &vfs) < 0) {
                        log_error_errno(errno, "Failed to stat file system of passed file, ignoring: %m");
                        return;
                }

                /* Refuse operating on file systems that have
                 * mandatory locking enabled, see:
                 *
                 * https://github.com/systemd/systemd/issues/1822
                 */
                if (vfs.f_flag & ST_MANDLOCK) {
                        log_error("Received file descriptor from file system with mandatory locking enable, refusing.");
                        return;
                }

                /* Make the fd non-blocking. On regular files this has
                 * the effect of bypassing mandatory locking. Of
                 * course, this should normally not be necessary given
                 * the check above, but let's better be safe than
                 * sorry, after all NFS is pretty confusing regarding
                 * file system flags, and we better don't trust it,
                 * and so is SMB. */
                r = fd_nonblock(fd, true);
                if (r < 0) {
                        log_error_errno(r, "Failed to make fd non-blocking, ignoring: %m");
                        return;
                }

                /* The file is not sealed, we can't map the file here, since
                 * clients might then truncate it and trigger a SIGBUS for
                 * us. So let's stupidly read it */

                p = malloc(st.st_size);
                if (!p) {
                        log_oom();
                        return;
                }

                n = pread(fd, p, st.st_size, 0);
                if (n < 0)
                        log_error_errno(errno, "Failed to read file, ignoring: %m");
                else if (n > 0)
                        server_process_native_message(s, p, n, ucred, tv, label, label_len);
        }
}
예제 #8
0
/* Mount legacy cgroup hierarchy when cgroup namespaces are unsupported. */
static int mount_legacy_cgns_unsupported(
                const char *dest,
                CGroupUnified unified_requested,
                bool userns,
                uid_t uid_shift,
                uid_t uid_range,
                const char *selinux_apifs_context) {

        _cleanup_set_free_free_ Set *controllers = NULL;
        const char *cgroup_root;
        int r;

        cgroup_root = prefix_roota(dest, "/sys/fs/cgroup");

        (void) mkdir_p(cgroup_root, 0755);

        /* Mount a tmpfs to /sys/fs/cgroup if it's not mounted there yet. */
        r = path_is_mount_point(cgroup_root, dest, AT_SYMLINK_FOLLOW);
        if (r < 0)
                return log_error_errno(r, "Failed to determine if /sys/fs/cgroup is already mounted: %m");
        if (r == 0) {
                _cleanup_free_ char *options = NULL;

                r = tmpfs_patch_options("mode=755", uid_shift == 0 ? UID_INVALID : uid_shift, selinux_apifs_context, &options);
                if (r < 0)
                        return log_oom();

                r = mount_verbose(LOG_ERR, "tmpfs", cgroup_root, "tmpfs",
                                  MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, options);
                if (r < 0)
                        return r;
        }

        r = cg_all_unified();
        if (r < 0)
                return r;
        if (r > 0)
                goto skip_controllers;

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

        for (;;) {
                _cleanup_free_ char *controller = NULL, *origin = NULL, *combined = NULL;

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

                origin = prefix_root("/sys/fs/cgroup/", controller);
                if (!origin)
                        return log_oom();

                r = readlink_malloc(origin, &combined);
                if (r == -EINVAL) {
                        /* Not a symbolic link, but directly a single cgroup hierarchy */

                        r = mount_legacy_cgroup_hierarchy(dest, controller, controller, true);
                        if (r < 0)
                                return r;

                } else if (r < 0)
                        return log_error_errno(r, "Failed to read link %s: %m", origin);
                else {
                        _cleanup_free_ char *target = NULL;

                        target = prefix_root(dest, origin);
                        if (!target)
                                return log_oom();

                        /* A symbolic link, a combination of controllers in one hierarchy */

                        if (!filename_is_valid(combined)) {
                                log_warning("Ignoring invalid combined hierarchy %s.", combined);
                                continue;
                        }

                        r = mount_legacy_cgroup_hierarchy(dest, combined, combined, true);
                        if (r < 0)
                                return r;

                        r = symlink_idempotent(combined, target, false);
                        if (r == -EINVAL)
                                return log_error_errno(r, "Invalid existing symlink for combined hierarchy: %m");
                        if (r < 0)
                                return log_error_errno(r, "Failed to create symlink for combined hierarchy: %m");
                }
        }

skip_controllers:
        if (unified_requested >= CGROUP_UNIFIED_SYSTEMD) {
                r = mount_legacy_cgroup_hierarchy(dest, SYSTEMD_CGROUP_CONTROLLER_HYBRID, "unified", false);
                if (r < 0)
                        return r;
        }

        r = mount_legacy_cgroup_hierarchy(dest, SYSTEMD_CGROUP_CONTROLLER_LEGACY, "systemd", false);
        if (r < 0)
                return r;

        return mount_verbose(LOG_ERR, NULL, cgroup_root, NULL,
                             MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755");
}
예제 #9
0
파일: r_texture.c 프로젝트: eledot/erszebet
/*
=================
r_texture_load
=================
*/
erbool r_texture_load (const char *name, int type, image_t *out_image, r_texture_t **tex)
{
    int gltex, nlen, w, h, texw, texh;
    char tmp[MISC_MAX_FILENAME], *namecopy;
    image_t image;
    r_texture_t *t, clone;

    if (NULL == name || type < 0 || type >= STSIZE(types) || NULL == tex)
    {
        sys_printf("bad args (name=%p, type=%i, tex=%p)\n", name, type, tex);
        return false;
    }

    *tex = NULL;

    if (!filename_is_valid(name))
        return false;

    /* check if it was loaded earlier */
    clone.name = name;
    t = sglib_r_texture_t_find_member(textures, &clone);

    if (NULL != t)
    {
        t->ref++;
        *tex = t;
        return true;
    }

    snprintf(tmp, sizeof(tmp), "tex/%s", name);

    if (!image_load(tmp, &image))
        goto error;

    w = image.width;
    h = image.height;

    if (NULL != out_image)
    {
        memcpy(out_image, &image, sizeof(image));
        out_image->data = mem_alloc(r_mempool, w * h << 2);
        memcpy(out_image->data, image.data, w * h << 2);
    }

    if (!gl_texture_create(&image, types[type], &gltex, &texw, &texh))
    {
        sys_printf("failed to create gl texture \"%s\" (%ix%i)\n", name, w, h);
        goto error;
    }

    mem_free(image.data);

    nlen = strlen(name) + 1;

    if (NULL == (t = mem_alloc(r_mempool, sizeof(r_texture_t) + nlen)))
    {
        gl_texture_delete(gltex);
        goto error;
    }

    namecopy = (char *)t + sizeof(r_texture_t);
    strlcpy(namecopy, name, nlen);

    t->name = namecopy;
    t->type = type;
    t->gltex = gltex;
    t->ref = 1;
    t->w = w;
    t->h = h;
    t->texw = (float)w / (float)texw;
    t->texh = (float)h / (float)texh;

    *tex = t;

    sglib_r_texture_t_add(&textures, t);

    return true;

error:

    if (NULL != image.data)
        mem_free(image.data);

    return false;
}