Compare commits

..

No commits in common. "cc479760b4736082d26ec332f2423a9ab23d59c5" and "2edc4942163fa12b5c5da5427cbe01ad87ff8dc4" have entirely different histories.

28 changed files with 355 additions and 473 deletions

View File

@ -1,7 +1,4 @@
---
# vi: ts=2 sw=2 et:
language: bash
sudo: required
dist: bionic
services:
- docker
@ -12,40 +9,88 @@ env:
- CI_MANAGERS="$TRAVIS_BUILD_DIR/travis-ci/managers"
- CI_TOOLS="$TRAVIS_BUILD_DIR/travis-ci/tools"
- REPO_ROOT="$TRAVIS_BUILD_DIR"
jobs:
- DEBIAN_RELEASE=testing PHASE="RUN_GCC"
- DEBIAN_RELEASE=testing PHASE="RUN_GCC_ASAN_UBSAN"
- DEBIAN_RELEASE=testing PHASE="RUN_CLANG"
- DEBIAN_RELEASE=testing PHASE="RUN_CLANG_ASAN_UBSAN"
stages:
# 'Test' is the default stage (for matrix jobs)
- name: Test
- name: Build & test
if: type != cron
# Run Coverity periodically instead of for each commit/PR
- name: Coverity
if: type = cron
# Matrix job definition - this is run for each combination of env variables
# from the env.jobs array above
jobs:
include:
- stage: Build & test
name: Debian Testing
language: bash
env:
- DEBIAN_RELEASE="testing"
- CONT_NAME="systemd-debian-$DEBIAN_RELEASE"
- DOCKER_EXEC="docker exec -ti $CONT_NAME"
before_install:
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
- docker --version
install:
- $CI_MANAGERS/debian.sh SETUP
script:
- $CI_MANAGERS/debian.sh $PHASE || travis_terminate 1
- $CI_MANAGERS/debian.sh RUN || travis_terminate 1
after_script:
- $CI_MANAGERS/debian.sh CLEANUP
- name: Debian Testing (ASan+UBSan)
language: bash
env:
- DEBIAN_RELEASE="testing"
- CONT_NAME="systemd-debian-$DEBIAN_RELEASE"
- DOCKER_EXEC="docker exec -ti $CONT_NAME"
before_install:
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
- docker --version
install:
- $CI_MANAGERS/debian.sh SETUP
script:
- $CI_MANAGERS/debian.sh RUN_ASAN || travis_terminate 1
after_script:
- $CI_MANAGERS/debian.sh CLEANUP
- name: Debian Testing (clang)
language: bash
env:
- DEBIAN_RELEASE="testing"
- CONT_NAME="systemd-debian-$DEBIAN_RELEASE"
- DOCKER_EXEC="docker exec -ti $CONT_NAME"
before_install:
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
- docker --version
install:
- $CI_MANAGERS/debian.sh SETUP
script:
- $CI_MANAGERS/debian.sh RUN_CLANG || travis-travis_terminate 1
after_script:
- $CI_MANAGERS/debian.sh CLEANUP
- name: Debian Testing (clang ASan+UBSan)
language: bash
env:
- DEBIAN_RELEASE="testing"
- CONT_NAME="systemd-debian-$DEBIAN_RELEASE"
- DOCKER_EXEC="docker exec -ti $CONT_NAME"
before_install:
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
- docker --version
install:
- $CI_MANAGERS/debian.sh SETUP
script:
- $CI_MANAGERS/debian.sh RUN_CLANG_ASAN || travis_terminate 1
after_script:
- $CI_MANAGERS/debian.sh CLEANUP
# Inject another (single) job into the matrix for Coverity
jobs:
include:
- stage: Coverity
language: bash
env:
- FEDORA_RELEASE="latest"
- CONT_NAME="coverity-fedora-$FEDORA_RELEASE"
- DOCKER_EXEC="docker exec -ti $CONT_NAME"
- TOOL_BASE="/var/tmp/coverity-scan-analysis"
- DOCKER_RUN="docker run -v $TOOL_BASE:$TOOL_BASE:rw --env-file .cov-env"
# Coverity env variables

View File

@ -19,8 +19,7 @@
<xsl:template match="citerefentry[not(@project)]">
<a>
<xsl:attribute name="href">
<xsl:value-of select="refentrytitle"/>
<xsl:text>.html#</xsl:text>
<xsl:value-of select="refentrytitle"/><xsl:text>.html#</xsl:text>
<xsl:value-of select="refentrytitle/@target"/>
</xsl:attribute>
<xsl:call-template name="inline.charseq"/>
@ -134,15 +133,6 @@
</a>
</xsl:template>
<xsl:template match="citerefentry[@project='url']">
<a>
<xsl:attribute name="href">
<xsl:value-of select="refentrytitle/@url"/>
</xsl:attribute>
<xsl:call-template name="inline.charseq"/>
</a>
</xsl:template>
<!--
- helper template to do conflict resolution between various headings with the same inferred ID attribute/tag from the headerlink template
- this conflict resolution is necessary to prevent malformed HTML output (multiple ID attributes with the same value)

View File

