Пример #1
0
int get_user_creds_clean(
                const char **username,
                uid_t *uid, gid_t *gid,
                const char **home,
                const char **shell) {

        int r;

        /* Like get_user_creds(), but resets home/shell to NULL if they don't contain anything relevant. */

        r = get_user_creds(username, uid, gid, home, shell);
        if (r < 0)
                return r;

        if (shell &&
            (isempty(*shell) || PATH_IN_SET(*shell,
                                            "/bin/nologin",
                                            "/sbin/nologin",
                                            "/usr/bin/nologin",
                                            "/usr/sbin/nologin")))
                *shell = NULL;

        if (home &&
            (isempty(*home) || path_equal(*home, "/")))
                *home = NULL;

        return 0;
}
Пример #2
0
static char *specifier_user_name(char specifier, void *data, void *userdata) {
        InstallInfo *i = userdata;
        const char *username;
        _cleanup_free_ char *tmp = NULL;
        char *printed = NULL;

        assert(i);

        if (i->user)
                username = i->user;
        else
                /* get USER env from env or our own uid */
                username = tmp = getusername_malloc();

        switch (specifier) {
        case 'u':
                printed = strdup(username);
                break;
        case 'U': {
                /* fish username from passwd */
                uid_t uid;
                int r;

                r = get_user_creds(&username, &uid, NULL, NULL, NULL);
                if (r < 0)
                        return NULL;

                if (asprintf(&printed, "%d", uid) < 0)
                        return NULL;
                break;
        }}

        return printed;
}
Пример #3
0
static char *specifier_user_home(char specifier, void *data, void *userdata) {
        Unit *u = userdata;
        ExecContext *c;
        int r;
        const char *username, *home;

        assert(u);

        c = unit_get_exec_context(u);

        /* return HOME if set, otherwise from passwd */
        if (!c || !c->user) {
                char *h;

                r = get_home_dir(&h);
                if (r < 0)
                        return NULL;

                return h;
        }

        username = c->user;
        r = get_user_creds(&username, NULL, NULL, &home, NULL);
        if (r < 0)
               return NULL;

        return strdup(home);
}
Пример #4
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;
}
Пример #5
0
static int condition_test_user(Condition *c) {
        uid_t id;
        int r;
        _cleanup_free_ char *username = NULL;
        const char *u;

        assert(c);
        assert(c->parameter);
        assert(c->type == CONDITION_USER);

        r = parse_uid(c->parameter, &id);
        if (r >= 0)
                return id == getuid() || id == geteuid();

        if (streq("@system", c->parameter))
                return uid_is_system(getuid()) || uid_is_system(geteuid());

        username = getusername_malloc();
        if (!username)
                return -ENOMEM;

        if (streq(username, c->parameter))
                return 1;

        if (getpid_cached() == 1)
                return streq(c->parameter, "root");

        u = c->parameter;
        r = get_user_creds(&u, &id, NULL, NULL, NULL);
        if (r < 0)
                return 0;

        return id == getuid() || id == geteuid();
}
Пример #6
0
static char *specifier_user_shell(char specifier, void *data, void *userdata) {
        Unit *u = userdata;
        ExecContext *c;
        int r;
        const char *username, *shell;

        assert(u);

        c = unit_get_exec_context(u);

        /* return HOME if set, otherwise from passwd */
        if (!c || !c->user) {
                char *sh;

                r = get_shell(&sh);
                if (r < 0)
                        return strdup("/bin/sh");

                return sh;
        }

        username = c->user;
        r = get_user_creds(&username, NULL, NULL, NULL, &shell);
        if (r < 0)
                return strdup("/bin/sh");

        return strdup(shell);
}
Пример #7
0
int main(int argc, char *argv[]) {
        int r, accept_fd;
        uid_t uid, bus_uid;
        gid_t gid;

        log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
        log_parse_environment();
        log_open();

        bus_uid = getuid();

        if (geteuid() == 0) {
                const char *user = "******";

                r = get_user_creds(&user, &uid, &gid, NULL, NULL);
                if (r < 0) {
                        log_error_errno(r, "Cannot resolve user name %s: %m", user);
                        goto finish;
                }

                r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
                if (r < 0) {
                        log_error_errno(r, "Cannot drop privileges: %m");
                        goto finish;
                }
        }

        r = parse_argv(argc, argv);
        if (r <= 0)
                goto finish;

        r = sd_listen_fds(0);
        if (r != 1) {
                log_error("Illegal number of file descriptors passed");
                goto finish;
        }

        accept_fd = SD_LISTEN_FDS_START;

        r = fd_nonblock(accept_fd, false);
        if (r < 0) {
                log_error_errno(r, "Cannot mark accept-fd non-blocking: %m");
                goto finish;
        }

        r = loop_clients(accept_fd, bus_uid);

finish:
        sd_notify(false,
                  "STOPPING=1\n"
                  "STATUS=Shutting down.");

        strv_free(arg_configuration);
        free(arg_address);

        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
Пример #8
0
static void test_add_acls_for_user(void) {
        char fn[] = "/tmp/test-empty.XXXXXX";
        _cleanup_close_ int fd = -1;
        char *cmd;
        uid_t uid;
        int r;

        fd = mkostemp_safe(fn, O_RDWR|O_CLOEXEC);
        assert_se(fd >= 0);

        /* Use the mode that user journal files use */
        assert_se(fchmod(fd, 0640) == 0);

        cmd = strjoina("ls -l ", fn);
        assert_se(system(cmd) == 0);

        cmd = strjoina("getfacl -p ", fn);
        assert_se(system(cmd) == 0);

        if (getuid() == 0) {
                const char *nobody = "nobody";
                r = get_user_creds(&nobody, &uid, NULL, NULL, NULL);
                if (r < 0)
                        uid = 0;
        } else
                uid = getuid();

        r = add_acls_for_user(fd, uid);
        assert_se(r >= 0);

        cmd = strjoina("ls -l ", fn);
        assert_se(system(cmd) == 0);

        cmd = strjoina("getfacl -p ", fn);
        assert_se(system(cmd) == 0);

        /* set the acls again */

        r = add_acls_for_user(fd, uid);
        assert_se(r >= 0);

        cmd = strjoina("ls -l ", fn);
        assert_se(system(cmd) == 0);

        cmd = strjoina("getfacl -p ", fn);
        assert_se(system(cmd) == 0);

        unlink(fn);
}
Пример #9
0
int main(int argc, char *argv[]) {
        uid_t uid;
        int r;
        const char* name = argv[1] ?: "nfsnobody";

        r = get_user_creds(&name, &uid, NULL, NULL, NULL);
        if (r < 0) {
                log_full_errno(r == -ESRCH ? LOG_NOTICE : LOG_ERR,
                               r, "Failed to resolve \"%s\": %m", name);
                return r == -ESRCH ? EXIT_TEST_SKIP : EXIT_FAILURE;
        }

        r = clean_ipc_by_uid(uid);
        return  r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
Пример #10
0
static char *specifier_user_shell(char specifier, void *data, void *userdata) {
        Unit *u = userdata;
        ExecContext *c;
        int r;
        const char *username, *shell;
        char *ret;

        assert(u);

        c = unit_get_exec_context(u);

        if (c && c->user)
                username = c->user;
        else
                username = "******";

        /* return /bin/sh for root, otherwise the value from passwd */
        r = get_user_creds(&username, NULL, NULL, NULL, &shell);
        if (r < 0) {
                log_warning_unit(u->id,
                                 "Failed to determine shell: %s",
                                 strerror(-r));
                return NULL;
        }

        if (!path_is_absolute(shell)) {
                log_warning_unit(u->id,
                                 "Shell %s is not absolute, ignoring.",
                                 shell);
        }

        ret = strdup(shell);
        if (!ret)
                log_oom();

        return ret;
}
Пример #11
0
static char *specifier_user_name(char specifier, void *data, void *userdata) {
        Unit *u = userdata;
        ExecContext *c;
        int r;
        const char *username;
        _cleanup_free_ char *tmp = NULL;
        uid_t uid;
        char *printed = NULL;

        assert(u);

        c = unit_get_exec_context(u);

        if (c && c->user)
                username = c->user;
        else
                /* get USER env from env or our own uid */
                username = tmp = getusername_malloc();

        /* fish username from passwd */
        r = get_user_creds(&username, &uid, NULL, NULL, NULL);
        if (r < 0)
                return NULL;

        switch (specifier) {
                case 'U':
                        if (asprintf(&printed, "%d", uid) < 0)
                                return NULL;
                        break;
                case 'u':
                        printed = strdup(username);
                        break;
        }

        return printed;
}
Пример #12
0
static void test_get_user_creds_one(const char *id, const char *name, uid_t uid, gid_t gid, const char *home, const char *shell) {
        const char *rhome = NULL;
        const char *rshell = NULL;
        uid_t ruid = UID_INVALID;
        gid_t rgid = GID_INVALID;
        int r;

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

        r = get_user_creds(&id, &ruid, &rgid, &rhome, &rshell, 0);
        log_info_errno(r, "got \"%s\", "UID_FMT", "GID_FMT", \"%s\", \"%s\": %m",
                       id, ruid, rgid, strnull(rhome), strnull(rshell));
        if (!synthesize_nobody() && streq(name, NOBODY_USER_NAME)) {
                log_info("(skipping detailed tests because nobody is not synthesized)");
                return;
        }
        assert_se(r == 0);
        assert_se(streq_ptr(id, name));
        assert_se(ruid == uid);
        assert_se(rgid == gid);
        assert_se(path_equal(rhome, home));
        assert_se(path_equal(rshell, shell));
}
Пример #13
0
int main(int argc, char *argv[]) {
        _cleanup_manager_free_ Manager *m = NULL;
        const char *user = "******";
        uid_t uid;
        gid_t gid;
        int r;

        log_set_target(LOG_TARGET_AUTO);
        log_parse_environment();
        log_open();

        umask(0022);

        if (argc != 1) {
                log_error("This program takes no arguments.");
                r = -EINVAL;
                goto out;
        }

        r = get_user_creds(&user, &uid, &gid, NULL, NULL);
        if (r < 0) {
                log_error("Cannot resolve user name %s: %s", user, strerror(-r));
                goto out;
        }

        /* Always create the directories people can create inotify
         * watches in. */
        r = mkdir_safe_label("/run/systemd/netif", 0755, uid, gid);
        if (r < 0)
                log_error("Could not create runtime directory: %s",
                          strerror(-r));

        r = mkdir_safe_label("/run/systemd/netif/links", 0755, uid, gid);
        if (r < 0)
                log_error("Could not create runtime directory 'links': %s",
                          strerror(-r));

        r = mkdir_safe_label("/run/systemd/netif/leases", 0755, uid, gid);
        if (r < 0)
                log_error("Could not create runtime directory 'leases': %s",
                          strerror(-r));

        r = drop_privileges(uid, gid,
                            (1ULL << CAP_NET_ADMIN) |
                            (1ULL << CAP_NET_BIND_SERVICE) |
                            (1ULL << CAP_NET_BROADCAST) |
                            (1ULL << CAP_NET_RAW));
        if (r < 0)
                goto out;

        assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0);

        r = manager_new(&m);
        if (r < 0) {
                log_error("Could not create manager: %s", strerror(-r));
                goto out;
        }

        r = manager_udev_listen(m);
        if (r < 0) {
                log_error("Could not connect to udev: %s", strerror(-r));
                goto out;
        }

        r = manager_rtnl_listen(m);
        if (r < 0) {
                log_error("Could not connect to rtnl: %s", strerror(-r));
                goto out;
        }

        r = manager_bus_listen(m);
        if (r < 0) {
                log_error("Could not connect to system bus: %s", strerror(-r));
                goto out;
        }

        r = manager_load_config(m);
        if (r < 0) {
                log_error("Could not load configuration files: %s", strerror(-r));
                goto out;
        }

        r = manager_rtnl_enumerate_links(m);
        if (r < 0) {
                log_error("Could not enumerate links: %s", strerror(-r));
                goto out;
        }

        sd_notify(false,
                  "READY=1\n"
                  "STATUS=Processing requests...");

        r = sd_event_loop(m->event);
        if (r < 0) {
                log_error("Event loop failed: %s", strerror(-r));
                goto out;
        }

out:
        sd_notify(false,
                  "STOPPING=1\n"
                  "STATUS=Shutting down...");

        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
Пример #14
0
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;
}
Пример #15
0
int main(int argc, char *argv[]) {
        _cleanup_(manager_freep) Manager *m = NULL;
        const char *user = "******";
        uid_t uid;
        gid_t gid;
        int r;

        log_set_target(LOG_TARGET_AUTO);
        log_parse_environment();
        log_open();

        if (argc != 1) {
                log_error("This program takes no arguments.");
                r = -EINVAL;
                goto finish;
        }

        umask(0022);

        r = mac_selinux_init();
        if (r < 0) {
                log_error_errno(r, "SELinux setup failed: %m");
                goto finish;
        }

        r = get_user_creds(&user, &uid, &gid, NULL, NULL);
        if (r < 0) {
                log_error_errno(r, "Cannot resolve user name %s: %m", user);
                goto finish;
        }

        /* Always create the directory where resolv.conf will live */
        r = mkdir_safe_label("/run/systemd/resolve", 0755, uid, gid, false);
        if (r < 0) {
                log_error_errno(r, "Could not create runtime directory: %m");
                goto finish;
        }

        /* Drop privileges, but only if we have been started as root. If we are not running as root we assume all
         * privileges are already dropped. */
        if (getuid() == 0) {

                /* Drop privileges, but keep three caps. Note that we drop those too, later on (see below) */
                r = drop_privileges(uid, gid,
                                    (UINT64_C(1) << CAP_NET_RAW)|          /* needed for SO_BINDTODEVICE */
                                    (UINT64_C(1) << CAP_NET_BIND_SERVICE)| /* needed to bind on port 53 */
                                    (UINT64_C(1) << CAP_SETPCAP)           /* needed in order to drop the caps later */);
                if (r < 0)
                        goto finish;
        }

        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGUSR1, SIGUSR2, SIGRTMIN+1, -1) >= 0);

        r = manager_new(&m);
        if (r < 0) {
                log_error_errno(r, "Could not create manager: %m");
                goto finish;
        }

        r = manager_start(m);
        if (r < 0) {
                log_error_errno(r, "Failed to start manager: %m");
                goto finish;
        }

        /* Write finish default resolv.conf to avoid a dangling symlink */
        (void) manager_write_resolv_conf(m);

        /* Let's drop the remaining caps now */
        r = capability_bounding_set_drop(0, true);
        if (r < 0) {
                log_error_errno(r, "Failed to drop remaining caps: %m");
                goto finish;
        }

        sd_notify(false,
                  "READY=1\n"
                  "STATUS=Processing requests...");

        r = sd_event_loop(m->event);
        if (r < 0) {
                log_error_errno(r, "Event loop failed: %m");
                goto finish;
        }

        sd_event_get_exit_code(m->event, &r);

