예제 #1
0
static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) {
        _cleanup_close_ int fd;
        TunTap *t = NULL;
        const char *user;
        const char *group;
        uid_t uid;
        gid_t gid;
        int r;

        assert(netdev);
        assert(ifr);

        fd = open(TUN_DEV, O_RDWR);
        if (fd < 0)
                return log_netdev_error_errno(netdev, -errno,  "Failed to open tun dev: %m");

        r = ioctl(fd, TUNSETIFF, ifr);
        if (r < 0)
                return log_netdev_error_errno(netdev, -errno, "TUNSETIFF failed on tun dev: %m");

        if (netdev->kind == NETDEV_KIND_TAP)
                t = TAP(netdev);
        else
                t = TUN(netdev);

        assert(t);

        if(t->user_name) {

                user = t->user_name;

                r = get_user_creds(&user, &uid, NULL, NULL, NULL);
                if (r < 0)
                        return log_netdev_error_errno(netdev, r, "Cannot resolve user name %s: %m", t->user_name);

                r = ioctl(fd, TUNSETOWNER, uid);
                if (r < 0)
                        return log_netdev_error_errno(netdev, -errno, "TUNSETOWNER failed on tun dev: %m");
        }

        if (t->group_name) {

                group = t->group_name;

                r = get_group_creds(&group, &gid);
                if (r < 0)
                        return log_netdev_error_errno(netdev, r, "Cannot resolve group name %s: %m", t->group_name);

                r = ioctl(fd, TUNSETGROUP, gid);
                if (r < 0)
                        return log_netdev_error_errno(netdev, -errno, "TUNSETGROUP failed on tun dev: %m");

        }

        r = ioctl(fd, TUNSETPERSIST, 1);
        if (r < 0)
                return log_netdev_error_errno(netdev, -errno, "TUNSETPERSIST failed on tun dev: %m");

        return 0;
}
예제 #2
0
파일: user-util.c 프로젝트: aulanov/systemd
int in_group(const char *name) {
        int r;
        gid_t gid;

        r = get_group_creds(&name, &gid);
        if (r < 0)
                return r;

        return in_gid(gid);
}
예제 #3
0
static void test_get_group_creds_one(const char *id, const char *name, gid_t gid) {
        gid_t rgid = GID_INVALID;
        int r;

        log_info("/* %s(\"%s\", \"%s\", "GID_FMT") */", __func__, id, name, gid);

        r = get_group_creds(&id, &rgid, 0);
        log_info_errno(r, "got \"%s\", "GID_FMT": %m", id, rgid);
        if (!synthesize_nobody() && streq(name, NOBODY_GROUP_NAME)) {
                log_info("(skipping detailed tests because nobody is not synthesized)");
                return;
        }
        assert_se(r == 0);
        assert_se(streq_ptr(id, name));
        assert_se(rgid == gid);
}
예제 #4
0
static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) {
        _cleanup_close_ int fd;
        const char *user;
        const char *group;
        uid_t uid;
        gid_t gid;
        int r = 0;

        fd = open(TUN_DEV, O_RDWR);
        if (fd < 0) {
                log_error_netdev(netdev,
                                 "Failed to open tun dev: %s",
                                 strerror(-r));
                return r;
        }

        r = ioctl(fd, TUNSETIFF, ifr);
        if (r < 0) {
                log_error_netdev(netdev,
                                 "TUNSETIFF failed on tun dev: %s",
                                 strerror(-r));
                return r;
        }

        if(netdev->user_name) {

                user = netdev->user_name;

                r = get_user_creds(&user, &uid, NULL, NULL, NULL);
                if (r < 0) {
                        log_error("Cannot resolve user name %s: %s",
                                  netdev->user_name, strerror(-r));
                        return 0;
                }

                r = ioctl(fd, TUNSETOWNER, uid);
                if ( r < 0) {
                        log_error_netdev(netdev,
                                         "TUNSETOWNER failed on tun dev: %s",
                                         strerror(-r));
                }
        }

        if(netdev->group_name) {

                group = netdev->group_name;

                r = get_group_creds(&group, &gid);
                if (r < 0) {
                        log_error("Cannot resolve group name %s: %s",
                                  netdev->group_name, strerror(-r));
                        return 0;
                }

                r = ioctl(fd, TUNSETGROUP, gid);
                if( r < 0) {
                        log_error_netdev(netdev,
                                         "TUNSETGROUP failed on tun dev: %s",
                                         strerror(-r));
                        return r;
                }

        }

        r = ioctl(fd, TUNSETPERSIST, 1);
        if (r < 0) {
                log_error_netdev(netdev,
                                 "TUNSETPERSIST failed on tun dev: %s",
                                 strerror(-r));
                return r;
        }

        return r;
}
예제 #5
0
파일: tmpfiles.c 프로젝트: adsr/systemd
static int parse_line(const char *fname, unsigned line, const char *buffer) {
        Item *i, *existing;
        char *mode = NULL, *user = NULL, *group = NULL, *age = NULL;
        char type;
        Hashmap *h;
        int r, n = -1;

        assert(fname);
        assert(line >= 1);
        assert(buffer);

        i = new0(Item, 1);
        if (!i) {
                log_error("Out of memory");
                return -ENOMEM;
        }

        if (sscanf(buffer,
                   "%c "
                   "%ms "
                   "%ms "
                   "%ms "
                   "%ms "
                   "%ms "
                   "%n",
                   &type,
                   &i->path,
                   &mode,
                   &user,
                   &group,
                   &age,
                   &n) < 2) {
                log_error("[%s:%u] Syntax error.", fname, line);
                r = -EIO;
                goto finish;
        }

        if (n >= 0)  {
                n += strspn(buffer+n, WHITESPACE);
                if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) {
                        i->argument = unquote(buffer+n, "\"");
                        if (!i->argument) {
                                log_error("Out of memory");
                                return -ENOMEM;
                        }
                }
        }

        switch(type) {

        case CREATE_FILE:
        case TRUNCATE_FILE:
        case CREATE_DIRECTORY:
        case TRUNCATE_DIRECTORY:
        case CREATE_FIFO:
        case IGNORE_PATH:
        case REMOVE_PATH:
        case RECURSIVE_REMOVE_PATH:
        case RELABEL_PATH:
        case RECURSIVE_RELABEL_PATH:
                break;

        case CREATE_SYMLINK:
                if (!i->argument) {
                        log_error("[%s:%u] Symlink file requires argument.", fname, line);
                        r = -EBADMSG;
                        goto finish;
                }
                break;

        case WRITE_FILE:
                if (!i->argument) {
                        log_error("[%s:%u] Write file requires argument.", fname, line);
                        r = -EBADMSG;
                        goto finish;
                }
                break;

        case CREATE_CHAR_DEVICE:
        case CREATE_BLOCK_DEVICE: {
                unsigned major, minor;

                if (!i->argument) {
                        log_error("[%s:%u] Device file requires argument.", fname, line);
                        r = -EBADMSG;
                        goto finish;
                }

                if (sscanf(i->argument, "%u:%u", &major, &minor) != 2) {
                        log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i->argument);
                        r = -EBADMSG;
                        goto finish;
                }

                i->major_minor = makedev(major, minor);
                break;
        }

        default:
                log_error("[%s:%u] Unknown file type '%c'.", fname, line, type);
                r = -EBADMSG;
                goto finish;
        }

        i->type = type;

        if (!path_is_absolute(i->path)) {
                log_error("[%s:%u] Path '%s' not absolute.", fname, line, i->path);
                r = -EBADMSG;
                goto finish;
        }

        path_kill_slashes(i->path);

        if (arg_prefix && !path_startswith(i->path, arg_prefix)) {
                r = 0;
                goto finish;
        }

        if (user && !streq(user, "-")) {
                const char *u = user;

                r = get_user_creds(&u, &i->uid, NULL, NULL, NULL);
                if (r < 0) {
                        log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
                        goto finish;
                }

                i->uid_set = true;
        }

        if (group && !streq(group, "-")) {
                const char *g = group;

                r = get_group_creds(&g, &i->gid);
                if (r < 0) {
                        log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
                        goto finish;
                }

                i->gid_set = true;
        }

        if (mode && !streq(mode, "-")) {
                unsigned m;

                if (sscanf(mode, "%o", &m) != 1) {
                        log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
                        r = -ENOENT;
                        goto finish;
                }

                i->mode = m;
                i->mode_set = true;
        } else
                i->mode =
                        i->type == CREATE_DIRECTORY ||
                        i->type == TRUNCATE_DIRECTORY ? 0755 : 0644;

        if (age && !streq(age, "-")) {
                const char *a = age;

                if (*a == '~') {
                        i->keep_first_level = true;
                        a++;
                }

                if (parse_usec(a, &i->age) < 0) {
                        log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
                        r = -EBADMSG;
                        goto finish;
                }

                i->age_set = true;
        }

        h = needs_glob(i->type) ? globs : items;

        existing = hashmap_get(h, i->path);
        if (existing) {

                /* Two identical items are fine */
                if (!item_equal(existing, i))
                        log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path);

                r = 0;
                goto finish;
        }

        r = hashmap_put(h, i->path, i);
        if (r < 0) {
                log_error("Failed to insert item %s: %s", i->path, strerror(-r));
                goto finish;
        }

        i = NULL;
        r = 0;

