mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-13 13:17:43 +03:00
Merge pull request #24803 from DaanDeMeyer/repart-copy-deny-list
repart: Don't descend into directories assigned to other partitions
This commit is contained in:
commit
46fddd8eb6
@ -15,6 +15,7 @@
|
||||
#include "fileio.h"
|
||||
#include "filesystems.h"
|
||||
#include "fs-util.h"
|
||||
#include "hash-funcs.h"
|
||||
#include "macro.h"
|
||||
#include "missing_fs.h"
|
||||
#include "missing_magic.h"
|
||||
@ -441,3 +442,20 @@ int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct s
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void inode_hash_func(const struct stat *q, struct siphash *state) {
|
||||
siphash24_compress(&q->st_dev, sizeof(q->st_dev), state);
|
||||
siphash24_compress(&q->st_ino, sizeof(q->st_ino), state);
|
||||
}
|
||||
|
||||
int inode_compare_func(const struct stat *a, const struct stat *b) {
|
||||
int r;
|
||||
|
||||
r = CMP(a->st_dev, b->st_dev);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
return CMP(a->st_ino, b->st_ino);
|
||||
}
|
||||
|
||||
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(inode_hash_ops, struct stat, inode_hash_func, inode_compare_func, free);
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "macro.h"
|
||||
#include "missing_stat.h"
|
||||
#include "siphash24.h"
|
||||
|
||||
int is_symlink(const char *path);
|
||||
int is_dir_full(int atfd, const char *fname, bool follow);
|
||||
@ -96,3 +97,7 @@ int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct s
|
||||
struct new_statx nsx; \
|
||||
} var
|
||||
#endif
|
||||
|
||||
void inode_hash_func(const struct stat *q, struct siphash *state);
|
||||
int inode_compare_func(const struct stat *a, const struct stat *b);
|
||||
extern const struct hash_ops inode_hash_ops;
|
||||
|
@ -1126,9 +1126,9 @@ static int action_list_or_mtree_or_copy(DissectedImage *m, LoopDevice *d) {
|
||||
if (errno != ENOENT)
|
||||
return log_error_errno(errno, "Failed to open destination '%s': %m", arg_target);
|
||||
|
||||
r = copy_tree_at(source_fd, ".", dfd, bn, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS);
|
||||
r = copy_tree_at(source_fd, ".", dfd, bn, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS, NULL);
|
||||
} else
|
||||
r = copy_tree_at(source_fd, ".", target_fd, ".", UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS);
|
||||
r = copy_tree_at(source_fd, ".", target_fd, ".", UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to copy '%s' to '%s' in image '%s': %m", arg_source, arg_target, arg_image);
|
||||
|
||||
|
@ -1036,7 +1036,7 @@ static int copy_skel(int root_fd, const char *skel) {
|
||||
|
||||
assert(root_fd >= 0);
|
||||
|
||||
r = copy_tree_at(AT_FDCWD, skel, root_fd, ".", UID_INVALID, GID_INVALID, COPY_MERGE|COPY_REPLACE);
|
||||
r = copy_tree_at(AT_FDCWD, skel, root_fd, ".", UID_INVALID, GID_INVALID, COPY_MERGE|COPY_REPLACE, NULL);
|
||||
if (r == -ENOENT) {
|
||||
log_info("Skeleton directory %s missing, ignoring.", skel);
|
||||
return 0;
|
||||
|
@ -245,7 +245,7 @@ static int tar_pull_make_local_copy(TarPull *i) {
|
||||
BTRFS_SNAPSHOT_FALLBACK_DIRECTORY|
|
||||
BTRFS_SNAPSHOT_RECURSIVE);
|
||||
else
|
||||
r = copy_tree(i->final_path, t, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_HARDLINKS);
|
||||
r = copy_tree(i->final_path, t, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_HARDLINKS, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create local image: %m");
|
||||
|
||||
|
@ -1014,9 +1014,9 @@ int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_erro
|
||||
* 0 or to the actual UID shift depending on the direction we copy. If no UID shift is set we'll copy
|
||||
* the UID/GIDs as they are. */
|
||||
if (copy_from)
|
||||
r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, uid_shift == 0 ? UID_INVALID : 0, uid_shift == 0 ? GID_INVALID : 0, copy_flags);
|
||||
r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, uid_shift == 0 ? UID_INVALID : 0, uid_shift == 0 ? GID_INVALID : 0, copy_flags, NULL);
|
||||
else
|
||||
r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, uid_shift == 0 ? UID_INVALID : uid_shift, uid_shift == 0 ? GID_INVALID : uid_shift, copy_flags);
|
||||
r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, uid_shift == 0 ? UID_INVALID : uid_shift, uid_shift == 0 ? GID_INVALID : uid_shift, copy_flags, NULL);
|
||||
|
||||
hostfd = safe_close(hostfd);
|
||||
containerfd = safe_close(containerfd);
|
||||
|
@ -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);
|
||||
@ -3273,13 +3274,15 @@ static int do_copy_files(Partition *p, const char *root) {
|
||||
sfd, ".",
|
||||
pfd, fn,
|
||||
UID_INVALID, GID_INVALID,
|
||||
COPY_REFLINK|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS);
|
||||
COPY_REFLINK|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS,
|
||||
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);
|
||||
COPY_REFLINK|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS,
|
||||
denylist);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to copy '%s' to '%s%s': %m", *source, strempty(arg_root), *target);
|
||||
} else {
|
||||
@ -3339,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;
|
||||
|
||||
@ -3362,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);
|
||||
@ -3378,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;
|
||||
|
||||
@ -3391,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);
|
||||
@ -3425,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)
|
||||
@ -3444,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;
|
||||
@ -3507,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;
|
||||
|
||||
@ -3526,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);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "pretty-print.h"
|
||||
#include "recurse-dir.h"
|
||||
#include "sort-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-table.h"
|
||||
#include "strv.h"
|
||||
#include "terminal-util.h"
|
||||
@ -543,23 +544,6 @@ static int boot_entry_compare(const BootEntry *a, const BootEntry *b) {
|
||||
return -strverscmp_improved(a->id, b->id);
|
||||
}
|
||||
|
||||
static void inode_hash_func(const struct stat *q, struct siphash *state) {
|
||||
siphash24_compress(&q->st_dev, sizeof(q->st_dev), state);
|
||||
siphash24_compress(&q->st_ino, sizeof(q->st_ino), state);
|
||||
}
|
||||
|
||||
static int inode_compare_func(const struct stat *a, const struct stat *b) {
|
||||
int r;
|
||||
|
||||
r = CMP(a->st_dev, b->st_dev);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
return CMP(a->st_ino, b->st_ino);
|
||||
}
|
||||
|
||||
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(inode_hash_ops, struct stat, inode_hash_func, inode_compare_func, free);
|
||||
|
||||
static int config_check_inode_relevant_and_unseen(BootConfig *config, int fd, const char *fname) {
|
||||
_cleanup_free_ char *d = NULL;
|
||||
struct stat st;
|
||||
|
@ -687,6 +687,7 @@ static int fd_copy_tree_generic(
|
||||
uid_t override_uid,
|
||||
gid_t override_gid,
|
||||
CopyFlags copy_flags,
|
||||
const Set *denylist,
|
||||
HardlinkContext *hardlink_context,
|
||||
const char *display_path,
|
||||
copy_progress_path_t progress_path,
|
||||
@ -877,6 +878,7 @@ static int fd_copy_directory(
|
||||
uid_t override_uid,
|
||||
gid_t override_gid,
|
||||
CopyFlags copy_flags,
|
||||
const Set *denylist,
|
||||
HardlinkContext *hardlink_context,
|
||||
const char *display_path,
|
||||
copy_progress_path_t progress_path,
|
||||
@ -979,6 +981,11 @@ static int fd_copy_directory(
|
||||
return r;
|
||||
}
|
||||
|
||||
if (set_contains(denylist, &buf)) {
|
||||
log_debug("%s/%s is in the denylist, skipping", from, de->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (S_ISDIR(buf.st_mode)) {
|
||||
/*
|
||||
* Don't descend into directories on other file systems, if this is requested. We do a simple
|
||||
@ -1011,7 +1018,10 @@ static int fd_copy_directory(
|
||||
}
|
||||
}
|
||||
|
||||
q = fd_copy_tree_generic(dirfd(d), de->d_name, &buf, fdt, de->d_name, original_device, depth_left-1, override_uid, override_gid, copy_flags, hardlink_context, child_display_path, progress_path, progress_bytes, userdata);
|
||||
q = fd_copy_tree_generic(dirfd(d), de->d_name, &buf, fdt, de->d_name, original_device,
|
||||
depth_left-1, override_uid, override_gid, copy_flags, denylist,
|
||||
hardlink_context, child_display_path, progress_path, progress_bytes,
|
||||
userdata);
|
||||
|
||||
if (q == -EINTR) /* Propagate SIGINT/SIGTERM up instantly */
|
||||
return q;
|
||||
@ -1082,6 +1092,7 @@ static int fd_copy_tree_generic(
|
||||
uid_t override_uid,
|
||||
gid_t override_gid,
|
||||
CopyFlags copy_flags,
|
||||
const Set *denylist,
|
||||
HardlinkContext *hardlink_context,
|
||||
const char *display_path,
|
||||
copy_progress_path_t progress_path,
|
||||
@ -1090,7 +1101,9 @@ static int fd_copy_tree_generic(
|
||||
int r;
|
||||
|
||||
if (S_ISDIR(st->st_mode))
|
||||
return fd_copy_directory(df, from, st, dt, to, original_device, depth_left-1, override_uid, override_gid, copy_flags, hardlink_context, display_path, progress_path, progress_bytes, userdata);
|
||||
return fd_copy_directory(df, from, st, dt, to, original_device, depth_left-1, override_uid,
|
||||
override_gid, copy_flags, denylist, hardlink_context, display_path,
|
||||
progress_path, progress_bytes, userdata);
|
||||
|
||||
r = fd_copy_leaf(df, from, st, dt, to, override_uid, override_gid, copy_flags, hardlink_context, display_path, progress_bytes, userdata);
|
||||
/* We just tried to copy a leaf node of the tree. If it failed because the node already exists *and* the COPY_REPLACE flag has been provided, we should unlink the node and re-copy. */
|
||||
@ -1113,6 +1126,7 @@ int copy_tree_at_full(
|
||||
uid_t override_uid,
|
||||
gid_t override_gid,
|
||||
CopyFlags copy_flags,
|
||||
const Set *denylist,
|
||||
copy_progress_path_t progress_path,
|
||||
copy_progress_bytes_t progress_bytes,
|
||||
void *userdata) {
|
||||
@ -1126,7 +1140,9 @@ int copy_tree_at_full(
|
||||
if (fstatat(fdf, from, &st, AT_SYMLINK_NOFOLLOW) < 0)
|
||||
return -errno;
|
||||
|
||||
r = fd_copy_tree_generic(fdf, from, &st, fdt, to, st.st_dev, COPY_DEPTH_MAX, override_uid, override_gid, copy_flags, NULL, NULL, progress_path, progress_bytes, userdata);
|
||||
r = fd_copy_tree_generic(fdf, from, &st, fdt, to, st.st_dev, COPY_DEPTH_MAX, override_uid,
|
||||
override_gid, copy_flags, denylist, NULL, NULL, progress_path,
|
||||
progress_bytes, userdata);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1188,7 +1204,7 @@ int copy_directory_fd_full(
|
||||
COPY_DEPTH_MAX,
|
||||
UID_INVALID, GID_INVALID,
|
||||
copy_flags,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
progress_path,
|
||||
progress_bytes,
|
||||
userdata);
|
||||
@ -1231,7 +1247,7 @@ int copy_directory_full(
|
||||
COPY_DEPTH_MAX,
|
||||
UID_INVALID, GID_INVALID,
|
||||
copy_flags,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
progress_path,
|
||||
progress_bytes,
|
||||
userdata);
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "set.h"
|
||||
|
||||
typedef enum CopyFlags {
|
||||
COPY_REFLINK = 1 << 0, /* Try to reflink */
|
||||
COPY_MERGE = 1 << 1, /* Merge existing trees with our new one to copy */
|
||||
@ -45,12 +47,12 @@ static inline int copy_file_atomic(const char *from, const char *to, mode_t mode
|
||||
return copy_file_atomic_full(from, to, mode, chattr_flags, chattr_mask, copy_flags, NULL, NULL);
|
||||
}
|
||||
|
||||
int copy_tree_at_full(int fdf, const char *from, int fdt, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata);
|
||||
static inline int copy_tree_at(int fdf, const char *from, int fdt, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags) {
|
||||
return copy_tree_at_full(fdf, from, fdt, to, override_uid, override_gid, copy_flags, NULL, NULL, NULL);
|
||||
int copy_tree_at_full(int fdf, const char *from, int fdt, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags, const Set *denylist, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata);
|
||||
static inline int copy_tree_at(int fdf, const char *from, int fdt, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags, const Set *denylist) {
|
||||
return copy_tree_at_full(fdf, from, fdt, to, override_uid, override_gid, copy_flags, denylist, NULL, NULL, NULL);
|
||||
}
|
||||
static inline int copy_tree(const char *from, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags) {
|
||||
return copy_tree_at_full(AT_FDCWD, from, AT_FDCWD, to, override_uid, override_gid, copy_flags, NULL, NULL, NULL);
|
||||
static inline int copy_tree(const char *from, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags, const Set *denylist) {
|
||||
return copy_tree_at_full(AT_FDCWD, from, AT_FDCWD, to, override_uid, override_gid, copy_flags, denylist, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
int copy_directory_fd_full(int dirfd, const char *to, CopyFlags copy_flags, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata);
|
||||
|
@ -688,7 +688,7 @@ static int dissect_image(
|
||||
continue;
|
||||
|
||||
assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0);
|
||||
designator = PARTITION_ROOT_OF_ARCH(architecture);
|
||||
designator = partition_root_of_arch(architecture);
|
||||
rw = !(pflags & SD_GPT_FLAG_READ_ONLY);
|
||||
growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS);
|
||||
|
||||
@ -713,7 +713,7 @@ static int dissect_image(
|
||||
continue;
|
||||
|
||||
assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0);
|
||||
designator = PARTITION_VERITY_OF(PARTITION_ROOT_OF_ARCH(architecture));
|
||||
designator = partition_verity_of(partition_root_of_arch(architecture));
|
||||
fstype = "DM_verity_hash";
|
||||
rw = false;
|
||||
|
||||
@ -733,7 +733,7 @@ static int dissect_image(
|
||||
continue;
|
||||
|
||||
assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0);
|
||||
designator = PARTITION_VERITY_SIG_OF(PARTITION_ROOT_OF_ARCH(architecture));
|
||||
designator = partition_verity_sig_of(partition_root_of_arch(architecture));
|
||||
fstype = "verity_hash_signature";
|
||||
rw = false;
|
||||
|
||||
@ -750,7 +750,7 @@ static int dissect_image(
|
||||
continue;
|
||||
|
||||
assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0);
|
||||
designator = PARTITION_USR_OF_ARCH(architecture);
|
||||
designator = partition_usr_of_arch(architecture);
|
||||
rw = !(pflags & SD_GPT_FLAG_READ_ONLY);
|
||||
growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS);
|
||||
|
||||
@ -774,7 +774,7 @@ static int dissect_image(
|
||||
continue;
|
||||
|
||||
assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0);
|
||||
designator = PARTITION_VERITY_OF(PARTITION_USR_OF_ARCH(architecture));
|
||||
designator = partition_verity_of(partition_usr_of_arch(architecture));
|
||||
fstype = "DM_verity_hash";
|
||||
rw = false;
|
||||
|
||||
@ -794,7 +794,7 @@ static int dissect_image(
|
||||
continue;
|
||||
|
||||
assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0);
|
||||
designator = PARTITION_VERITY_SIG_OF(PARTITION_USR_OF_ARCH(architecture));
|
||||
designator = partition_verity_sig_of(partition_usr_of_arch(architecture));
|
||||
fstype = "verity_hash_signature";
|
||||
rw = false;
|
||||
|
||||
@ -884,7 +884,7 @@ static int dissect_image(
|
||||
* let the newest version win. This permits a simple A/B versioning
|
||||
* scheme in OS images. */
|
||||
|
||||
if (!PARTITION_DESIGNATOR_VERSIONED(designator) ||
|
||||
if (!partition_designator_is_versioned(designator) ||
|
||||
strverscmp_improved(m->partitions[designator].label, label) >= 0)
|
||||
continue;
|
||||
|
||||
@ -2369,7 +2369,7 @@ int dissected_image_decrypt(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
k = PARTITION_VERITY_OF(i);
|
||||
k = partition_verity_of(i);
|
||||
if (k >= 0) {
|
||||
r = verity_partition(i, p, m->partitions + k, verity, flags | DISSECT_IMAGE_VERITY_SHARE, d);
|
||||
if (r < 0)
|
||||
@ -2711,7 +2711,7 @@ int dissected_image_load_verity_sig_partition(
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
d = PARTITION_VERITY_SIG_OF(verity->designator < 0 ? PARTITION_ROOT : verity->designator);
|
||||
d = partition_verity_sig_of(verity->designator < 0 ? PARTITION_ROOT : verity->designator);
|
||||
assert(d >= 0);
|
||||
|
||||
p = m->partitions + d;
|
||||
@ -3170,7 +3170,7 @@ bool dissected_image_verity_candidate(const DissectedImage *image, PartitionDesi
|
||||
if (image->single_file_system)
|
||||
return partition_designator == PARTITION_ROOT && image->has_verity;
|
||||
|
||||
return PARTITION_VERITY_OF(partition_designator) >= 0;
|
||||
return partition_verity_of(partition_designator) >= 0;
|
||||
}
|
||||
|
||||
bool dissected_image_verity_ready(const DissectedImage *image, PartitionDesignator partition_designator) {
|
||||
@ -3187,7 +3187,7 @@ bool dissected_image_verity_ready(const DissectedImage *image, PartitionDesignat
|
||||
if (image->single_file_system)
|
||||
return partition_designator == PARTITION_ROOT;
|
||||
|
||||
k = PARTITION_VERITY_OF(partition_designator);
|
||||
k = partition_verity_of(partition_designator);
|
||||
return k >= 0 && image->partitions[k].found;
|
||||
}
|
||||
|
||||
@ -3204,7 +3204,7 @@ bool dissected_image_verity_sig_ready(const DissectedImage *image, PartitionDesi
|
||||
if (image->single_file_system)
|
||||
return partition_designator == PARTITION_ROOT;
|
||||
|
||||
k = PARTITION_VERITY_SIG_OF(partition_designator);
|
||||
k = partition_verity_sig_of(partition_designator);
|
||||
return k >= 0 && image->partitions[k].found;
|
||||
}
|
||||
|
||||
@ -3306,34 +3306,6 @@ int mount_image_privately_interactively(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *const partition_designator_table[] = {
|
||||
[PARTITION_ROOT] = "root",
|
||||
[PARTITION_ROOT_SECONDARY] = "root-secondary",
|
||||
[PARTITION_ROOT_OTHER] = "root-other",
|
||||
[PARTITION_USR] = "usr",
|
||||
[PARTITION_USR_SECONDARY] = "usr-secondary",
|
||||
[PARTITION_USR_OTHER] = "usr-other",
|
||||
[PARTITION_HOME] = "home",
|
||||
[PARTITION_SRV] = "srv",
|
||||
[PARTITION_ESP] = "esp",
|
||||
[PARTITION_XBOOTLDR] = "xbootldr",
|
||||
[PARTITION_SWAP] = "swap",
|
||||
[PARTITION_ROOT_VERITY] = "root-verity",
|
||||
[PARTITION_ROOT_SECONDARY_VERITY] = "root-secondary-verity",
|
||||
[PARTITION_ROOT_OTHER_VERITY] = "root-other-verity",
|
||||
[PARTITION_USR_VERITY] = "usr-verity",
|
||||
[PARTITION_USR_SECONDARY_VERITY] = "usr-secondary-verity",
|
||||
[PARTITION_USR_OTHER_VERITY] = "usr-other-verity",
|
||||
[PARTITION_ROOT_VERITY_SIG] = "root-verity-sig",
|
||||
[PARTITION_ROOT_SECONDARY_VERITY_SIG] = "root-secondary-verity-sig",
|
||||
[PARTITION_ROOT_OTHER_VERITY_SIG] = "root-other-verity-sig",
|
||||
[PARTITION_USR_VERITY_SIG] = "usr-verity-sig",
|
||||
[PARTITION_USR_SECONDARY_VERITY_SIG] = "usr-secondary-verity-sig",
|
||||
[PARTITION_USR_OTHER_VERITY_SIG] = "usr-other-verity-sig",
|
||||
[PARTITION_TMP] = "tmp",
|
||||
[PARTITION_VAR] = "var",
|
||||
};
|
||||
|
||||
static bool mount_options_relax_extension_release_checks(const MountOptions *options) {
|
||||
if (!options)
|
||||
return false;
|
||||
@ -3461,5 +3433,3 @@ int verity_dissect_and_mount(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(partition_designator, PartitionDesignator);
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "sd-id128.h"
|
||||
|
||||
#include "architecture.h"
|
||||
#include "gpt.h"
|
||||
#include "list.h"
|
||||
#include "loop-util.h"
|
||||
#include "macro.h"
|
||||
@ -41,147 +42,6 @@ struct DissectedPartition {
|
||||
.mount_node_fd = -1, \
|
||||
})
|
||||
|
||||
typedef enum PartitionDesignator {
|
||||
PARTITION_ROOT,
|
||||
PARTITION_ROOT_SECONDARY, /* Secondary architecture */
|
||||
PARTITION_ROOT_OTHER,
|
||||
PARTITION_USR,
|
||||
PARTITION_USR_SECONDARY,
|
||||
PARTITION_USR_OTHER,
|
||||
PARTITION_HOME,
|
||||
PARTITION_SRV,
|
||||
PARTITION_ESP,
|
||||
PARTITION_XBOOTLDR,
|
||||
PARTITION_SWAP,
|
||||
PARTITION_ROOT_VERITY, /* verity data for the PARTITION_ROOT partition */
|
||||
PARTITION_ROOT_SECONDARY_VERITY, /* verity data for the PARTITION_ROOT_SECONDARY partition */
|
||||
PARTITION_ROOT_OTHER_VERITY,
|
||||
PARTITION_USR_VERITY,
|
||||
PARTITION_USR_SECONDARY_VERITY,
|
||||
PARTITION_USR_OTHER_VERITY,
|
||||
PARTITION_ROOT_VERITY_SIG, /* PKCS#7 signature for root hash for the PARTITION_ROOT partition */
|
||||
PARTITION_ROOT_SECONDARY_VERITY_SIG, /* ditto for the PARTITION_ROOT_SECONDARY partition */
|
||||
PARTITION_ROOT_OTHER_VERITY_SIG,
|
||||
PARTITION_USR_VERITY_SIG,
|
||||
PARTITION_USR_SECONDARY_VERITY_SIG,
|
||||
PARTITION_USR_OTHER_VERITY_SIG,
|
||||
PARTITION_TMP,
|
||||
PARTITION_VAR,
|
||||
_PARTITION_DESIGNATOR_MAX,
|
||||
_PARTITION_DESIGNATOR_INVALID = -EINVAL,
|
||||
} PartitionDesignator;
|
||||
|
||||
static inline bool PARTITION_DESIGNATOR_VERSIONED(PartitionDesignator d) {
|
||||
/* Returns true for all designators where we want to support a concept of "versioning", i.e. which
|
||||
* likely contain software binaries (or hashes thereof) that make sense to be versioned as a
|
||||
* whole. We use this check to automatically pick the newest version of these partitions, by version
|
||||
* comparing the partition labels. */
|
||||
|
||||
return IN_SET(d,
|
||||
PARTITION_ROOT,
|
||||
PARTITION_ROOT_SECONDARY,
|
||||
PARTITION_ROOT_OTHER,
|
||||
PARTITION_USR,
|
||||
PARTITION_USR_SECONDARY,
|
||||
PARTITION_USR_OTHER,
|
||||
PARTITION_ROOT_VERITY,
|
||||
PARTITION_ROOT_SECONDARY_VERITY,
|
||||
PARTITION_ROOT_OTHER_VERITY,
|
||||
PARTITION_USR_VERITY,
|
||||
PARTITION_USR_SECONDARY_VERITY,
|
||||
PARTITION_USR_OTHER_VERITY,
|
||||
PARTITION_ROOT_VERITY_SIG,
|
||||
PARTITION_ROOT_SECONDARY_VERITY_SIG,
|
||||
PARTITION_ROOT_OTHER_VERITY_SIG,
|
||||
PARTITION_USR_VERITY_SIG,
|
||||
PARTITION_USR_SECONDARY_VERITY_SIG,
|
||||
PARTITION_USR_OTHER_VERITY_SIG);
|
||||
}
|
||||
|
||||
static inline PartitionDesignator PARTITION_VERITY_OF(PartitionDesignator p) {
|
||||
switch (p) {
|
||||
|
||||
case PARTITION_ROOT:
|
||||
return PARTITION_ROOT_VERITY;
|
||||
|
||||
case PARTITION_ROOT_SECONDARY:
|
||||
return PARTITION_ROOT_SECONDARY_VERITY;
|
||||
|
||||
case PARTITION_ROOT_OTHER:
|
||||
return PARTITION_ROOT_OTHER_VERITY;
|
||||
|
||||
case PARTITION_USR:
|
||||
return PARTITION_USR_VERITY;
|
||||
|
||||
case PARTITION_USR_SECONDARY:
|
||||
return PARTITION_USR_SECONDARY_VERITY;
|
||||
|
||||
case PARTITION_USR_OTHER:
|
||||
return PARTITION_USR_OTHER_VERITY;
|
||||
|
||||
default:
|
||||
return _PARTITION_DESIGNATOR_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static inline PartitionDesignator PARTITION_VERITY_SIG_OF(PartitionDesignator p) {
|
||||
switch (p) {
|
||||
|
||||
case PARTITION_ROOT:
|
||||
return PARTITION_ROOT_VERITY_SIG;
|
||||
|
||||
case PARTITION_ROOT_SECONDARY:
|
||||
return PARTITION_ROOT_SECONDARY_VERITY_SIG;
|
||||
|
||||
case PARTITION_ROOT_OTHER:
|
||||
return PARTITION_ROOT_OTHER_VERITY_SIG;
|
||||
|
||||
case PARTITION_USR:
|
||||
return PARTITION_USR_VERITY_SIG;
|
||||
|
||||
case PARTITION_USR_SECONDARY:
|
||||
return PARTITION_USR_SECONDARY_VERITY_SIG;
|
||||
|
||||
case PARTITION_USR_OTHER:
|
||||
return PARTITION_USR_OTHER_VERITY_SIG;
|
||||
|
||||
default:
|
||||
return _PARTITION_DESIGNATOR_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static inline PartitionDesignator PARTITION_ROOT_OF_ARCH(Architecture arch) {
|
||||
switch (arch) {
|
||||
|
||||
case native_architecture():
|
||||
return PARTITION_ROOT;
|
||||
|
||||
#ifdef ARCHITECTURE_SECONDARY
|
||||
case ARCHITECTURE_SECONDARY:
|
||||
return PARTITION_ROOT_SECONDARY;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return PARTITION_ROOT_OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
static inline PartitionDesignator PARTITION_USR_OF_ARCH(Architecture arch) {
|
||||
switch (arch) {
|
||||
|
||||
case native_architecture():
|
||||
return PARTITION_USR;
|
||||
|
||||
#ifdef ARCHITECTURE_SECONDARY
|
||||
case ARCHITECTURE_SECONDARY:
|
||||
return PARTITION_USR_SECONDARY;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return PARTITION_USR_OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
typedef enum DissectImageFlags {
|
||||
DISSECT_IMAGE_DEVICE_READ_ONLY = 1 << 0, /* Make device read-only */
|
||||
DISSECT_IMAGE_DISCARD_ON_LOOP = 1 << 1, /* Turn on "discard" if on a loop device and file system supports it */
|
||||
@ -298,9 +158,6 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DecryptedImage*, decrypted_image_unref);
|
||||
|
||||
int dissected_image_relinquish(DissectedImage *m);
|
||||
|
||||
const char* partition_designator_to_string(PartitionDesignator d) _const_;
|
||||
PartitionDesignator partition_designator_from_string(const char *name) _pure_;
|
||||
|
||||
int verity_settings_load(VeritySettings *verity, const char *image, const char *root_hash_path, const char *root_hash_sig_path);
|
||||
void verity_settings_done(VeritySettings *verity);
|
||||
|
||||
|
297
src/shared/gpt.c
297
src/shared/gpt.c
@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "gpt.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "utf8.h"
|
||||
|
||||
@ -14,13 +15,173 @@
|
||||
#pragma message "Please define GPT partition types for your architecture."
|
||||
#endif
|
||||
|
||||
bool partition_designator_is_versioned(PartitionDesignator d) {
|
||||
/* Returns true for all designators where we want to support a concept of "versioning", i.e. which
|
||||
* likely contain software binaries (or hashes thereof) that make sense to be versioned as a
|
||||
* whole. We use this check to automatically pick the newest version of these partitions, by version
|
||||
* comparing the partition labels. */
|
||||
|
||||
return IN_SET(d,
|
||||
PARTITION_ROOT,
|
||||
PARTITION_ROOT_SECONDARY,
|
||||
PARTITION_ROOT_OTHER,
|
||||
PARTITION_USR,
|
||||
PARTITION_USR_SECONDARY,
|
||||
PARTITION_USR_OTHER,
|
||||
PARTITION_ROOT_VERITY,
|
||||
PARTITION_ROOT_SECONDARY_VERITY,
|
||||
PARTITION_ROOT_OTHER_VERITY,
|
||||
PARTITION_USR_VERITY,
|
||||
PARTITION_USR_SECONDARY_VERITY,
|
||||
PARTITION_USR_OTHER_VERITY,
|
||||
PARTITION_ROOT_VERITY_SIG,
|
||||
PARTITION_ROOT_SECONDARY_VERITY_SIG,
|
||||
PARTITION_ROOT_OTHER_VERITY_SIG,
|
||||
PARTITION_USR_VERITY_SIG,
|
||||
PARTITION_USR_SECONDARY_VERITY_SIG,
|
||||
PARTITION_USR_OTHER_VERITY_SIG);
|
||||
}
|
||||
|
||||
PartitionDesignator partition_verity_of(PartitionDesignator p) {
|
||||
switch (p) {
|
||||
|
||||
case PARTITION_ROOT:
|
||||
return PARTITION_ROOT_VERITY;
|
||||
|
||||
case PARTITION_ROOT_SECONDARY:
|
||||
return PARTITION_ROOT_SECONDARY_VERITY;
|
||||
|
||||
case PARTITION_ROOT_OTHER:
|
||||
return PARTITION_ROOT_OTHER_VERITY;
|
||||
|
||||
case PARTITION_USR:
|
||||
return PARTITION_USR_VERITY;
|
||||
|
||||
case PARTITION_USR_SECONDARY:
|
||||
return PARTITION_USR_SECONDARY_VERITY;
|
||||
|
||||
case PARTITION_USR_OTHER:
|
||||
return PARTITION_USR_OTHER_VERITY;
|
||||
|
||||
default:
|
||||
return _PARTITION_DESIGNATOR_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
PartitionDesignator partition_verity_sig_of(PartitionDesignator p) {
|
||||
switch (p) {
|
||||
|
||||
case PARTITION_ROOT:
|
||||
return PARTITION_ROOT_VERITY_SIG;
|
||||
|
||||
case PARTITION_ROOT_SECONDARY:
|
||||
return PARTITION_ROOT_SECONDARY_VERITY_SIG;
|
||||
|
||||
case PARTITION_ROOT_OTHER:
|
||||
return PARTITION_ROOT_OTHER_VERITY_SIG;
|
||||
|
||||
case PARTITION_USR:
|
||||
return PARTITION_USR_VERITY_SIG;
|
||||
|
||||
case PARTITION_USR_SECONDARY:
|
||||
return PARTITION_USR_SECONDARY_VERITY_SIG;
|
||||
|
||||
case PARTITION_USR_OTHER:
|
||||
return PARTITION_USR_OTHER_VERITY_SIG;
|
||||
|
||||
default:
|
||||
return _PARTITION_DESIGNATOR_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
PartitionDesignator partition_root_of_arch(Architecture arch) {
|
||||
switch (arch) {
|
||||
|
||||
case native_architecture():
|
||||
return PARTITION_ROOT;
|
||||
|
||||
#ifdef ARCHITECTURE_SECONDARY
|
||||
case ARCHITECTURE_SECONDARY:
|
||||
return PARTITION_ROOT_SECONDARY;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return PARTITION_ROOT_OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
PartitionDesignator partition_usr_of_arch(Architecture arch) {
|
||||
switch (arch) {
|
||||
|
||||
case native_architecture():
|
||||
return PARTITION_USR;
|
||||
|
||||
#ifdef ARCHITECTURE_SECONDARY
|
||||
case ARCHITECTURE_SECONDARY:
|
||||
return PARTITION_USR_SECONDARY;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return PARTITION_USR_OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *const partition_designator_table[] = {
|
||||
[PARTITION_ROOT] = "root",
|
||||
[PARTITION_ROOT_SECONDARY] = "root-secondary",
|
||||
[PARTITION_ROOT_OTHER] = "root-other",
|
||||
[PARTITION_USR] = "usr",
|
||||
[PARTITION_USR_SECONDARY] = "usr-secondary",
|
||||
[PARTITION_USR_OTHER] = "usr-other",
|
||||
[PARTITION_HOME] = "home",
|
||||
[PARTITION_SRV] = "srv",
|
||||
[PARTITION_ESP] = "esp",
|
||||
[PARTITION_XBOOTLDR] = "xbootldr",
|
||||
[PARTITION_SWAP] = "swap",
|
||||
[PARTITION_ROOT_VERITY] = "root-verity",
|
||||
[PARTITION_ROOT_SECONDARY_VERITY] = "root-secondary-verity",
|
||||
[PARTITION_ROOT_OTHER_VERITY] = "root-other-verity",
|
||||
[PARTITION_USR_VERITY] = "usr-verity",
|
||||
[PARTITION_USR_SECONDARY_VERITY] = "usr-secondary-verity",
|
||||
[PARTITION_USR_OTHER_VERITY] = "usr-other-verity",
|
||||
[PARTITION_ROOT_VERITY_SIG] = "root-verity-sig",
|
||||
[PARTITION_ROOT_SECONDARY_VERITY_SIG] = "root-secondary-verity-sig",
|
||||
[PARTITION_ROOT_OTHER_VERITY_SIG] = "root-other-verity-sig",
|
||||
[PARTITION_USR_VERITY_SIG] = "usr-verity-sig",
|
||||
[PARTITION_USR_SECONDARY_VERITY_SIG] = "usr-secondary-verity-sig",
|
||||
[PARTITION_USR_OTHER_VERITY_SIG] = "usr-other-verity-sig",
|
||||
[PARTITION_TMP] = "tmp",
|
||||
[PARTITION_VAR] = "var",
|
||||
[PARTITION_USER_HOME] = "user-home",
|
||||
[PARTITION_LINUX_GENERIC] = "linux-generic",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(partition_designator, PartitionDesignator);
|
||||
|
||||
static const char *const partition_mountpoint_table[] = {
|
||||
[PARTITION_ROOT] = "/\0",
|
||||
[PARTITION_ROOT_SECONDARY] = "/\0",
|
||||
[PARTITION_ROOT_OTHER] = "/\0",
|
||||
[PARTITION_USR] = "/usr\0",
|
||||
[PARTITION_USR_SECONDARY] = "/usr\0",
|
||||
[PARTITION_USR_OTHER] = "/usr\0",
|
||||
[PARTITION_HOME] = "/home\0",
|
||||
[PARTITION_SRV] = "/srv\0",
|
||||
[PARTITION_ESP] = "/efi\0/boot\0",
|
||||
[PARTITION_XBOOTLDR] = "/boot\0",
|
||||
[PARTITION_TMP] = "/var/tmp\0",
|
||||
[PARTITION_VAR] = "/var\0",
|
||||
};
|
||||
|
||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(partition_mountpoint, PartitionDesignator);
|
||||
|
||||
#define _GPT_ARCH_SEXTET(arch, name) \
|
||||
{ SD_GPT_ROOT_##arch, "root-" name, ARCHITECTURE_##arch, .is_root = true }, \
|
||||
{ SD_GPT_ROOT_##arch##_VERITY, "root-" name "-verity", ARCHITECTURE_##arch, .is_root_verity = true }, \
|
||||
{ SD_GPT_ROOT_##arch##_VERITY_SIG, "root-" name "-verity-sig", ARCHITECTURE_##arch, .is_root_verity_sig = true }, \
|
||||
{ SD_GPT_USR_##arch, "usr-" name, ARCHITECTURE_##arch, .is_usr = true }, \
|
||||
{ SD_GPT_USR_##arch##_VERITY, "usr-" name "-verity", ARCHITECTURE_##arch, .is_usr_verity = true }, \
|
||||
{ SD_GPT_USR_##arch##_VERITY_SIG, "usr-" name "-verity-sig", ARCHITECTURE_##arch, .is_usr_verity_sig = true }
|
||||
{ SD_GPT_ROOT_##arch, "root-" name, ARCHITECTURE_##arch, .designator = PARTITION_ROOT_OTHER }, \
|
||||
{ SD_GPT_ROOT_##arch##_VERITY, "root-" name "-verity", ARCHITECTURE_##arch, .designator = PARTITION_ROOT_OTHER_VERITY }, \
|
||||
{ SD_GPT_ROOT_##arch##_VERITY_SIG, "root-" name "-verity-sig", ARCHITECTURE_##arch, .designator = PARTITION_ROOT_OTHER_VERITY_SIG }, \
|
||||
{ SD_GPT_USR_##arch, "usr-" name, ARCHITECTURE_##arch, .designator = PARTITION_USR_OTHER }, \
|
||||
{ SD_GPT_USR_##arch##_VERITY, "usr-" name "-verity", ARCHITECTURE_##arch, .designator = PARTITION_USR_OTHER_VERITY }, \
|
||||
{ SD_GPT_USR_##arch##_VERITY_SIG, "usr-" name "-verity-sig", ARCHITECTURE_##arch, .designator = PARTITION_USR_OTHER_VERITY_SIG }
|
||||
|
||||
const GptPartitionType gpt_partition_type_table[] = {
|
||||
_GPT_ARCH_SEXTET(ALPHA, "alpha"),
|
||||
@ -43,26 +204,31 @@ const GptPartitionType gpt_partition_type_table[] = {
|
||||
_GPT_ARCH_SEXTET(X86, "x86"),
|
||||
_GPT_ARCH_SEXTET(X86_64, "x86-64"),
|
||||
#ifdef SD_GPT_ROOT_NATIVE
|
||||
{ SD_GPT_ROOT_NATIVE, "root", native_architecture(), .is_root = true },
|
||||
{ SD_GPT_ROOT_NATIVE_VERITY, "root-verity", native_architecture(), .is_root_verity = true },
|
||||
{ SD_GPT_ROOT_NATIVE_VERITY_SIG, "root-verity-sig", native_architecture(), .is_root_verity_sig = true },
|
||||
{ SD_GPT_USR_NATIVE, "usr", native_architecture(), .is_usr = true },
|
||||
{ SD_GPT_USR_NATIVE_VERITY, "usr-verity", native_architecture(), .is_usr_verity = true },
|
||||
{ SD_GPT_USR_NATIVE_VERITY_SIG, "usr-verity-sig", native_architecture(), .is_usr_verity_sig = true },
|
||||
{ SD_GPT_ROOT_NATIVE, "root", native_architecture(), .designator = PARTITION_ROOT },
|
||||
{ SD_GPT_ROOT_NATIVE_VERITY, "root-verity", native_architecture(), .designator = PARTITION_ROOT_VERITY },
|
||||
{ SD_GPT_ROOT_NATIVE_VERITY_SIG, "root-verity-sig", native_architecture(), .designator = PARTITION_ROOT_VERITY_SIG },
|
||||
{ SD_GPT_USR_NATIVE, "usr", native_architecture(), .designator = PARTITION_USR },
|
||||
{ SD_GPT_USR_NATIVE_VERITY, "usr-verity", native_architecture(), .designator = PARTITION_USR_VERITY },
|
||||
{ SD_GPT_USR_NATIVE_VERITY_SIG, "usr-verity-sig", native_architecture(), .designator = PARTITION_USR_VERITY_SIG },
|
||||
#endif
|
||||
#ifdef SD_GPT_ROOT_SECONDARY
|
||||
_GPT_ARCH_SEXTET(SECONDARY, "secondary"),
|
||||
{ SD_GPT_ROOT_NATIVE, "root-secondary", native_architecture(), .designator = PARTITION_ROOT_SECONDARY },
|
||||
{ SD_GPT_ROOT_NATIVE_VERITY, "root-secondary-verity", native_architecture(), .designator = PARTITION_ROOT_SECONDARY_VERITY },
|
||||
{ SD_GPT_ROOT_NATIVE_VERITY_SIG, "root-secondary-verity-sig", native_architecture(), .designator = PARTITION_ROOT_SECONDARY_VERITY_SIG },
|
||||
{ SD_GPT_USR_NATIVE, "usr-secondary", native_architecture(), .designator = PARTITION_USR_SECONDARY },
|
||||
{ SD_GPT_USR_NATIVE_VERITY, "usr-secondary-verity", native_architecture(), .designator = PARTITION_USR_SECONDARY_VERITY },
|
||||
{ SD_GPT_USR_NATIVE_VERITY_SIG, "usr-secondary-verity-sig", native_architecture(), .designator = PARTITION_USR_SECONDARY_VERITY_SIG },
|
||||
#endif
|
||||
|
||||
{ SD_GPT_ESP, "esp", _ARCHITECTURE_INVALID },
|
||||
{ SD_GPT_XBOOTLDR, "xbootldr", _ARCHITECTURE_INVALID },
|
||||
{ SD_GPT_SWAP, "swap", _ARCHITECTURE_INVALID },
|
||||
{ SD_GPT_HOME, "home", _ARCHITECTURE_INVALID },
|
||||
{ SD_GPT_SRV, "srv", _ARCHITECTURE_INVALID },
|
||||
{ SD_GPT_VAR, "var", _ARCHITECTURE_INVALID },
|
||||
{ SD_GPT_TMP, "tmp", _ARCHITECTURE_INVALID },
|
||||
{ SD_GPT_USER_HOME, "user-home", _ARCHITECTURE_INVALID },
|
||||
{ SD_GPT_LINUX_GENERIC, "linux-generic", _ARCHITECTURE_INVALID },
|
||||
{ SD_GPT_ESP, "esp", _ARCHITECTURE_INVALID, .designator = PARTITION_ESP },
|
||||
{ SD_GPT_XBOOTLDR, "xbootldr", _ARCHITECTURE_INVALID, .designator = PARTITION_XBOOTLDR },
|
||||
{ SD_GPT_SWAP, "swap", _ARCHITECTURE_INVALID, .designator = PARTITION_SWAP },
|
||||
{ SD_GPT_HOME, "home", _ARCHITECTURE_INVALID, .designator = PARTITION_HOME },
|
||||
{ SD_GPT_SRV, "srv", _ARCHITECTURE_INVALID, .designator = PARTITION_SRV },
|
||||
{ SD_GPT_VAR, "var", _ARCHITECTURE_INVALID, .designator = PARTITION_VAR },
|
||||
{ SD_GPT_TMP, "tmp", _ARCHITECTURE_INVALID, .designator = PARTITION_TMP },
|
||||
{ SD_GPT_USER_HOME, "user-home", _ARCHITECTURE_INVALID, .designator = PARTITION_USER_HOME },
|
||||
{ SD_GPT_LINUX_GENERIC, "linux-generic", _ARCHITECTURE_INVALID, .designator = PARTITION_LINUX_GENERIC },
|
||||
{}
|
||||
};
|
||||
|
||||
@ -140,55 +306,86 @@ static GptPartitionType gpt_partition_type_from_uuid(sd_id128_t id) {
|
||||
if (pt)
|
||||
return *pt;
|
||||
|
||||
return (GptPartitionType) { .uuid = id, .arch = _ARCHITECTURE_INVALID };
|
||||
return (GptPartitionType) {
|
||||
.uuid = id,
|
||||
.arch = _ARCHITECTURE_INVALID,
|
||||
.designator = _PARTITION_DESIGNATOR_INVALID,
|
||||
};
|
||||
}
|
||||
|
||||
bool gpt_partition_type_is_root(sd_id128_t id) {
|
||||
return gpt_partition_type_from_uuid(id).is_root;
|
||||
return IN_SET(gpt_partition_type_from_uuid(id).designator,
|
||||
PARTITION_ROOT,
|
||||
PARTITION_ROOT_SECONDARY,
|
||||
PARTITION_ROOT_OTHER);
|
||||
}
|
||||
|
||||
bool gpt_partition_type_is_root_verity(sd_id128_t id) {
|
||||
return gpt_partition_type_from_uuid(id).is_root_verity;
|
||||
return IN_SET(gpt_partition_type_from_uuid(id).designator,
|
||||
PARTITION_ROOT_VERITY,
|
||||
PARTITION_ROOT_SECONDARY_VERITY,
|
||||
PARTITION_ROOT_OTHER_VERITY);
|
||||
}
|
||||
|
||||
bool gpt_partition_type_is_root_verity_sig(sd_id128_t id) {
|
||||
return gpt_partition_type_from_uuid(id).is_root_verity_sig;
|
||||
return IN_SET(gpt_partition_type_from_uuid(id).designator,
|
||||
PARTITION_ROOT_VERITY_SIG,
|
||||
PARTITION_ROOT_SECONDARY_VERITY_SIG,
|
||||
PARTITION_ROOT_OTHER_VERITY_SIG);
|
||||
}
|
||||
|
||||
bool gpt_partition_type_is_usr(sd_id128_t id) {
|
||||
return gpt_partition_type_from_uuid(id).is_usr;
|
||||
return IN_SET(gpt_partition_type_from_uuid(id).designator,
|
||||
PARTITION_USR,
|
||||
PARTITION_USR_SECONDARY,
|
||||
PARTITION_USR_OTHER);
|
||||
}
|
||||
|
||||
bool gpt_partition_type_is_usr_verity(sd_id128_t id) {
|
||||
return gpt_partition_type_from_uuid(id).is_usr_verity;
|
||||
return IN_SET(gpt_partition_type_from_uuid(id).designator,
|
||||
PARTITION_USR_VERITY,
|
||||
PARTITION_USR_SECONDARY_VERITY,
|
||||
PARTITION_USR_OTHER_VERITY);
|
||||
}
|
||||
|
||||
bool gpt_partition_type_is_usr_verity_sig(sd_id128_t id) {
|
||||
return gpt_partition_type_from_uuid(id).is_usr_verity_sig;
|
||||
return IN_SET(gpt_partition_type_from_uuid(id).designator,
|
||||
PARTITION_USR_VERITY_SIG,
|
||||
PARTITION_USR_SECONDARY_VERITY_SIG,
|
||||
PARTITION_USR_OTHER_VERITY_SIG);
|
||||
}
|
||||
|
||||
const char *gpt_partition_type_mountpoint_nulstr(sd_id128_t id) {
|
||||
PartitionDesignator d = gpt_partition_type_from_uuid(id).designator;
|
||||
if (d < 0)
|
||||
return NULL;
|
||||
|
||||
return partition_mountpoint_to_string(d);
|
||||
}
|
||||
|
||||
bool gpt_partition_type_knows_read_only(sd_id128_t id) {
|
||||
return gpt_partition_type_is_root(id) ||
|
||||
gpt_partition_type_is_usr(id) ||
|
||||
sd_id128_in_set(id,
|
||||
SD_GPT_HOME,
|
||||
SD_GPT_SRV,
|
||||
SD_GPT_VAR,
|
||||
SD_GPT_TMP,
|
||||
SD_GPT_XBOOTLDR) ||
|
||||
gpt_partition_type_is_root_verity(id) || /* pretty much implied, but let's set the bit to make things really clear */
|
||||
gpt_partition_type_is_usr_verity(id); /* ditto */
|
||||
/* pretty much implied, but let's set the bit to make things really clear */
|
||||
gpt_partition_type_is_root_verity(id) ||
|
||||
gpt_partition_type_is_usr_verity(id) ||
|
||||
IN_SET(gpt_partition_type_from_uuid(id).designator,
|
||||
PARTITION_HOME,
|
||||
PARTITION_SRV,
|
||||
PARTITION_VAR,
|
||||
PARTITION_TMP,
|
||||
PARTITION_XBOOTLDR);
|
||||
}
|
||||
|
||||
bool gpt_partition_type_knows_growfs(sd_id128_t id) {
|
||||
return gpt_partition_type_is_root(id) ||
|
||||
gpt_partition_type_is_usr(id) ||
|
||||
sd_id128_in_set(id,
|
||||
SD_GPT_HOME,
|
||||
SD_GPT_SRV,
|
||||
SD_GPT_VAR,
|
||||
SD_GPT_TMP,
|
||||
SD_GPT_XBOOTLDR);
|
||||
IN_SET(gpt_partition_type_from_uuid(id).designator,
|
||||
PARTITION_HOME,
|
||||
PARTITION_SRV,
|
||||
PARTITION_VAR,
|
||||
PARTITION_TMP,
|
||||
PARTITION_XBOOTLDR);
|
||||
}
|
||||
|
||||
bool gpt_partition_type_knows_no_auto(sd_id128_t id) {
|
||||
@ -196,11 +393,11 @@ bool gpt_partition_type_knows_no_auto(sd_id128_t id) {
|
||||
gpt_partition_type_is_root_verity(id) ||
|
||||
gpt_partition_type_is_usr(id) ||
|
||||
gpt_partition_type_is_usr_verity(id) ||
|
||||
sd_id128_in_set(id,
|
||||
SD_GPT_HOME,
|
||||
SD_GPT_SRV,
|
||||
SD_GPT_VAR,
|
||||
SD_GPT_TMP,
|
||||
SD_GPT_XBOOTLDR,
|
||||
SD_GPT_SWAP);
|
||||
IN_SET(gpt_partition_type_from_uuid(id).designator,
|
||||
PARTITION_HOME,
|
||||
PARTITION_SRV,
|
||||
PARTITION_VAR,
|
||||
PARTITION_TMP,
|
||||
PARTITION_XBOOTLDR,
|
||||
PARTITION_SWAP);
|
||||
}
|
||||
|
@ -10,6 +10,48 @@
|
||||
/* maximum length of gpt label */
|
||||
#define GPT_LABEL_MAX 36
|
||||
|
||||
typedef enum PartitionDesignator {
|
||||
PARTITION_ROOT, /* Primary architecture */
|
||||
PARTITION_ROOT_SECONDARY, /* Secondary architecture */
|
||||
PARTITION_ROOT_OTHER, /* Any architecture not covered by the primary or secondary architecture. */
|
||||
PARTITION_USR,
|
||||
PARTITION_USR_SECONDARY,
|
||||
PARTITION_USR_OTHER,
|
||||
PARTITION_HOME,
|
||||
PARTITION_SRV,
|
||||
PARTITION_ESP,
|
||||
PARTITION_XBOOTLDR,
|
||||
PARTITION_SWAP,
|
||||
PARTITION_ROOT_VERITY, /* verity data for the PARTITION_ROOT partition */
|
||||
PARTITION_ROOT_SECONDARY_VERITY, /* verity data for the PARTITION_ROOT_SECONDARY partition */
|
||||
PARTITION_ROOT_OTHER_VERITY,
|
||||
PARTITION_USR_VERITY,
|
||||
PARTITION_USR_SECONDARY_VERITY,
|
||||
PARTITION_USR_OTHER_VERITY,
|
||||
PARTITION_ROOT_VERITY_SIG, /* PKCS#7 signature for root hash for the PARTITION_ROOT partition */
|
||||
PARTITION_ROOT_SECONDARY_VERITY_SIG, /* ditto for the PARTITION_ROOT_SECONDARY partition */
|
||||
PARTITION_ROOT_OTHER_VERITY_SIG,
|
||||
PARTITION_USR_VERITY_SIG,
|
||||
PARTITION_USR_SECONDARY_VERITY_SIG,
|
||||
PARTITION_USR_OTHER_VERITY_SIG,
|
||||
PARTITION_TMP,
|
||||
PARTITION_VAR,
|
||||
PARTITION_USER_HOME,
|
||||
PARTITION_LINUX_GENERIC,
|
||||
_PARTITION_DESIGNATOR_MAX,
|
||||
_PARTITION_DESIGNATOR_INVALID = -EINVAL,
|
||||
} PartitionDesignator;
|
||||
|
||||
bool partition_designator_is_versioned(PartitionDesignator d);
|
||||
|
||||
PartitionDesignator partition_verity_of(PartitionDesignator p);
|
||||
PartitionDesignator partition_verity_sig_of(PartitionDesignator p);
|
||||
PartitionDesignator partition_root_of_arch(Architecture arch);
|
||||
PartitionDesignator partition_usr_of_arch(Architecture arch);
|
||||
|
||||
const char* partition_designator_to_string(PartitionDesignator d) _const_;
|
||||
PartitionDesignator partition_designator_from_string(const char *name) _pure_;
|
||||
|
||||
const char *gpt_partition_type_uuid_to_string(sd_id128_t id);
|
||||
const char *gpt_partition_type_uuid_to_string_harder(
|
||||
sd_id128_t id,
|
||||
@ -25,13 +67,7 @@ typedef struct GptPartitionType {
|
||||
sd_id128_t uuid;
|
||||
const char *name;
|
||||
Architecture arch;
|
||||
|
||||
bool is_root:1;
|
||||
bool is_root_verity:1;
|
||||
bool is_root_verity_sig:1;
|
||||
bool is_usr:1;
|
||||
bool is_usr_verity:1;
|
||||
bool is_usr_verity_sig:1;
|
||||
PartitionDesignator designator;
|
||||
} GptPartitionType;
|
||||
|
||||
extern const GptPartitionType gpt_partition_type_table[];
|
||||
@ -45,6 +81,8 @@ bool gpt_partition_type_is_usr(sd_id128_t id);
|
||||
bool gpt_partition_type_is_usr_verity(sd_id128_t id);
|
||||
bool gpt_partition_type_is_usr_verity_sig(sd_id128_t id);
|
||||
|
||||
const char *gpt_partition_type_mountpoint_nulstr(sd_id128_t id);
|
||||
|
||||
bool gpt_partition_type_knows_read_only(sd_id128_t id);
|
||||
bool gpt_partition_type_knows_growfs(sd_id128_t id);
|
||||
bool gpt_partition_type_knows_no_auto(sd_id128_t id);
|
||||
|
@ -67,11 +67,11 @@ TEST(copy_tree_replace_file) {
|
||||
|
||||
/* The file exists- now overwrite original contents, and test the COPY_REPLACE flag. */
|
||||
|
||||
assert_se(copy_tree(src, dst, UID_INVALID, GID_INVALID, COPY_REFLINK) == -EEXIST);
|
||||
assert_se(copy_tree(src, dst, UID_INVALID, GID_INVALID, COPY_REFLINK, NULL) == -EEXIST);
|
||||
|
||||
assert_se(read_file_at_and_streq(AT_FDCWD, dst, "foo foo foo\n"));
|
||||
|
||||
assert_se(copy_tree(src, dst, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_REPLACE) == 0);
|
||||
assert_se(copy_tree(src, dst, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_REPLACE, NULL) == 0);
|
||||
|
||||
assert_se(read_file_at_and_streq(AT_FDCWD, dst, "bar bar\n"));
|
||||
}
|
||||
@ -91,14 +91,14 @@ TEST(copy_tree_replace_dirs) {
|
||||
assert_se(write_string_file_at(dst, "bar", "dest file 2", WRITE_STRING_FILE_CREATE) == 0);
|
||||
|
||||
/* Copying without COPY_REPLACE should fail because the destination file already exists. */
|
||||
assert_se(copy_tree_at(src, ".", dst, ".", UID_INVALID, GID_INVALID, COPY_REFLINK) == -EEXIST);
|
||||
assert_se(copy_tree_at(src, ".", dst, ".", UID_INVALID, GID_INVALID, COPY_REFLINK, NULL) == -EEXIST);
|
||||
|
||||
assert_se(read_file_at_and_streq(src, "foo", "src file 1\n"));
|
||||
assert_se(read_file_at_and_streq(src, "bar", "src file 2\n"));
|
||||
assert_se(read_file_at_and_streq(dst, "foo", "dest file 1\n"));
|
||||
assert_se(read_file_at_and_streq(dst, "bar", "dest file 2\n"));
|
||||
|
||||
assert_se(copy_tree_at(src, ".", dst, ".", UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_REPLACE|COPY_MERGE) == 0);
|
||||
assert_se(copy_tree_at(src, ".", dst, ".", UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_REPLACE|COPY_MERGE, NULL) == 0);
|
||||
|
||||
assert_se(read_file_at_and_streq(src, "foo", "src file 1\n"));
|
||||
assert_se(read_file_at_and_streq(src, "bar", "src file 2\n"));
|
||||
@ -131,6 +131,8 @@ TEST(copy_file_fd) {
|
||||
}
|
||||
|
||||
TEST(copy_tree) {
|
||||
_cleanup_set_free_ Set *denylist = NULL;
|
||||
_cleanup_free_ char *cp = NULL;
|
||||
char original_dir[] = "/tmp/test-copy_tree/";
|
||||
char copy_dir[] = "/tmp/test-copy_tree-copy/";
|
||||
char **files = STRV_MAKE("file", "dir1/file", "dir1/dir2/file", "dir1/dir2/dir3/dir4/dir5/file");
|
||||
@ -138,7 +140,7 @@ TEST(copy_tree) {
|
||||
"link2", "dir1/file");
|
||||
char **hardlinks = STRV_MAKE("hlink", "file",
|
||||
"hlink2", "dir1/file");
|
||||
const char *unixsockp;
|
||||
const char *unixsockp, *ignorep;
|
||||
struct stat st;
|
||||
int xattr_worked = -1; /* xattr support is optional in temporary directories, hence use it if we can,
|
||||
* but don't fail if we can't */
|
||||
@ -184,7 +186,14 @@ TEST(copy_tree) {
|
||||
unixsockp = strjoina(original_dir, "unixsock");
|
||||
assert_se(mknod(unixsockp, S_IFSOCK|0644, 0) >= 0);
|
||||
|
||||
assert_se(copy_tree(original_dir, copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_MERGE|COPY_HARDLINKS) == 0);
|
||||
ignorep = strjoina(original_dir, "ignore/file");
|
||||
assert_se(write_string_file(ignorep, "ignore", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755) == 0);
|
||||
assert_se(RET_NERRNO(stat(ignorep, &st)) >= 0);
|
||||
assert_se(cp = memdup(&st, sizeof(st)));
|
||||
assert_se(set_ensure_put(&denylist, &inode_hash_ops, cp) >= 0);
|
||||
TAKE_PTR(cp);
|
||||
|
||||
assert_se(copy_tree(original_dir, copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_MERGE|COPY_HARDLINKS, denylist) == 0);
|
||||
|
||||
STRV_FOREACH(p, files) {
|
||||
_cleanup_free_ char *buf, *f, *c = NULL;
|
||||
@ -236,8 +245,11 @@ TEST(copy_tree) {
|
||||
assert_se(stat(unixsockp, &st) >= 0);
|
||||
assert_se(S_ISSOCK(st.st_mode));
|
||||
|
||||
assert_se(copy_tree(original_dir, copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK) < 0);
|
||||
assert_se(copy_tree("/tmp/inexistent/foo/bar/fsdoi", copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK) < 0);
|
||||
assert_se(copy_tree(original_dir, copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK, denylist) < 0);
|
||||
assert_se(copy_tree("/tmp/inexistent/foo/bar/fsdoi", copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK, denylist) < 0);
|
||||
|
||||
ignorep = strjoina(copy_dir, "ignore/file");
|
||||
assert_se(RET_NERRNO(access(ignorep, F_OK)) == -ENOENT);
|
||||
|
||||
(void) rm_rf(copy_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
(void) rm_rf(original_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
|
@ -1637,7 +1637,8 @@ static int copy_files(Item *i) {
|
||||
dfd, bn,
|
||||
i->uid_set ? i->uid : UID_INVALID,
|
||||
i->gid_set ? i->gid : GID_INVALID,
|
||||
COPY_REFLINK | COPY_MERGE_EMPTY | COPY_MAC_CREATE | COPY_HARDLINKS);
|
||||
COPY_REFLINK | COPY_MERGE_EMPTY | COPY_MAC_CREATE | COPY_HARDLINKS,
|
||||
NULL);
|
||||
|
||||
fd = openat(dfd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH);
|
||||
if (fd < 0) {
|
||||
|
@ -777,6 +777,60 @@ EOF
|
||||
systemd-dissect -U "$imgs/mnt"
|
||||
}
|
||||
|
||||
test_issue_24786() {
|
||||
local defs imgs root output
|
||||
|
||||
if systemd-detect-virt --quiet --container; then
|
||||
echo "Skipping verity test in container."
|
||||
return
|
||||
fi
|
||||
|
||||
defs="$(mktemp --directory "/tmp/test-repart.XXXXXXXXXX")"
|
||||
imgs="$(mktemp --directory "/var/tmp/test-repart.XXXXXXXXXX")"
|
||||
root="$(mktemp --directory "/var/tmp/test-repart.XXXXXXXXXX")"
|
||||
# shellcheck disable=SC2064
|
||||
trap "rm -rf '$defs' '$imgs' '$root'" RETURN
|
||||
|
||||
touch "$root/abc"
|
||||
mkdir "$root/usr"
|
||||
touch "$root/usr/def"
|
||||
|
||||
cat >"$defs/00-root.conf" <<EOF
|
||||
[Partition]
|
||||
Type=root-${architecture}
|
||||
CopyFiles=/
|
||||
EOF
|
||||
|
||||
cat >"$defs/10-usr.conf" <<EOF
|
||||
[Partition]
|
||||
Type=usr-${architecture}
|
||||
CopyFiles=/usr:/
|
||||
EOF
|
||||
|
||||
output=$(systemd-repart --definitions="$defs" \
|
||||
--seed="$seed" \
|
||||
--dry-run=no \
|
||||
--empty=create \
|
||||
--size=auto \
|
||||
--json=pretty \
|
||||
--root="$root" \
|
||||
"$imgs/zzz")
|
||||
|
||||
loop=$(losetup -P --show -f "$imgs/zzz")
|
||||
udevadm wait --timeout 60 --settle "${loop:?}"
|
||||
|
||||
mkdir "$imgs/mnt"
|
||||
mount -t ext4 "${loop}p1" "$imgs/mnt"
|
||||
assert_rc 0 ls "$imgs/mnt/abc"
|
||||
assert_rc 2 ls "$imgs/mnt/usr"
|
||||
mkdir "$imgs/mnt/usr"
|
||||
mount -t ext4 "${loop}p2" "$imgs/mnt/usr"
|
||||
assert_rc 0 ls "$imgs/mnt/usr/def"
|
||||
|
||||
umount -R "$imgs/mnt"
|
||||
losetup -d "$loop"
|
||||
}
|
||||
|
||||
test_sector() {
|
||||
local defs imgs output loop
|
||||
local start size ratio
|
||||
@ -845,6 +899,7 @@ test_issue_21817
|
||||
test_issue_24553
|
||||
test_zero_uuid
|
||||
test_verity
|
||||
test_issue_24786
|
||||
|
||||
# Valid block sizes on the Linux block layer are >= 512 and <= PAGE_SIZE, and
|
||||
# must be powers of 2. Which leaves exactly four different ones to test on
|
||||
|
Loading…
Reference in New Issue
Block a user