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; }
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); }
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); }
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; }
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; }
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"); }