finish:
        free(user);
        free(group);
        free(mode);
        free(age);

        if (i)
                item_free(i);

        return r;
}
예제 #6
0
파일: run.c 프로젝트: pszewczyk/systemd
static int start_transient_scope(
    sd_bus *bus,
    char **argv) {

    _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
    _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
    _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
    _cleanup_strv_free_ char **env = NULL, **user_env = NULL;
    _cleanup_free_ char *scope = NULL;
    const char *object = NULL;
    int r;

    assert(bus);
    assert(argv);

    r = bus_wait_for_jobs_new(bus, &w);
    if (r < 0)
        return log_oom();

    if (arg_unit) {
        r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".scope", &scope);
        if (r < 0)
            return log_error_errno(r, "Failed to mangle scope name: %m");
    } else {
        r = make_unit_name(bus, UNIT_SCOPE, &scope);
        if (r < 0)
            return r;
    }

    r = sd_bus_message_new_method_call(
            bus,
            &m,
            "org.freedesktop.systemd1",
            "/org/freedesktop/systemd1",
            "org.freedesktop.systemd1.Manager",
            "StartTransientUnit");
    if (r < 0)
        return bus_log_create_error(r);

    r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
    if (r < 0)
        return bus_log_create_error(r);

    /* Name and Mode */
    r = sd_bus_message_append(m, "ss", scope, "fail");
    if (r < 0)
        return bus_log_create_error(r);

    /* Properties */
    r = sd_bus_message_open_container(m, 'a', "(sv)");
    if (r < 0)
        return bus_log_create_error(r);

    r = transient_scope_set_properties(m);
    if (r < 0)
        return bus_log_create_error(r);

    r = sd_bus_message_close_container(m);
    if (r < 0)
        return bus_log_create_error(r);

    /* Auxiliary units */
    r = sd_bus_message_append(m, "a(sa(sv))", 0);
    if (r < 0)
        return bus_log_create_error(r);

    polkit_agent_open_if_enabled();

    r = sd_bus_call(bus, m, 0, &error, &reply);
    if (r < 0) {
        log_error("Failed to start transient scope unit: %s", bus_error_message(&error, -r));
        return r;
    }

    if (arg_nice_set) {
        if (setpriority(PRIO_PROCESS, 0, arg_nice) < 0)
            return log_error_errno(errno, "Failed to set nice level: %m");
    }

    if (arg_exec_group) {
        gid_t gid;

        r = get_group_creds(&arg_exec_group, &gid);
        if (r < 0)
            return log_error_errno(r, "Failed to resolve group %s: %m", arg_exec_group);

        if (setresgid(gid, gid, gid) < 0)
            return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
    }

    if (arg_exec_user) {
        const char *home, *shell;
        uid_t uid;
        gid_t gid;

        r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell);
        if (r < 0)
            return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user);

        r = strv_extendf(&user_env, "HOME=%s", home);
        if (r < 0)
            return log_oom();

        r = strv_extendf(&user_env, "SHELL=%s", shell);
        if (r < 0)
            return log_oom();

        r = strv_extendf(&user_env, "USER=%s", arg_exec_user);
        if (r < 0)
            return log_oom();

        r = strv_extendf(&user_env, "LOGNAME=%s", arg_exec_user);
        if (r < 0)
            return log_oom();

        if (!arg_exec_group) {
            if (setresgid(gid, gid, gid) < 0)
                return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
        }

        if (setresuid(uid, uid, uid) < 0)
            return log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", uid);
    }

    env = strv_env_merge(3, environ, user_env, arg_environment);
    if (!env)
        return log_oom();

    r = sd_bus_message_read(reply, "o", &object);
    if (r < 0)
        return bus_log_parse_error(r);

    r = bus_wait_for_jobs_one(w, object, arg_quiet);
    if (r < 0)
        return r;

    if (!arg_quiet)
        log_info("Running scope as unit: %s", scope);

    execvpe(argv[0], argv, env);

    return log_error_errno(errno, "Failed to execute: %m");
}