mirror of
https://github.com/systemd/systemd
synced 2026-03-24 15:55:00 +01:00
Compare commits
18 Commits
2f363b407f
...
ba037640bf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba037640bf | ||
|
|
059b3b466d | ||
|
|
6ceb76bfcf | ||
|
|
736fc4b479 | ||
|
|
b6c86e145a | ||
|
|
795e066d22 | ||
|
|
54492552a1 | ||
|
|
9e104bd3aa | ||
|
|
56a53a5974 | ||
|
|
2791af18e4 | ||
|
|
0bd766553c | ||
|
|
bd6d8eec5e | ||
|
|
9d10457a3e | ||
|
|
4be5c2870f | ||
|
|
d0cb79b8a9 | ||
|
|
bc3f700a4a | ||
|
|
7f9e3c5919 | ||
|
|
79e6bfb1e6 |
@ -39,7 +39,7 @@ jobs:
|
||||
trigger: pull_request
|
||||
fmf_url: https://src.fedoraproject.org/rpms/systemd
|
||||
# This is automatically updated by tools/fetch-distro.py --update fedora
|
||||
fmf_ref: 12f95f807fef5075a8842dd107f83b4c41d5ac26
|
||||
fmf_ref: cac8dde28a1298bbc2bee40e9ab3b9308392f691
|
||||
targets:
|
||||
- fedora-rawhide-x86_64
|
||||
# testing-farm in the Fedora repository is explicitly configured to use testing-farm bare metal runners as
|
||||
|
||||
@ -4901,7 +4901,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
has no main PID. The control PID is the PID of the current start/stop/reload process running and is 0
|
||||
if no such process is currently running. That means that <varname>ExecMainPID</varname> and
|
||||
<varname>MainPID</varname> differ in the way that the latter immediately reflects whether a main
|
||||
process is currently running while the latter possible contains information collected from the last run
|
||||
process is currently running while the former possibly contains information collected from the last run
|
||||
even if the process is no longer around.</para>
|
||||
|
||||
<para><varname>StatusText</varname>, <varname>StatusErrno</varname>, <varname>StatusBusError</varname>,
|
||||
|
||||
@ -26,11 +26,11 @@
|
||||
<para>In systemd, whenever a disk image (DDI) implementing the <ulink
|
||||
url="https://uapi-group.org/specifications/specs/discoverable_partitions_specification">UAPI.2
|
||||
Discoverable Partitions Specification</ulink> is activated, a policy may be specified controlling which
|
||||
partitions to mount and what kind of cryptographic protection to require. Such a disk image dissection
|
||||
policy is a string that contains per-partition-type rules, separated by colons
|
||||
(<literal>:</literal>). The individual rules consist of a partition identifier, an equal sign
|
||||
(<literal>=</literal>), and one or more flags which may be set per partition. If multiple flags are
|
||||
specified per partition they are separated by a plus sign (<literal>+</literal>).</para>
|
||||
partitions to mount and what kind of cryptographic protection to require, and which type of filesystem
|
||||
is allowed. Such a disk image dissection policy is a string that contains per-partition-type rules,
|
||||
separated by colons (<literal>:</literal>). The individual rules consist of a partition identifier, an
|
||||
equal sign (<literal>=</literal>), and one or more flags which may be set per partition. If multiple
|
||||
flags are specified per partition they are separated by a plus sign (<literal>+</literal>).</para>
|
||||
|
||||
<para>The partition identifiers currently defined are: <option>root</option>, <option>usr</option>,
|
||||
<option>home</option>, <option>srv</option>, <option>esp</option>, <option>xbootldr</option>,
|
||||
@ -71,6 +71,46 @@
|
||||
image.</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>The following filesystem policy flags are defined that dictate which filesystem types are allowed
|
||||
for which partition:</para>
|
||||
|
||||
<table>
|
||||
<title>
|
||||
Filesystems types supported by the policy
|
||||
</title>
|
||||
|
||||
<tgroup cols='1'>
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Filesystem flag</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><literal>btrfs</literal></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>erofs</literal></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>ext4</literal></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>f2fs</literal></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>squashfs</literal></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>vfat</literal></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>xfs</literal></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<para>By setting a combination of the flags above, alternatives can be declared. For example the
|
||||
combination <literal>unused+absent</literal> means: the partition may exist (in which case it shall not
|
||||
be used) or may be absent. The combination of
|
||||
@ -175,6 +215,11 @@
|
||||
does not have to be, and ignores swap partitions, and uses all other partitions if they are available, possibly with encryption.</para>
|
||||
|
||||
<programlisting>root=unprotected+encrypted:swap=absent+unused:=unprotected+encrypted+absent</programlisting>
|
||||
|
||||
<para>The following image policy string dictates a single root partition that can only be erofs or squashfs,
|
||||
and ignores swap partitions, and uses all other partitions if they are available, possibly with encryption.</para>
|
||||
|
||||
<programlisting>root=erofs+squashfs:swap=absent+unused:=unprotected+encrypted+absent</programlisting>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
||||
17
meson.build
17
meson.build
@ -2517,6 +2517,7 @@ foreach dict : executables
|
||||
|
||||
is_test = name.startswith('test-')
|
||||
is_fuzz = name.startswith('fuzz-')
|
||||
is_standalone = name.endswith('.standalone')
|
||||
|
||||
build = true
|
||||
foreach cond : dict.get('conditions', [])
|
||||
@ -2529,17 +2530,13 @@ foreach dict : executables
|
||||
continue
|
||||
endif
|
||||
|
||||
if name.endswith('.standalone') and not have_standalone_binaries
|
||||
continue
|
||||
endif
|
||||
|
||||
exe_sources = dict.get('sources', []) + dict.get('extract', [])
|
||||
|
||||
kwargs = {}
|
||||
foreach key, val : dict
|
||||
if key in ['name', 'dbus', 'public', 'conditions', 'type', 'suite',
|
||||
'timeout', 'parallel', 'objects', 'sources', 'extract',
|
||||
'include_directories']
|
||||
'include_directories', 'build_by_default']
|
||||
continue
|
||||
endif
|
||||
|
||||
@ -2551,7 +2548,7 @@ foreach dict : executables
|
||||
endforeach
|
||||
|
||||
include_directories = dict['include_directories']
|
||||
if not is_test
|
||||
if not is_test and exe_sources.length() > 0
|
||||
include_directories += fs.parent(exe_sources[0])
|
||||
endif
|
||||
|
||||
@ -2579,17 +2576,21 @@ foreach dict : executables
|
||||
endforeach
|
||||
endif
|
||||
|
||||
build_by_default = dict.get('build_by_default',
|
||||
have_standalone_binaries or not is_standalone)
|
||||
|
||||
exe = executable(
|
||||
name,
|
||||
sources : exe_sources,
|
||||
kwargs : kwargs,
|
||||
implicit_include_directories : false,
|
||||
include_directories : include_directories,
|
||||
build_by_default: build_by_default,
|
||||
)
|
||||
|
||||
executables_by_name += { name : exe }
|
||||
|
||||
if not name.endswith('.standalone')
|
||||
if not is_standalone
|
||||
sources += exe_sources
|
||||
endif
|
||||
|
||||
@ -2602,7 +2603,7 @@ foreach dict : executables
|
||||
}
|
||||
endif
|
||||
|
||||
if dict.get('build_by_default', true)
|
||||
if build_by_default
|
||||
if dict.get('dbus', false)
|
||||
dbus_programs += exe
|
||||
endif
|
||||
|
||||
@ -9,5 +9,5 @@ Profiles=!hyperscale
|
||||
Environment=
|
||||
GIT_URL=https://src.fedoraproject.org/rpms/systemd.git
|
||||
GIT_BRANCH=rawhide
|
||||
GIT_COMMIT=12f95f807fef5075a8842dd107f83b4c41d5ac26
|
||||
GIT_COMMIT=cac8dde28a1298bbc2bee40e9ab3b9308392f691
|
||||
PKG_SUBDIR=fedora
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
#include "string-util.h"
|
||||
|
||||
static int table_add_designator_line(Table *table, PartitionDesignator d, PartitionPolicyFlags f) {
|
||||
_cleanup_free_ char *q = NULL;
|
||||
_cleanup_free_ char *q = NULL, *t = NULL;
|
||||
const char *color;
|
||||
int r;
|
||||
|
||||
@ -19,6 +19,9 @@ static int table_add_designator_line(Table *table, PartitionDesignator d, Partit
|
||||
if (partition_policy_flags_to_string(f & _PARTITION_POLICY_USE_MASK, /* simplify= */ true, &q) < 0)
|
||||
return log_oom();
|
||||
|
||||
if (partition_policy_flags_to_string(f & _PARTITION_POLICY_FSTYPE_MASK, /* simplify= */ true, &t) < 0)
|
||||
return log_oom();
|
||||
|
||||
color = (f & _PARTITION_POLICY_USE_MASK) == PARTITION_POLICY_IGNORE ? ansi_grey() :
|
||||
((f & (PARTITION_POLICY_UNPROTECTED|PARTITION_POLICY_ENCRYPTED|PARTITION_POLICY_ENCRYPTEDWITHINTEGRITY|PARTITION_POLICY_VERITY|PARTITION_POLICY_SIGNED|PARTITION_POLICY_ABSENT)) ==
|
||||
(PARTITION_POLICY_UNPROTECTED|PARTITION_POLICY_ENCRYPTED|PARTITION_POLICY_ENCRYPTEDWITHINTEGRITY|PARTITION_POLICY_VERITY|PARTITION_POLICY_SIGNED|PARTITION_POLICY_ABSENT)) ? ansi_highlight_yellow() :
|
||||
@ -72,6 +75,11 @@ static int table_add_designator_line(Table *table, PartitionDesignator d, Partit
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
r = table_add_many(table,
|
||||
TABLE_STRING, isempty(t) ? "-" : t);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -128,7 +136,7 @@ int verb_image_policy(int argc, char *argv[], void *userdata) {
|
||||
ansi_highlight(), as_string_simplified, ansi_normal(),
|
||||
ansi_grey(), as_string, ansi_normal());
|
||||
|
||||
table = table_new("partition", "mode", "read-only", "growfs");
|
||||
table = table_new("partition", "mode", "read-only", "growfs", "fstype");
|
||||
if (!table)
|
||||
return log_oom();
|
||||
|
||||
|
||||
@ -4350,7 +4350,7 @@ static bool manager_journal_is_running(Manager *m) {
|
||||
u = manager_get_unit(m, SPECIAL_JOURNALD_SERVICE);
|
||||
if (!u)
|
||||
return false;
|
||||
if (!IN_SET(SERVICE(u)->state, SERVICE_RELOAD, SERVICE_RUNNING))
|
||||
if (!UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u)) || SERVICE(u)->state == SERVICE_EXITED)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
@ -2550,6 +2550,22 @@ int setup_namespace(const NamespaceParameters *p, char **reterr_path) {
|
||||
|
||||
SET_FLAG(dissect_image_flags, DISSECT_IMAGE_NO_PARTITION_TABLE, p->verity && p->verity->data_path);
|
||||
|
||||
/* First check if we have a verity device already open and with a fstype pinned by policy. If it
|
||||
* cannot be found, then fallback to the slow path (full dissect). */
|
||||
r = dissected_image_new_from_existing_verity(
|
||||
p->root_image,
|
||||
p->verity,
|
||||
p->root_image_options,
|
||||
p->root_image_policy,
|
||||
/* image_filter= */ NULL,
|
||||
p->runtime_scope,
|
||||
dissect_image_flags,
|
||||
&dissected_image);
|
||||
if (r < 0 && !ERRNO_IS_NEG_DEVICE_ABSENT(r) && r != -ENOPKG)
|
||||
return r;
|
||||
if (r >= 0)
|
||||
log_debug("Reusing pre-existing verity-protected root image %s", p->root_image);
|
||||
else {
|
||||
if (p->runtime_scope == RUNTIME_SCOPE_SYSTEM) {
|
||||
/* In system mode we mount directly */
|
||||
|
||||
@ -2589,7 +2605,7 @@ int setup_namespace(const NamespaceParameters *p, char **reterr_path) {
|
||||
|
||||
r = dissected_image_decrypt(
|
||||
dissected_image,
|
||||
NULL,
|
||||
/* passphrase= */ NULL,
|
||||
p->verity,
|
||||
p->root_image_policy,
|
||||
dissect_image_flags);
|
||||
@ -2611,6 +2627,7 @@ int setup_namespace(const NamespaceParameters *p, char **reterr_path) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p->root_directory)
|
||||
root = p->root_directory;
|
||||
|
||||
@ -4,40 +4,6 @@ if conf.get('ENABLE_IMPORTD') != 1
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
systemd_importd_sources = files(
|
||||
'importd.c',
|
||||
)
|
||||
systemd_importd_extract_sources = files(
|
||||
'import-common.c',
|
||||
'import-compress.c',
|
||||
'qcow2-util.c',
|
||||
)
|
||||
|
||||
systemd_pull_sources = files(
|
||||
'pull.c',
|
||||
'pull-raw.c',
|
||||
'pull-tar.c',
|
||||
'pull-job.c',
|
||||
'pull-common.c',
|
||||
'curl-util.c',
|
||||
)
|
||||
|
||||
systemd_import_sources = files(
|
||||
'import.c',
|
||||
'import-raw.c',
|
||||
'import-tar.c',
|
||||
)
|
||||
|
||||
systemd_import_fs_sources = files(
|
||||
'import-fs.c',
|
||||
)
|
||||
|
||||
systemd_export_sources = files(
|
||||
'export.c',
|
||||
'export-tar.c',
|
||||
'export-raw.c',
|
||||
)
|
||||
|
||||
common_deps = [
|
||||
libbzip2,
|
||||
libcurl,
|
||||
@ -50,14 +16,27 @@ executables += [
|
||||
libexec_template + {
|
||||
'name' : 'systemd-importd',
|
||||
'dbus' : true,
|
||||
'sources' : systemd_importd_sources,
|
||||
'extract' : systemd_importd_extract_sources,
|
||||
'sources' : files(
|
||||
'importd.c',
|
||||
),
|
||||
'extract' : files(
|
||||
'import-common.c',
|
||||
'import-compress.c',
|
||||
'qcow2-util.c',
|
||||
),
|
||||
'dependencies' : [common_deps, threads],
|
||||
},
|
||||
libexec_template + {
|
||||
'name' : 'systemd-pull',
|
||||
'public' : true,
|
||||
'sources' : systemd_pull_sources,
|
||||
'sources' : files(
|
||||
'pull.c',
|
||||
'pull-raw.c',
|
||||
'pull-tar.c',
|
||||
'pull-job.c',
|
||||
'pull-common.c',
|
||||
'curl-util.c',
|
||||
),
|
||||
'objects' : ['systemd-importd'],
|
||||
'dependencies' : common_deps + [
|
||||
libopenssl,
|
||||
@ -66,21 +45,31 @@ executables += [
|
||||
libexec_template + {
|
||||
'name' : 'systemd-import',
|
||||
'public' : true,
|
||||
'sources' : systemd_import_sources,
|
||||
'sources' : files(
|
||||
'import.c',
|
||||
'import-raw.c',
|
||||
'import-tar.c',
|
||||
),
|
||||
'objects' : ['systemd-importd'],
|
||||
'dependencies' : common_deps,
|
||||
},
|
||||
libexec_template + {
|
||||
'name' : 'systemd-import-fs',
|
||||
'public' : true,
|
||||
'sources' : systemd_import_fs_sources,
|
||||
'sources' : files(
|
||||
'import-fs.c',
|
||||
),
|
||||
'objects' : ['systemd-importd'],
|
||||
'dependencies' : common_deps,
|
||||
},
|
||||
libexec_template + {
|
||||
'name' : 'systemd-export',
|
||||
'public' : true,
|
||||
'sources' : systemd_export_sources,
|
||||
'sources' : files(
|
||||
'export.c',
|
||||
'export-tar.c',
|
||||
'export-raw.c',
|
||||
),
|
||||
'objects' : ['systemd-importd'],
|
||||
'dependencies' : common_deps,
|
||||
},
|
||||
|
||||
@ -8,7 +8,7 @@ executables += [
|
||||
executable_template + {
|
||||
'name' : 'systemd-repart',
|
||||
'public' : true,
|
||||
'sources' : files('repart.c'),
|
||||
'extract' : files('repart.c'),
|
||||
'link_with' : [
|
||||
libshared,
|
||||
libshared_fdisk,
|
||||
@ -24,8 +24,7 @@ executables += [
|
||||
executable_template + {
|
||||
'name' : 'systemd-repart.standalone',
|
||||
'public' : true,
|
||||
'sources' : files('repart.c'),
|
||||
'c_args' : '-DSTANDALONE',
|
||||
'objects' : ['systemd-repart'],
|
||||
'link_with' : [
|
||||
libc_wrapper_static,
|
||||
libbasic_static,
|
||||
|
||||
@ -843,12 +843,15 @@ static int open_partition(
|
||||
int r;
|
||||
|
||||
assert(node);
|
||||
assert(loop);
|
||||
assert(loop || !is_partition);
|
||||
|
||||
fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
if (!loop)
|
||||
return TAKE_FD(fd);
|
||||
|
||||
/* Check if the block device is a child of (or equivalent to) the originally provided one. */
|
||||
r = block_device_new_from_fd(fd, is_partition ? BLOCK_DEVICE_LOOKUP_WHOLE_DISK : 0, &dev);
|
||||
if (r < 0)
|
||||
@ -911,6 +914,85 @@ static bool image_filter_test(const ImageFilter *filter, PartitionDesignator d,
|
||||
return fnmatch(filter->pattern[d], strempty(label), FNM_NOESCAPE) == 0;
|
||||
}
|
||||
|
||||
static int dissect_image_from_unpartitioned(
|
||||
const char *devname,
|
||||
uint64_t diskseq,
|
||||
const sd_id128_t *uuid,
|
||||
bool encrypted,
|
||||
const VeritySettings *verity,
|
||||
const MountOptions *mount_options,
|
||||
const ImagePolicy *policy,
|
||||
const ImageFilter *filter,
|
||||
int *mount_node_fd, /* taken over on success */
|
||||
char **fstype, /* taken over on success */
|
||||
DissectedImage *m,
|
||||
DissectImageFlags flags,
|
||||
PartitionPolicyFlags found_flags) {
|
||||
|
||||
_cleanup_free_ char *n = NULL, *o = NULL;
|
||||
const char *options = NULL;
|
||||
int r;
|
||||
|
||||
assert(devname);
|
||||
assert(m);
|
||||
assert(fstype);
|
||||
|
||||
if (!image_filter_test(filter, PARTITION_ROOT, /* label= */ NULL)) /* do a filter check with an empty partition label */
|
||||
return -ECOMM;
|
||||
|
||||
r = image_policy_may_use(policy, PARTITION_ROOT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) /* policy says ignore this, so we ignore it */
|
||||
return -ENOPKG;
|
||||
|
||||
r = image_policy_check_protection(policy, PARTITION_ROOT, found_flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = image_policy_check_partition_flags(policy, PARTITION_ROOT, 0); /* we have no gpt partition flags, hence check against all bits off */
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = make_partition_devname(devname, diskseq, /* nr= */ -1, flags, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
m->single_file_system = true;
|
||||
m->encrypted = encrypted;
|
||||
|
||||
m->has_verity = verity && verity->data_path;
|
||||
m->verity_ready = verity_settings_data_covers(verity, PARTITION_ROOT);
|
||||
|
||||
m->has_verity_sig = false; /* signature not embedded, must be specified */
|
||||
m->verity_sig_ready = m->verity_ready && iovec_is_set(&verity->root_hash);
|
||||
|
||||
if (uuid)
|
||||
m->image_uuid = *uuid;
|
||||
|
||||
options = mount_options_from_designator(mount_options, PARTITION_ROOT);
|
||||
if (options) {
|
||||
o = strdup(options);
|
||||
if (!o)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
m->partitions[PARTITION_ROOT] = (DissectedPartition) {
|
||||
.found = true,
|
||||
.rw = !m->verity_ready && !fstype_is_ro(*fstype),
|
||||
.partno = -1,
|
||||
.architecture = _ARCHITECTURE_INVALID,
|
||||
.fstype = TAKE_PTR(*fstype),
|
||||
.node = TAKE_PTR(n),
|
||||
.mount_options = TAKE_PTR(o),
|
||||
.mount_node_fd = mount_node_fd ? TAKE_FD(*mount_node_fd) : -EBADF,
|
||||
.size = UINT64_MAX,
|
||||
.fsmount_fd = -EBADF,
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dissect_image(
|
||||
DissectedImage *m,
|
||||
int fd,
|
||||
@ -1030,38 +1112,41 @@ static int dissect_image(
|
||||
if ((!(flags & DISSECT_IMAGE_GPT_ONLY) &&
|
||||
(flags & DISSECT_IMAGE_GENERIC_ROOT)) ||
|
||||
(flags & DISSECT_IMAGE_NO_PARTITION_TABLE)) {
|
||||
_cleanup_free_ char *root_fstype_string = NULL;
|
||||
const char *usage = NULL;
|
||||
bool encrypted;
|
||||
|
||||
r = partition_policy_determine_fstype(policy, PARTITION_ROOT, &encrypted, &root_fstype_string);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* If flags permit this, also allow using non-partitioned single-filesystem images */
|
||||
|
||||
if (root_fstype_string)
|
||||
usage = encrypted ? "crypto" : "filesystem";
|
||||
else
|
||||
(void) sym_blkid_probe_lookup_value(b, "USAGE", &usage, NULL);
|
||||
if (STRPTR_IN_SET(usage, "filesystem", "crypto")) {
|
||||
_cleanup_free_ char *t = NULL, *n = NULL, *o = NULL;
|
||||
const char *fstype = NULL, *options = NULL;
|
||||
_cleanup_free_ char *t = NULL;
|
||||
const char *fstype = NULL;
|
||||
_cleanup_close_ int mount_node_fd = -EBADF;
|
||||
sd_id128_t uuid = SD_ID128_NULL;
|
||||
PartitionPolicyFlags found_flags;
|
||||
bool encrypted;
|
||||
|
||||
/* OK, we have found a file system, that's our root partition then. */
|
||||
|
||||
if (!image_filter_test(filter, PARTITION_ROOT, /* label= */ NULL)) /* do a filter check with an empty partition label */
|
||||
return -ECOMM;
|
||||
|
||||
r = image_policy_may_use(policy, PARTITION_ROOT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) /* policy says ignore this, so we ignore it */
|
||||
return -ENOPKG;
|
||||
|
||||
if (!root_fstype_string) {
|
||||
(void) sym_blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
|
||||
|
||||
/* blkid will return FAT's serial number as UUID, hence it is quite possible that
|
||||
* parsing this will fail. We'll ignore the ID, since it's just too short to be
|
||||
* useful as true identifier. */
|
||||
(void) blkid_probe_lookup_value_id128(b, "UUID", &uuid);
|
||||
} else
|
||||
/* The policy fstype flags translate to the literal fstype name of each filesystem. */
|
||||
fstype = root_fstype_string;
|
||||
|
||||
encrypted = streq_ptr(fstype, "crypto_LUKS");
|
||||
encrypted = encrypted || streq_ptr(fstype, "crypto_LUKS");
|
||||
|
||||
if (verity_settings_data_covers(verity, PARTITION_ROOT))
|
||||
found_flags = iovec_is_set(&verity->root_hash_sig) ? PARTITION_POLICY_SIGNED : PARTITION_POLICY_VERITY;
|
||||
@ -1074,14 +1159,6 @@ static int dissect_image(
|
||||
} else
|
||||
found_flags = PARTITION_POLICY_UNPROTECTED;
|
||||
|
||||
r = image_policy_check_protection(policy, PARTITION_ROOT, found_flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = image_policy_check_partition_flags(policy, PARTITION_ROOT, 0); /* we have no gpt partition flags, hence check against all bits off */
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (FLAGS_SET(flags, DISSECT_IMAGE_PIN_PARTITION_DEVICES)) {
|
||||
mount_node_fd = open_partition(devname, /* is_partition= */ false, m->loop);
|
||||
if (mount_node_fd < 0)
|
||||
@ -1094,43 +1171,20 @@ static int dissect_image(
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
r = make_partition_devname(devname, diskseq, -1, flags, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
m->single_file_system = true;
|
||||
m->encrypted = encrypted;
|
||||
|
||||
m->has_verity = verity && verity->data_path;
|
||||
m->verity_ready = verity_settings_data_covers(verity, PARTITION_ROOT);
|
||||
|
||||
m->has_verity_sig = false; /* signature not embedded, must be specified */
|
||||
m->verity_sig_ready = m->verity_ready && iovec_is_set(&verity->root_hash);
|
||||
|
||||
m->image_uuid = uuid;
|
||||
|
||||
options = mount_options_from_designator(mount_options, PARTITION_ROOT);
|
||||
if (options) {
|
||||
o = strdup(options);
|
||||
if (!o)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
m->partitions[PARTITION_ROOT] = (DissectedPartition) {
|
||||
.found = true,
|
||||
.rw = !m->verity_ready && !fstype_is_ro(fstype),
|
||||
.partno = -1,
|
||||
.architecture = _ARCHITECTURE_INVALID,
|
||||
.fstype = TAKE_PTR(t),
|
||||
.node = TAKE_PTR(n),
|
||||
.mount_options = TAKE_PTR(o),
|
||||
.mount_node_fd = TAKE_FD(mount_node_fd),
|
||||
.offset = 0,
|
||||
.size = UINT64_MAX,
|
||||
.fsmount_fd = -EBADF,
|
||||
};
|
||||
|
||||
return 0;
|
||||
return dissect_image_from_unpartitioned(
|
||||
devname,
|
||||
diskseq,
|
||||
&uuid,
|
||||
encrypted,
|
||||
verity,
|
||||
mount_options,
|
||||
policy,
|
||||
filter,
|
||||
&mount_node_fd,
|
||||
&t,
|
||||
m,
|
||||
flags,
|
||||
found_flags);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1555,10 +1609,15 @@ static int dissect_image(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Local override via env var or designator type wins */
|
||||
if (fstype) {
|
||||
t = strdup(fstype);
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
r = partition_policy_determine_fstype(policy, type.designator, /* ret_encrypted= */ NULL, &t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (label) {
|
||||
@ -1896,6 +1955,97 @@ static int dissect_image(
|
||||
}
|
||||
#endif
|
||||
|
||||
int dissected_image_new_from_existing_verity(
|
||||
const char *src,
|
||||
const VeritySettings *verity,
|
||||
const MountOptions *options,
|
||||
const ImagePolicy *image_policy,
|
||||
const ImageFilter *image_filter,
|
||||
RuntimeScope runtime_scope,
|
||||
DissectImageFlags dissect_image_flags,
|
||||
DissectedImage **ret) {
|
||||
|
||||
/* Look for an already set up dm-verity device with a single filesystem, according to our naming
|
||||
* scheme and image policy, and if it is pinned by filesystem type set up the image directly. */
|
||||
|
||||
#if HAVE_BLKID
|
||||
_cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL;
|
||||
_cleanup_free_ char *node = NULL, *root_hash_encoded = NULL, *root_fstype_string = NULL;
|
||||
_cleanup_close_ int mount_node_fd = -EBADF;
|
||||
PartitionPolicyFlags found_flags;
|
||||
bool encrypted = false;
|
||||
int r;
|
||||
|
||||
assert(!verity || verity->designator < 0 || IN_SET(verity->designator, PARTITION_ROOT, PARTITION_USR));
|
||||
assert(!verity || iovec_is_valid(&verity->root_hash));
|
||||
assert(!verity || iovec_is_valid(&verity->root_hash_sig));
|
||||
assert(!verity || iovec_is_set(&verity->root_hash) || !iovec_is_set(&verity->root_hash_sig));
|
||||
assert(ret);
|
||||
|
||||
/* Shortcut: this deals only with verity images and requires a policy, and only for system services */
|
||||
if (runtime_scope != RUNTIME_SCOPE_SYSTEM ||
|
||||
!FLAGS_SET(dissect_image_flags, DISSECT_IMAGE_VERITY_SHARE) ||
|
||||
!image_policy ||
|
||||
!verity ||
|
||||
!verity->data_path ||
|
||||
(verity->designator >= 0 && verity->designator != PARTITION_ROOT) ||
|
||||
!iovec_is_set(&verity->root_hash))
|
||||
return -ENOPKG;
|
||||
|
||||
/* The policy fstype flags translate to the literal fstype name of each filesystem.
|
||||
* Input must be a single filesystem image, if the policy specifies more than one, we need to dissect */
|
||||
r = partition_policy_determine_fstype(image_policy, PARTITION_ROOT, &encrypted, &root_fstype_string);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!root_fstype_string)
|
||||
return -ENOPKG;
|
||||
|
||||
if (verity_settings_data_covers(verity, PARTITION_ROOT))
|
||||
found_flags = iovec_is_set(&verity->root_hash_sig) ? PARTITION_POLICY_SIGNED : PARTITION_POLICY_VERITY;
|
||||
else
|
||||
found_flags = encrypted ? PARTITION_POLICY_ENCRYPTED : PARTITION_POLICY_UNPROTECTED;
|
||||
|
||||
root_hash_encoded = hexmem(verity->root_hash.iov_base, verity->root_hash.iov_len);
|
||||
if (!root_hash_encoded)
|
||||
return -ENOMEM;
|
||||
|
||||
node = strjoin("/dev/mapper/", root_hash_encoded, "-verity");
|
||||
if (!node)
|
||||
return -ENOMEM;
|
||||
|
||||
r = dissected_image_new(src, &dissected_image);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
mount_node_fd = open_partition(node, /* is_partition= */ false, /* loop= */ NULL);
|
||||
if (mount_node_fd < 0)
|
||||
return mount_node_fd;
|
||||
|
||||
r = dissect_image_from_unpartitioned(
|
||||
node,
|
||||
/* diskseq= */ 0,
|
||||
/* uuid= */ NULL,
|
||||
encrypted,
|
||||
verity,
|
||||
options,
|
||||
image_policy,
|
||||
image_filter,
|
||||
&mount_node_fd,
|
||||
&root_fstype_string,
|
||||
dissected_image,
|
||||
dissect_image_flags,
|
||||
found_flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(dissected_image);
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
int dissect_image_file(
|
||||
const char *path,
|
||||
const VeritySettings *verity,
|
||||
@ -4636,6 +4786,22 @@ int verity_dissect_and_mount(
|
||||
DISSECT_IMAGE_ALLOW_USERSPACE_VERITY |
|
||||
DISSECT_IMAGE_VERITY_SHARE;
|
||||
|
||||
/* First check if we have a verity device already open and with a fstype pinned by policy. If it
|
||||
* cannot be found, then fallback to the slow path (full dissect). */
|
||||
r = dissected_image_new_from_existing_verity(
|
||||
src_fd >= 0 ? FORMAT_PROC_FD_PATH(src_fd) : src,
|
||||
verity,
|
||||
options,
|
||||
image_policy,
|
||||
image_filter,
|
||||
runtime_scope,
|
||||
dissect_image_flags,
|
||||
&dissected_image);
|
||||
if (r < 0 && !ERRNO_IS_NEG_DEVICE_ABSENT(r) && r != -ENOPKG)
|
||||
return r;
|
||||
if (r >= 0)
|
||||
log_debug("Reusing pre-existing verity-protected image %s", src_fd >= 0 ? FORMAT_PROC_FD_PATH(src_fd) : src);
|
||||
else {
|
||||
if (runtime_scope == RUNTIME_SCOPE_SYSTEM) {
|
||||
/* Note that we don't use loop_device_make here, as the FD is most likely O_PATH which would not be
|
||||
* accepted by LOOP_CONFIGURE, so just let loop_device_make_by_path reopen it as a regular FD. */
|
||||
@ -4701,6 +4867,7 @@ int verity_dissect_and_mount(
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (dest) {
|
||||
r = mkdir_p_label(dest, 0755);
|
||||
|
||||
@ -165,6 +165,7 @@ int dissect_image_file(const char *path, const VeritySettings *verity, const Mou
|
||||
int dissect_image_file_and_warn(const char *path, const VeritySettings *verity, const MountOptions *mount_options, const ImagePolicy *image_policy, const ImageFilter *filter, DissectImageFlags flags, DissectedImage **ret);
|
||||
int dissect_loop_device(LoopDevice *loop, const VeritySettings *verity, const MountOptions *mount_options, const ImagePolicy *image_policy, const ImageFilter *image_filter, DissectImageFlags flags, DissectedImage **ret);
|
||||
int dissect_loop_device_and_warn(LoopDevice *loop, const VeritySettings *verity, const MountOptions *mount_options, const ImagePolicy *image_policy, const ImageFilter *image_filter, DissectImageFlags flags, DissectedImage **ret);
|
||||
int dissected_image_new_from_existing_verity(const char *src, const VeritySettings *verity, const MountOptions *options, const ImagePolicy *image_policy, const ImageFilter *image_filter, RuntimeScope runtime_scope, DissectImageFlags dissect_image_flags, DissectedImage **ret);
|
||||
|
||||
void dissected_image_close(DissectedImage *m);
|
||||
DissectedImage* dissected_image_unref(DissectedImage *m);
|
||||
|
||||
@ -207,6 +207,20 @@ static PartitionPolicyFlags policy_flag_from_string_one(const char *s) {
|
||||
return PARTITION_POLICY_GROWFS_ON;
|
||||
if (streq(s, "growfs-off"))
|
||||
return PARTITION_POLICY_GROWFS_OFF;
|
||||
if (streq(s, "btrfs"))
|
||||
return PARTITION_POLICY_BTRFS;
|
||||
if (streq(s, "erofs"))
|
||||
return PARTITION_POLICY_EROFS;
|
||||
if (streq(s, "ext4"))
|
||||
return PARTITION_POLICY_EXT4;
|
||||
if (streq(s, "f2fs"))
|
||||
return PARTITION_POLICY_F2FS;
|
||||
if (streq(s, "squashfs"))
|
||||
return PARTITION_POLICY_SQUASHFS;
|
||||
if (streq(s, "vfat"))
|
||||
return PARTITION_POLICY_VFAT;
|
||||
if (streq(s, "xfs"))
|
||||
return PARTITION_POLICY_XFS;
|
||||
|
||||
return _PARTITION_POLICY_FLAGS_INVALID;
|
||||
}
|
||||
@ -389,7 +403,7 @@ int image_policy_from_string(const char *s, bool graceful, ImagePolicy **ret) {
|
||||
|
||||
int partition_policy_flags_to_string(PartitionPolicyFlags flags, bool simplify, char **ret) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
const char *l[CONST_LOG2U(_PARTITION_POLICY_MASK + 1) + 1]; /* one string per known flag at most */
|
||||
const char *l[CONST_LOG2U(_PARTITION_POLICY_MASK + _PARTITION_POLICY_FSTYPE_MASK + 1) + 1]; /* one string per known flag at most */
|
||||
size_t m = 0;
|
||||
|
||||
assert(ret);
|
||||
@ -449,6 +463,23 @@ int partition_policy_flags_to_string(PartitionPolicyFlags flags, bool simplify,
|
||||
l[m++] = "growfs-on";
|
||||
}
|
||||
|
||||
/* These flags must translate to the literal fstype name of each filesystem, as accepted by
|
||||
* `mount -t`. */
|
||||
if (flags & PARTITION_POLICY_BTRFS)
|
||||
l[m++] = "btrfs";
|
||||
if (flags & PARTITION_POLICY_EROFS)
|
||||
l[m++] = "erofs";
|
||||
if (flags & PARTITION_POLICY_EXT4)
|
||||
l[m++] = "ext4";
|
||||
if (flags & PARTITION_POLICY_F2FS)
|
||||
l[m++] = "f2fs";
|
||||
if (flags & PARTITION_POLICY_SQUASHFS)
|
||||
l[m++] = "squashfs";
|
||||
if (flags & PARTITION_POLICY_VFAT)
|
||||
l[m++] = "vfat";
|
||||
if (flags & PARTITION_POLICY_XFS)
|
||||
l[m++] = "xfs";
|
||||
|
||||
if (m == 0)
|
||||
buf = strdup("-");
|
||||
else {
|
||||
@ -461,9 +492,46 @@ int partition_policy_flags_to_string(PartitionPolicyFlags flags, bool simplify,
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = TAKE_PTR(buf);
|
||||
return (int) m;
|
||||
}
|
||||
|
||||
int partition_policy_determine_fstype(
|
||||
const ImagePolicy *policy,
|
||||
PartitionDesignator designator,
|
||||
bool *ret_encrypted,
|
||||
char **ret_fstype) {
|
||||
|
||||
_cleanup_free_ char *fstype = NULL;
|
||||
PartitionPolicyFlags policy_flags;
|
||||
int r;
|
||||
|
||||
assert(designator >= 0 && designator < _PARTITION_DESIGNATOR_MAX);
|
||||
assert(ret_fstype);
|
||||
|
||||
policy_flags = image_policy_get_exhaustively(policy, designator);
|
||||
if (policy_flags < 0)
|
||||
return policy_flags;
|
||||
|
||||
/* The policy fstype flags translate to the literal fstype name of each filesystem. */
|
||||
r = partition_policy_flags_to_string(policy_flags & _PARTITION_POLICY_FSTYPE_MASK, /* simplify= */ true, &fstype);
|
||||
if (r < 0)
|
||||
return r;
|
||||
/* Input must be a single filesystem type, if the policy specifies more than one, return NULL */
|
||||
if (r != 1) {
|
||||
if (ret_encrypted)
|
||||
*ret_encrypted = false;
|
||||
*ret_fstype = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the policy also allows unprotected or verity filesystems, don't set the 'encrypted' flag */
|
||||
if (ret_encrypted)
|
||||
*ret_encrypted = (policy_flags & (PARTITION_POLICY_ENCRYPTED|PARTITION_POLICY_ENCRYPTEDWITHINTEGRITY)) &&
|
||||
!(policy_flags & (PARTITION_POLICY_VERITY|PARTITION_POLICY_SIGNED|PARTITION_POLICY_UNPROTECTED));
|
||||
*ret_fstype = TAKE_PTR(fstype);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool partition_policy_flags_extended_equal(PartitionPolicyFlags a, PartitionPolicyFlags b) {
|
||||
return partition_policy_flags_extend(a) == partition_policy_flags_extend(b);
|
||||
}
|
||||
|
||||
@ -36,6 +36,19 @@ typedef enum PartitionPolicyFlags {
|
||||
|
||||
_PARTITION_POLICY_MASK = _PARTITION_POLICY_USE_MASK|_PARTITION_POLICY_READ_ONLY_MASK|_PARTITION_POLICY_GROWFS_MASK,
|
||||
|
||||
/* Policies can impose filesystem type requirements on images. These flags translate to the literal
|
||||
* fstype name of each filesystem. */
|
||||
PARTITION_POLICY_BTRFS = 1 << 11,
|
||||
PARTITION_POLICY_EROFS = 1 << 12,
|
||||
PARTITION_POLICY_EXT4 = 1 << 13,
|
||||
PARTITION_POLICY_F2FS = 1 << 14,
|
||||
PARTITION_POLICY_SQUASHFS = 1 << 15,
|
||||
PARTITION_POLICY_VFAT = 1 << 16,
|
||||
PARTITION_POLICY_XFS = 1 << 17,
|
||||
_PARTITION_POLICY_FSTYPE_MASK = PARTITION_POLICY_BTRFS|PARTITION_POLICY_EROFS|PARTITION_POLICY_EXT4|
|
||||
PARTITION_POLICY_F2FS|PARTITION_POLICY_SQUASHFS|
|
||||
PARTITION_POLICY_VFAT|PARTITION_POLICY_XFS,
|
||||
|
||||
_PARTITION_POLICY_FLAGS_INVALID = -EINVAL,
|
||||
_PARTITION_POLICY_FLAGS_ERRNO_MAX = -ERRNO_MAX, /* Ensure the whole errno range fits into this enum */
|
||||
} PartitionPolicyFlags;
|
||||
@ -84,6 +97,8 @@ PartitionPolicyFlags partition_policy_flags_reduce(PartitionPolicyFlags flags);
|
||||
PartitionPolicyFlags partition_policy_flags_from_string(const char *s, bool graceful);
|
||||
int partition_policy_flags_to_string(PartitionPolicyFlags flags, bool simplify, char **ret);
|
||||
|
||||
int partition_policy_determine_fstype(const ImagePolicy *policy, PartitionDesignator designator, bool *ret_encrypted, char **ret_fstype);
|
||||
|
||||
int image_policy_from_string(const char *s, bool graceful, ImagePolicy **ret);
|
||||
int image_policy_to_string(const ImagePolicy *policy, bool simplify, char **ret);
|
||||
|
||||
|
||||
@ -1715,9 +1715,11 @@ int add_matches_for_unit_full(sd_journal *j, MatchUnitFlag flags, const char *un
|
||||
/* Look for messages from the service itself */
|
||||
(r = journal_add_match_pair(j, "_SYSTEMD_UNIT", unit)) ||
|
||||
|
||||
/* Look for messages from PID 1 about this service */
|
||||
/* Look for messages from PID 1 about this service. Note that the actual match is placed
|
||||
* on init.scope rather than _PID=1, as we want to match messages from helper processes
|
||||
* forked off by init too. */
|
||||
(r = sd_journal_add_disjunction(j)) ||
|
||||
(r = sd_journal_add_match(j, "_PID=1", SIZE_MAX)) ||
|
||||
(r = sd_journal_add_match(j, "_SYSTEMD_CGROUP=/init.scope", SIZE_MAX)) ||
|
||||
(r = journal_add_match_pair(j, "UNIT", unit)) ||
|
||||
|
||||
/* Look for messages from authorized daemons about this service */
|
||||
|
||||
@ -455,6 +455,18 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifdef __COVERITY__
|
||||
# define ASSERT_NOT_STREQ(expr1, expr2) __coverity_check__(!streq_ptr((expr1), (expr2)))
|
||||
#else
|
||||
# define ASSERT_NOT_STREQ(expr1, expr2) \
|
||||
({ \
|
||||
const char *_expr1 = (expr1), *_expr2 = (expr2); \
|
||||
if (streq_ptr(_expr1, _expr2)) \
|
||||
log_test_failed("Expected \"%s != %s\", got \"%s == %s\"", \
|
||||
#expr1, #expr2, strnull(_expr1), strnull(_expr2)); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifdef __COVERITY__
|
||||
# define ASSERT_STRNEQ(expr1, expr2, n) __coverity_check__(strneq_ptr((expr1), (expr2), (n)))
|
||||
#else
|
||||
|
||||
@ -4,13 +4,7 @@ if conf.get('HAVE_LIBMOUNT') != 1
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
systemd_shutdown_sources = files(
|
||||
'detach-dm.c',
|
||||
'detach-loopback.c',
|
||||
'detach-md.c',
|
||||
'shutdown.c',
|
||||
)
|
||||
systemd_shutdown_extract_sources = files(
|
||||
shutdown_detach_sources = files(
|
||||
'detach-swap.c',
|
||||
'umount.c',
|
||||
)
|
||||
@ -18,14 +12,17 @@ systemd_shutdown_extract_sources = files(
|
||||
executables += [
|
||||
libexec_template + {
|
||||
'name' : 'systemd-shutdown',
|
||||
'sources' : systemd_shutdown_sources,
|
||||
'extract' : systemd_shutdown_extract_sources,
|
||||
'extract' : files(
|
||||
'detach-dm.c',
|
||||
'detach-loopback.c',
|
||||
'detach-md.c',
|
||||
'shutdown.c',
|
||||
) + shutdown_detach_sources,
|
||||
'dependencies' : libmount_cflags,
|
||||
},
|
||||
libexec_template + {
|
||||
'name' : 'systemd-shutdown.standalone',
|
||||
'sources' : systemd_shutdown_sources + systemd_shutdown_extract_sources,
|
||||
'c_args' : '-DSTANDALONE',
|
||||
'objects' : ['systemd-shutdown'],
|
||||
'link_with' : [
|
||||
libc_wrapper_static,
|
||||
libbasic_static,
|
||||
@ -35,8 +32,8 @@ executables += [
|
||||
'dependencies' : libmount_cflags,
|
||||
},
|
||||
test_template + {
|
||||
'sources' : files('test-umount.c'),
|
||||
'objects' : ['systemd-shutdown'],
|
||||
'sources' : files('test-umount.c') +
|
||||
shutdown_detach_sources,
|
||||
'dependencies' : libmount_cflags,
|
||||
},
|
||||
]
|
||||
|
||||
@ -8,14 +8,13 @@ executables += [
|
||||
executable_template + {
|
||||
'name' : 'systemd-sysusers',
|
||||
'public' : true,
|
||||
'sources' : files('sysusers.c'),
|
||||
'extract' : files('sysusers.c'),
|
||||
'dependencies' : libaudit_cflags,
|
||||
},
|
||||
executable_template + {
|
||||
'name' : 'systemd-sysusers.standalone',
|
||||
'public' : true,
|
||||
'sources' : files('sysusers.c'),
|
||||
'c_args' : '-DSTANDALONE',
|
||||
'objects' : ['systemd-sysusers'],
|
||||
'link_with' : [
|
||||
libc_wrapper_static,
|
||||
libbasic_static,
|
||||
|
||||
@ -2151,15 +2151,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_IMAGE:
|
||||
#ifdef STANDALONE
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"This systemd-sysusers version is compiled without support for --image=.");
|
||||
#else
|
||||
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ARG_IMAGE_POLICY:
|
||||
r = parse_image_policy_argument(optarg, &arg_image_policy);
|
||||
@ -2283,10 +2278,8 @@ static int read_credential_lines(Context *c) {
|
||||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
#ifndef STANDALONE
|
||||
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
|
||||
_cleanup_(umount_and_freep) char *mounted_dir = NULL;
|
||||
#endif
|
||||
_cleanup_close_ int lock = -EBADF;
|
||||
_cleanup_(context_done) Context c = {
|
||||
.audit_fd = -EBADF,
|
||||
@ -2314,7 +2307,6 @@ static int run(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
#ifndef STANDALONE
|
||||
if (arg_image) {
|
||||
assert(!arg_root);
|
||||
|
||||
@ -2338,9 +2330,6 @@ static int run(int argc, char *argv[]) {
|
||||
if (!arg_root)
|
||||
return log_oom();
|
||||
}
|
||||
#else
|
||||
assert(!arg_image);
|
||||
#endif
|
||||
|
||||
/* Prepare to emit audit events, but only if we're operating on the host system. */
|
||||
if (!arg_root)
|
||||
|
||||
@ -92,6 +92,10 @@ TEST_RET(test_image_policy_to_string) {
|
||||
test_policy_string("swap=open:root=signed+read-only-on+growfs-off:=absent");
|
||||
test_policy_string("=-");
|
||||
test_policy_string("=");
|
||||
test_policy_string("root=ext4+squashfs+verity");
|
||||
test_policy_string("usr=encrypted+erofs+read-only-off");
|
||||
test_policy_string("home=unprotected+btrfs");
|
||||
test_policy_string("=vfat+erofs");
|
||||
|
||||
test_policy_equiv("", image_policy_equiv_ignore);
|
||||
test_policy_equiv("-", image_policy_equiv_ignore);
|
||||
@ -197,4 +201,68 @@ TEST(image_policy_ignore_designators) {
|
||||
test_policy_ignore_designators_one("~", ((const PartitionDesignator[]) { PARTITION_VAR, PARTITION_ESP, PARTITION_VAR }), 2, "var=ignore:esp=ignore:=absent");
|
||||
}
|
||||
|
||||
TEST(partition_policy_determine_fstype) {
|
||||
_cleanup_(image_policy_freep) ImagePolicy *p = NULL;
|
||||
_cleanup_free_ char *fstype = NULL;
|
||||
bool encrypted;
|
||||
int r;
|
||||
|
||||
ASSERT_OK(image_policy_from_string("root=ext4+encrypted", /* graceful= */ false, &p));
|
||||
r = partition_policy_determine_fstype(p, PARTITION_ROOT, &encrypted, &fstype);
|
||||
ASSERT_GT(r, 0);
|
||||
ASSERT_STREQ(fstype, "ext4");
|
||||
ASSERT_TRUE(encrypted);
|
||||
|
||||
fstype = mfree(fstype);
|
||||
p = image_policy_free(p);
|
||||
ASSERT_OK(image_policy_from_string("usr=verity+erofs", /* graceful= */ false, &p));
|
||||
r = partition_policy_determine_fstype(p, PARTITION_USR, &encrypted, &fstype);
|
||||
ASSERT_GT(r, 0);
|
||||
ASSERT_STREQ(fstype, "erofs");
|
||||
ASSERT_FALSE(encrypted);
|
||||
fstype = mfree(fstype);
|
||||
r = partition_policy_determine_fstype(p, PARTITION_ROOT, &encrypted, &fstype);
|
||||
ASSERT_EQ(r, 0);
|
||||
ASSERT_FALSE(fstype);
|
||||
ASSERT_FALSE(encrypted);
|
||||
|
||||
fstype = mfree(fstype);
|
||||
p = image_policy_free(p);
|
||||
ASSERT_OK(image_policy_from_string("root=ext4+erofs", /* graceful= */ false, &p));
|
||||
r = partition_policy_determine_fstype(p, PARTITION_ROOT, &encrypted, &fstype);
|
||||
ASSERT_EQ(r, 0);
|
||||
ASSERT_FALSE(fstype);
|
||||
ASSERT_FALSE(encrypted);
|
||||
|
||||
fstype = mfree(fstype);
|
||||
p = image_policy_free(p);
|
||||
ASSERT_OK(image_policy_from_string("root=encrypted", /* graceful= */ false, &p));
|
||||
r = partition_policy_determine_fstype(p, PARTITION_ROOT, &encrypted, &fstype);
|
||||
ASSERT_EQ(r, 0);
|
||||
ASSERT_FALSE(fstype);
|
||||
ASSERT_FALSE(encrypted);
|
||||
|
||||
fstype = mfree(fstype);
|
||||
p = image_policy_free(p);
|
||||
ASSERT_OK(image_policy_from_string("", /* graceful= */ false, &p));
|
||||
r = partition_policy_determine_fstype(p, PARTITION_ROOT, &encrypted, &fstype);
|
||||
ASSERT_EQ(r, 0);
|
||||
ASSERT_FALSE(fstype);
|
||||
ASSERT_FALSE(encrypted);
|
||||
|
||||
fstype = mfree(fstype);
|
||||
r = partition_policy_determine_fstype(/* policy= */ NULL, PARTITION_ROOT, &encrypted, &fstype);
|
||||
ASSERT_EQ(r, 0);
|
||||
ASSERT_FALSE(fstype);
|
||||
ASSERT_FALSE(encrypted);
|
||||
|
||||
fstype = mfree(fstype);
|
||||
p = image_policy_free(p);
|
||||
ASSERT_OK(image_policy_from_string("root=encrypted+signed+btrfs", /* graceful= */ false, &p));
|
||||
r = partition_policy_determine_fstype(p, PARTITION_ROOT, &encrypted, &fstype);
|
||||
ASSERT_GT(r, 0);
|
||||
ASSERT_STREQ(fstype, "btrfs");
|
||||
ASSERT_FALSE(encrypted);
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_INFO);
|
||||
|
||||
@ -91,6 +91,11 @@ TEST(ASSERT) {
|
||||
ASSERT_SIGNAL(ASSERT_STREQ(null, "bar"), SIGABRT);
|
||||
ASSERT_SIGNAL(ASSERT_STREQ("foo", "bar"), SIGABRT);
|
||||
|
||||
ASSERT_NOT_STREQ("foo", "bar");
|
||||
ASSERT_NOT_STREQ("foo", NULL);
|
||||
ASSERT_SIGNAL(ASSERT_NOT_STREQ("foo", "foo"), SIGABRT);
|
||||
ASSERT_SIGNAL(ASSERT_NOT_STREQ(NULL, NULL), SIGABRT);
|
||||
|
||||
ASSERT_EQ(0, 0);
|
||||
ASSERT_EQ(-1, -1);
|
||||
ASSERT_SIGNAL(ASSERT_EQ(255, -1), SIGABRT);
|
||||
|
||||
@ -17,7 +17,7 @@ static void test_uid_to_name_one(uid_t uid, const char *name) {
|
||||
|
||||
log_info("/* %s("UID_FMT", \"%s\") */", __func__, uid, name);
|
||||
|
||||
assert_se(t = uid_to_name(uid));
|
||||
t = ASSERT_NOT_NULL(uid_to_name(uid));
|
||||
if (!synthesize_nobody() && streq(name, NOBODY_USER_NAME)) {
|
||||
log_info("(skipping detailed tests because nobody is not synthesized)");
|
||||
return;
|
||||
@ -37,7 +37,7 @@ static void test_gid_to_name_one(gid_t gid, const char *name) {
|
||||
|
||||
log_info("/* %s("GID_FMT", \"%s\") */", __func__, gid, name);
|
||||
|
||||
assert_se(t = gid_to_name(gid));
|
||||
t = ASSERT_NOT_NULL(gid_to_name(gid));
|
||||
if (!synthesize_nobody() && streq(name, NOBODY_GROUP_NAME)) {
|
||||
log_info("(skipping detailed tests because nobody is not synthesized)");
|
||||
return;
|
||||
@ -53,290 +53,238 @@ TEST(gid_to_name) {
|
||||
}
|
||||
|
||||
TEST(parse_uid) {
|
||||
int r;
|
||||
uid_t uid;
|
||||
|
||||
r = parse_uid("0", &uid);
|
||||
assert_se(r == 0);
|
||||
assert_se(uid == 0);
|
||||
ASSERT_OK(parse_uid("0", &uid));
|
||||
ASSERT_EQ(uid, 0u);
|
||||
|
||||
r = parse_uid("1", &uid);
|
||||
assert_se(r == 0);
|
||||
assert_se(uid == 1);
|
||||
ASSERT_OK(parse_uid("1", &uid));
|
||||
ASSERT_EQ(uid, 1u);
|
||||
|
||||
r = parse_uid("01", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 1);
|
||||
ASSERT_ERROR(parse_uid("01", &uid), EINVAL);
|
||||
ASSERT_EQ(uid, 1u);
|
||||
ASSERT_ERROR(parse_uid("001", &uid), EINVAL);
|
||||
|
||||
r = parse_uid("001", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 1);
|
||||
ASSERT_OK(parse_uid("100", &uid));
|
||||
ASSERT_EQ(uid, 100u);
|
||||
|
||||
r = parse_uid("100", &uid);
|
||||
assert_se(r == 0);
|
||||
assert_se(uid == 100);
|
||||
|
||||
r = parse_uid("65535", &uid);
|
||||
assert_se(r == -ENXIO);
|
||||
assert_se(uid == 100);
|
||||
|
||||
r = parse_uid("0x1234", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
|
||||
r = parse_uid("0o1234", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
|
||||
r = parse_uid("0b1234", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
|
||||
r = parse_uid("+1234", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
|
||||
r = parse_uid("-1234", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
|
||||
r = parse_uid(" 1234", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
|
||||
r = parse_uid("01234", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
|
||||
r = parse_uid("001234", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
|
||||
r = parse_uid("0001234", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
|
||||
r = parse_uid("-0", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
|
||||
r = parse_uid("+0", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
|
||||
r = parse_uid("00", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
|
||||
r = parse_uid("000", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
|
||||
r = parse_uid("asdsdas", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
ASSERT_ERROR(parse_uid("65535", &uid), ENXIO);
|
||||
ASSERT_ERROR(parse_uid("0x1234", &uid), EINVAL);
|
||||
ASSERT_ERROR(parse_uid("0o1234", &uid), EINVAL);
|
||||
ASSERT_ERROR(parse_uid("0b1234", &uid), EINVAL);
|
||||
ASSERT_ERROR(parse_uid("+1234", &uid), EINVAL);
|
||||
ASSERT_ERROR(parse_uid("-1234", &uid), EINVAL);
|
||||
ASSERT_ERROR(parse_uid(" 1234", &uid), EINVAL);
|
||||
ASSERT_ERROR(parse_uid("01234", &uid), EINVAL);
|
||||
ASSERT_ERROR(parse_uid("001234", &uid), EINVAL);
|
||||
ASSERT_ERROR(parse_uid("0001234", &uid), EINVAL);
|
||||
ASSERT_ERROR(parse_uid("-0", &uid), EINVAL);
|
||||
ASSERT_ERROR(parse_uid("+0", &uid), EINVAL);
|
||||
ASSERT_ERROR(parse_uid("00", &uid), EINVAL);
|
||||
ASSERT_ERROR(parse_uid("000", &uid), EINVAL);
|
||||
ASSERT_ERROR(parse_uid("asdsdas", &uid), EINVAL);
|
||||
}
|
||||
|
||||
TEST(uid_ptr) {
|
||||
ASSERT_NOT_NULL(UID_TO_PTR(0));
|
||||
ASSERT_NOT_NULL(UID_TO_PTR(1000));
|
||||
|
||||
assert_se(PTR_TO_UID(UID_TO_PTR(0)) == 0);
|
||||
assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000);
|
||||
ASSERT_EQ(PTR_TO_UID(UID_TO_PTR(0)), 0u);
|
||||
ASSERT_EQ(PTR_TO_UID(UID_TO_PTR(1000)), 1000u);
|
||||
}
|
||||
|
||||
TEST(valid_user_group_name_relaxed) {
|
||||
assert_se(!valid_user_group_name(NULL, VALID_USER_RELAX));
|
||||
assert_se(!valid_user_group_name("", VALID_USER_RELAX));
|
||||
assert_se(!valid_user_group_name("1", VALID_USER_RELAX));
|
||||
assert_se(!valid_user_group_name("65535", VALID_USER_RELAX));
|
||||
assert_se(!valid_user_group_name("-1", VALID_USER_RELAX));
|
||||
assert_se(!valid_user_group_name("foo\nbar", VALID_USER_RELAX));
|
||||
assert_se(!valid_user_group_name("0123456789012345678901234567890123456789", VALID_USER_RELAX));
|
||||
assert_se(!valid_user_group_name("aaa:bbb", VALID_USER_RELAX|VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name(".aaa:bbb", VALID_USER_RELAX|VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name(".", VALID_USER_RELAX));
|
||||
assert_se(!valid_user_group_name("..", VALID_USER_RELAX));
|
||||
ASSERT_FALSE(valid_user_group_name(NULL, VALID_USER_RELAX));
|
||||
ASSERT_FALSE(valid_user_group_name("", VALID_USER_RELAX));
|
||||
ASSERT_FALSE(valid_user_group_name("1", VALID_USER_RELAX));
|
||||
ASSERT_FALSE(valid_user_group_name("65535", VALID_USER_RELAX));
|
||||
ASSERT_FALSE(valid_user_group_name("-1", VALID_USER_RELAX));
|
||||
ASSERT_FALSE(valid_user_group_name("foo\nbar", VALID_USER_RELAX));
|
||||
ASSERT_FALSE(valid_user_group_name("0123456789012345678901234567890123456789", VALID_USER_RELAX));
|
||||
ASSERT_FALSE(valid_user_group_name("aaa:bbb", VALID_USER_RELAX|VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name(".aaa:bbb", VALID_USER_RELAX|VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name(".", VALID_USER_RELAX));
|
||||
ASSERT_FALSE(valid_user_group_name("..", VALID_USER_RELAX));
|
||||
|
||||
assert_se(valid_user_group_name("root", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("lennart", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("LENNART", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("_kkk", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("kkk-", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("kk-k", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("eff.eff", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("eff.", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("-kkk", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("rööt", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name(".eff", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name(".1", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name(".65535", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name(".-1", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name(".-kkk", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name(".rööt", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("...", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("root", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("lennart", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("LENNART", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("_kkk", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("kkk-", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("kk-k", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("eff.eff", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("eff.", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("-kkk", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("rööt", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name(".eff", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name(".1", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name(".65535", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name(".-1", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name(".-kkk", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name(".rööt", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("...", VALID_USER_RELAX));
|
||||
|
||||
assert_se(valid_user_group_name("some5", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("5some", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("INNER5NUMBER", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("some5", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("5some", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("INNER5NUMBER", VALID_USER_RELAX));
|
||||
|
||||
assert_se(valid_user_group_name("piff.paff@ad.domain.example", VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("Dāvis", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("piff.paff@ad.domain.example", VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("Dāvis", VALID_USER_RELAX));
|
||||
}
|
||||
|
||||
TEST(valid_user_group_name) {
|
||||
assert_se(!valid_user_group_name(NULL, 0));
|
||||
assert_se(!valid_user_group_name("", 0));
|
||||
assert_se(!valid_user_group_name("1", 0));
|
||||
assert_se(!valid_user_group_name("65535", 0));
|
||||
assert_se(!valid_user_group_name("-1", 0));
|
||||
assert_se(!valid_user_group_name("-kkk", 0));
|
||||
assert_se(!valid_user_group_name("rööt", 0));
|
||||
assert_se(!valid_user_group_name(".", 0));
|
||||
assert_se(!valid_user_group_name(".eff", 0));
|
||||
assert_se(!valid_user_group_name("foo\nbar", 0));
|
||||
assert_se(!valid_user_group_name("0123456789012345678901234567890123456789", 0));
|
||||
assert_se(!valid_user_group_name("aaa:bbb", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name(".", 0));
|
||||
assert_se(!valid_user_group_name("..", 0));
|
||||
assert_se(!valid_user_group_name("...", 0));
|
||||
assert_se(!valid_user_group_name(".1", 0));
|
||||
assert_se(!valid_user_group_name(".65535", 0));
|
||||
assert_se(!valid_user_group_name(".-1", 0));
|
||||
assert_se(!valid_user_group_name(".-kkk", 0));
|
||||
assert_se(!valid_user_group_name(".rööt", 0));
|
||||
assert_se(!valid_user_group_name(".aaa:bbb", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name(NULL, 0));
|
||||
ASSERT_FALSE(valid_user_group_name("", 0));
|
||||
ASSERT_FALSE(valid_user_group_name("1", 0));
|
||||
ASSERT_FALSE(valid_user_group_name("65535", 0));
|
||||
ASSERT_FALSE(valid_user_group_name("-1", 0));
|
||||
ASSERT_FALSE(valid_user_group_name("-kkk", 0));
|
||||
ASSERT_FALSE(valid_user_group_name("rööt", 0));
|
||||
ASSERT_FALSE(valid_user_group_name(".", 0));
|
||||
ASSERT_FALSE(valid_user_group_name(".eff", 0));
|
||||
ASSERT_FALSE(valid_user_group_name("foo\nbar", 0));
|
||||
ASSERT_FALSE(valid_user_group_name("0123456789012345678901234567890123456789", 0));
|
||||
ASSERT_FALSE(valid_user_group_name("aaa:bbb", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name(".", 0));
|
||||
ASSERT_FALSE(valid_user_group_name("..", 0));
|
||||
ASSERT_FALSE(valid_user_group_name("...", 0));
|
||||
ASSERT_FALSE(valid_user_group_name(".1", 0));
|
||||
ASSERT_FALSE(valid_user_group_name(".65535", 0));
|
||||
ASSERT_FALSE(valid_user_group_name(".-1", 0));
|
||||
ASSERT_FALSE(valid_user_group_name(".-kkk", 0));
|
||||
ASSERT_FALSE(valid_user_group_name(".rööt", 0));
|
||||
ASSERT_FALSE(valid_user_group_name(".aaa:bbb", VALID_USER_ALLOW_NUMERIC));
|
||||
|
||||
assert_se(valid_user_group_name("root", 0));
|
||||
assert_se(valid_user_group_name("lennart", 0));
|
||||
assert_se(valid_user_group_name("LENNART", 0));
|
||||
assert_se(valid_user_group_name("_kkk", 0));
|
||||
assert_se(valid_user_group_name("kkk-", 0));
|
||||
assert_se(valid_user_group_name("kk-k", 0));
|
||||
assert_se(!valid_user_group_name("eff.eff", 0));
|
||||
assert_se(!valid_user_group_name("eff.", 0));
|
||||
ASSERT_TRUE(valid_user_group_name("root", 0));
|
||||
ASSERT_TRUE(valid_user_group_name("lennart", 0));
|
||||
ASSERT_TRUE(valid_user_group_name("LENNART", 0));
|
||||
ASSERT_TRUE(valid_user_group_name("_kkk", 0));
|
||||
ASSERT_TRUE(valid_user_group_name("kkk-", 0));
|
||||
ASSERT_TRUE(valid_user_group_name("kk-k", 0));
|
||||
ASSERT_FALSE(valid_user_group_name("eff.eff", 0));
|
||||
ASSERT_FALSE(valid_user_group_name("eff.", 0));
|
||||
|
||||
assert_se(valid_user_group_name("some5", 0));
|
||||
assert_se(!valid_user_group_name("5some", 0));
|
||||
assert_se(valid_user_group_name("INNER5NUMBER", 0));
|
||||
ASSERT_TRUE(valid_user_group_name("some5", 0));
|
||||
ASSERT_FALSE(valid_user_group_name("5some", 0));
|
||||
ASSERT_TRUE(valid_user_group_name("INNER5NUMBER", 0));
|
||||
|
||||
assert_se(!valid_user_group_name("piff.paff@ad.domain.example", 0));
|
||||
assert_se(!valid_user_group_name("Dāvis", 0));
|
||||
ASSERT_FALSE(valid_user_group_name("piff.paff@ad.domain.example", 0));
|
||||
ASSERT_FALSE(valid_user_group_name("Dāvis", 0));
|
||||
}
|
||||
|
||||
TEST(valid_user_group_name_or_numeric_relaxed) {
|
||||
assert_se(!valid_user_group_name(NULL, VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(!valid_user_group_name("", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("0", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("1", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("65534", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(!valid_user_group_name("65535", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("65536", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(!valid_user_group_name("-1", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(!valid_user_group_name("foo\nbar", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(!valid_user_group_name("0123456789012345678901234567890123456789", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(!valid_user_group_name("aaa:bbb", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(!valid_user_group_name(".", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(!valid_user_group_name("..", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_FALSE(valid_user_group_name(NULL, VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_FALSE(valid_user_group_name("", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("0", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("1", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("65534", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_FALSE(valid_user_group_name("65535", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("65536", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_FALSE(valid_user_group_name("-1", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_FALSE(valid_user_group_name("foo\nbar", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_FALSE(valid_user_group_name("0123456789012345678901234567890123456789", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_FALSE(valid_user_group_name("aaa:bbb", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_FALSE(valid_user_group_name(".", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_FALSE(valid_user_group_name("..", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
|
||||
assert_se(valid_user_group_name("root", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("lennart", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("LENNART", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("_kkk", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("kkk-", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("kk-k", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("-kkk", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("rööt", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name(".eff", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("eff.eff", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("eff.", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("...", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("root", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("lennart", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("LENNART", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("_kkk", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("kkk-", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("kk-k", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("-kkk", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("rööt", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name(".eff", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("eff.eff", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("eff.", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("...", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
|
||||
assert_se(valid_user_group_name("some5", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("5some", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("INNER5NUMBER", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("some5", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("5some", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("INNER5NUMBER", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
|
||||
assert_se(valid_user_group_name("piff.paff@ad.domain.example", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
assert_se(valid_user_group_name("Dāvis", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("piff.paff@ad.domain.example", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
ASSERT_TRUE(valid_user_group_name("Dāvis", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
}
|
||||
|
||||
TEST(valid_user_group_name_or_numeric) {
|
||||
assert_se(!valid_user_group_name(NULL, VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name("", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(valid_user_group_name("0", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(valid_user_group_name("1", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(valid_user_group_name("65534", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name("65535", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(valid_user_group_name("65536", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name("-1", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name("-kkk", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name("rööt", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name(".", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name("..", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name("...", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name(".eff", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name("eff.eff", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name("eff.", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name("foo\nbar", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name("0123456789012345678901234567890123456789", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name("aaa:bbb", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name(NULL, VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name("", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_TRUE(valid_user_group_name("0", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_TRUE(valid_user_group_name("1", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_TRUE(valid_user_group_name("65534", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name("65535", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_TRUE(valid_user_group_name("65536", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name("-1", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name("-kkk", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name("rööt", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name(".", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name("..", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name("...", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name(".eff", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name("eff.eff", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name("eff.", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name("foo\nbar", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name("0123456789012345678901234567890123456789", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name("aaa:bbb", VALID_USER_ALLOW_NUMERIC));
|
||||
|
||||
assert_se(valid_user_group_name("root", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(valid_user_group_name("lennart", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(valid_user_group_name("LENNART", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(valid_user_group_name("_kkk", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(valid_user_group_name("kkk-", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(valid_user_group_name("kk-k", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_TRUE(valid_user_group_name("root", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_TRUE(valid_user_group_name("lennart", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_TRUE(valid_user_group_name("LENNART", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_TRUE(valid_user_group_name("_kkk", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_TRUE(valid_user_group_name("kkk-", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_TRUE(valid_user_group_name("kk-k", VALID_USER_ALLOW_NUMERIC));
|
||||
|
||||
assert_se(valid_user_group_name("some5", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name("5some", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(valid_user_group_name("INNER5NUMBER", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_TRUE(valid_user_group_name("some5", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name("5some", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_TRUE(valid_user_group_name("INNER5NUMBER", VALID_USER_ALLOW_NUMERIC));
|
||||
|
||||
assert_se(!valid_user_group_name("piff.paff@ad.domain.example", VALID_USER_ALLOW_NUMERIC));
|
||||
assert_se(!valid_user_group_name("Dāvis", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name("piff.paff@ad.domain.example", VALID_USER_ALLOW_NUMERIC));
|
||||
ASSERT_FALSE(valid_user_group_name("Dāvis", VALID_USER_ALLOW_NUMERIC));
|
||||
}
|
||||
|
||||
TEST(valid_gecos) {
|
||||
assert_se(!valid_gecos(NULL));
|
||||
assert_se(valid_gecos(""));
|
||||
assert_se(valid_gecos("test"));
|
||||
assert_se(valid_gecos("Ümläüt"));
|
||||
assert_se(!valid_gecos("In\nvalid"));
|
||||
assert_se(!valid_gecos("In:valid"));
|
||||
ASSERT_FALSE(valid_gecos(NULL));
|
||||
ASSERT_TRUE(valid_gecos(""));
|
||||
ASSERT_TRUE(valid_gecos("test"));
|
||||
ASSERT_TRUE(valid_gecos("Ümläüt"));
|
||||
ASSERT_FALSE(valid_gecos("In\nvalid"));
|
||||
ASSERT_FALSE(valid_gecos("In:valid"));
|
||||
}
|
||||
|
||||
TEST(valid_home) {
|
||||
assert_se(!valid_home(NULL));
|
||||
assert_se(!valid_home(""));
|
||||
assert_se(!valid_home("."));
|
||||
assert_se(!valid_home("/home/.."));
|
||||
assert_se(!valid_home("/home/../"));
|
||||
assert_se(!valid_home("/home\n/foo"));
|
||||
assert_se(!valid_home("./piep"));
|
||||
assert_se(!valid_home("piep"));
|
||||
assert_se(!valid_home("/home/user:lennart"));
|
||||
ASSERT_FALSE(valid_home(NULL));
|
||||
ASSERT_FALSE(valid_home(""));
|
||||
ASSERT_FALSE(valid_home("."));
|
||||
ASSERT_FALSE(valid_home("/home/.."));
|
||||
ASSERT_FALSE(valid_home("/home/../"));
|
||||
ASSERT_FALSE(valid_home("/home\n/foo"));
|
||||
ASSERT_FALSE(valid_home("./piep"));
|
||||
ASSERT_FALSE(valid_home("piep"));
|
||||
ASSERT_FALSE(valid_home("/home/user:lennart"));
|
||||
|
||||
assert_se(valid_home("/"));
|
||||
assert_se(valid_home("/home"));
|
||||
assert_se(valid_home("/home/foo"));
|
||||
assert_se(valid_home("/home/foo/"));
|
||||
ASSERT_TRUE(valid_home("/"));
|
||||
ASSERT_TRUE(valid_home("/home"));
|
||||
ASSERT_TRUE(valid_home("/home/foo"));
|
||||
ASSERT_TRUE(valid_home("/home/foo/"));
|
||||
}
|
||||
|
||||
TEST(valid_shell) {
|
||||
assert_se(!valid_shell(NULL));
|
||||
assert_se(!valid_shell(""));
|
||||
assert_se(!valid_shell("."));
|
||||
assert_se(!valid_shell("/shell/.."));
|
||||
assert_se(!valid_shell("/shell/../"));
|
||||
assert_se(!valid_shell("/shell\n/foo"));
|
||||
assert_se(!valid_shell("./piep"));
|
||||
assert_se(!valid_shell("piep"));
|
||||
assert_se(!valid_shell("/shell/user:lennart"));
|
||||
assert_se(!valid_shell("/"));
|
||||
assert_se(!valid_shell("/bin/sh/"));
|
||||
assert_se(valid_shell("/shell"));
|
||||
assert_se(valid_shell("/shell/foo"));
|
||||
assert_se(valid_shell("/bin/sh"));
|
||||
ASSERT_FALSE(valid_shell(NULL));
|
||||
ASSERT_FALSE(valid_shell(""));
|
||||
ASSERT_FALSE(valid_shell("."));
|
||||
ASSERT_FALSE(valid_shell("/shell/.."));
|
||||
ASSERT_FALSE(valid_shell("/shell/../"));
|
||||
ASSERT_FALSE(valid_shell("/shell\n/foo"));
|
||||
ASSERT_FALSE(valid_shell("./piep"));
|
||||
ASSERT_FALSE(valid_shell("piep"));
|
||||
ASSERT_FALSE(valid_shell("/shell/user:lennart"));
|
||||
ASSERT_FALSE(valid_shell("/"));
|
||||
ASSERT_FALSE(valid_shell("/bin/sh/"));
|
||||
ASSERT_TRUE(valid_shell("/shell"));
|
||||
ASSERT_TRUE(valid_shell("/shell/foo"));
|
||||
ASSERT_TRUE(valid_shell("/bin/sh"));
|
||||
}
|
||||
|
||||
static void test_get_user_creds_one(const char *id, const char *name, uid_t uid, gid_t gid, const char *home, const char *shell) {
|
||||
@ -356,11 +304,11 @@ static void test_get_user_creds_one(const char *id, const char *name, uid_t uid,
|
||||
log_info("(skipping detailed tests because nobody is not synthesized)");
|
||||
return;
|
||||
}
|
||||
assert_se(r == 0);
|
||||
ASSERT_OK(r);
|
||||
ASSERT_STREQ(id, name);
|
||||
assert_se(ruid == uid);
|
||||
assert_se(rgid == gid);
|
||||
assert_se(path_equal(rhome, home));
|
||||
ASSERT_EQ(ruid, uid);
|
||||
ASSERT_EQ(rgid, gid);
|
||||
ASSERT_TRUE(path_equal(rhome, home));
|
||||
}
|
||||
|
||||
TEST(get_user_creds) {
|
||||
@ -382,9 +330,9 @@ static void test_get_group_creds_one(const char *id, const char *name, gid_t gid
|
||||
log_info("(skipping detailed tests because nobody is not synthesized)");
|
||||
return;
|
||||
}
|
||||
assert_se(r == 0);
|
||||
ASSERT_OK(r);
|
||||
ASSERT_STREQ(id, name);
|
||||
assert_se(rgid == gid);
|
||||
ASSERT_EQ(rgid, gid);
|
||||
}
|
||||
|
||||
TEST(get_group_creds) {
|
||||
@ -397,20 +345,20 @@ TEST(get_group_creds) {
|
||||
TEST(make_salt) {
|
||||
_cleanup_free_ char *s, *t;
|
||||
|
||||
assert_se(make_salt(&s) == 0);
|
||||
ASSERT_OK(make_salt(&s));
|
||||
log_info("got %s", s);
|
||||
|
||||
assert_se(make_salt(&t) == 0);
|
||||
ASSERT_OK(make_salt(&t));
|
||||
log_info("got %s", t);
|
||||
|
||||
assert_se(!streq(s, t));
|
||||
ASSERT_NOT_STREQ(s, t);
|
||||
}
|
||||
|
||||
TEST(in_gid) {
|
||||
assert_se(in_gid(getgid()) >= 0);
|
||||
assert_se(in_gid(getegid()) >= 0);
|
||||
assert_se(in_gid(GID_INVALID) < 0);
|
||||
assert_se(in_gid(TTY_GID) == 0); /* The TTY gid is for owning ttys, it would be really really weird if we were in it. */
|
||||
ASSERT_OK(in_gid(getgid()));
|
||||
ASSERT_OK(in_gid(getegid()));
|
||||
ASSERT_FAIL(in_gid(GID_INVALID));
|
||||
ASSERT_OK_ZERO(in_gid(TTY_GID)); /* The TTY gid is for owning ttys, it would be really really weird if we were in it. */
|
||||
}
|
||||
|
||||
TEST(gid_lists_ops) {
|
||||
@ -429,63 +377,76 @@ TEST(gid_lists_ops) {
|
||||
_cleanup_free_ gid_t *res4 = NULL;
|
||||
int nresult;
|
||||
|
||||
nresult = merge_gid_lists(l2, ELEMENTSOF(l2), l3, ELEMENTSOF(l3), &res1);
|
||||
assert_se(nresult >= 0);
|
||||
assert_se(memcmp_nn(res1, nresult, result1, ELEMENTSOF(result1)) == 0);
|
||||
nresult = ASSERT_OK(merge_gid_lists(l2, ELEMENTSOF(l2), l3, ELEMENTSOF(l3), &res1));
|
||||
ASSERT_EQ(memcmp_nn(res1, nresult, result1, ELEMENTSOF(result1)), 0);
|
||||
|
||||
nresult = merge_gid_lists(NULL, 0, l2, ELEMENTSOF(l2), &res2);
|
||||
assert_se(nresult >= 0);
|
||||
assert_se(memcmp_nn(res2, nresult, l2, ELEMENTSOF(l2)) == 0);
|
||||
nresult = ASSERT_OK(merge_gid_lists(NULL, 0, l2, ELEMENTSOF(l2), &res2));
|
||||
ASSERT_EQ(memcmp_nn(res2, nresult, l2, ELEMENTSOF(l2)), 0);
|
||||
|
||||
nresult = merge_gid_lists(l1, ELEMENTSOF(l1), l1, ELEMENTSOF(l1), &res3);
|
||||
assert_se(nresult >= 0);
|
||||
assert_se(memcmp_nn(l1, ELEMENTSOF(l1), res3, nresult) == 0);
|
||||
nresult = ASSERT_OK(merge_gid_lists(l1, ELEMENTSOF(l1), l1, ELEMENTSOF(l1), &res3));
|
||||
ASSERT_EQ(memcmp_nn(l1, ELEMENTSOF(l1), res3, nresult), 0);
|
||||
|
||||
nresult = merge_gid_lists(l1, ELEMENTSOF(l1), l4, ELEMENTSOF(l4), &res4);
|
||||
assert_se(nresult >= 0);
|
||||
assert_se(memcmp_nn(result2, ELEMENTSOF(result2), res4, nresult) == 0);
|
||||
nresult = ASSERT_OK(merge_gid_lists(l1, ELEMENTSOF(l1), l4, ELEMENTSOF(l4), &res4));
|
||||
ASSERT_EQ(memcmp_nn(result2, ELEMENTSOF(result2), res4, nresult), 0);
|
||||
|
||||
ASSERT_OK(nresult = getgroups_alloc(&gids));
|
||||
assert_se(gids || nresult == 0);
|
||||
nresult = ASSERT_OK(getgroups_alloc(&gids));
|
||||
if (nresult > 0)
|
||||
ASSERT_TRUE(gids);
|
||||
}
|
||||
|
||||
TEST(parse_uid_range) {
|
||||
uid_t a = 4711, b = 4711;
|
||||
|
||||
assert_se(parse_uid_range("", &a, &b) == -EINVAL && a == 4711 && b == 4711);
|
||||
assert_se(parse_uid_range(" ", &a, &b) == -EINVAL && a == 4711 && b == 4711);
|
||||
assert_se(parse_uid_range("x", &a, &b) == -EINVAL && a == 4711 && b == 4711);
|
||||
ASSERT_ERROR(parse_uid_range("", &a, &b), EINVAL);
|
||||
ASSERT_ERROR(parse_uid_range(" ", &a, &b), EINVAL);
|
||||
ASSERT_ERROR(parse_uid_range("x", &a, &b), EINVAL);
|
||||
ASSERT_EQ(a, 4711u);
|
||||
ASSERT_EQ(b, 4711u);
|
||||
|
||||
assert_se(parse_uid_range("0", &a, &b) >= 0 && a == 0 && b == 0);
|
||||
assert_se(parse_uid_range("1", &a, &b) >= 0 && a == 1 && b == 1);
|
||||
assert_se(parse_uid_range("2-2", &a, &b) >= 0 && a == 2 && b == 2);
|
||||
assert_se(parse_uid_range("3-3", &a, &b) >= 0 && a == 3 && b == 3);
|
||||
assert_se(parse_uid_range("4-5", &a, &b) >= 0 && a == 4 && b == 5);
|
||||
ASSERT_OK(parse_uid_range("0", &a, &b));
|
||||
ASSERT_EQ(a, 0u);
|
||||
ASSERT_EQ(b, 0u);
|
||||
|
||||
assert_se(parse_uid_range("7-6", &a, &b) == -EINVAL && a == 4 && b == 5);
|
||||
assert_se(parse_uid_range("-1", &a, &b) == -EINVAL && a == 4 && b == 5);
|
||||
assert_se(parse_uid_range("01", &a, &b) == -EINVAL && a == 4 && b == 5);
|
||||
assert_se(parse_uid_range("001", &a, &b) == -EINVAL && a == 4 && b == 5);
|
||||
assert_se(parse_uid_range("+1", &a, &b) == -EINVAL && a == 4 && b == 5);
|
||||
assert_se(parse_uid_range("1--1", &a, &b) == -EINVAL && a == 4 && b == 5);
|
||||
assert_se(parse_uid_range(" 1", &a, &b) == -EINVAL && a == 4 && b == 5);
|
||||
assert_se(parse_uid_range(" 1-2", &a, &b) == -EINVAL && a == 4 && b == 5);
|
||||
assert_se(parse_uid_range("1 -2", &a, &b) == -EINVAL && a == 4 && b == 5);
|
||||
assert_se(parse_uid_range("1- 2", &a, &b) == -EINVAL && a == 4 && b == 5);
|
||||
assert_se(parse_uid_range("1-2 ", &a, &b) == -EINVAL && a == 4 && b == 5);
|
||||
assert_se(parse_uid_range("01-2", &a, &b) == -EINVAL && a == 4 && b == 5);
|
||||
assert_se(parse_uid_range("1-02", &a, &b) == -EINVAL && a == 4 && b == 5);
|
||||
assert_se(parse_uid_range("001-2", &a, &b) == -EINVAL && a == 4 && b == 5);
|
||||
assert_se(parse_uid_range("1-002", &a, &b) == -EINVAL && a == 4 && b == 5);
|
||||
assert_se(parse_uid_range(" 01", &a, &b) == -EINVAL && a == 4 && b == 5);
|
||||
ASSERT_OK(parse_uid_range("1", &a, &b));
|
||||
ASSERT_EQ(a, 1u);
|
||||
ASSERT_EQ(b, 1u);
|
||||
|
||||
ASSERT_OK(parse_uid_range("2-2", &a, &b));
|
||||
ASSERT_EQ(a, 2u);
|
||||
ASSERT_EQ(b, 2u);
|
||||
|
||||
ASSERT_OK(parse_uid_range("3-3", &a, &b));
|
||||
ASSERT_EQ(a, 3u);
|
||||
ASSERT_EQ(b, 3u);
|
||||
|
||||
ASSERT_OK(parse_uid_range("4-5", &a, &b));
|
||||
ASSERT_EQ(a, 4u);
|
||||
ASSERT_EQ(b, 5u);
|
||||
|
||||
ASSERT_ERROR(parse_uid_range("7-6", &a, &b), EINVAL);
|
||||
ASSERT_ERROR(parse_uid_range("-1", &a, &b), EINVAL);
|
||||
ASSERT_ERROR(parse_uid_range("01", &a, &b), EINVAL);
|
||||
ASSERT_ERROR(parse_uid_range("001", &a, &b), EINVAL);
|
||||
ASSERT_ERROR(parse_uid_range("+1", &a, &b), EINVAL);
|
||||
ASSERT_ERROR(parse_uid_range("1--1", &a, &b), EINVAL);
|
||||
ASSERT_ERROR(parse_uid_range(" 1", &a, &b), EINVAL);
|
||||
ASSERT_ERROR(parse_uid_range(" 1-2", &a, &b), EINVAL);
|
||||
ASSERT_ERROR(parse_uid_range("1 -2", &a, &b), EINVAL);
|
||||
ASSERT_ERROR(parse_uid_range("1- 2", &a, &b), EINVAL);
|
||||
ASSERT_ERROR(parse_uid_range("1-2 ", &a, &b), EINVAL);
|
||||
ASSERT_ERROR(parse_uid_range("01-2", &a, &b), EINVAL);
|
||||
ASSERT_ERROR(parse_uid_range("1-02", &a, &b), EINVAL);
|
||||
ASSERT_ERROR(parse_uid_range("001-2", &a, &b), EINVAL);
|
||||
ASSERT_ERROR(parse_uid_range("1-002", &a, &b), EINVAL);
|
||||
ASSERT_ERROR(parse_uid_range(" 01", &a, &b), EINVAL);
|
||||
}
|
||||
|
||||
static void test_mangle_gecos_one(const char *input, const char *expected) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
|
||||
assert_se(p = mangle_gecos(input));
|
||||
p = ASSERT_NOT_NULL(mangle_gecos(input));
|
||||
ASSERT_STREQ(p, expected);
|
||||
assert_se(valid_gecos(p));
|
||||
ASSERT_TRUE(valid_gecos(p));
|
||||
}
|
||||
|
||||
TEST(mangle_gecos) {
|
||||
|
||||
@ -4,26 +4,20 @@ if conf.get('ENABLE_TMPFILES') != 1
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
systemd_tmpfiles_sources = files(
|
||||
'tmpfiles.c',
|
||||
)
|
||||
systemd_tmpfiles_extract_sources = files(
|
||||
'offline-passwd.c',
|
||||
)
|
||||
offline_passwd_c = files('offline-passwd.c')
|
||||
|
||||
executables += [
|
||||
executable_template + {
|
||||
'name' : 'systemd-tmpfiles',
|
||||
'public' : true,
|
||||
'sources' : systemd_tmpfiles_sources,
|
||||
'extract' : systemd_tmpfiles_extract_sources,
|
||||
'extract' : files('tmpfiles.c') +
|
||||
offline_passwd_c,
|
||||
'dependencies' : libacl_cflags,
|
||||
},
|
||||
executable_template + {
|
||||
'name' : 'systemd-tmpfiles.standalone',
|
||||
'public' : true,
|
||||
'sources' : systemd_tmpfiles_sources + systemd_tmpfiles_extract_sources,
|
||||
'c_args' : '-DSTANDALONE',
|
||||
'objects' : ['systemd-tmpfiles'],
|
||||
'link_with' : [
|
||||
libc_wrapper_static,
|
||||
libbasic_static,
|
||||
@ -33,7 +27,7 @@ executables += [
|
||||
'dependencies' : libacl_cflags,
|
||||
},
|
||||
test_template + {
|
||||
'sources' : files('test-offline-passwd.c'),
|
||||
'objects' : ['systemd-tmpfiles'],
|
||||
'sources' : files('test-offline-passwd.c') +
|
||||
offline_passwd_c,
|
||||
},
|
||||
]
|
||||
|
||||
@ -4316,14 +4316,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_IMAGE:
|
||||
#ifdef STANDALONE
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"This systemd-tmpfiles version is compiled without support for --image=.");
|
||||
#else
|
||||
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image);
|
||||
if (r < 0)
|
||||
return r;
|
||||
#endif
|
||||
|
||||
/* Imply -E here since it makes little sense to create files persistently in the /run mountpoint of a disk image */
|
||||
_fallthrough_;
|
||||
|
||||
@ -4560,10 +4556,8 @@ DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(item_array_hash_ops, char, string_
|
||||
ItemArray, item_array_free);
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
#ifndef STANDALONE
|
||||
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
|
||||
_cleanup_(umount_and_freep) char *mounted_dir = NULL;
|
||||
#endif
|
||||
_cleanup_strv_free_ char **config_dirs = NULL;
|
||||
_cleanup_(context_done) Context c = {};
|
||||
bool invalid_config = false;
|
||||
@ -4642,7 +4636,6 @@ static int run(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
#ifndef STANDALONE
|
||||
if (arg_image) {
|
||||
assert(!arg_root);
|
||||
|
||||
@ -4666,9 +4659,6 @@ static int run(int argc, char *argv[]) {
|
||||
if (!arg_root)
|
||||
return log_oom();
|
||||
}
|
||||
#else
|
||||
assert(!arg_image);
|
||||
#endif
|
||||
|
||||
c.items = ordered_hashmap_new(&item_array_hash_ops);
|
||||
c.globs = ordered_hashmap_new(&item_array_hash_ops);
|
||||
|
||||
@ -507,10 +507,54 @@ NONEXISTENT_VDIR="/tmp/$VBASE-nonexistent.v"
|
||||
mkdir "$VDIR" "$EMPTY_VDIR"
|
||||
|
||||
ln -s /tmp/app0.raw "$VDIR/${VBASE}_0.raw"
|
||||
ln -s /tmp/app0.verity "$VDIR/${VBASE}_0.verity"
|
||||
ln -s /tmp/app0.roothash "$VDIR/${VBASE}_0.roothash"
|
||||
ln -s /tmp/app1.raw "$VDIR/${VBASE}_1.raw"
|
||||
|
||||
systemd-run -P -p ExtensionImages="$VDIR -$EMPTY_VDIR -$NONEXISTENT_VDIR" bash -o pipefail -c '/opt/script1.sh | grep ID'
|
||||
|
||||
# Check dissect shortcut for verity images
|
||||
# No verity for the second img (previous test benefits from variations), remove it for the next one
|
||||
rm -f "$VDIR/${VBASE}_1.raw"
|
||||
cat >/run/systemd/system/testservice-50e-vpick.service <<EOF
|
||||
[Service]
|
||||
Type=notify
|
||||
NotifyAccess=all
|
||||
MountAPIVFS=yes
|
||||
TemporaryFileSystem=/run /var/lib
|
||||
StateDirectory=app-vpick
|
||||
RootImage=$MINIMAL_IMAGE.raw
|
||||
RootImagePolicy=root=squashfs
|
||||
ExtensionImages=$VDIR:x-systemd.relax-extension-release-check -$EMPTY_VDIR -$NONEXISTENT_VDIR
|
||||
ExtensionImagePolicy=root=squashfs
|
||||
# Relevant only for sanitizer runs
|
||||
UnsetEnvironment=LD_PRELOAD
|
||||
ExecStartPre=bash -c '/opt/script0.sh | grep ID'
|
||||
ExecStart=sh -c 'echo "READY=1" | socat -t 5 - UNIX-SENDTO:\$\$NOTIFY_SOCKET; sleep infinity'
|
||||
EOF
|
||||
systemctl start testservice-50e-vpick.service
|
||||
systemctl is-active testservice-50e-vpick.service
|
||||
# Ensure the device is preopened for reuse. Note that sd-dissect -M does not work on older
|
||||
# kernels, <something> makes the devices disappear on Ubuntu 24.04/C9S, so set them
|
||||
# up by hand. Don't fail if it's already set up.
|
||||
veritysetup open "$MINIMAL_IMAGE.raw" "$(cat "$MINIMAL_IMAGE.roothash")-verity" "$MINIMAL_IMAGE.verity" --root-hash-file "$MINIMAL_IMAGE.roothash" ||:
|
||||
veritysetup open "$VDIR/${VBASE}_0.raw" "$(cat "$VDIR/${VBASE}_0.roothash")-verity" "$VDIR/${VBASE}_0.verity" --root-hash-file "$VDIR/${VBASE}_0.roothash" ||:
|
||||
mkdir -p /tmp/img /tmp/ext
|
||||
mount -o ro "/dev/mapper/$(cat "$MINIMAL_IMAGE.roothash")-verity" /tmp/img
|
||||
mount -o ro "/dev/mapper/$(cat "$VDIR/${VBASE}_0.roothash")-verity" /tmp/ext
|
||||
journalctl --sync
|
||||
since="$(date '+%H:%M:%S')"
|
||||
systemctl restart testservice-50e-vpick.service
|
||||
systemctl is-active testservice-50e-vpick.service
|
||||
journalctl --sync
|
||||
timeout -v 30 journalctl --since "$since" -n all --follow | grep -m 2 -F 'Reusing pre-existing verity-protected root image'
|
||||
timeout -v 30 journalctl --since "$since" -n all --follow | grep -m 2 -F 'Reusing pre-existing verity-protected image'
|
||||
systemctl stop testservice-50e-vpick.service
|
||||
umount -R /tmp/img
|
||||
umount -R /tmp/ext
|
||||
veritysetup close "$(cat "$MINIMAL_IMAGE.roothash")-verity" ||:
|
||||
veritysetup close "$(cat "$VDIR/${VBASE}_0.roothash")-verity" ||:
|
||||
|
||||
rm -rf "$VDIR" "$EMPTY_VDIR"
|
||||
|
||||
# ExtensionDirectories will set up an overlay
|
||||
@ -787,6 +831,49 @@ rm -f /run/systemd/system/testservice-50k.service
|
||||
systemctl daemon-reload
|
||||
rm -rf "$VDIR" "$VDIR2" /tmp/vpickminimg /tmp/markers/
|
||||
|
||||
# Check dissect shortcut for verity images
|
||||
cat >/run/systemd/system/testservice-50m.service <<EOF
|
||||
[Service]
|
||||
Type=notify
|
||||
NotifyAccess=all
|
||||
TemporaryFileSystem=/run /var/lib
|
||||
StateDirectory=app0
|
||||
RootImage=$MINIMAL_IMAGE.raw
|
||||
RootImagePolicy=root=squashfs
|
||||
ExtensionImages=/tmp/app0.raw /tmp/app1.raw
|
||||
ExtensionImagePolicy=root=squashfs
|
||||
MountImages=/tmp/app0.raw:/var/lib/app
|
||||
MountImagePolicy=root=squashfs
|
||||
# Relevant only for sanitizer runs
|
||||
UnsetEnvironment=LD_PRELOAD
|
||||
ExecStartPre=bash -o pipefail -c '/opt/script0.sh | grep ID'
|
||||
ExecStartPre=bash -o pipefail -c '/opt/script1.sh | grep ID'
|
||||
ExecStartPre=test -e "/dev/mapper/$(</tmp/app0.roothash)-verity"
|
||||
ExecStart=sh -c 'echo "READY=1" | socat -t 5 - UNIX-SENDTO:\$\$NOTIFY_SOCKET; sleep infinity'
|
||||
EOF
|
||||
systemctl start testservice-50m.service
|
||||
systemctl is-active testservice-50m.service
|
||||
# Ensure the device is preopened for reuse. Note that sd-dissect -M does not work on older
|
||||
# kernels, <something> makes the devices disappear on Ubuntu 24.04/C9S, so set them
|
||||
# up by hand. Don't fail if it's already set up.
|
||||
veritysetup open "$MINIMAL_IMAGE.raw" "$(cat "$MINIMAL_IMAGE.roothash")-verity" "$MINIMAL_IMAGE.verity" --root-hash-file "$MINIMAL_IMAGE.roothash" ||:
|
||||
veritysetup open /tmp/app0.raw "$(cat /tmp/app0.roothash)-verity" /tmp/app0.verity --root-hash-file /tmp/app0.roothash ||:
|
||||
mkdir -p /tmp/img /tmp/ext
|
||||
mount -o ro "/dev/mapper/$(cat "$MINIMAL_IMAGE.roothash")-verity" /tmp/img
|
||||
mount -o ro "/dev/mapper/$(cat /tmp/app0.roothash)-verity" /tmp/ext
|
||||
journalctl --sync
|
||||
since="$(date '+%H:%M:%S')"
|
||||
systemctl restart testservice-50m.service
|
||||
systemctl is-active testservice-50m.service
|
||||
journalctl --sync
|
||||
timeout -v 30 journalctl --since "$since" -n all --follow | grep -m 4 -F 'Reusing pre-existing verity-protected root image'
|
||||
timeout -v 30 journalctl --since "$since" -n all --follow | grep -m 8 -F 'Reusing pre-existing verity-protected image'
|
||||
systemctl stop testservice-50m.service
|
||||
umount /tmp/img
|
||||
umount /tmp/ext
|
||||
veritysetup close "$(cat "$MINIMAL_IMAGE.roothash")-verity" ||:
|
||||
veritysetup close "$(cat /tmp/app0.roothash)-verity" ||:
|
||||
|
||||
# Test that an extension consisting of an empty directory under /etc/extensions/ takes precedence
|
||||
mkdir -p /var/lib/extensions/
|
||||
ln -s /tmp/app-nodistro.raw /var/lib/extensions/app-nodistro.raw
|
||||
|
||||
@ -35,7 +35,7 @@ def parse_args():
|
||||
return p.parse_args()
|
||||
|
||||
def read_config(distro: str):
|
||||
cmd = ['mkosi', '--json', '-d', distro, 'summary']
|
||||
cmd = ['mkosi', '--json', '-d', distro, '-f', 'summary']
|
||||
if args.profile:
|
||||
cmd += ['--profile', args.profile]
|
||||
print(f"+ {shlex.join(cmd)}")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user