1
0
mirror of https://github.com/systemd/systemd synced 2025-11-17 07:44:46 +01:00

Compare commits

...

17 Commits

Author SHA1 Message Date
Mike Yuan
a4dae3c118
rules.d/60-block.rules: fix typo 2025-11-02 10:56:31 +01:00
Yu Watanabe
c29e304562
Several OpenSSL related cleanups (#39455) 2025-11-02 17:21:51 +09:00
Alberto Planas
ab1f4e506f repart: support "nodatacow" in btrfs subvolumes
In btrfs-progs 6.15 it is planned to add a new parameter in mkfs.btrfs
--inode-flags, that can set attributes for subvolumes, directories, and
files.

The current supported attributes are "nodatacow", to disable CoW, and
"nodatasum", to disable the checksum.

This commit extend the "Subvolunes=" option to understand the
"nodatacow" flag for subvolums only.

If RepartOffline is enabled it will build the image without loopback
devices, using the correct --inode-flags parameters.

If RepartOffline is disabled it will use loopback devices and set the
btrfs attributes accordingly.

Signed-off-by: Alberto Planas <aplanas@suse.com>
2025-11-02 17:13:31 +09:00
Yu Watanabe
eeedea94da repart: fix typo
Follow-up for 15734190c7cbfe5aed90647179e7dbbca592c8c5.
2025-11-02 17:03:03 +09:00
Yu Watanabe
4f589e8a50 resolvectl: fix typo
Follow-up for 7517e41a49d9fa7d79567ec293fe0a353bd1441b.
2025-11-02 17:00:23 +09:00
Yu Watanabe
b7d752a67e openssl-util: drop unnecessary functions when OpenSSL support is disabled 2025-11-02 16:07:46 +09:00
Yu Watanabe
84946f12b5 openssl-util: sort cleanup functions 2025-11-02 16:07:46 +09:00
Yu Watanabe
c604b78b92 repart: drop OpenSSL specific logics when OpenSSL support is disabled 2025-11-02 16:07:46 +09:00
Yu Watanabe
e3ae29ead7 repart: merge common conditions
No functional change, just refactoring.
2025-11-02 16:07:46 +09:00
Yu Watanabe
6e91c5d8ea repart: make sign_verity_roothash() take Context
No functional change, just refactoring.
2025-11-02 16:07:46 +09:00
Yu Watanabe
0158eabb01 repart: load x509 certificate and private key after Context is allocated
This splits out context_load_keys() from parse_argv().
No functional change, just refactoring.
2025-11-02 16:07:46 +09:00
Yu Watanabe
219a67c131 bootctl: return earlier when secure boot auto-enrollment is requested but OpenSSL support is disabled 2025-11-02 16:07:46 +09:00
Yu Watanabe
1b48b63b51 bootctl: move conditions into corresponding functions 2025-11-02 16:07:46 +09:00
Yu Watanabe
61d1f394cc openssl-util: drop unused fake type definitions when OpenSSL is disabled 2025-11-02 16:07:46 +09:00
Yu Watanabe
09ae1c8ade pe-binary: drop pe_hash() and friends when OpenSSL support is disabled
These three functions are currently only used by sbsign, which requires
OpenSSL. Moreover, pe_hash() and uki_hash() anyway do not work if
OpenSSL is disabled. Let's only declare them when OpenSSL support is
enabled.
2025-11-02 16:07:46 +09:00
Yu Watanabe
ab9b3bec6a openssl-util: drop unused string_hashsum() and friends when OpenSSL is disabled 2025-11-02 16:07:46 +09:00
Yu Watanabe
a47a403ca2 resolvectl: return earlier from openpgp command when OpenSSL support is disabled
When OpenSSL is disabled, string_hashsum_sha256()/_sha224() in
resolve_openpgp() will fail anyway. Let's return earlier.
2025-11-02 16:07:46 +09:00
17 changed files with 292 additions and 247 deletions

View File

@ -612,6 +612,10 @@
<entry><literal>ro</literal></entry> <entry><literal>ro</literal></entry>
<entry>Make this subvolume read-only.</entry> <entry>Make this subvolume read-only.</entry>
</row> </row>
<row id='C'>
<entry><literal>nodatacow</literal></entry>
<entry>Disable data CoW for this subvolume.</entry>
</row>
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>

View File

@ -16,7 +16,7 @@ ACTION!="remove", SUBSYSTEM=="block", \
ACTION=="change", SUBSYSTEM=="block", KERNEL=="loop*", ENV{DISK_MEDIA_CHANGE}=="1", TEST!="loop/backing_file", GROUP="disk", MODE="660" ACTION=="change", SUBSYSTEM=="block", KERNEL=="loop*", ENV{DISK_MEDIA_CHANGE}=="1", TEST!="loop/backing_file", GROUP="disk", MODE="660"
# Provide a somewhat cleaned up field indicating the subsystem various # Provide a somewhat cleaned up field indicating the subsystem various
# 'virtual' block devices belong too, in order to avoid replicating name based # 'virtual' block devices belong to, in order to avoid replicating name based
# pattern matching in every consumer # pattern matching in every consumer
ACTION!="remove", SUBSYSTEM=="block", KERNEL=="dm-*", ENV{ID_BLOCK_SUBSYSTEM}="dm" ACTION!="remove", SUBSYSTEM=="block", KERNEL=="dm-*", ENV{ID_BLOCK_SUBSYSTEM}="dm"
ACTION!="remove", SUBSYSTEM=="block", KERNEL=="loop*", ENV{ID_BLOCK_SUBSYSTEM}="loop" ACTION!="remove", SUBSYSTEM=="block", KERNEL=="loop*", ENV{ID_BLOCK_SUBSYSTEM}="loop"

View File

@ -1,7 +1,16 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "basic-forward.h" #include "basic-forward.h"
typedef enum BtrfsSubvolFlags {
BTRFS_SUBVOL_RO = 1 << 0,
BTRFS_SUBVOL_NODATACOW = 1 << 1,
_BTRFS_SUBVOL_FLAGS_MASK = BTRFS_SUBVOL_NODATACOW|BTRFS_SUBVOL_RO,
_BTRFS_SUBVOL_FLAGS_INVALID = -EINVAL,
_BTRFS_SUBVOL_FLAGS_ERRNO_MAX = -ERRNO_MAX, /* Ensure the whole errno range fits into this enum */
} BtrfsSubvolFlags;
int btrfs_validate_subvolume_name(const char *name); int btrfs_validate_subvolume_name(const char *name);
int btrfs_subvol_make(int dir_fd, const char *path); int btrfs_subvol_make(int dir_fd, const char *path);

View File

@ -9,6 +9,7 @@
#include "fd-util.h" #include "fd-util.h"
#include "format-util.h" #include "format-util.h"
#include "fs-util.h" #include "fs-util.h"
#include "hashmap.h"
#include "log.h" #include "log.h"
#include "mkdir.h" #include "mkdir.h"
#include "path-util.h" #include "path-util.h"
@ -202,7 +203,7 @@ int mkdir_p_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, g
return mkdir_p_internal(prefix, path, mode, uid, gid, flags, mkdirat_errno_wrapper); return mkdir_p_internal(prefix, path, mode, uid, gid, flags, mkdirat_errno_wrapper);
} }
int mkdir_p_root_full(const char *root, const char *p, uid_t uid, gid_t gid, mode_t m, usec_t ts, char **subvolumes) { int mkdir_p_root_full(const char *root, const char *p, uid_t uid, gid_t gid, mode_t m, usec_t ts, Hashmap *subvolumes) {
_cleanup_free_ char *pp = NULL, *bn = NULL; _cleanup_free_ char *pp = NULL, *bn = NULL;
_cleanup_close_ int dfd = -EBADF; _cleanup_close_ int dfd = -EBADF;
int r; int r;
@ -237,10 +238,17 @@ int mkdir_p_root_full(const char *root, const char *p, uid_t uid, gid_t gid, mod
if (r < 0) if (r < 0)
return r; return r;
XOpenFlags flags = 0;
if (hashmap_contains(subvolumes, p)) {
flags = XO_SUBVOLUME;
if ((PTR_TO_INT(hashmap_get(subvolumes, p)) & BTRFS_SUBVOL_NODATACOW))
flags |= XO_NOCOW;
}
_cleanup_close_ int nfd = xopenat_full( _cleanup_close_ int nfd = xopenat_full(
dfd, bn, dfd, bn,
O_DIRECTORY|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, O_DIRECTORY|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC,
path_strv_contains(subvolumes, p) ? XO_SUBVOLUME : 0, flags,
m); m);
if (nfd == -EEXIST) if (nfd == -EEXIST)
return 0; return 0;

View File

@ -22,7 +22,7 @@ static inline int mkdir_parents(const char *path, mode_t mode) {
int mkdir_parents_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags); int mkdir_parents_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags);
int mkdir_p(const char *path, mode_t mode); int mkdir_p(const char *path, mode_t mode);
int mkdir_p_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags); int mkdir_p_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags);
int mkdir_p_root_full(const char *root, const char *p, uid_t uid, gid_t gid, mode_t m, usec_t ts, char **subvolumes); int mkdir_p_root_full(const char *root, const char *p, uid_t uid, gid_t gid, mode_t m, usec_t ts, Hashmap *subvolumes);
static inline int mkdir_p_root(const char *root, const char *p, uid_t uid, gid_t gid, mode_t m) { static inline int mkdir_p_root(const char *root, const char *p, uid_t uid, gid_t gid, mode_t m) {
return mkdir_p_root_full(root, p, uid, gid, m, USEC_INFINITY, NULL); return mkdir_p_root_full(root, p, uid, gid, m, USEC_INFINITY, NULL);
} }

