1 /* SPDX-License-Identifier: LGPL-2.1+ */
10 #include "mount-util.h"
11 #include "path-util.h"
13 #include "smack-util.h"
14 #include "stdio-util.h"
15 #include "string-util.h"
17 #include "user-util.h"
18 /// Additional includes needed by elogind
19 #include "user-runtime-dir.h"
21 #if 0 /// UNNEEDED by elogind
22 static int gather_configuration(size_t *runtime_dir_size) {
26 manager_reset_config(&m);
28 r = manager_parse_config_file(&m);
30 log_warning_errno(r, "Failed to parse logind.conf: %m");
32 *runtime_dir_size = m.runtime_dir_size;
37 static int user_mkdir_runtime_path(const char *runtime_path, uid_t uid, gid_t gid, size_t runtime_dir_size) {
41 assert(path_is_absolute(runtime_path));
42 assert(uid_is_valid(uid));
43 assert(gid_is_valid(gid));
45 r = mkdir_safe_label("/run/user", 0755, 0, 0, MKDIR_WARN_MODE);
47 return log_error_errno(r, "Failed to create /run/user: %m");
49 if (path_is_mount_point(runtime_path, NULL, 0) >= 0)
50 log_debug("%s is already a mount point", runtime_path);
52 char options[sizeof("mode=0700,uid=,gid=,size=,smackfsroot=*")
53 + DECIMAL_STR_MAX(uid_t)
54 + DECIMAL_STR_MAX(gid_t)
55 + DECIMAL_STR_MAX(size_t)];
58 "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu%s",
59 uid, gid, runtime_dir_size,
60 mac_smack_use() ? ",smackfsroot=*" : "");
62 (void) mkdir_label(runtime_path, 0700);
64 r = mount("tmpfs", runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, options);
66 if (!IN_SET(errno, EPERM, EACCES)) {
67 r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", runtime_path);
71 log_debug_errno(errno, "Failed to mount per-user tmpfs directory %s.\n"
72 "Assuming containerized execution, ignoring: %m", runtime_path);
74 r = chmod_and_chown(runtime_path, 0700, uid, gid);
76 log_error_errno(r, "Failed to change ownership and mode of \"%s\": %m", runtime_path);
81 r = label_fix(runtime_path, 0);
83 log_warning_errno(r, "Failed to fix label of \"%s\", ignoring: %m", runtime_path);
89 /* Try to clean up, but ignore errors */
90 (void) rmdir(runtime_path);
94 static int user_remove_runtime_path(const char *runtime_path) {
98 assert(path_is_absolute(runtime_path));
100 r = rm_rf(runtime_path, 0);
102 log_error_errno(r, "Failed to remove runtime directory %s (before unmounting): %m", runtime_path);
104 /* Ignore cases where the directory isn't mounted, as that's
105 * quite possible, if we lacked the permissions to mount
107 r = umount2(runtime_path, MNT_DETACH);
108 if (r < 0 && !IN_SET(errno, EINVAL, ENOENT))
109 log_error_errno(errno, "Failed to unmount user runtime directory %s: %m", runtime_path);
111 r = rm_rf(runtime_path, REMOVE_ROOT);
113 log_error_errno(r, "Failed to remove runtime directory %s (after unmounting): %m", runtime_path);
118 #if 0 /// having a User instance, elogind can ask its manager directly.
119 static int do_mount(const char *runtime_path, uid_t uid, gid_t gid) {
120 size_t runtime_dir_size;
122 assert_se(gather_configuration(&runtime_dir_size) == 0);
124 static int do_mount(const char *runtime_path, size_t runtime_dir_size, uid_t uid, gid_t gid) {
127 log_debug("Will mount %s owned by "UID_FMT":"GID_FMT, runtime_path, uid, gid);
128 return user_mkdir_runtime_path(runtime_path, uid, gid, runtime_dir_size);
131 static int do_umount(const char *runtime_path) {
132 log_debug("Will remove %s", runtime_path);
133 return user_remove_runtime_path(runtime_path);
136 #if 0 /// elogind does this internally as we have no unit chain being init.
137 int main(int argc, char *argv[]) {
141 char runtime_path[sizeof("/run/user") + DECIMAL_STR_MAX(uid_t)];
144 log_parse_environment();
148 log_error("This program takes two arguments.");
151 if (!STR_IN_SET(argv[1], "start", "stop")) {
152 log_error("First argument must be either \"start\" or \"stop\".");
159 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
162 r == -ESRCH ? "No such user \"%s\"" :
163 r == -ENOMSG ? "UID \"%s\" is invalid or has an invalid main group"
164 : "Failed to look up user \"%s\": %m",
168 xsprintf(runtime_path, "/run/user/" UID_FMT, uid);
170 if (streq(argv[1], "start"))
171 r = do_mount(runtime_path, uid, gid);
172 else if (streq(argv[1], "stop"))
173 r = do_umount(runtime_path);
175 assert_not_reached("Unknown verb!");
177 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
180 int user_runtime_dir(const char *verb, User *u) {
185 assert_se(u->manager);
187 if (streq(verb, "start"))
188 r = do_mount(u->runtime_path, u->manager->runtime_dir_size, u->uid, u->gid);
189 else if (streq(verb, "stop"))
190 r = do_umount(u->runtime_path);
192 assert_not_reached("Unknown verb!");