mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-11 05:17:44 +03:00
homed: allow overriding the root directory for home dirs via env var (i.e. use a different path than /home/)
This is a debugging feature. It's sometimes incredibly useful to be able to run a second instance of homed that operates on another dir than /home/. Specifically, if you build homed from the source tree you can now run an instance of it pretty reasonably directly from the build tree via: sudo SYSTEMD_HOME_DEBUG_SUFFIX=foo SYSTEMD_HOMEWORK_PATH=$(pwd)/build/systemd-homework SYSTEMD_HOME_ROOT=/home/foo ./build/systemd-homed And then talk to it via sudo SYSTEMD_HOME_DEBUG_SUFFIX=foo homectl … (you might need to tweak your dbus policy for this to work fully though)
This commit is contained in:
parent
86019efa44
commit
2700fecdb3
@ -1085,3 +1085,14 @@ int is_this_me(const char *username) {
|
||||
|
||||
return uid == getuid();
|
||||
}
|
||||
|
||||
const char *get_home_root(void) {
|
||||
const char *e;
|
||||
|
||||
/* For debug purposes allow overriding where we look for home dirs */
|
||||
e = secure_getenv("SYSTEMD_HOME_ROOT");
|
||||
if (e && path_is_absolute(e) && path_is_normalized(e))
|
||||
return e;
|
||||
|
||||
return "/home";
|
||||
}
|
||||
|
@ -112,6 +112,8 @@ bool is_nologin_shell(const char *shell);
|
||||
|
||||
int is_this_me(const char *username);
|
||||
|
||||
const char *get_home_root(void);
|
||||
|
||||
/* A locked *and* invalid password for "struct spwd"'s .sp_pwdp and "struct passwd"'s .pw_passwd field */
|
||||
#define PASSWORD_LOCKED_AND_INVALID "!*"
|
||||
|
||||
|
@ -83,35 +83,38 @@ static void manager_watch_home(Manager *m) {
|
||||
m->inotify_event_source = sd_event_source_disable_unref(m->inotify_event_source);
|
||||
m->scan_slash_home = false;
|
||||
|
||||
if (statfs("/home/", &sfs) < 0) {
|
||||
if (statfs(get_home_root(), &sfs) < 0) {
|
||||
log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
|
||||
"Failed to statfs() /home/ directory, disabling automatic scanning.");
|
||||
"Failed to statfs() %s directory, disabling automatic scanning.", get_home_root());
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_network_fs(&sfs)) {
|
||||
log_info("/home/ is a network file system, disabling automatic scanning.");
|
||||
log_info("%s is a network file system, disabling automatic scanning.", get_home_root());
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_fs_type(&sfs, AUTOFS_SUPER_MAGIC)) {
|
||||
log_info("/home/ is on autofs, disabling automatic scanning.");
|
||||
log_info("%s is on autofs, disabling automatic scanning.", get_home_root());
|
||||
return;
|
||||
}
|
||||
|
||||
m->scan_slash_home = true;
|
||||
|
||||
r = sd_event_add_inotify(m->event, &m->inotify_event_source, "/home/",
|
||||
r = sd_event_add_inotify(m->event, &m->inotify_event_source, get_home_root(),
|
||||
IN_CREATE|IN_CLOSE_WRITE|IN_DELETE_SELF|IN_MOVE_SELF|IN_ONLYDIR|IN_MOVED_TO|IN_MOVED_FROM|IN_DELETE,
|
||||
on_home_inotify, m);
|
||||
if (r < 0)
|
||||
log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
|
||||
"Failed to create inotify watch on /home/, ignoring.");
|
||||
"Failed to create inotify watch on %s, ignoring.", get_home_root());
|
||||
|
||||
(void) sd_event_source_set_description(m->inotify_event_source, "home-inotify");
|
||||
|
||||
log_info("Watching %s.", get_home_root());
|
||||
}
|
||||
|
||||
static int on_home_inotify(sd_event_source *s, const struct inotify_event *event, void *userdata) {
|
||||
_cleanup_free_ char *j = NULL;
|
||||
Manager *m = userdata;
|
||||
const char *e, *n;
|
||||
|
||||
@ -121,15 +124,15 @@ static int on_home_inotify(sd_event_source *s, const struct inotify_event *event
|
||||
if ((event->mask & (IN_Q_OVERFLOW|IN_MOVE_SELF|IN_DELETE_SELF|IN_IGNORED|IN_UNMOUNT)) != 0) {
|
||||
|
||||
if (FLAGS_SET(event->mask, IN_Q_OVERFLOW))
|
||||
log_debug("/home/ inotify queue overflow, rescanning.");
|
||||
log_debug("%s inotify queue overflow, rescanning.", get_home_root());
|
||||
else if (FLAGS_SET(event->mask, IN_MOVE_SELF))
|
||||
log_info("/home/ moved or renamed, recreating watch and rescanning.");
|
||||
log_info("%s moved or renamed, recreating watch and rescanning.", get_home_root());
|
||||
else if (FLAGS_SET(event->mask, IN_DELETE_SELF))
|
||||
log_info("/home/ deleted, recreating watch and rescanning.");
|
||||
log_info("%s deleted, recreating watch and rescanning.", get_home_root());
|
||||
else if (FLAGS_SET(event->mask, IN_UNMOUNT))
|
||||
log_info("/home/ unmounted, recreating watch and rescanning.");
|
||||
log_info("%s unmounted, recreating watch and rescanning.", get_home_root());
|
||||
else if (FLAGS_SET(event->mask, IN_IGNORED))
|
||||
log_info("/home/ watch invalidated, recreating watch and rescanning.");
|
||||
log_info("%s watch invalidated, recreating watch and rescanning.", get_home_root());
|
||||
|
||||
manager_watch_home(m);
|
||||
(void) manager_gc_images(m);
|
||||
@ -150,15 +153,19 @@ static int on_home_inotify(sd_event_source *s, const struct inotify_event *event
|
||||
if (!suitable_user_name(n))
|
||||
return 0;
|
||||
|
||||
j = path_join(get_home_root(), event->name);
|
||||
if (!j)
|
||||
return log_oom();
|
||||
|
||||
if ((event->mask & (IN_CREATE|IN_CLOSE_WRITE|IN_MOVED_TO)) != 0) {
|
||||
if (FLAGS_SET(event->mask, IN_CREATE))
|
||||
log_debug("/home/%s has been created, having a look.", event->name);
|
||||
log_debug("%s has been created, having a look.", j);
|
||||
else if (FLAGS_SET(event->mask, IN_CLOSE_WRITE))
|
||||
log_debug("/home/%s has been modified, having a look.", event->name);
|
||||
log_debug("%s has been modified, having a look.", j);
|
||||
else if (FLAGS_SET(event->mask, IN_MOVED_TO))
|
||||
log_debug("/home/%s has been moved in, having a look.", event->name);
|
||||
log_debug("%s has been moved in, having a look.", j);
|
||||
|
||||
(void) manager_assess_image(m, -1, "/home/", event->name);
|
||||
(void) manager_assess_image(m, -1, get_home_root(), event->name);
|
||||
(void) bus_manager_emit_auto_login_changed(m);
|
||||
}
|
||||
|
||||
@ -166,11 +173,11 @@ static int on_home_inotify(sd_event_source *s, const struct inotify_event *event
|
||||
Home *h;
|
||||
|
||||
if (FLAGS_SET(event->mask, IN_DELETE))
|
||||
log_debug("/home/%s has been deleted, revalidating.", event->name);
|
||||
log_debug("%s has been deleted, revalidating.", j);
|
||||
else if (FLAGS_SET(event->mask, IN_CLOSE_WRITE))
|
||||
log_debug("/home/%s has been closed after writing, revalidating.", event->name);
|
||||
log_debug("%s has been closed after writing, revalidating.", j);
|
||||
else if (FLAGS_SET(event->mask, IN_MOVED_FROM))
|
||||
log_debug("/home/%s has been moved away, revalidating.", event->name);
|
||||
log_debug("%s has been moved away, revalidating.", j);
|
||||
|
||||
h = hashmap_get(m->homes_by_name, n);
|
||||
if (h) {
|
||||
@ -487,7 +494,7 @@ static int search_quota(uid_t uid, const char *exclude_quota_path) {
|
||||
* comprehensive, but should cover most cases. Note that in an ideal world every user would be
|
||||
* registered in NSS and avoid our own UID range, but for all other cases, it's a good idea to be
|
||||
* paranoid and check quota if we can. */
|
||||
FOREACH_STRING(where, "/home/", "/tmp/", "/var/", "/var/mail/", "/var/tmp/", "/var/spool/") {
|
||||
FOREACH_STRING(where, get_home_root(), "/tmp/", "/var/", "/var/mail/", "/var/tmp/", "/var/spool/") {
|
||||
struct dqblk req;
|
||||
struct stat st;
|
||||
|
||||
@ -914,13 +921,13 @@ int manager_enumerate_images(Manager *m) {
|
||||
if (!m->scan_slash_home)
|
||||
return 0;
|
||||
|
||||
d = opendir("/home/");
|
||||
d = opendir(get_home_root());
|
||||
if (!d)
|
||||
return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
|
||||
"Failed to open /home/: %m");
|
||||
"Failed to open %s: %m", get_home_root());
|
||||
|
||||
FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read /home/ directory: %m"))
|
||||
(void) manager_assess_image(m, dirfd(d), "/home", de->d_name);
|
||||
FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read %s directory: %m", get_home_root()))
|
||||
(void) manager_assess_image(m, dirfd(d), get_home_root(), de->d_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1129,12 +1129,12 @@ static int determine_default_storage(UserStorage *ret) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine whether we are in a container: %m");
|
||||
if (r == 0) {
|
||||
r = path_is_encrypted("/home");
|
||||
r = path_is_encrypted(get_home_root());
|
||||
if (r > 0)
|
||||
log_info("/home is encrypted, not using '%s' storage, in order to avoid double encryption.", user_storage_to_string(USER_LUKS));
|
||||
log_info("%s is encrypted, not using '%s' storage, in order to avoid double encryption.", get_home_root(), user_storage_to_string(USER_LUKS));
|
||||
else {
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to determine if /home is encrypted, ignoring: %m");
|
||||
log_warning_errno(r, "Failed to determine if %s is encrypted, ignoring: %m", get_home_root());
|
||||
|
||||
r = dlopen_cryptsetup();
|
||||
if (r < 0)
|
||||
@ -1148,14 +1148,14 @@ static int determine_default_storage(UserStorage *ret) {
|
||||
} else
|
||||
log_info("Running in container, not using '%s' storage.", user_storage_to_string(USER_LUKS));
|
||||
|
||||
r = path_is_fs_type("/home", BTRFS_SUPER_MAGIC);
|
||||
r = path_is_fs_type(get_home_root(), BTRFS_SUPER_MAGIC);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to determine file system of /home, ignoring: %m");
|
||||
log_warning_errno(r, "Failed to determine file system of %s, ignoring: %m", get_home_root());
|
||||
if (r > 0) {
|
||||
log_info("/home is on btrfs, using '%s' as storage.", user_storage_to_string(USER_SUBVOLUME));
|
||||
log_info("%s is on btrfs, using '%s' as storage.", get_home_root(), user_storage_to_string(USER_SUBVOLUME));
|
||||
*ret = USER_SUBVOLUME;
|
||||
} else {
|
||||
log_info("/home is on simple file system, using '%s' as storage.", user_storage_to_string(USER_DIRECTORY));
|
||||
log_info("%s is on simple file system, using '%s' as storage.", get_home_root(), user_storage_to_string(USER_DIRECTORY));
|
||||
*ret = USER_DIRECTORY;
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ int user_record_synthesize(
|
||||
if (!ip)
|
||||
return -ENOMEM;
|
||||
|
||||
hd = path_join("/home/", user_name);
|
||||
hd = path_join(get_home_root(), user_name);
|
||||
if (!hd)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1408,11 +1408,11 @@ int user_record_build_image_path(UserStorage storage, const char *user_name_and_
|
||||
return 0;
|
||||
}
|
||||
|
||||
z = strjoin("/home/", user_name_and_realm, suffix);
|
||||
z = strjoin(get_home_root(), "/", user_name_and_realm, suffix);
|
||||
if (!z)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = z;
|
||||
*ret = path_simplify(z);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1437,7 +1437,7 @@ static int user_record_augment(UserRecord *h, JsonDispatchFlags json_flags) {
|
||||
return 0;
|
||||
|
||||
if (!h->home_directory && !h->home_directory_auto) {
|
||||
h->home_directory_auto = path_join("/home/", h->user_name);
|
||||
h->home_directory_auto = path_join(get_home_root(), h->user_name);
|
||||
if (!h->home_directory_auto)
|
||||
return json_log_oom(h->json, json_flags);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user