View File

@ -623,12 +623,13 @@ static int efi_timestamp(EFI_TIME *ret) {
return 0; return 0;
} }
#endif
static int install_secure_boot_auto_enroll(const char *esp, X509 *certificate, EVP_PKEY *private_key) { static int install_secure_boot_auto_enroll(const char *esp, X509 *certificate, EVP_PKEY *private_key) {
#if HAVE_OPENSSL
int r; int r;
if (!arg_secure_boot_auto_enroll)
return 0;
_cleanup_free_ uint8_t *dercert = NULL; _cleanup_free_ uint8_t *dercert = NULL;
int dercertsz; int dercertsz;
dercertsz = i2d_X509(certificate, &dercert); dercertsz = i2d_X509(certificate, &dercert);
@ -752,10 +753,8 @@ static int install_secure_boot_auto_enroll(const char *esp, X509 *certificate, E
} }
return 0; return 0;
#else
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL is not supported, cannot set up secure boot auto-enrollment.");
#endif
} }
#endif
static bool same_entry(uint16_t id, sd_id128_t uuid, const char *path) { static bool same_entry(uint16_t id, sd_id128_t uuid, const char *path) {
_cleanup_free_ char *opath = NULL; _cleanup_free_ char *opath = NULL;
@ -963,6 +962,7 @@ static int are_we_installed(const char *esp_path) {
return r == 0; return r == 0;
} }
#if HAVE_OPENSSL
static int load_secure_boot_auto_enroll( static int load_secure_boot_auto_enroll(
X509 **ret_certificate, X509 **ret_certificate,
EVP_PKEY **ret_private_key) { EVP_PKEY **ret_private_key) {
@ -1022,6 +1022,7 @@ static int load_secure_boot_auto_enroll(
return 0; return 0;
} }
#endif
int verb_install(int argc, char *argv[], void *userdata) { int verb_install(int argc, char *argv[], void *userdata) {
sd_id128_t uuid = SD_ID128_NULL; sd_id128_t uuid = SD_ID128_NULL;
@ -1037,11 +1038,13 @@ int verb_install(int argc, char *argv[], void *userdata) {
/* Support graceful mode only for updates, unless forcibly enabled in chroot environments */ /* Support graceful mode only for updates, unless forcibly enabled in chroot environments */
graceful = arg_graceful() == ARG_GRACEFUL_FORCE || (!install && arg_graceful() != ARG_GRACEFUL_NO); graceful = arg_graceful() == ARG_GRACEFUL_FORCE || (!install && arg_graceful() != ARG_GRACEFUL_NO);
#if HAVE_OPENSSL
_cleanup_(EVP_PKEY_freep) EVP_PKEY *private_key = NULL; _cleanup_(EVP_PKEY_freep) EVP_PKEY *private_key = NULL;
_cleanup_(X509_freep) X509 *certificate = NULL; _cleanup_(X509_freep) X509 *certificate = NULL;
r = load_secure_boot_auto_enroll(&certificate, &private_key); r = load_secure_boot_auto_enroll(&certificate, &private_key);
if (r < 0) if (r < 0)
return r; return r;
#endif
r = acquire_esp(/* unprivileged_mode= */ false, graceful, &part, &pstart, &psize, &uuid, NULL); r = acquire_esp(/* unprivileged_mode= */ false, graceful, &part, &pstart, &psize, &uuid, NULL);
if (graceful && r == -ENOKEY) if (graceful && r == -ENOKEY)
@ -1101,17 +1104,15 @@ int verb_install(int argc, char *argv[], void *userdata) {
if (r < 0) if (r < 0)
return r; return r;
if (arg_install_random_seed) {
r = install_random_seed(arg_esp_path); r = install_random_seed(arg_esp_path);
if (r < 0) if (r < 0)
return r; return r;
}
if (arg_secure_boot_auto_enroll) { #if HAVE_OPENSSL
r = install_secure_boot_auto_enroll(arg_esp_path, certificate, private_key); r = install_secure_boot_auto_enroll(arg_esp_path, certificate, private_key);
if (r < 0) if (r < 0)
return r; return r;
} #endif
} }
r = install_loader_specification(arg_dollar_boot_path()); r = install_loader_specification(arg_dollar_boot_path());

View File

@ -122,6 +122,9 @@ int install_random_seed(const char *esp) {
assert_cc(RANDOM_EFI_SEED_SIZE == SHA256_DIGEST_SIZE); assert_cc(RANDOM_EFI_SEED_SIZE == SHA256_DIGEST_SIZE);
if (!arg_install_random_seed)
return 0;
esp_fd = open(esp, O_DIRECTORY|O_RDONLY|O_CLOEXEC); esp_fd = open(esp, O_DIRECTORY|O_RDONLY|O_CLOEXEC);
if (esp_fd < 0) if (esp_fd < 0)
return log_error_errno(errno, "Failed to open ESP directory '%s': %m", esp); return log_error_errno(errno, "Failed to open ESP directory '%s': %m", esp);

View File

@ -654,11 +654,17 @@ static int parse_argv(int argc, char *argv[]) {
if (arg_dry_run && argv[optind] && !STR_IN_SET(argv[optind], "unlink", "cleanup")) if (arg_dry_run && argv[optind] && !STR_IN_SET(argv[optind], "unlink", "cleanup"))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--dry-run is only supported with --unlink or --cleanup"); return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--dry-run is only supported with --unlink or --cleanup");
if (arg_secure_boot_auto_enroll && !arg_certificate) if (arg_secure_boot_auto_enroll) {
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Secure boot auto-enrollment requested but no certificate provided"); #if HAVE_OPENSSL
if (!arg_certificate)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Secure boot auto-enrollment requested but no certificate provided.");
if (arg_secure_boot_auto_enroll && !arg_private_key) if (!arg_private_key)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Secure boot auto-enrollment requested but no private key provided"); return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Secure boot auto-enrollment requested but no private key provided.");
#else
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Secure boot auto-enrollment requested but OpenSSL support is disabled.");
#endif
}
r = sd_varlink_invocation(SD_VARLINK_ALLOW_ACCEPT); r = sd_varlink_invocation(SD_VARLINK_ALLOW_ACCEPT);
if (r < 0) if (r < 0)

View File

@ -332,33 +332,29 @@ static void copy_files_free_many(CopyFiles *f, size_t n) {
free(f); free(f);
} }
typedef enum SubvolumeFlags { static BtrfsSubvolFlags subvolume_flags_from_string_one(const char *s) {
SUBVOLUME_RO = 1 << 0,
_SUBVOLUME_FLAGS_MASK = SUBVOLUME_RO,
_SUBVOLUME_FLAGS_INVALID = -EINVAL,
_SUBVOLUME_FLAGS_ERRNO_MAX = -ERRNO_MAX, /* Ensure the whole errno range fits into this enum */
} SubvolumeFlags;
static SubvolumeFlags subvolume_flags_from_string_one(const char *s) {
/* This is a bitmask (i.e. not dense), hence we don't use the "string-table.h" stuff here. */ /* This is a bitmask (i.e. not dense), hence we don't use the "string-table.h" stuff here. */
assert(s); assert(s);
if (streq(s, "ro")) if (streq(s, "ro"))
return SUBVOLUME_RO; return BTRFS_SUBVOL_RO;
return _SUBVOLUME_FLAGS_INVALID; if (streq(s, "nodatacow"))
return BTRFS_SUBVOL_NODATACOW;
return _BTRFS_SUBVOL_FLAGS_INVALID;
} }
static SubvolumeFlags subvolume_flags_from_string(const char *s) { static BtrfsSubvolFlags subvolume_flags_from_string(const char *s) {
SubvolumeFlags flags = 0; BtrfsSubvolFlags flags = 0;
int r; int r;
assert(s); assert(s);
for (;;) { for (;;) {
_cleanup_free_ char *f = NULL; _cleanup_free_ char *f = NULL;
SubvolumeFlags ff; BtrfsSubvolFlags ff;
r = extract_first_word(&s, &f, ",", EXTRACT_DONT_COALESCE_SEPARATORS); r = extract_first_word(&s, &f, ",", EXTRACT_DONT_COALESCE_SEPARATORS);
if (r < 0) if (r < 0)
@ -378,7 +374,7 @@ static SubvolumeFlags subvolume_flags_from_string(const char *s) {
typedef struct Subvolume { typedef struct Subvolume {
char *path; char *path;
SubvolumeFlags flags; BtrfsSubvolFlags flags;
} Subvolume; } Subvolume;
static Subvolume* subvolume_free(Subvolume *s) { static Subvolume* subvolume_free(Subvolume *s) {
@ -521,8 +517,10 @@ struct Context {
bool from_scratch; bool from_scratch;
#if HAVE_OPENSSL
X509 *certificate; X509 *certificate;
EVP_PKEY *private_key; EVP_PKEY *private_key;
#endif
bool defer_partitions_empty; bool defer_partitions_empty;
bool defer_partitions_factory_reset; bool defer_partitions_factory_reset;
@ -852,11 +850,7 @@ static Context* context_new(
char **definitions, char **definitions,
EmptyMode empty, EmptyMode empty,
bool dry_run, bool dry_run,
sd_id128_t seed, sd_id128_t seed) {
X509 *certificate,
EVP_PKEY *private_key) {
/* Note: This function takes ownership of the certificate and private_key arguments. */
_cleanup_strv_free_ char **d = NULL; _cleanup_strv_free_ char **d = NULL;
if (!strv_isempty(definitions)) { if (!strv_isempty(definitions)) {
@ -875,8 +869,6 @@ static Context* context_new(
.end = UINT64_MAX, .end = UINT64_MAX,
.total = UINT64_MAX, .total = UINT64_MAX,
.seed = seed, .seed = seed,
.certificate = certificate,
.private_key = private_key,
.empty = empty, .empty = empty,
.dry_run = dry_run, .dry_run = dry_run,
.backing_fd = -EBADF, .backing_fd = -EBADF,
@ -916,8 +908,10 @@ static Context* context_free(Context *context) {
else else
free(context->node); free(context->node);
#if HAVE_OPENSSL
X509_free(context->certificate); X509_free(context->certificate);
EVP_PKEY_free(context->private_key); EVP_PKEY_free(context->private_key);
#endif
context->link = sd_varlink_unref(context->link); context->link = sd_varlink_unref(context->link);
@ -2327,7 +2321,7 @@ static int config_parse_subvolumes(
} }
if (f) { if (f) {
SubvolumeFlags flags = subvolume_flags_from_string(f); BtrfsSubvolFlags flags = subvolume_flags_from_string(f);
if (flags == -EBADRQC) { if (flags == -EBADRQC) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Unknown subvolume flag in subvolume, ignoring: %s", f); log_syntax(unit, LOG_WARNING, filename, line, r, "Unknown subvolume flag in subvolume, ignoring: %s", f);
continue; continue;
@ -5496,9 +5490,8 @@ static int partition_format_verity_hash(
} }
static int sign_verity_roothash( static int sign_verity_roothash(
Context *context,
const struct iovec *roothash, const struct iovec *roothash,
X509 *certificate,
EVP_PKEY *private_key,
struct iovec *ret_signature) { struct iovec *ret_signature) {
#if HAVE_OPENSSL #if HAVE_OPENSSL
@ -5508,8 +5501,10 @@ static int sign_verity_roothash(
_cleanup_free_ uint8_t *sig = NULL; _cleanup_free_ uint8_t *sig = NULL;
int sigsz; int sigsz;
assert(context);
assert(context->certificate);
assert(context->private_key);
assert(roothash); assert(roothash);
assert(private_key);
assert(iovec_is_set(roothash)); assert(iovec_is_set(roothash));
assert(ret_signature); assert(ret_signature);
@ -5521,7 +5516,7 @@ static int sign_verity_roothash(
if (!rb) if (!rb)
return log_oom(); return log_oom();
p7 = PKCS7_sign(certificate, private_key, NULL, rb, PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY); p7 = PKCS7_sign(context->certificate, context->private_key, NULL, rb, PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY);
if (!p7) if (!p7)
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to calculate PKCS7 signature: %s", return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to calculate PKCS7 signature: %s",
ERR_error_string(ERR_get_error(), NULL)); ERR_error_string(ERR_get_error(), NULL));
@ -5569,6 +5564,7 @@ static int partition_format_verity_sig(Context *context, Partition *p) {
Partition *hp, *rp; Partition *hp, *rp;
uint8_t fp[X509_FINGERPRINT_SIZE]; uint8_t fp[X509_FINGERPRINT_SIZE];
int whole_fd, r; int whole_fd, r;
bool has_fp = false;
assert(p->verity == VERITY_SIG); assert(p->verity == VERITY_SIG);
@ -5585,13 +5581,20 @@ static int partition_format_verity_sig(Context *context, Partition *p) {
verity_settings = lookup_verity_settings_by_uuid_pair(rp->current_uuid, hp->current_uuid); verity_settings = lookup_verity_settings_by_uuid_pair(rp->current_uuid, hp->current_uuid);
if (!context->private_key && !verity_settings) if (!verity_settings) {
#if HAVE_OPENSSL
if (!context->private_key)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Verity signature partition signing requested but no private key provided (--private-key=)."); "Verity signature partition signing requested but no private key provided (--private-key=).");
if (!context->certificate && !verity_settings) if (!context->certificate)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Verity signature partition signing requested but no PEM certificate provided (--certificate=)."); "Verity signature partition signing requested but no PEM certificate provided (--certificate=).");
#else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Verity signature partition signing requested but OpenSSL support is disabled.");
#endif
}
(void) partition_hint(p, context->node, &hint); (void) partition_hint(p, context->node, &hint);
@ -5607,7 +5610,7 @@ static int partition_format_verity_sig(Context *context, Partition *p) {
.iov_len = verity_settings->root_hash_size, .iov_len = verity_settings->root_hash_size,
}; };
} else { } else {
r = sign_verity_roothash(&hp->roothash, context->certificate, context->private_key, &sig_free); r = sign_verity_roothash(context, &hp->roothash, &sig_free);
if (r < 0) if (r < 0)
return r; return r;
@ -5615,14 +5618,17 @@ static int partition_format_verity_sig(Context *context, Partition *p) {
roothash = hp->roothash; roothash = hp->roothash;
} }
#if HAVE_OPENSSL
r = x509_fingerprint(context->certificate, fp); r = x509_fingerprint(context->certificate, fp);
if (r < 0) if (r < 0)
return log_error_errno(r, "Unable to calculate X509 certificate fingerprint: %m"); return log_error_errno(r, "Unable to calculate X509 certificate fingerprint: %m");
has_fp = true;
#endif
r = sd_json_buildo( r = sd_json_buildo(
&v, &v,
SD_JSON_BUILD_PAIR("rootHash", SD_JSON_BUILD_HEX(roothash.iov_base, roothash.iov_len)), SD_JSON_BUILD_PAIR("rootHash", SD_JSON_BUILD_HEX(roothash.iov_base, roothash.iov_len)),
SD_JSON_BUILD_PAIR("certificateFingerprint", SD_JSON_BUILD_HEX(fp, sizeof(fp))), SD_JSON_BUILD_PAIR_CONDITION(has_fp, "certificateFingerprint", SD_JSON_BUILD_HEX(fp, sizeof(fp))),
SD_JSON_BUILD_PAIR("signature", JSON_BUILD_IOVEC_BASE64(&sig))); SD_JSON_BUILD_PAIR("signature", JSON_BUILD_IOVEC_BASE64(&sig)));
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to build verity signature JSON object: %m"); return log_error_errno(r, "Failed to build verity signature JSON object: %m");
@ -5973,7 +5979,7 @@ static int make_copy_files_denylist(
return 0; return 0;
} }
static int add_subvolume_path(const char *path, Set **subvolumes) { static int add_subvolume_path(const char *path, BtrfsSubvolFlags flags, Hashmap **subvolumes) {
_cleanup_free_ struct stat *st = NULL; _cleanup_free_ struct stat *st = NULL;
int r; int r;
@ -5990,63 +5996,71 @@ static int add_subvolume_path(const char *path, Set **subvolumes) {
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to stat source file '%s/%s': %m", strempty(arg_copy_source), path); return log_error_errno(r, "Failed to stat source file '%s/%s': %m", strempty(arg_copy_source), path);
r = set_ensure_consume(subvolumes, &inode_hash_ops, TAKE_PTR(st)); r = hashmap_ensure_put(subvolumes, &inode_hash_ops, st, INT_TO_PTR(flags));
if (r < 0) if (r < 0)
return log_oom(); return log_oom();
TAKE_PTR(st);
return 0; return 0;
} }
static int make_subvolumes_strv(const Partition *p, char ***ret) { static int make_subvolumes_hashmap(const Partition *p, Hashmap **ret) {
_cleanup_strv_free_ char **subvolumes = NULL; _cleanup_hashmap_free_ Hashmap *hashmap = NULL;
Subvolume *subvolume; Subvolume *subvolume;
int r; int r;
assert(p); assert(p);
assert(ret); assert(ret);
ORDERED_HASHMAP_FOREACH(subvolume, p->subvolumes) ORDERED_HASHMAP_FOREACH(subvolume, p->subvolumes) {
if (strv_extend(&subvolumes, subvolume->path) < 0) _cleanup_free_ char *path = NULL;
path = strdup(subvolume->path);
if (!path)
return log_oom(); return log_oom();
if (p->suppressing) { r = hashmap_ensure_put(&hashmap, &path_hash_ops_free, path, INT_TO_PTR(subvolume->flags));
char **suppressing; if (r < 0)
return log_oom();
r = make_subvolumes_strv(p->suppressing, &suppressing); TAKE_PTR(path);
}
if (p->suppressing) {
Hashmap *suppressing;
r = make_subvolumes_hashmap(p->suppressing, &suppressing);
if (r < 0) if (r < 0)
return r; return r;
r = strv_extend_strv_consume(&subvolumes, suppressing, /* filter_duplicates= */ true); r = hashmap_merge(hashmap, suppressing);
if (r < 0) if (r < 0)
return log_oom(); return log_oom();
} }
*ret = TAKE_PTR(subvolumes); *ret = TAKE_PTR(hashmap);
return 0; return 0;
} }
static int make_subvolumes_set( static int make_subvolumes_by_source_inode_hashmap(
const Partition *p, const Partition *p,
const char *source, const char *source,
const char *target, const char *target,
Set **ret) { Hashmap **ret) {
_cleanup_strv_free_ char **paths = NULL; _cleanup_hashmap_free_ Hashmap *hashmap = NULL;
_cleanup_set_free_ Set *subvolumes = NULL; Subvolume *subvolume;
int r; int r;
assert(p); assert(p);
assert(target); assert(target);
assert(ret); assert(ret);
r = make_subvolumes_strv(p, &paths); ORDERED_HASHMAP_FOREACH(subvolume, p->subvolumes) {
if (r < 0)
return r;
STRV_FOREACH(subvolume, paths) {
_cleanup_free_ char *path = NULL; _cleanup_free_ char *path = NULL;
const char *s = path_startswith(*subvolume, target); const char *s = path_startswith(subvolume->path, target);
if (!s) if (!s)
continue; continue;
@ -6054,12 +6068,24 @@ static int make_subvolumes_set(
if (!path) if (!path)
return log_oom(); return log_oom();
r = add_subvolume_path(path, &subvolumes); r = add_subvolume_path(path, subvolume->flags, &hashmap);
if (r < 0) if (r < 0)
return r; return r;
} }
*ret = TAKE_PTR(subvolumes); if (p->suppressing) {
Hashmap *suppressing;
r = make_subvolumes_by_source_inode_hashmap(p->suppressing, source, target, &suppressing);
if (r < 0)
return r;
r = hashmap_merge(hashmap, suppressing);
if (r < 0)
return log_oom();
}
*ret = TAKE_PTR(hashmap);
return 0; return 0;
} }
@ -6127,13 +6153,13 @@ static int file_is_denylisted(const char *source, Hashmap *denylist) {
} }
static int do_copy_files(Context *context, Partition *p, const char *root) { static int do_copy_files(Context *context, Partition *p, const char *root) {
_cleanup_strv_free_ char **subvolumes = NULL; _cleanup_hashmap_free_ Hashmap *subvolumes = NULL;
int r; int r;
assert(p); assert(p);
assert(root); assert(root);
r = make_subvolumes_strv(p, &subvolumes); r = make_subvolumes_hashmap(p, &subvolumes);
if (r < 0) if (r < 0)
return r; return r;
@ -6177,7 +6203,7 @@ static int do_copy_files(Context *context, Partition *p, const char *root) {
FOREACH_ARRAY(line, copy_files, n_copy_files) { FOREACH_ARRAY(line, copy_files, n_copy_files) {
_cleanup_hashmap_free_ Hashmap *denylist = NULL; _cleanup_hashmap_free_ Hashmap *denylist = NULL;
_cleanup_set_free_ Set *subvolumes_by_source_inode = NULL; _cleanup_hashmap_free_ Hashmap *subvolumes_by_source_inode = NULL;
_cleanup_close_ int sfd = -EBADF, pfd = -EBADF, tfd = -EBADF; _cleanup_close_ int sfd = -EBADF, pfd = -EBADF, tfd = -EBADF;
usec_t ts = epoch_or_infinity(); usec_t ts = epoch_or_infinity();
@ -6187,7 +6213,7 @@ static int do_copy_files(Context *context, Partition *p, const char *root) {
if (r > 0) if (r > 0)
continue; continue;
r = make_subvolumes_set(p, line->source, line->target, &subvolumes_by_source_inode); r = make_subvolumes_by_source_inode_hashmap(p, line->source, line->target, &subvolumes_by_source_inode);
if (r < 0) if (r < 0)
return r; return r;
@ -6302,14 +6328,14 @@ static int do_copy_files(Context *context, Partition *p, const char *root) {
} }
static int do_make_directories(Partition *p, const char *root) { static int do_make_directories(Partition *p, const char *root) {
_cleanup_strv_free_ char **subvolumes = NULL; _cleanup_hashmap_free_ Hashmap *subvolumes = NULL;
_cleanup_free_ char **override_dirs = NULL; _cleanup_free_ char **override_dirs = NULL;
int r; int r;
assert(p); assert(p);
assert(root); assert(root);
r = make_subvolumes_strv(p, &subvolumes); r = make_subvolumes_hashmap(p, &subvolumes);
if (r < 0) if (r < 0)
return r; return r;
@ -6355,7 +6381,7 @@ static int make_subvolumes_read_only(Partition *p, const char *root) {
int r; int r;
ORDERED_HASHMAP_FOREACH(subvolume, p->subvolumes) { ORDERED_HASHMAP_FOREACH(subvolume, p->subvolumes) {
if (!FLAGS_SET(subvolume->flags, SUBVOLUME_RO)) if (!FLAGS_SET(subvolume->flags, BTRFS_SUBVOL_RO))
continue; continue;
path = path_join(root, subvolume->path); path = path_join(root, subvolume->path);
@ -6623,7 +6649,7 @@ static int append_btrfs_subvols(char ***l, OrderedHashmap *subvolumes, const cha
if (streq_ptr(subvolume->path, default_subvolume) && !strextend(&s, "default")) if (streq_ptr(subvolume->path, default_subvolume) && !strextend(&s, "default"))
return log_oom(); return log_oom();
if (FLAGS_SET(subvolume->flags, SUBVOLUME_RO) && !strextend_with_separator(&s, "-", "ro")) if (FLAGS_SET(subvolume->flags, BTRFS_SUBVOL_RO) && !strextend_with_separator(&s, "-", "ro"))
return log_oom(); return log_oom();
if (!strextend_with_separator(&s, ":", subvolume->path)) if (!strextend_with_separator(&s, ":", subvolume->path))
@ -6637,6 +6663,28 @@ static int append_btrfs_subvols(char ***l, OrderedHashmap *subvolumes, const cha
return 0; return 0;
} }
static int append_btrfs_inode_flags(char ***l, OrderedHashmap *subvolumes) {
Subvolume *subvolume;
int r;
assert(l);
ORDERED_HASHMAP_FOREACH(subvolume, subvolumes) {
if (!FLAGS_SET(subvolume->flags, BTRFS_SUBVOL_NODATACOW))
continue;
_cleanup_free_ char *s = strjoin("nodatacow:", subvolume->path);
if (!s)
return log_oom();
r = strv_extend_many(l, "--inode-flags", s);
if (r < 0)
return log_oom();
}
return 0;
}
static int finalize_extra_mkfs_options(const Partition *p, const char *root, char ***ret) { static int finalize_extra_mkfs_options(const Partition *p, const char *root, char ***ret) {
_cleanup_strv_free_ char **sv = NULL; _cleanup_strv_free_ char **sv = NULL;
int r; int r;
@ -6655,10 +6703,18 @@ static int finalize_extra_mkfs_options(const Partition *p, const char *root, cha
if (r < 0) if (r < 0)
return r; return r;
r = append_btrfs_inode_flags(&sv, p->subvolumes);
if (r < 0)
return r;
if (p->suppressing) { if (p->suppressing) {
r = append_btrfs_subvols(&sv, p->suppressing->subvolumes, NULL); r = append_btrfs_subvols(&sv, p->suppressing->subvolumes, NULL);
if (r < 0) if (r < 0)
return r; return r;
r = append_btrfs_inode_flags(&sv, p->suppressing->subvolumes);
if (r < 0)
return r;
} }
} }
@ -8684,6 +8740,57 @@ static int context_minimize(Context *context) {
return 0; return 0;
} }
static int context_load_keys(Context *context) {
#if HAVE_OPENSSL
int r;
assert(context);
if (arg_certificate) {
if (arg_certificate_source_type == OPENSSL_CERTIFICATE_SOURCE_FILE) {
r = parse_path_argument(arg_certificate, /*suppress_root=*/ false, &arg_certificate);
if (r < 0)
return r;
}
r = openssl_load_x509_certificate(
arg_certificate_source_type,
arg_certificate_source,
arg_certificate,
&context->certificate);
if (r < 0)
return log_error_errno(r, "Failed to load X.509 certificate from %s: %m", arg_certificate);
}
if (arg_private_key) {
if (arg_private_key_source_type == OPENSSL_KEY_SOURCE_FILE) {
r = parse_path_argument(arg_private_key, /*suppress_root=*/ false, &arg_private_key);
if (r < 0)
return r;
}
r = openssl_load_private_key(
arg_private_key_source_type,
arg_private_key_source,
arg_private_key,
&(AskPasswordRequest) {
.tty_fd = -EBADF,
.id = "repart-private-key-pin",
.keyring = arg_private_key,
.credential = "repart.private-key-pin",
.until = USEC_INFINITY,
.hup_fd = -EBADF,
},
&context->private_key,
/* ret_user_interface= */ NULL);
if (r < 0)
return log_error_errno(r, "Failed to load private key from %s: %m", arg_private_key);
}
#endif
return 0;
}
static int parse_partition_types(const char *p, GptPartitionType **partitions, size_t *n_partitions) { static int parse_partition_types(const char *p, GptPartitionType **partitions, size_t *n_partitions) {
int r; int r;
@ -8888,13 +8995,7 @@ static int help(void) {
return 0; return 0;
} }
static int parse_argv( static int parse_argv(int argc, char *argv[]) {
int argc,
char *argv[],
X509 **ret_certificate,
EVP_PKEY **ret_private_key,
OpenSSLAskPasswordUI **ret_ui) {
enum { enum {
ARG_VERSION = 0x100, ARG_VERSION = 0x100,
ARG_NO_PAGER, ARG_NO_PAGER,
@ -8993,17 +9094,11 @@ static int parse_argv(
{} {}
}; };
_cleanup_(X509_freep) X509 *certificate = NULL;
_cleanup_(openssl_ask_password_ui_freep) OpenSSLAskPasswordUI *ui = NULL;
_cleanup_(EVP_PKEY_freep) EVP_PKEY *private_key = NULL;
bool auto_public_key_pcr_mask = true, auto_pcrlock = true; bool auto_public_key_pcr_mask = true, auto_pcrlock = true;
int c, r; int c, r;
assert(argc >= 0); assert(argc >= 0);
assert(argv); assert(argv);
assert(ret_certificate);
assert(ret_private_key);
assert(ret_ui);
while ((c = getopt_long(argc, argv, "hs:SCP", options, NULL)) >= 0) while ((c = getopt_long(argc, argv, "hs:SCP", options, NULL)) >= 0)
@ -9544,47 +9639,6 @@ static int parse_argv(
*p = gpt_partition_type_override_architecture(*p, arg_architecture); *p = gpt_partition_type_override_architecture(*p, arg_architecture);
} }
if (arg_certificate) {
if (arg_certificate_source_type == OPENSSL_CERTIFICATE_SOURCE_FILE) {
r = parse_path_argument(arg_certificate, /*suppress_root=*/ false, &arg_certificate);
if (r < 0)
return r;
}
r = openssl_load_x509_certificate(
arg_certificate_source_type,
arg_certificate_source,
arg_certificate,
&certificate);
if (r < 0)
return log_error_errno(r, "Failed to load X.509 certificate from %s: %m", arg_certificate);
}
if (arg_private_key) {
if (arg_private_key_source_type == OPENSSL_KEY_SOURCE_FILE) {
r = parse_path_argument(arg_private_key, /*suppress_root=*/ false, &arg_private_key);
if (r < 0)
return r;
}
r = openssl_load_private_key(
arg_private_key_source_type,
arg_private_key_source,
arg_private_key,
&(AskPasswordRequest) {
.tty_fd = -EBADF,
.id = "repart-private-key-pin",
.keyring = arg_private_key,
.credential = "repart.private-key-pin",
.until = USEC_INFINITY,
.hup_fd = -EBADF,
},
&private_key,
&ui);
if (r < 0)
return log_error_errno(r, "Failed to load private key from %s: %m", arg_private_key);
}
if (arg_append_fstab && !arg_generate_fstab) if (arg_append_fstab && !arg_generate_fstab)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No --generate-fstab= specified for --append-fstab=%s.", append_mode_to_string(arg_append_fstab)); return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No --generate-fstab= specified for --append-fstab=%s.", append_mode_to_string(arg_append_fstab));
@ -9596,10 +9650,6 @@ static int parse_argv(
arg_pager_flags |= PAGER_DISABLE; arg_pager_flags |= PAGER_DISABLE;
} }
*ret_certificate = TAKE_PTR(certificate);
*ret_private_key = TAKE_PTR(private_key);
*ret_ui = TAKE_PTR(ui);
return 1; return 1;
} }
@ -10220,9 +10270,7 @@ static int vl_method_run(
p.definitions, p.definitions,
p.empty, p.empty,
p.dry_run, p.dry_run,
p.seed, p.seed);
/* certificate= */ NULL,
/* private_key= */ NULL);
if (!context) if (!context)
return log_oom(); return log_oom();
@ -10361,9 +10409,6 @@ static int vl_server(void) {
} }
static int run(int argc, char *argv[]) { static int run(int argc, char *argv[]) {
_cleanup_(X509_freep) X509 *certificate = NULL;
_cleanup_(openssl_ask_password_ui_freep) OpenSSLAskPasswordUI *ui = NULL;
_cleanup_(EVP_PKEY_freep) EVP_PKEY *private_key = NULL;
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL; _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
_cleanup_(umount_and_freep) char *mounted_dir = NULL; _cleanup_(umount_and_freep) char *mounted_dir = NULL;
_cleanup_(context_freep) Context* context = NULL; _cleanup_(context_freep) Context* context = NULL;
@ -10372,7 +10417,7 @@ static int run(int argc, char *argv[]) {
log_setup(); log_setup();
r = parse_argv(argc, argv, &certificate, &private_key, &ui); r = parse_argv(argc, argv);
if (r <= 0) if (r <= 0)
return r; return r;
@ -10438,14 +10483,13 @@ static int run(int argc, char *argv[]) {
arg_definitions, arg_definitions,
arg_empty, arg_empty,
arg_dry_run, arg_dry_run,
arg_seed, arg_seed);
certificate,
private_key);
if (!context) if (!context)
return log_oom(); return log_oom();
TAKE_PTR(certificate); r = context_load_keys(context);
TAKE_PTR(private_key); if (r < 0)
return r;
context->defer_partitions_empty = arg_defer_partitions_empty; context->defer_partitions_empty = arg_defer_partitions_empty;
context->defer_partitions_factory_reset = arg_defer_partitions_factory_reset; context->defer_partitions_factory_reset = arg_defer_partitions_factory_reset;

View File

@ -1014,6 +1014,7 @@ static int verb_service(int argc, char **argv, void *userdata) {
return resolve_service(bus, argv[1], argv[2], argv[3]); return resolve_service(bus, argv[1], argv[2], argv[3]);
} }
#if HAVE_OPENSSL
static int resolve_openpgp(sd_bus *bus, const char *address) { static int resolve_openpgp(sd_bus *bus, const char *address) {
int r; int r;
@ -1053,7 +1054,7 @@ static int resolve_openpgp(sd_bus *bus, const char *address) {
arg_class ?: DNS_CLASS_IN, arg_class ?: DNS_CLASS_IN,
arg_type ?: DNS_TYPE_OPENPGPKEY, arg_type ?: DNS_TYPE_OPENPGPKEY,
/* warn_missing= */ false); /* warn_missing= */ false);
if (!IN_SET(r, -ENXIO, -ESRCH)) /* Not NXDOMAIN or NODATA? Then fail immedately. */ if (!IN_SET(r, -ENXIO, -ESRCH)) /* Not NXDOMAIN or NODATA? Then fail immediately. */
return r; return r;
hashed = mfree(hashed); hashed = mfree(hashed);
@ -1074,8 +1075,10 @@ static int resolve_openpgp(sd_bus *bus, const char *address) {
arg_type ?: DNS_TYPE_OPENPGPKEY, arg_type ?: DNS_TYPE_OPENPGPKEY,
/* warn_missing= */ true); /* warn_missing= */ true);
} }
#endif
static int verb_openpgp(int argc, char **argv, void *userdata) { static int verb_openpgp(int argc, char **argv, void *userdata) {
#if HAVE_OPENSSL
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r, ret = 0; int r, ret = 0;
@ -1090,6 +1093,9 @@ static int verb_openpgp(int argc, char **argv, void *userdata) {
RET_GATHER(ret, resolve_openpgp(bus, *p)); RET_GATHER(ret, resolve_openpgp(bus, *p));
return ret; return ret;
#else
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled, cannot query Open PGP keys.");
#endif
} }
static int resolve_tlsa(sd_bus *bus, const char *family, const char *address) { static int resolve_tlsa(sd_bus *bus, const char *family, const char *address) {

View File

@ -12,6 +12,7 @@
#include <unistd.h> #include <unistd.h>
#include "alloc-util.h" #include "alloc-util.h"
#include "btrfs.h"
#include "chattr-util.h" #include "chattr-util.h"
#include "copy.h" #include "copy.h"
#include "dirent-util.h" #include "dirent-util.h"
@ -891,7 +892,7 @@ static int fd_copy_tree_generic(
gid_t override_gid, gid_t override_gid,
CopyFlags copy_flags, CopyFlags copy_flags,
Hashmap *denylist, Hashmap *denylist,
Set *subvolumes, Hashmap *subvolumes,
HardlinkContext *hardlink_context, HardlinkContext *hardlink_context,
const char *display_path, const char *display_path,
copy_progress_path_t progress_path, copy_progress_path_t progress_path,
@ -1111,7 +1112,7 @@ static int fd_copy_directory(
gid_t override_gid, gid_t override_gid,
CopyFlags copy_flags, CopyFlags copy_flags,
Hashmap *denylist, Hashmap *denylist,
Set *subvolumes, Hashmap *subvolumes,
HardlinkContext *hardlink_context, HardlinkContext *hardlink_context,
const char *display_path, const char *display_path,
copy_progress_path_t progress_path, copy_progress_path_t progress_path,
@ -1160,9 +1161,16 @@ static int fd_copy_directory(
exists = r >= 0; exists = r >= 0;
XOpenFlags flags = copy_flags & COPY_MAC_CREATE ? XO_LABEL : 0;
if (hashmap_contains(subvolumes, st)) {
flags |= XO_SUBVOLUME;
if ((PTR_TO_INT(hashmap_get(subvolumes, st)) & BTRFS_SUBVOL_NODATACOW))
flags |= XO_NOCOW;
}
fdt = xopenat_lock_full(dt, to, fdt = xopenat_lock_full(dt, to,
O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW|(exists ? 0 : O_CREAT|O_EXCL), O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW|(exists ? 0 : O_CREAT|O_EXCL),
(copy_flags & COPY_MAC_CREATE ? XO_LABEL : 0)|(set_contains(subvolumes, st) ? XO_SUBVOLUME : 0), flags,
st->st_mode & 07777, st->st_mode & 07777,
copy_flags & COPY_LOCK_BSD ? LOCK_BSD : LOCK_NONE, copy_flags & COPY_LOCK_BSD ? LOCK_BSD : LOCK_NONE,
LOCK_EX); LOCK_EX);
@ -1331,7 +1339,7 @@ static int fd_copy_tree_generic(
gid_t override_gid, gid_t override_gid,
CopyFlags copy_flags, CopyFlags copy_flags,
Hashmap *denylist, Hashmap *denylist,
Set *subvolumes, Hashmap *subvolumes,
HardlinkContext *hardlink_context, HardlinkContext *hardlink_context,
const char *display_path, const char *display_path,
copy_progress_path_t progress_path, copy_progress_path_t progress_path,
@ -1380,7 +1388,7 @@ int copy_tree_at_full(
gid_t override_gid, gid_t override_gid,
CopyFlags copy_flags, CopyFlags copy_flags,
Hashmap *denylist, Hashmap *denylist,
Set *subvolumes, Hashmap *subvolumes,
copy_progress_path_t progress_path, copy_progress_path_t progress_path,
copy_progress_bytes_t progress_bytes, copy_progress_bytes_t progress_bytes,
void *userdata) { void *userdata) {

View File

@ -80,11 +80,11 @@ static inline int copy_file_atomic(const char *from, const char *to, mode_t mode
return copy_file_atomic_full(from, to, mode, 0, 0, copy_flags, NULL, NULL); return copy_file_atomic_full(from, to, mode, 0, 0, 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, Hashmap *denylist, Set *subvolumes, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata); 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, Hashmap *denylist, Hashmap *subvolumes, 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, Hashmap *denylist, Set *subvolumes) { 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, Hashmap *denylist, Hashmap *subvolumes) {
return copy_tree_at_full(fdf, from, fdt, to, override_uid, override_gid, copy_flags, denylist, subvolumes, NULL, NULL, NULL); return copy_tree_at_full(fdf, from, fdt, to, override_uid, override_gid, copy_flags, denylist, subvolumes, 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, Hashmap *denylist, Set *subvolumes) { static inline int copy_tree(const char *from, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags, Hashmap *denylist, Hashmap *subvolumes) {
return copy_tree_at_full(AT_FDCWD, from, AT_FDCWD, to, override_uid, override_gid, copy_flags, denylist, subvolumes, NULL, NULL, NULL); return copy_tree_at_full(AT_FDCWD, from, AT_FDCWD, to, override_uid, override_gid, copy_flags, denylist, subvolumes, NULL, NULL, NULL);
} }

View File

@ -1644,25 +1644,20 @@ static int load_x509_certificate_from_provider(const char *provider, const char
return -EOPNOTSUPP; return -EOPNOTSUPP;
#endif #endif
} }
#endif
OpenSSLAskPasswordUI* openssl_ask_password_ui_free(OpenSSLAskPasswordUI *ui) { OpenSSLAskPasswordUI* openssl_ask_password_ui_free(OpenSSLAskPasswordUI *ui) {
#if HAVE_OPENSSL && !defined(OPENSSL_NO_UI_CONSOLE)
if (!ui) if (!ui)
return NULL; return NULL;
#ifndef OPENSSL_NO_UI_CONSOLE
assert(UI_get_default_method() == ui->method); assert(UI_get_default_method() == ui->method);
UI_set_default_method(UI_OpenSSL()); UI_set_default_method(UI_OpenSSL());
UI_destroy_method(ui->method); UI_destroy_method(ui->method);
return mfree(ui);
#else
assert(ui == NULL);
return NULL;
#endif #endif
return mfree(ui);
} }
int x509_fingerprint(X509 *cert, uint8_t buffer[static SHA256_DIGEST_SIZE]) { int x509_fingerprint(X509 *cert, uint8_t buffer[static SHA256_DIGEST_SIZE]) {
#if HAVE_OPENSSL
_cleanup_free_ uint8_t *der = NULL; _cleanup_free_ uint8_t *der = NULL;
int dersz; int dersz;
@ -1674,9 +1669,6 @@ int x509_fingerprint(X509 *cert, uint8_t buffer[static SHA256_DIGEST_SIZE]) {
sha256_direct(der, dersz, buffer); sha256_direct(der, dersz, buffer);
return 0; return 0;
#else
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL is not supported, cannot calculate X509 fingerprint.");
#endif
} }
int openssl_load_x509_certificate( int openssl_load_x509_certificate(
@ -1684,7 +1676,7 @@ int openssl_load_x509_certificate(
const char *certificate_source, const char *certificate_source,
const char *certificate, const char *certificate,
X509 **ret) { X509 **ret) {
#if HAVE_OPENSSL
int r; int r;
assert(certificate); assert(certificate);
@ -1708,9 +1700,6 @@ int openssl_load_x509_certificate(
certificate_source); certificate_source);
return 0; return 0;
#else
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL is not supported, cannot load X509 certificate.");
#endif
} }
int openssl_load_private_key( int openssl_load_private_key(
@ -1720,7 +1709,7 @@ int openssl_load_private_key(
const AskPasswordRequest *request, const AskPasswordRequest *request,
EVP_PKEY **ret_private_key, EVP_PKEY **ret_private_key,
OpenSSLAskPasswordUI **ret_user_interface) { OpenSSLAskPasswordUI **ret_user_interface) {
#if HAVE_OPENSSL
int r; int r;
assert(private_key); assert(private_key);
@ -1763,10 +1752,8 @@ int openssl_load_private_key(
} }
return 0; return 0;
#else
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL is not supported, cannot load private key.");
#endif
} }
#endif
int parse_openssl_certificate_source_argument( int parse_openssl_certificate_source_argument(
const char *argument, const char *argument,

View File

@ -55,22 +55,24 @@ int parse_openssl_key_source_argument(const char *argument, char **private_key_s
# endif # endif
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_MACRO(void*, OPENSSL_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_MACRO(void*, OPENSSL_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(X509_NAME*, X509_NAME_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ASN1_OCTET_STRING*, ASN1_OCTET_STRING_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_PKEY_CTX*, EVP_PKEY_CTX_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ASN1_TIME*, ASN1_TIME_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_CIPHER_CTX*, EVP_CIPHER_CTX_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(BIO*, BIO_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_POINT*, EC_POINT_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(BIO*, BIO_free_all, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_GROUP*, EC_GROUP_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(BIGNUM*, BN_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(BIGNUM*, BN_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(BN_CTX*, BN_CTX_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(BN_CTX*, BN_CTX_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_GROUP*, EC_GROUP_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_POINT*, EC_POINT_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ECDSA_SIG*, ECDSA_SIG_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ECDSA_SIG*, ECDSA_SIG_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_CIPHER_CTX*, EVP_CIPHER_CTX_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MD_CTX*, EVP_MD_CTX_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_PKEY*, EVP_PKEY_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_PKEY_CTX*, EVP_PKEY_CTX_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(PKCS7*, PKCS7_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(PKCS7*, PKCS7_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(PKCS7_SIGNER_INFO*, PKCS7_SIGNER_INFO_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(PKCS7_SIGNER_INFO*, PKCS7_SIGNER_INFO_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(SSL*, SSL_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(SSL*, SSL_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(BIO*, BIO_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(X509*, X509_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(BIO*, BIO_free_all, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(X509_NAME*, X509_NAME_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MD_CTX*, EVP_MD_CTX_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ASN1_OCTET_STRING*, ASN1_OCTET_STRING_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ASN1_TIME*, ASN1_TIME_free, NULL);
static inline STACK_OF(X509_ALGOR) *x509_algor_free_many(STACK_OF(X509_ALGOR) *attrs) { static inline STACK_OF(X509_ALGOR) *x509_algor_free_many(STACK_OF(X509_ALGOR) *attrs) {
if (!attrs) if (!attrs)
@ -170,44 +172,13 @@ int digest_and_sign(const EVP_MD *md, EVP_PKEY *privkey, const void *data, size_
int pkcs7_new(X509 *certificate, EVP_PKEY *private_key, const char *hash_algorithm, PKCS7 **ret_p7, PKCS7_SIGNER_INFO **ret_si); int pkcs7_new(X509 *certificate, EVP_PKEY *private_key, const char *hash_algorithm, PKCS7 **ret_p7, PKCS7_SIGNER_INFO **ret_si);
int string_hashsum(const char *s, size_t len, const char *md_algorithm, char **ret); int string_hashsum(const char *s, size_t len, const char *md_algorithm, char **ret);
static inline int string_hashsum_sha224(const char *s, size_t len, char **ret) {
#else return string_hashsum(s, len, "SHA224", ret);
typedef struct X509 X509;
typedef struct EVP_PKEY EVP_PKEY;
typedef struct EVP_MD EVP_MD;
typedef struct UI_METHOD UI_METHOD;
typedef struct ASN1_TYPE ASN1_TYPE;
typedef struct ASN1_STRING ASN1_STRING;
static inline void* X509_free(X509 *p) {
assert(p == NULL);
return NULL;
} }
static inline int string_hashsum_sha256(const char *s, size_t len, char **ret) {
static inline void* EVP_PKEY_free(EVP_PKEY *p) { return string_hashsum(s, len, "SHA256", ret);
assert(p == NULL);
return NULL;
} }
static inline int string_hashsum(const char *s, size_t len, const char *md_algorithm, char **ret) {
return -EOPNOTSUPP;
}
#endif
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(X509*, X509_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_PKEY*, EVP_PKEY_free, NULL);
struct OpenSSLAskPasswordUI {
AskPasswordRequest request;
UI_METHOD *method;
};
OpenSSLAskPasswordUI* openssl_ask_password_ui_free(OpenSSLAskPasswordUI *ui);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OpenSSLAskPasswordUI*, openssl_ask_password_ui_free, NULL);
int x509_fingerprint(X509 *cert, uint8_t buffer[static X509_FINGERPRINT_SIZE]); int x509_fingerprint(X509 *cert, uint8_t buffer[static X509_FINGERPRINT_SIZE]);
int openssl_load_x509_certificate( int openssl_load_x509_certificate(
@ -224,10 +195,13 @@ int openssl_load_private_key(
EVP_PKEY **ret_private_key, EVP_PKEY **ret_private_key,
OpenSSLAskPasswordUI **ret_user_interface); OpenSSLAskPasswordUI **ret_user_interface);
static inline int string_hashsum_sha224(const char *s, size_t len, char **ret) { struct OpenSSLAskPasswordUI {
return string_hashsum(s, len, "SHA224", ret); AskPasswordRequest request;
} #ifndef OPENSSL_NO_UI_CONSOLE
UI_METHOD *method;
#endif
};
static inline int string_hashsum_sha256(const char *s, size_t len, char **ret) { OpenSSLAskPasswordUI* openssl_ask_password_ui_free(OpenSSLAskPasswordUI *ui);
return string_hashsum(s, len, "SHA256", ret); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OpenSSLAskPasswordUI*, openssl_ask_password_ui_free, NULL);
} #endif

View File

@ -336,13 +336,12 @@ static int hash_file(int fd, EVP_MD_CTX *md_ctx, uint64_t offset, uint64_t size)
static int section_offset_cmp(const IMAGE_SECTION_HEADER *a, const IMAGE_SECTION_HEADER *b) { static int section_offset_cmp(const IMAGE_SECTION_HEADER *a, const IMAGE_SECTION_HEADER *b) {
return CMP(ASSERT_PTR(a)->PointerToRawData, ASSERT_PTR(b)->PointerToRawData); return CMP(ASSERT_PTR(a)->PointerToRawData, ASSERT_PTR(b)->PointerToRawData);
} }
#endif
int pe_hash(int fd, int pe_hash(int fd,
const EVP_MD *md, const EVP_MD *md,
void **ret_hash, void **ret_hash,
size_t *ret_hash_size) { size_t *ret_hash_size) {
#if HAVE_OPENSSL
_cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *mdctx = NULL; _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *mdctx = NULL;
_cleanup_free_ IMAGE_SECTION_HEADER *sections = NULL; _cleanup_free_ IMAGE_SECTION_HEADER *sections = NULL;
_cleanup_free_ IMAGE_DOS_HEADER *dos_header = NULL; _cleanup_free_ IMAGE_DOS_HEADER *dos_header = NULL;
@ -449,9 +448,6 @@ int pe_hash(int fd,
*ret_hash_size = hash_size; *ret_hash_size = hash_size;
return 0; return 0;
#else
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL is not supported, cannot calculate PE hash.");
#endif
} }
int pe_checksum(int fd, uint32_t *ret) { int pe_checksum(int fd, uint32_t *ret) {
@ -503,7 +499,6 @@ int pe_checksum(int fd, uint32_t *ret) {
return 0; return 0;
} }
#if HAVE_OPENSSL
typedef void* SectionHashArray[_UNIFIED_SECTION_MAX]; typedef void* SectionHashArray[_UNIFIED_SECTION_MAX];
static void section_hash_array_done(SectionHashArray *array) { static void section_hash_array_done(SectionHashArray *array) {
@ -512,13 +507,12 @@ static void section_hash_array_done(SectionHashArray *array) {
for (size_t i = 0; i < _UNIFIED_SECTION_MAX; i++) for (size_t i = 0; i < _UNIFIED_SECTION_MAX; i++)
free((*array)[i]); free((*array)[i]);
} }
#endif
int uki_hash(int fd, int uki_hash(int fd,
const EVP_MD *md, const EVP_MD *md,
void* ret_hashes[static _UNIFIED_SECTION_MAX], void* ret_hashes[static _UNIFIED_SECTION_MAX],
size_t *ret_hash_size) { size_t *ret_hash_size) {
#if HAVE_OPENSSL
_cleanup_(section_hash_array_done) SectionHashArray hashes = {}; _cleanup_(section_hash_array_done) SectionHashArray hashes = {};
_cleanup_free_ IMAGE_SECTION_HEADER *sections = NULL; _cleanup_free_ IMAGE_SECTION_HEADER *sections = NULL;
_cleanup_free_ IMAGE_DOS_HEADER *dos_header = NULL; _cleanup_free_ IMAGE_DOS_HEADER *dos_header = NULL;
@ -605,7 +599,5 @@ int uki_hash(int fd,
*ret_hash_size = (unsigned) hsz; *ret_hash_size = (unsigned) hsz;
return 0; return 0;
#else
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL is not supported, cannot calculate UKI hash.");
#endif
} }
#endif

View File

@ -151,8 +151,11 @@ bool pe_is_addon(const PeHeader *pe_header, const IMAGE_SECTION_HEADER *sections
bool pe_is_native(const PeHeader *pe_header); bool pe_is_native(const PeHeader *pe_header);
int pe_is_native_fd(int fd); int pe_is_native_fd(int fd);
#if HAVE_OPENSSL
int pe_hash(int fd, const EVP_MD *md, void **ret_hash, size_t *ret_hash_size); int pe_hash(int fd, const EVP_MD *md, void **ret_hash, size_t *ret_hash_size);
/* This does not depend on OpenSSL, but is currently only used by sbsign which requires OpenSSL. */
int pe_checksum(int fd, uint32_t *ret); int pe_checksum(int fd, uint32_t *ret);
int uki_hash(int fd, const EVP_MD *md, void *ret_hashes[static _UNIFIED_SECTION_MAX], size_t *ret_hash_size); int uki_hash(int fd, const EVP_MD *md, void *ret_hashes[static _UNIFIED_SECTION_MAX], size_t *ret_hash_size);
#endif

View File

@ -114,7 +114,7 @@ SD_VARLINK_DEFINE_INTERFACE(
&vl_error_ConflictingDiskLabelPresent, &vl_error_ConflictingDiskLabelPresent,
SD_VARLINK_SYMBOL_COMMENT("The target disk has insufficient free space to fit all requested partitions. (But the disk would fit, if emptied.)"), SD_VARLINK_SYMBOL_COMMENT("The target disk has insufficient free space to fit all requested partitions. (But the disk would fit, if emptied.)"),
&vl_error_InsufficientFreeSpace, &vl_error_InsufficientFreeSpace,
SD_VARLINK_SYMBOL_COMMENT("The target disk is too small to fit the installation. (Regardless if emtied or not.)"), SD_VARLINK_SYMBOL_COMMENT("The target disk is too small to fit the installation. (Regardless if emptied or not.)"),
&vl_error_DiskTooSmall, &vl_error_DiskTooSmall,
SD_VARLINK_SYMBOL_COMMENT("Return a list of candidate block devices, i.e. that support partition scanning and other requirements for successful operation."), SD_VARLINK_SYMBOL_COMMENT("Return a list of candidate block devices, i.e. that support partition scanning and other requirements for successful operation."),