mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-10 01:17:44 +03:00
repart: Don't descend into directories assigned to other partitions
Let's say we have the following repart definitions files root.conf and home.conf: ``` [Partition] Type=root CopyFiles=/ ``` ``` [Partition] Type=home CopyFiles=/home ``` Currently, we'd end up copying /home to both the root partition and the home partition. To prevent this from happening, let's adopt a new policy when copying files for a partition: We won't copy any files/directories that appear in the CopyFiles= list of another partition, unless that directory explicitly appears in our own CopyFiles= list. This way, we prevent copying /home twice into the root and home partition, but should a user really want that behavior, they can have it by adding /home to the CopyFIles= list of the root partition as well.
This commit is contained in:
parent
58b4ad76ca
commit
c0fad2d9b6
@ -51,6 +51,7 @@
|
||||
#include "mkfs-util.h"
|
||||
#include "mount-util.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "nulstr-util.h"
|
||||
#include "openssl-util.h"
|
||||
#include "parse-argument.h"
|
||||
#include "parse-helpers.h"
|
||||
@ -3227,7 +3228,7 @@ static int context_copy_blocks(Context *context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_copy_files(Partition *p, const char *root) {
|
||||
static int do_copy_files(Partition *p, const char *root, const Set *denylist) {
|
||||
int r;
|
||||
|
||||
assert(p);
|
||||
@ -3274,14 +3275,14 @@ static int do_copy_files(Partition *p, const char *root) {
|
||||
pfd, fn,
|
||||
UID_INVALID, GID_INVALID,
|
||||
COPY_REFLINK|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS,
|
||||
NULL);
|
||||
denylist);
|
||||
} else
|
||||
r = copy_tree_at(
|
||||
sfd, ".",
|
||||
tfd, ".",
|
||||
UID_INVALID, GID_INVALID,
|
||||
COPY_REFLINK|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS,
|
||||
NULL);
|
||||
denylist);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to copy '%s' to '%s%s': %m", *source, strempty(arg_root), *target);
|
||||
} else {
|
||||
@ -3341,7 +3342,7 @@ static int do_make_directories(Partition *p, const char *root) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int partition_populate_directory(Partition *p, char **ret_root, char **ret_tmp_root) {
|
||||
static int partition_populate_directory(Partition *p, const Set *denylist, char **ret_root, char **ret_tmp_root) {
|
||||
_cleanup_(rm_rf_physical_and_freep) char *root = NULL;
|
||||
int r;
|
||||
|
||||
@ -3364,7 +3365,8 @@ static int partition_populate_directory(Partition *p, char **ret_root, char **re
|
||||
* allocate a temporary directory, it's stored in "ret_tmp_root" to indicate it should be removed.
|
||||
* Otherwise, we return the directory to use in "root" to indicate it should not be removed. */
|
||||
|
||||
if (strv_length(p->copy_files) == 2 && strv_length(p->make_directories) == 0 && streq(p->copy_files[1], "/")) {
|
||||
if (strv_length(p->copy_files) == 2 && strv_length(p->make_directories) == 0 &&
|
||||
streq(p->copy_files[1], "/") && set_isempty(denylist)) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
|
||||
r = chase_symlinks(p->copy_files[0], arg_root, CHASE_PREFIX_ROOT, &s, NULL);
|
||||
@ -3380,7 +3382,7 @@ static int partition_populate_directory(Partition *p, char **ret_root, char **re
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create temporary directory: %m");
|
||||
|
||||
r = do_copy_files(p, root);
|
||||
r = do_copy_files(p, root, denylist);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -3393,7 +3395,7 @@ static int partition_populate_directory(Partition *p, char **ret_root, char **re
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int partition_populate_filesystem(Partition *p, const char *node) {
|
||||
static int partition_populate_filesystem(Partition *p, const char *node, const Set *denylist) {
|
||||
int r;
|
||||
|
||||
assert(p);
|
||||
@ -3427,7 +3429,7 @@ static int partition_populate_filesystem(Partition *p, const char *node) {
|
||||
if (mount_nofollow_verbose(LOG_ERR, node, fs, p->format, MS_NOATIME|MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL) < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
if (do_copy_files(p, fs) < 0)
|
||||
if (do_copy_files(p, fs, denylist) < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
if (do_make_directories(p, fs) < 0)
|
||||
@ -3446,13 +3448,60 @@ static int partition_populate_filesystem(Partition *p, const char *node) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int make_copy_files_denylist(Context *context, Set **ret) {
|
||||
_cleanup_set_free_ Set *denylist = NULL;
|
||||
int r;
|
||||
|
||||
assert(context);
|
||||
assert(ret);
|
||||
|
||||
LIST_FOREACH(partitions, p, context->partitions) {
|
||||
const char *s;
|
||||
|
||||
const char *sources = gpt_partition_type_mountpoint_nulstr(p->type_uuid);
|
||||
if (!sources)
|
||||
continue;
|
||||
|
||||
NULSTR_FOREACH(s, sources) {
|
||||
_cleanup_free_ char *d = NULL;
|
||||
struct stat st;
|
||||
|
||||
r = chase_symlinks_and_stat(s, arg_root, CHASE_PREFIX_ROOT, NULL, &st, NULL);
|
||||
if (r == -ENOENT)
|
||||
continue;
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to stat source file '%s%s': %m",
|
||||
strempty(arg_root), s);
|
||||
|
||||
if (set_contains(denylist, &st))
|
||||
continue;
|
||||
|
||||
d = memdup(&st, sizeof(st));
|
||||
if (!d)
|
||||
return log_oom();
|
||||
if (set_ensure_put(&denylist, &inode_hash_ops, d) < 0)
|
||||
return log_oom();
|
||||
|
||||
TAKE_PTR(d);
|
||||
}
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(denylist);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int context_mkfs(Context *context) {
|
||||
_cleanup_set_free_ Set *denylist = NULL;
|
||||
int fd = -1, r;
|
||||
|
||||
assert(context);
|
||||
|
||||
/* Make a file system */
|
||||
|
||||
r = make_copy_files_denylist(context, &denylist);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
LIST_FOREACH(partitions, p, context->partitions) {
|
||||
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
|
||||
@ -3509,7 +3558,7 @@ static int context_mkfs(Context *context) {
|
||||
* using read-only filesystems such as squashfs, we can't populate after creating the
|
||||
* filesystem because it's read-only, so instead we create a temporary root to use as the
|
||||
* source tree when generating the read-only filesystem. */
|
||||
r = partition_populate_directory(p, &root, &tmp_root);
|
||||
r = partition_populate_directory(p, denylist, &root, &tmp_root);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -3528,7 +3577,7 @@ static int context_mkfs(Context *context) {
|
||||
return log_error_errno(errno, "Failed to unlock LUKS device: %m");
|
||||
|
||||
/* Now, we can populate all the other filesystems that aren't read-only. */
|
||||
r = partition_populate_filesystem(p, fsdev);
|
||||
r = partition_populate_filesystem(p, fsdev, denylist);
|
||||
if (r < 0) {
|
||||
encrypted_dev_fd = safe_close(encrypted_dev_fd);
|
||||
(void) deactivate_luks(cd, encrypted);
|
||||
|
Loading…
Reference in New Issue
Block a user