mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-07 17:17:44 +03:00
homework: rework directory backend to set up mounts in /run/systemd/user-home-mount before moving them to /home
This does what we already do for the LUKS backend: instead of mounting the source directory directly to the final home dir, we instead bind mount it to /run/systemd/user-home-mount (where /run/ is unshared and specific to our own mount namespace), then adjust its mount flags and then bind mount it in a single atomic operation into the final destination, fully set up. This doesn't improve much on its own, but it makes things a tiny bit more correct: this way MS_NODEV/MS_NOEXEC/MS_NOSUID will already be applied when the bind mount appears in the host mount namespace, instead of being adjusted after the fact. Doing things this way also makes things work more like the LUKS backend, reducing surprises. Most importantly it's preparation for doing uidmapping for directory homes, added in a later commit.
This commit is contained in:
parent
cfef46f5fe
commit
2ba38f78c3
@ -5,6 +5,7 @@
|
||||
#include "btrfs-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "homework-directory.h"
|
||||
#include "homework-mount.h"
|
||||
#include "homework-quota.h"
|
||||
#include "mkdir.h"
|
||||
#include "mount-util.h"
|
||||
@ -14,10 +15,38 @@
|
||||
#include "umask-util.h"
|
||||
|
||||
int home_setup_directory(UserRecord *h, HomeSetup *setup) {
|
||||
const char *ip;
|
||||
int r;
|
||||
|
||||
assert(h);
|
||||
assert(setup);
|
||||
assert(setup->root_fd < 0);
|
||||
|
||||
setup->root_fd = open(user_record_image_path(h), O_RDONLY|O_CLOEXEC|O_DIRECTORY);
|
||||
/* We'll bind mount the image directory to a new mount point where we'll start adjusting it. Only
|
||||
* once that's complete we'll move the thing to its final place eventually. */
|
||||
r = home_unshare_and_mkdir();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
assert_se(ip = user_record_image_path(h));
|
||||
|
||||
r = mount_follow_verbose(LOG_ERR, ip, HOME_RUNTIME_WORK_DIR, NULL, MS_BIND, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
setup->undo_mount = true;
|
||||
|
||||
/* Turn off any form of propagation for this */
|
||||
r = mount_nofollow_verbose(LOG_ERR, NULL, HOME_RUNTIME_WORK_DIR, NULL, MS_PRIVATE, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Adjust MS_SUID and similar flags */
|
||||
r = mount_nofollow_verbose(LOG_ERR, NULL, HOME_RUNTIME_WORK_DIR, NULL, MS_BIND|MS_REMOUNT|user_record_mount_flags(h), NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
setup->root_fd = open(HOME_RUNTIME_WORK_DIR, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW);
|
||||
if (setup->root_fd < 0)
|
||||
return log_error_errno(errno, "Failed to open home directory: %m");
|
||||
|
||||
@ -31,7 +60,7 @@ int home_activate_directory(
|
||||
UserRecord **ret_home) {
|
||||
|
||||
_cleanup_(user_record_unrefp) UserRecord *new_home = NULL, *header_home = NULL;
|
||||
const char *hdo, *hd, *ipo, *ip;
|
||||
const char *hd, *hdo;
|
||||
int r;
|
||||
|
||||
assert(h);
|
||||
@ -39,9 +68,6 @@ int home_activate_directory(
|
||||
assert(setup);
|
||||
assert(ret_home);
|
||||
|
||||
assert_se(ipo = user_record_image_path(h));
|
||||
ip = strdupa_safe(ipo); /* copy out, since reconciliation might cause changing of the field */
|
||||
|
||||
assert_se(hdo = user_record_home_directory(h));
|
||||
hd = strdupa_safe(hdo);
|
||||
|
||||
@ -57,24 +83,15 @@ int home_activate_directory(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Close fd to private mount before moving mount */
|
||||
setup->root_fd = safe_close(setup->root_fd);
|
||||
|
||||
/* Create mount point to mount over if necessary */
|
||||
if (!path_equal(ip, hd))
|
||||
(void) mkdir_p(hd, 0700);
|
||||
|
||||
/* Create a mount point (even if the directory is already placed correctly), as a way to indicate
|
||||
* this mount point is now "activated". Moreover, we want to set per-user
|
||||
* MS_NOSUID/MS_NOEXEC/MS_NODEV. */
|
||||
r = mount_nofollow_verbose(LOG_ERR, ip, hd, NULL, MS_BIND, NULL);
|
||||
/* We are now done with everything, move the mount into place */
|
||||
r = home_move_mount(NULL, hd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = mount_nofollow_verbose(LOG_ERR, NULL, hd, NULL, MS_BIND|MS_REMOUNT|user_record_mount_flags(h), NULL);
|
||||
if (r < 0) {
|
||||
(void) umount_verbose(LOG_ERR, hd, UMOUNT_NOFOLLOW);
|
||||
return r;
|
||||
}
|
||||
setup->undo_mount = false;
|
||||
|
||||
setup->do_drop_caches = false;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user