@ -51,8 +51,7 @@
<para><filename>systemd-makefs</filename> knows very little about specific file
systems and swap devices, and after checking that the block device does not already
contain a file system or other content, it will execute binaries specific to
each filesystem type (<filename>/sbin/mkfs.<replaceable>type</replaceable></filename>
or <filename>/sbin/mkswap</filename>).</para>
each filesystem type (<filename>/sbin/mkfs.<replaceable>type</replaceable></filename>).</para>
<para><filename>systemd-growfs</filename> knows very little about specific file
systems and swap devices, and will instruct the kernel to grow the mounted
@ -62,7 +61,8 @@
number specific to each file system, so only certain types are supported.
Currently:
<citerefentry project='man-pages'><refentrytitle>ext4</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry project='url'><refentrytitle url='https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs(5)'>btrfs</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
btrfs (see
<citerefentry project='man-pages'><refentrytitle>btrfs-man5</refentrytitle><manvolnum>5</manvolnum></citerefentry>),
<citerefentry project='man-pages'><refentrytitle>xfs</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<!-- yes, that's what the man page is called. -->
and dm-crypt partitions (see

View File

@ -145,43 +145,6 @@
<xi:include href="system-only.xml" xpointer="singular"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>RootHash=</varname></term>
<listitem><para>Takes a data integrity (dm-verity) root hash specified in hexadecimal, or the path to a file
containing a root hash in ASCII hexadecimal format. This option enables data integrity checks using dm-verity,
if the used image contains the appropriate integrity data (see above) or if <varname>RootVerity=</varname> is used.
The specified hash must match the root hash of integrity data, and is usually at least 256 bits (and hence 64
formatted hexadecimal characters) long (in case of SHA256 for example). If this option is not specified, but
the image file carries the <literal>user.verity.roothash</literal> extended file attribute (see <citerefentry
project='man-pages'><refentrytitle>xattr</refentrytitle><manvolnum>7</manvolnum></citerefentry>), then the root
hash is read from it, also as formatted hexadecimal characters. If the extended file attribute is not found (or
is not supported by the underlying file system), but a file with the <filename>.roothash</filename> suffix is
found next to the image file, bearing otherwise the same name (except if the image has the
<filename>.raw</filename> suffix, in which case the root hash file must not have it in its name), the root hash
is read from it and automatically used, also as formatted hexadecimal characters.</para>
<xi:include href="system-only.xml" xpointer="singular"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>RootVerity=</varname></term>
<listitem><para>Takes the path to a data integrity (dm-verity) file. This option enables data integrity checks
using dm-verity, if <varname>RootImage=</varname> is used and a root-hash is passed and if the used image itself
does not contains the integrity data. The integrity data must be matched by the root hash. If this option is not
specified, but a file with the <filename>.verity</filename> suffix is found next to the image file, bearing otherwise
the same name (except if the image has the <filename>.raw</filename> suffix, in which case the verity data file must
not have it in its name), the verity data is read from it and automatically used.</para>
<para>This option is supported only for disk images that contain a single file system, without an enveloping partition
table. Images that contain a GPT partition table should instead include both root file system and matching Verity
data in the same image, implementing the
[Discoverable Partition Specification](https://systemd.io/DISCOVERABLE_PARTITIONS)</para>
<xi:include href="system-only.xml" xpointer="singular"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>MountAPIVFS=</varname></term>

View File

@ -39,18 +39,7 @@ static int cached_enforcing = -1;
static struct selabel_handle *label_hnd = NULL;
#define log_enforcing(...) log_full(mac_selinux_enforcing() ? LOG_ERR : LOG_WARNING, __VA_ARGS__)
#define log_enforcing_errno(error, ...) \
({ \
bool _enforcing = mac_selinux_enforcing(); \
int _level = _enforcing ? LOG_ERR : LOG_WARNING; \
int _e = (error); \
\
int _r = (log_get_max_level() >= LOG_PRI(_level)) \
? log_internal_realm(_level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \
: -ERRNO_VALUE(_e); \
_enforcing ? _r : 0; \
})
#define log_enforcing_errno(r, ...) log_full_errno(mac_selinux_enforcing() ? LOG_ERR : LOG_WARNING, r, __VA_ARGS__)
#endif
bool mac_selinux_use(void) {
@ -70,15 +59,14 @@ bool mac_selinux_enforcing(void) {
#if HAVE_SELINUX
if (_unlikely_(cached_enforcing < 0)) {
cached_enforcing = security_getenforce();
if (cached_enforcing < 0) {
log_debug_errno(errno, "Failed to get SELinux enforced status, continuing in enforcing mode: %m");
return true; /* treat failure as enforcing mode */
}
if (cached_enforcing == -1)
log_error_errno(errno, "Failed to get SELinux enforced status, continue in enforcing mode: %m");
else
log_debug("SELinux enforcing state cached to: %s", cached_enforcing ? "enforcing" : "permissive");
}
return cached_enforcing > 0;
/* treat failure as enforcing mode */
return (cached_enforcing != 0);
#else
return false;
#endif
@ -102,11 +90,11 @@ static int setenforce_callback(int enforcing) {
#endif
int mac_selinux_init(void) {
int r = 0;
#if HAVE_SELINUX
usec_t before_timestamp, after_timestamp;
struct mallinfo before_mallinfo, after_mallinfo;
char timespan[FORMAT_TIMESPAN_MAX];
int l;
selinux_set_callback(SELINUX_CB_POLICYLOAD, (union selinux_callback) mac_selinux_reload);
selinux_set_callback(SELINUX_CB_SETENFORCE, (union selinux_callback) setenforce_callback);
@ -121,8 +109,12 @@ int mac_selinux_init(void) {
before_timestamp = now(CLOCK_MONOTONIC);
label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
if (!label_hnd)
return log_enforcing_errno(errno, "Failed to initialize SELinux context: %m");
if (!label_hnd) {
log_enforcing_errno(errno, "Failed to initialize SELinux context: %m");
r = mac_selinux_enforcing() ? -errno : 0;
} else {
char timespan[FORMAT_TIMESPAN_MAX];
int l;
after_timestamp = now(CLOCK_MONOTONIC);
after_mallinfo = mallinfo();
@ -132,9 +124,10 @@ int mac_selinux_init(void) {
log_debug("Successfully loaded SELinux database in %s, size on heap is %iK.",
format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0),
(l+1023)/1024);
}
#endif
return 0;
return r;
}
void mac_selinux_finish(void) {
@ -233,7 +226,9 @@ int mac_selinux_fix_container(const char *path, const char *inside_path, LabelFi
return 0;
fail:
return log_enforcing_errno(r, "Unable to fix SELinux security context of %s (%s): %m", path, inside_path);
log_enforcing_errno(r, "Unable to fix SELinux security context of %s (%s): %m", path, inside_path);
if (mac_selinux_enforcing())
return r;
#endif
return 0;
@ -248,17 +243,21 @@ int mac_selinux_apply(const char *path, const char *label) {
assert(path);
assert(label);
if (setfilecon(path, label) < 0)
return log_enforcing_errno(errno, "Failed to set SELinux security context %s on path %s: %m", label, path);
if (setfilecon(path, label) < 0) {
log_enforcing_errno(errno, "Failed to set SELinux security context %s on path %s: %m", label, path);
if (mac_selinux_enforcing())
return -errno;
}
#endif
return 0;
}
int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
int r = -EOPNOTSUPP;
#if HAVE_SELINUX
_cleanup_freecon_ char *mycon = NULL, *fcon = NULL;
security_class_t sclass;
int r;
assert(exe);
assert(label);
@ -281,39 +280,36 @@ int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
r = security_compute_create_raw(mycon, fcon, sclass, label);
if (r < 0)
return -errno;
return 0;
#else
return -EOPNOTSUPP;
#endif
return r;
}
int mac_selinux_get_our_label(char **label) {
#if HAVE_SELINUX
int r;
int r = -EOPNOTSUPP;
assert(label);
#if HAVE_SELINUX
if (!mac_selinux_use())
return -EOPNOTSUPP;
r = getcon_raw(label);
if (r < 0)
return -errno;
return 0;
#else
return -EOPNOTSUPP;
#endif
return r;
}
int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *exec_label, char **label) {
int r = -EOPNOTSUPP;
#if HAVE_SELINUX
_cleanup_freecon_ char *mycon = NULL, *peercon = NULL, *fcon = NULL;
_cleanup_context_free_ context_t pcon = NULL, bcon = NULL;
security_class_t sclass;
const char *range = NULL;
int r;
assert(socket_fd >= 0);
assert(exe);
@ -366,11 +362,9 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
r = security_compute_create_raw(mycon, fcon, sclass, label);
if (r < 0)
return -errno;
return 0;
#else
return -EOPNOTSUPP;
#endif
return r;
}
char* mac_selinux_free(char *label) {
@ -405,21 +399,26 @@ static int selinux_create_file_prepare_abspath(const char *abspath, mode_t mode)
if (errno == ENOENT)
return 0;
return log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", abspath);
log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", abspath);
} else {
if (setfscreatecon_raw(filecon) >= 0)
return 0; /* Success! */
log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", filecon, abspath);
}
if (setfscreatecon_raw(filecon) < 0)
return log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", filecon, abspath);
if (mac_selinux_enforcing())
return -errno;
return 0;
}
#endif
int mac_selinux_create_file_prepare_at(int dirfd, const char *path, mode_t mode) {
int r = 0;
#if HAVE_SELINUX
_cleanup_free_ char *abspath = NULL;
int r;
assert(path);
@ -441,16 +440,15 @@ int mac_selinux_create_file_prepare_at(int dirfd, const char *path, mode_t mode)
return -ENOMEM;
}
return selinux_create_file_prepare_abspath(path, mode);
#else
return 0;
r = selinux_create_file_prepare_abspath(path, mode);
#endif
return r;
}
int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
#if HAVE_SELINUX
int r;
int r = 0;
#if HAVE_SELINUX
_cleanup_free_ char *abspath = NULL;
assert(path);
@ -462,10 +460,9 @@ int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
if (r < 0)
return r;
return selinux_create_file_prepare_abspath(abspath, mode);
#else
return 0;
r = selinux_create_file_prepare_abspath(abspath, mode);
#endif
return r;
}
void mac_selinux_create_file_clear(void) {
@ -483,13 +480,17 @@ void mac_selinux_create_file_clear(void) {
int mac_selinux_create_socket_prepare(const char *label) {
#if HAVE_SELINUX
assert(label);
if (!mac_selinux_use())
return 0;
if (setsockcreatecon(label) < 0)
return log_enforcing_errno(errno, "Failed to set SELinux security context %s for sockets: %m", label);
assert(label);
if (setsockcreatecon(label) < 0) {
log_enforcing_errno(errno, "Failed to set SELinux security context %s for sockets: %m", label);
if (mac_selinux_enforcing())
return -errno;
}
#endif
return 0;
@ -560,14 +561,15 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
if (errno == ENOENT)
goto skipped;
r = log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", path);
if (r < 0)
return r;
log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", path);
if (mac_selinux_enforcing())
return -errno;
} else {
if (setfscreatecon_raw(fcon) < 0) {
r = log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", fcon, path);
if (r < 0)
return r;
log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", fcon, path);
if (mac_selinux_enforcing())
return -errno;
} else
context_changed = true;
}
@ -575,7 +577,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
r = bind(fd, addr, addrlen) < 0 ? -errno : 0;
if (context_changed)
(void) setfscreatecon_raw(NULL);
setfscreatecon_raw(NULL);
return r;

View File

@ -746,25 +746,6 @@ static int property_get_log_extra_fields(
return sd_bus_message_close_container(reply);
}
static int property_get_root_hash(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
ExecContext *c = userdata;
assert(bus);
assert(c);
assert(property);
assert(reply);
return sd_bus_message_append_array(reply, 'y', c->root_hash, c->root_hash_size);
}
const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
@ -807,9 +788,6 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RootImage", "s", NULL, offsetof(ExecContext, root_image), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RootHash", "ay", property_get_root_hash, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RootHashPath", "s", NULL, offsetof(ExecContext, root_hash_path), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RootVerity", "s", NULL, offsetof(ExecContext, root_verity), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("CoredumpFilter", "t", property_get_coredump_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
@ -1280,55 +1258,6 @@ int bus_exec_context_set_transient_property(
if (streq(name, "RootImage"))
return bus_set_transient_path(u, name, &c->root_image, message, flags, error);
if (streq(name, "RootHash")) {
const void *roothash_decoded;
size_t roothash_decoded_size;
r = sd_bus_message_read_array(message, 'y', &roothash_decoded, &roothash_decoded_size);
if (r < 0)
return r;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *encoded = NULL;
if (roothash_decoded_size == 0) {
c->root_hash_path = mfree(c->root_hash_path);
c->root_hash = mfree(c->root_hash);
c->root_hash_size = 0;
unit_write_settingf(u, flags, name, "RootHash=");
} else {
_cleanup_free_ void *p;
encoded = hexmem(roothash_decoded, roothash_decoded_size);
if (!encoded)
return -ENOMEM;
p = memdup(roothash_decoded, roothash_decoded_size);
if (!p)
return -ENOMEM;
free_and_replace(c->root_hash, p);
c->root_hash_size = roothash_decoded_size;
c->root_hash_path = mfree(c->root_hash_path);
unit_write_settingf(u, flags, name, "RootHash=%s", encoded);
}
}
return 1;
}
if (streq(name, "RootHashPath")) {
c->root_hash_size = 0;
c->root_hash = mfree(c->root_hash);
return bus_set_transient_path(u, "RootHash", &c->root_hash_path, message, flags, error);
}
if (streq(name, "RootVerity"))
return bus_set_transient_path(u, name, &c->root_verity, message, flags, error);
if (streq(name, "RootDirectory"))
return bus_set_transient_path(u, name, &c->root_directory, message, flags, error);

View File

@ -54,7 +54,6 @@
#include "format-util.h"
#include "fs-util.h"
#include "glob-util.h"
#include "hexdecoct.h"
#include "io-util.h"
#include "ioprio.h"
#include "label.h"
@ -2667,7 +2666,6 @@ static int apply_mount_namespace(
needs_sandboxing ? context->protect_home : PROTECT_HOME_NO,
needs_sandboxing ? context->protect_system : PROTECT_SYSTEM_NO,
context->mount_flags,
context->root_hash, context->root_hash_size, context->root_hash_path, context->root_verity,
DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK,
error_path);
@ -4197,10 +4195,6 @@ void exec_context_done(ExecContext *c) {
c->working_directory = mfree(c->working_directory);
c->root_directory = mfree(c->root_directory);
c->root_image = mfree(c->root_image);
c->root_hash = mfree(c->root_hash);
c->root_hash_size = 0;
c->root_hash_path = mfree(c->root_hash_path);
c->root_verity = mfree(c->root_verity);
c->tty_path = mfree(c->tty_path);
c->syslog_identifier = mfree(c->syslog_identifier);
c->user = mfree(c->user);
@ -4605,19 +4599,6 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
if (c->root_image)
fprintf(f, "%sRootImage: %s\n", prefix, c->root_image);
if (c->root_hash) {
_cleanup_free_ char *encoded = NULL;
encoded = hexmem(c->root_hash, c->root_hash_size);
if (encoded)
fprintf(f, "%sRootHash: %s\n", prefix, encoded);
}
if (c->root_hash_path)
fprintf(f, "%sRootHash: %s\n", prefix, c->root_hash_path);
if (c->root_verity)
fprintf(f, "%sRootVerity: %s\n", prefix, c->root_verity);
STRV_FOREACH(e, c->environment)
fprintf(f, "%sEnvironment: %s\n", prefix, *e);

View File

@ -155,9 +155,7 @@ struct ExecContext {
char **unset_environment;
struct rlimit *rlimit[_RLIMIT_MAX];
char *working_directory, *root_directory, *root_image, *root_verity, *root_hash_path;
void *root_hash;
size_t root_hash_size;
char *working_directory, *root_directory, *root_image;
bool working_directory_missing_ok:1;
bool working_directory_home:1;

View File

@ -387,25 +387,62 @@ JobType job_type_lookup_merge(JobType a, JobType b) {
return job_merging_table[(a - 1) * a / 2 + b];
}
bool job_type_is_redundant(JobType a, UnitActiveState b) {
switch (a) {
bool job_later_link_matters(Job *j, JobType type, unsigned generation) {
JobDependency *l;
assert(j);
j->generation = generation;
LIST_FOREACH(subject, l, j->subject_list) {
UnitActiveState state = _UNIT_ACTIVE_STATE_INVALID;
/* Have we seen this before? */
if (l->object->generation == generation)
continue;
state = unit_active_state(l->object->unit);
switch (type) {
case JOB_START:
return IN_SET(b, UNIT_ACTIVE, UNIT_RELOADING);
return IN_SET(state, UNIT_INACTIVE, UNIT_FAILED) ||
job_later_link_matters(l->object, type, generation);
case JOB_STOP:
return IN_SET(b, UNIT_INACTIVE, UNIT_FAILED);
return IN_SET(state, UNIT_ACTIVE, UNIT_RELOADING) ||
job_later_link_matters(l->object, type, generation);
default:
assert_not_reached("Invalid job type");
}
}
return false;
}
bool job_is_redundant(Job *j, unsigned generation) {
assert(j);
UnitActiveState state = unit_active_state(j->unit);
switch (j->type) {
case JOB_START:
return IN_SET(state, UNIT_ACTIVE, UNIT_RELOADING) && !job_later_link_matters(j, JOB_START, generation);
case JOB_STOP:
return IN_SET(state, UNIT_INACTIVE, UNIT_FAILED) && !job_later_link_matters(j, JOB_STOP, generation);
case JOB_VERIFY_ACTIVE:
return IN_SET(b, UNIT_ACTIVE, UNIT_RELOADING);
return IN_SET(state, UNIT_ACTIVE, UNIT_RELOADING);
case JOB_RELOAD:
return
b == UNIT_RELOADING;
state == UNIT_RELOADING;
case JOB_RESTART:
return
b == UNIT_ACTIVATING;
state == UNIT_ACTIVATING;
case JOB_NOP:
return true;

View File

@ -196,7 +196,8 @@ _pure_ static inline bool job_type_is_superset(JobType a, JobType b) {
return a == job_type_lookup_merge(a, b);
}
bool job_type_is_redundant(JobType a, UnitActiveState b) _pure_;
bool job_later_link_matters(Job *j, JobType type, unsigned generation);
bool job_is_redundant(Job *j, unsigned generation);
/* Collapses a state-dependent job type into a simpler type by observing
* the state of the unit which it is going to be applied to. */

View File

@ -23,8 +23,6 @@ m4_define(`EXEC_CONTEXT_CONFIG_ITEMS',
`$1.WorkingDirectory, config_parse_working_directory, 0, offsetof($1, exec_context)
$1.RootDirectory, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_directory)
$1.RootImage, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_image)
$1.RootHash, config_parse_exec_root_hash, 0, offsetof($1, exec_context)
$1.RootVerity, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_verity)
$1.User, config_parse_user_group_compat, 0, offsetof($1, exec_context.user)
$1.Group, config_parse_user_group_compat, 0, offsetof($1, exec_context.group)
$1.SupplementaryGroups, config_parse_user_group_strv_compat, 0, offsetof($1, exec_context.supplementary_groups)

View File

@ -29,7 +29,6 @@
#include "errno-list.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "hexdecoct.h"
#include "io-util.h"
@ -1414,64 +1413,6 @@ int config_parse_exec_cpu_sched_prio(const char *unit,
return 0;
}
int config_parse_exec_root_hash(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
_cleanup_free_ void *roothash_decoded = NULL;
ExecContext *c = data;
size_t roothash_decoded_size = 0;
int r;
assert(data);
assert(filename);
assert(line);
assert(rvalue);
if (isempty(rvalue)) {
/* Reset if the empty string is assigned */
c->root_hash_path = mfree(c->root_hash_path);
c->root_hash = mfree(c->root_hash);
c->root_hash_size = 0;
return 0;
}
if (path_is_absolute(rvalue)) {
/* We have the path to a roothash to load and decode, eg: RootHash=/foo/bar.roothash */
_cleanup_free_ char *p = NULL;
p = strdup(rvalue);
if (!p)
return -ENOMEM;
free_and_replace(c->root_hash_path, p);
c->root_hash = mfree(c->root_hash);
c->root_hash_size = 0;
return 0;
}
/* We have a roothash to decode, eg: RootHash=012345789abcdef */
r = unhexmem(rvalue, strlen(rvalue), &roothash_decoded, &roothash_decoded_size);
if (r < 0)
return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to decode RootHash=, ignoring: %s", rvalue);
if (roothash_decoded_size < sizeof(sd_id128_t))
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "RootHash= is too short, ignoring: %s", rvalue);
free_and_replace(c->root_hash, roothash_decoded);
c->root_hash_size = roothash_decoded_size;
c->root_hash_path = mfree(c->root_hash_path);
return 0;
}
int config_parse_exec_cpu_affinity(const char *unit,
const char *filename,
unsigned line,

View File

@ -44,7 +44,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_sched_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_sched_prio);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_affinity);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_secure_bits);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_root_hash);
CONFIG_PARSER_PROTOTYPE(config_parse_capability_set);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_mount_flags);
CONFIG_PARSER_PROTOTYPE(config_parse_timer);

View File

@ -1257,20 +1257,16 @@ int setup_namespace(
ProtectHome protect_home,
ProtectSystem protect_system,
unsigned long mount_flags,
const void *root_hash,
size_t root_hash_size,
const char *root_hash_path,
const char *root_verity,
DissectImageFlags dissect_image_flags,
char **error_path) {
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
_cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
_cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL;
_cleanup_free_ void *root_hash_decoded = NULL;
_cleanup_free_ void *root_hash = NULL;
_cleanup_free_ char *verity_data = NULL;
MountEntry *m = NULL, *mounts = NULL;
size_t n_mounts;
size_t n_mounts, root_hash_size = 0;
bool require_prefix = false;
const char *root;
int r = 0;
@ -1299,16 +1295,16 @@ int setup_namespace(
if (r < 0)
return log_debug_errno(r, "Failed to create loop device for root image: %m");
r = verity_metadata_load(root_image, root_hash_path, root_hash ? NULL : &root_hash_decoded, root_hash ? NULL : &root_hash_size, root_verity ? NULL : &verity_data);
r = verity_metadata_load(root_image, &root_hash, &root_hash_size, &verity_data);
if (r < 0)
return log_debug_errno(r, "Failed to load root hash: %m");
dissect_image_flags |= root_verity || verity_data ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0;
dissect_image_flags |= verity_data ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0;
r = dissect_image(loop_device->fd, root_hash ?: root_hash_decoded, root_hash_size, root_verity ?: verity_data, dissect_image_flags, &dissected_image);
r = dissect_image(loop_device->fd, root_hash, root_hash_size, verity_data, dissect_image_flags, &dissected_image);
if (r < 0)
return log_debug_errno(r, "Failed to dissect image: %m");
r = dissected_image_decrypt(dissected_image, NULL, root_hash ?: root_hash_decoded, root_hash_size, root_verity ?: verity_data, dissect_image_flags, &decrypted_image);
r = dissected_image_decrypt(dissected_image, NULL, root_hash, root_hash_size, verity_data, dissect_image_flags, &decrypted_image);
if (r < 0)
return log_debug_errno(r, "Failed to decrypt dissected image: %m");
}

View File

@ -88,10 +88,6 @@ int setup_namespace(
ProtectHome protect_home,
ProtectSystem protect_system,
unsigned long mount_flags,
const void *root_hash,
size_t root_hash_size,
const char *root_hash_path,
const char *root_verity,
DissectImageFlags dissected_image_flags,
char **error_path);

View File

@ -279,7 +279,7 @@ static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) {
return 0;
}
static void transaction_drop_redundant(Transaction *tr) {
static void transaction_drop_redundant(Transaction *tr, unsigned generation) {
bool again;
/* Goes through the transaction and removes all jobs of the units whose jobs are all noops. If not
@ -299,7 +299,7 @@ static void transaction_drop_redundant(Transaction *tr) {
LIST_FOREACH(transaction, k, j)
if (tr->anchor_job == k ||
!job_type_is_redundant(k->type, unit_active_state(k->unit)) ||
!job_is_redundant(k, generation) ||
(k->unit->job && job_type_is_conflicting(k->type, k->unit->job->type))) {
keep = true;
break;
@ -735,7 +735,7 @@ int transaction_activate(
transaction_minimize_impact(tr);
/* Third step: Drop redundant jobs */
transaction_drop_redundant(tr);
transaction_drop_redundant(tr, generation++);
for (;;) {
/* Fourth step: Let's remove unneeded jobs that might
@ -777,7 +777,7 @@ int transaction_activate(
}
/* Eights step: Drop redundant jobs again, if the merging now allows us to drop more. */
transaction_drop_redundant(tr);
transaction_drop_redundant(tr, generation++);
/* Ninth step: check whether we can actually apply this */
r = transaction_is_destructive(tr, mode, e);

View File

@ -201,7 +201,7 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to set up loopback device: %m");
r = verity_metadata_load(arg_image, NULL, arg_root_hash ? NULL : &arg_root_hash, &arg_root_hash_size,
r = verity_metadata_load(arg_image, arg_root_hash ? NULL : &arg_root_hash, &arg_root_hash_size,
arg_verity_data ? NULL : &arg_verity_data);
if (r < 0)
return log_error_errno(r, "Failed to read verity artefacts for %s: %m", arg_image);

View File

@ -619,9 +619,9 @@ int mount_all(const char *dest,
#if HAVE_SELINUX
{ "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND,
MOUNT_MKDIR }, /* Bind mount first (mkdir/chown the mount point in case /sys/ is mounted as minimal skeleton tmpfs) */
0 }, /* Bind mount first */
{ NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT,
0 }, /* Then, make it r/o (don't mkdir/chown the mount point here, the previous entry already did that) */
0 }, /* Then, make it r/o */
#endif
};

View File

@ -5141,7 +5141,7 @@ static int run(int argc, char *argv[]) {
goto finish;
}
r = verity_metadata_load(arg_image, NULL, arg_root_hash ? NULL : &arg_root_hash, &arg_root_hash_size,
r = verity_metadata_load(arg_image, arg_root_hash ? NULL : &arg_root_hash, &arg_root_hash_size,
arg_verity_data ? NULL : &arg_verity_data);
if (r < 0) {
log_error_errno(r, "Failed to read verity artefacts for %s: %m", arg_image);

View File

@ -13,7 +13,6 @@
#include "escape.h"
#include "exec-util.h"
#include "exit-status.h"
#include "fileio.h"
#include "hexdecoct.h"
#include "hostname-util.h"
#include "in-addr-util.h"
@ -25,7 +24,6 @@
#include "nsflags.h"
#include "numa-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "rlimit-util.h"
#include "securebits-util.h"
@ -851,7 +849,6 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
"ProtectHome",
"SELinuxContext",
"RootImage",
"RootVerity",
"RuntimeDirectoryPreserve",
"Personality",
"KeyringMode",
@ -1418,24 +1415,6 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
return 1;
}
if (streq(field, "RootHash")) {
_cleanup_free_ void *roothash_decoded = NULL;
size_t roothash_decoded_size = 0;
/* We have the path to a roothash to load and decode, eg: RootHash=/foo/bar.roothash */
if (path_is_absolute(eq))
return bus_append_string(m, "RootHashPath", eq);
/* We have a roothash to decode, eg: RootHash=012345789abcdef */
r = unhexmem(eq, strlen(eq), &roothash_decoded, &roothash_decoded_size);
if (r < 0)
return log_error_errno(r, "Failed to decode RootHash= '%s': %m", eq);
if (roothash_decoded_size < sizeof(sd_id128_t))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "RootHash= '%s' is too short: %m", eq);
return bus_append_byte_array(m, field, roothash_decoded, roothash_decoded_size);
}
return 0;
}

View File

@ -1421,7 +1421,7 @@ int decrypted_image_relinquish(DecryptedImage *d) {
return 0;
}
int verity_metadata_load(const char *image, const char *root_hash_path, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data) {
int verity_metadata_load(const char *image, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data) {
_cleanup_free_ char *verity_filename = NULL;
_cleanup_free_ void *roothash_decoded = NULL;
size_t roothash_decoded_size = 0;
@ -1465,12 +1465,6 @@ int verity_metadata_load(const char *image, const char *root_hash_path, void **r
_cleanup_free_ char *text = NULL;
assert(ret_roothash_size);
if (root_hash_path) {
/* We have the path to a roothash to load and decode, eg: RootHash=/foo/bar.roothash */
r = read_one_line_file(root_hash_path, &text);
if (r < 0)
return r;
} else {
r = getxattr_malloc(image, "user.verity.roothash", &text, true);
if (r < 0) {
char *fn, *e, *n;
@ -1490,7 +1484,6 @@ int verity_metadata_load(const char *image, const char *root_hash_path, void **r
if (r < 0 && r != -ENOENT)
return r;
}
}
if (text) {
r = unhexmem(text, strlen(text), &roothash_decoded, &roothash_decoded_size);

View File

@ -100,6 +100,6 @@ int decrypted_image_relinquish(DecryptedImage *d);
const char* partition_designator_to_string(int i) _const_;
int partition_designator_from_string(const char *name) _pure_;
int verity_metadata_load(const char *image, const char *root_hash_path, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data);
int verity_metadata_load(const char *image, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data);
bool dissected_image_can_do_verity(const DissectedImage *image, unsigned partition_designator);
bool dissected_image_has_verity(const DissectedImage *image, unsigned partition_designator);

View File

@ -152,10 +152,6 @@ static void test_protect_kernel_logs(void) {
PROTECT_HOME_NO,
PROTECT_SYSTEM_NO,
0,
NULL,
0,
NULL,
NULL,
0,
NULL);
assert_se(r == 0);

View File

@ -76,10 +76,6 @@ int main(int argc, char *argv[]) {
PROTECT_HOME_NO,
PROTECT_SYSTEM_NO,
0,
NULL,
0,
NULL,
NULL,
0,
NULL);
if (r < 0) {

View File

@ -196,8 +196,6 @@ ReusePort=
RootDirectory=
RootDirectoryStartOnly=
RootImage=
RootHash=
RootVerity=
RuntimeMaxSec=
SELinuxContextFromNet=
SecureBits=

View File

@ -935,7 +935,7 @@ install_config_files() {
inst /etc/login.defs
inst /etc/group
inst /etc/shells
inst_any /etc/nsswitch.conf /usr/etc/nsswitch.conf
inst /etc/nsswitch.conf
inst /etc/pam.conf || :
inst /etc/os-release
inst /etc/localtime

View File

@ -9,25 +9,23 @@
# export CONT_NAME="my-fancy-container"
# travis-ci/managers/debian.sh SETUP RUN CLEANUP
PHASES=(${@:-SETUP RUN RUN_ASAN_UBSAN CLEANUP})
PHASES=(${@:-SETUP RUN RUN_ASAN CLEANUP})
DEBIAN_RELEASE="${DEBIAN_RELEASE:-testing}"
CONT_NAME="${CONT_NAME:-systemd-debian-$DEBIAN_RELEASE}"
CONT_NAME="${CONT_NAME:-debian-$DEBIAN_RELEASE-$RANDOM}"
DOCKER_EXEC="${DOCKER_EXEC:-docker exec -it $CONT_NAME}"
DOCKER_RUN="${DOCKER_RUN:-docker run}"
REPO_ROOT="${REPO_ROOT:-$PWD}"
ADDITIONAL_DEPS=(
ADDITIONAL_DEPS=(python3-libevdev
python3-pyparsing
clang
perl
libpwquality-dev
fdisk
libfdisk-dev
libp11-kit-dev
libpwquality-dev
libssl-dev
libzstd-dev
perl
python3-libevdev
python3-pyparsing
zstd
)
zstd)
function info() {
echo -e "\033[33;1m$1\033[0m"
@ -56,7 +54,7 @@ for phase in "${PHASES[@]}"; do
$DOCKER_EXEC apt-get -y build-dep systemd
$DOCKER_EXEC apt-get -y install "${ADDITIONAL_DEPS[@]}"
;;
RUN|RUN_GCC|RUN_CLANG)
RUN|RUN_CLANG)
if [[ "$phase" = "RUN_CLANG" ]]; then
ENV_VARS="-e CC=clang -e CXX=clang++"
fi
@ -64,8 +62,8 @@ for phase in "${PHASES[@]}"; do
$DOCKER_EXEC ninja -v -C build
docker exec -e "TRAVIS=$TRAVIS" -it $CONT_NAME ninja -C build test
;;
RUN_ASAN_UBSAN|RUN_GCC_ASAN_UBSAN|RUN_CLANG_ASAN_UBSAN)
if [[ "$phase" = "RUN_CLANG_ASAN_UBSAN" ]]; then
RUN_ASAN|RUN_CLANG_ASAN)
if [[ "$phase" = "RUN_CLANG_ASAN" ]]; then
ENV_VARS="-e CC=clang -e CXX=clang++"
# Build fuzzer regression tests only with clang (for now),
# see: https://github.com/systemd/systemd/pull/15886#issuecomment-632689604

View File

@ -9,32 +9,38 @@
# export CONT_NAME="my-fancy-container"
# travis-ci/managers/fedora.sh SETUP RUN CLEANUP
PHASES=(${@:-SETUP RUN RUN_ASAN_UBSAN CLEANUP})
PHASES=(${@:-SETUP RUN RUN_ASAN CLEANUP})
FEDORA_RELEASE="${FEDORA_RELEASE:-rawhide}"
CONT_NAME="${CONT_NAME:-systemd-fedora-$FEDORA_RELEASE}"
CONT_NAME="${CONT_NAME:-fedora-$FEDORA_RELEASE-$RANDOM}"
DOCKER_EXEC="${DOCKER_EXEC:-docker exec -it $CONT_NAME}"
DOCKER_RUN="${DOCKER_RUN:-docker run}"
REPO_ROOT="${REPO_ROOT:-$PWD}"
ADDITIONAL_DEPS=(
clang
dnf-plugins-core
hostname libasan
ADDITIONAL_DEPS=(dnf-plugins-core
jq iputils
hostname libasan
python3-pyparsing
python3-evdev
libubsan
clang
llvm
perl
libfdisk-devel
libpwquality-devel
libubsan
llvm
openssl-devel
p11-kit-devel
perl
python3-evdev
python3-pyparsing
)
p11-kit-devel)
info() {
echo -e "\033[33;1m$1\033[0m"
}
error() {
echo >&2 -e "\033[31;1m$1\033[0m"
}
success() {
echo >&2 -e "\033[32;1m$1\033[0m"
}
# Simple wrapper which retries given command up to five times
_retry() {
local EC=1
@ -88,8 +94,8 @@ for phase in "${PHASES[@]}"; do
$DOCKER_EXEC ninja -v -C build
$DOCKER_EXEC ninja -C build test
;;
RUN_ASAN|RUN_GCC_ASAN_UBSAN|RUN_CLANG_ASAN_UBSAN)
if [[ "$phase" = "RUN_CLANG_ASAN_UBSAN" ]]; then
RUN_ASAN|RUN_CLANG_ASAN)
if [[ "$phase" = "RUN_CLANG_ASAN" ]]; then
ENV_VARS="-e CC=clang -e CXX=clang++"
MESON_ARGS="-Db_lundef=false" # See https://github.com/mesonbuild/meson/issues/764
fi
@ -104,6 +110,46 @@ for phase in "${PHASES[@]}"; do
-t $CONT_NAME \
meson test --timeout-multiplier=3 -C ./build/ --print-errorlogs
;;
RUN_BUILD_CHECK_GCC|RUN_BUILD_CHECK_CLANG)
ARGS=(
"--optimization=0"
"--optimization=2"
"--optimization=3"
"--optimization=s"
"-Db_lto=true"
"-Db_ndebug=true"
)
if [[ "$phase" = "RUN_BUILD_CHECK_CLANG" ]]; then
ENV_VARS="-e CC=clang -e CXX=clang++"
$DOCKER_EXEC clang --version
else
$DOCKER_EXEC gcc --version
fi
for args in "${ARGS[@]}"; do
SECONDS=0
info "Checking build with $args"
# Redirect meson/ninja logs into separate files, otherwise we
# would trip over Travis' log size limit
if ! docker exec $ENV_VARS -it $CONT_NAME meson --werror $args build &> meson.log; then
cat meson.log
error "meson failed with $args"
exit 1
fi
if ! $DOCKER_EXEC ninja -v -C build &> ninja.log; then
cat ninja.log
error "ninja failed with $args"
exit 1
fi
$DOCKER_EXEC rm -fr build
rm -f meson.log ninja.log
success "Build with $args passed in $SECONDS seconds"
done
;;
CLEANUP)
info "Cleanup phase"
docker stop $CONT_NAME