finish:
        sd_notify(false,
                  "STOPPING=1\n"
                  "STATUS=Shutting down...");

        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
Пример #16
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;
}
Пример #17
0
int main(int argc, char *argv[]) {
        _cleanup_(manager_freep) Manager *m = NULL;
        const char *user = "******";
        uid_t uid;
        gid_t gid;
        int r;

        log_set_target(LOG_TARGET_AUTO);
        log_parse_environment();
        log_open();

        if (argc != 1) {
                log_error("This program takes no arguments.");
                r = -EINVAL;
                goto finish;
        }

        umask(0022);

        r = mac_selinux_init(NULL);
        if (r < 0) {
                log_error_errno(r, "SELinux setup failed: %m");
                goto finish;
        }

        r = get_user_creds(&user, &uid, &gid, NULL, NULL);
        if (r < 0) {
                log_error_errno(r, "Cannot resolve user name %s: %m", user);
                goto finish;
        }

        /* Always create the directory where resolv.conf will live */
        r = mkdir_safe_label("/run/systemd/resolve", 0755, uid, gid);
        if (r < 0) {
                log_error_errno(r, "Could not create runtime directory: %m");
                goto finish;
        }

        r = drop_privileges(uid, gid, 0);
        if (r < 0)
                goto finish;

        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGUSR1, -1) >= 0);

        r = manager_new(&m);
        if (r < 0) {
                log_error_errno(r, "Could not create manager: %m");
                goto finish;
        }

        r = manager_start(m);
        if (r < 0) {
                log_error_errno(r, "Failed to start manager: %m");
                goto finish;
        }

        /* Write finish default resolv.conf to avoid a dangling
         * symlink */
        r = manager_write_resolv_conf(m);
        if (r < 0)
                log_warning_errno(r, "Could not create resolv.conf: %m");

        sd_notify(false,
                  "READY=1\n"
                  "STATUS=Processing requests...");

        r = sd_event_loop(m->event);
        if (r < 0) {
                log_error_errno(r, "Event loop failed: %m");
                goto finish;
        }

        sd_event_get_exit_code(m->event, &r);

