X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flogin%2Flogind-user.c;h=961cbcb27b983b3ec3e4c76804c1b34d5bcbc6fe;hb=22fdeadcc06e95fe41ac4de872ec245c0887547f;hp=06fdbb36fc9758fc307b1dc43000db5fc8609181;hpb=00555a2ee1b008bccbb570320047307b8b9159f9;p=elogind.git diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 06fdbb36f..961cbcb27 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -19,6 +19,7 @@ along with systemd; If not, see . ***/ +#include #include #include #include @@ -28,10 +29,13 @@ #include "hashmap.h" #include "strv.h" #include "fileio.h" +#include "path-util.h" #include "special.h" #include "unit-name.h" #include "bus-util.h" #include "bus-error.h" +#include "conf-parser.h" +#include "clean-ipc.h" #include "logind-user.h" User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) { @@ -311,21 +315,35 @@ static int user_mkdir_runtime_path(User *u) { } if (!u->runtime_path) { - if (asprintf(&p, "/run/user/%lu", (unsigned long) u->uid) < 0) + if (asprintf(&p, "/run/user/" UID_FMT, u->uid) < 0) return log_oom(); } else p = u->runtime_path; - r = mkdir_safe_label(p, 0700, u->uid, u->gid); - if (r < 0) { - log_error("Failed to create runtime directory %s: %s", p, strerror(-r)); - free(p); - u->runtime_path = NULL; - return r; + if (path_is_mount_point(p, false) <= 0) { + _cleanup_free_ char *t = NULL; + + mkdir(p, 0700); + + if (asprintf(&t, "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size) < 0) { + r = log_oom(); + goto fail; + } + + r = mount("tmpfs", p, "tmpfs", MS_NODEV|MS_NOSUID, t); + if (r < 0) { + log_error("Failed to mount per-user tmpfs directory %s: %s", p, strerror(-r)); + goto fail; + } } u->runtime_path = p; return 0; + +fail: + free(p); + u->runtime_path = NULL; + return r; } static int user_start_slice(User *u) { @@ -484,6 +502,13 @@ static int user_remove_runtime_path(User *u) { if (!u->runtime_path) return 0; + r = rm_rf(u->runtime_path, false, false, false); + if (r < 0) + log_error("Failed to remove runtime directory %s: %s", u->runtime_path, strerror(-r)); + + if (umount2(u->runtime_path, MNT_DETACH) < 0) + log_error("Failed to unmount user runtime directory %s: %m", u->runtime_path); + r = rm_rf(u->runtime_path, false, true, false); if (r < 0) log_error("Failed to remove runtime directory %s: %s", u->runtime_path, strerror(-r)); @@ -494,13 +519,19 @@ static int user_remove_runtime_path(User *u) { return r; } -int user_stop(User *u) { +int user_stop(User *u, bool force) { Session *s; int r = 0, k; assert(u); + /* Stop jobs have already been queued */ + if (u->stopping) { + user_save(u); + return r; + } + LIST_FOREACH(sessions_by_user, s, u->sessions) { - k = session_stop(s); + k = session_stop(s, force); if (k < 0) r = k; } @@ -542,6 +573,13 @@ int user_finalize(User *u) { if (k < 0) r = k; + /* Clean SysV + POSIX IPC objects */ + if (u->manager->remove_ipc) { + k = clean_ipc(u->uid); + if (k < 0) + r = k; + } + unlink(u->state_file); user_add_to_gc_queue(u); @@ -685,3 +723,57 @@ static const char* const user_state_table[_USER_STATE_MAX] = { }; DEFINE_STRING_TABLE_LOOKUP(user_state, UserState); + +int config_parse_tmpfs_size( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + size_t *sz = data; + const char *e; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + e = endswith(rvalue, "%"); + if (e) { + unsigned long ul; + char *f; + + errno = 0; + ul = strtoul(rvalue, &f, 10); + if (errno != 0 || f != e) { + log_syntax(unit, LOG_ERR, filename, line, errno ? errno : EINVAL, "Failed to parse percentage value, ignoring: %s", rvalue); + return 0; + } + + if (ul <= 0 || ul >= 100) { + log_syntax(unit, LOG_ERR, filename, line, errno ? errno : EINVAL, "Percentage value out of range, ignoring: %s", rvalue); + return 0; + } + + *sz = PAGE_ALIGN((size_t) ((physical_memory() * (uint64_t) ul) / (uint64_t) 100)); + } else { + off_t o; + + r = parse_size(rvalue, 1024, &o); + if (r < 0 || (off_t) (size_t) o != o) { + log_syntax(unit, LOG_ERR, filename, line, r < 0 ? -r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue); + return 0; + } + + *sz = PAGE_ALIGN((size_t) o); + } + + return 0; +}