finish:
        sd_notify(false,
                  "STOPPING=1\n"
                  "STATUS=Shutting down...");

        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
Пример #18
0
int main(int argc, char *argv[]) {
        _cleanup_(manager_freep) Manager *m = NULL;
        const char *user = "******";
        uid_t uid;
        gid_t gid;
        int r;

        log_set_target(LOG_TARGET_AUTO);
        log_set_facility(LOG_CRON);
        log_parse_environment();
        log_open();

        umask(0022);

        if (argc != 1) {
                log_error("This program does not take arguments.");
                r = -EINVAL;
                goto finish;
        }

        r = get_user_creds(&user, &uid, &gid, NULL, NULL);
        if (r < 0) {
                log_error_errno(r, "Cannot resolve user name %s: %m", user);
                goto finish;
        }

        r = load_clock_timestamp(uid, gid);
        if (r < 0)
                goto finish;

        r = drop_privileges(uid, gid, (1ULL << CAP_SYS_TIME));
        if (r < 0)
                goto finish;

        /* We need one process for ourselves, plus one thread for the asynchronous resolver */
        if (setrlimit(RLIMIT_NPROC, &RLIMIT_MAKE_CONST(2)) < 0)
                log_warning_errno(errno, "Failed to lower RLIMIT_NPROC to 2: %m");

        assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0);

        r = manager_new(&m);
        if (r < 0) {
                log_error_errno(r, "Failed to allocate manager: %m");
                goto finish;
        }

        if (clock_is_localtime() > 0) {
                log_info("The system is configured to read the RTC time in the local time zone. "
                         "This mode can not be fully supported. All system time to RTC updates are disabled.");
                m->rtc_local_time = true;
        }

        r = manager_parse_config_file(m);
        if (r < 0)
                log_warning_errno(r, "Failed to parse configuration file: %m");

        log_debug("systemd-timesyncd running as pid %lu", (unsigned long) getpid());
        sd_notify(false,
                  "READY=1\n"
                  "STATUS=Daemon is running");

        if (network_is_online()) {
                r = manager_connect(m);
                if (r < 0)
                        goto finish;
        }

        r = sd_event_loop(m->event);
        if (r < 0) {
                log_error_errno(r, "Failed to run event loop: %m");
                goto finish;
        }

        /* if we got an authoritative time, store it in the file system */
        if (m->sync)
                touch("/var/lib/systemd/clock");

        sd_event_get_exit_code(m->event, &r);

finish:
        sd_notify(false,
                  "STOPPING=1\n"
                  "STATUS=Shutting down...");

        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
Пример #19
0
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");
}