Compare commits

..

12 Commits

Author SHA1 Message Date
Dave Reisner cc479760b4 Revert "job: Don't mark as redundant if deps are relevant"
This reverts commit 097537f07a.

At least Fedora and Debian have already reverted this at the distro
level because it causes more problems than it solves. Arch is debating
reverting it as well [0] but would strongly prefer that this happens
upstream first. Fixes #15188.

[0] https://bugs.archlinux.org/task/66458
2020-06-23 11:42:45 +02:00
Luca Boccassi 0389f4fa81 core: add RootHash and RootVerity service parameters
Allow to explicitly pass root hash (explicitly or as a file) and verity
device/file as unit options. Take precedence over implicit checks.
2020-06-23 10:50:09 +02:00
Lennart Poettering 6fe01ced0e nspawn: mkdir selinux mount point once, but not twice
Since #15533 we didn't create the mount point for selinuxfs anymore.

Before it we created it twice because we mount selinuxfs twice: once the
superblock, and once we remount its bind mound read-only. The second
mkdir would mean we'd chown() the host version of selinuxfs (since
there's only one selinuxfs superblock kernel-wide).

The right time to create mount point point is once: before we mount the
selinuxfs. But not a second time for the remount.

Fixes: #16032
2020-06-23 10:17:36 +02:00
Zbigniew Jędrzejewski-Szmek 75ae672bb2
Merge pull request #16196 from mrc0mmand/travis-simplification
travis: use a matrix for similar jobs
2020-06-23 10:16:18 +02:00
Zbigniew Jędrzejewski-Szmek 5c9918aca0
Merge pull request #16216 from nabijaczleweli/make-a-fuss
man/sd-makefs: mention that mkswap can also be run and fix deadlink to btrfs-man5(5)
2020-06-23 10:12:47 +02:00
Lennart Poettering 65804d6aff selinux-util: tweak log_enforcing_errno() to return the errno passed in or 0 when in non-enforcing mode
Also, some other, minor modernizations.
2020-06-23 07:48:44 +02:00
Elisei Roca 9e1732924d
test-functions: read /usr/etc/nsswitch.conf if /etc/nsswitch.conf does not exist (#16195)
See this for more info why and since when this change is needed: https://build.opensuse.org/request/show/807179.
2020-06-23 07:42:15 +02:00
наб affa893da0
man/sd-makefs: link to btrfs.wiki.kernel.org for btrfs-man5, since the man-pages link is dead
This also adds a <citerefentry project="url"> type,
since the other btrfs manpages use man-pages/die-net and are alive,
and btrfs.w.k.o won't be used anywhere else
2020-06-22 23:12:13 +02:00
наб c2ad8c0978
man/sd-makefs: also mention /sbin/mkswap 2020-06-19 01:15:20 +02:00
Frantisek Sumsal 0116d27a30 travis: sort dependencies 2020-06-16 18:49:37 +02:00
Frantisek Sumsal 305efcaf3c travis: drop stuff moved to GH Actions 2020-06-16 18:47:49 +02:00
Frantisek Sumsal eeb8c7accf travis: use a matrix for similar jobs 2020-06-16 18:47:39 +02:00
28 changed files with 473 additions and 355 deletions

View File

@ -1,127 +1,82 @@
sudo: required
---
# vi: ts=2 sw=2 et:
language: bash
dist: bionic
services:
- docker
- docker
env:
global:
- AUTHOR_EMAIL="$(git log -1 $TRAVIS_COMMIT --pretty=\"%aE\")"
- CI_MANAGERS="$TRAVIS_BUILD_DIR/travis-ci/managers"
- CI_TOOLS="$TRAVIS_BUILD_DIR/travis-ci/tools"
- REPO_ROOT="$TRAVIS_BUILD_DIR"
global:
- AUTHOR_EMAIL="$(git log -1 $TRAVIS_COMMIT --pretty=\"%aE\")"
- 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:
- name: Build & test
if: type != cron
# 'Test' is the default stage (for matrix jobs)
- name: Test
if: type != cron
# Run Coverity periodically instead of for each commit/PR
- name: Coverity
if: type = cron
- name: Coverity
if: type = cron
# Matrix job definition - this is run for each combination of env variables
# from the env.jobs array above
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
after_script:
- $CI_MANAGERS/debian.sh CLEANUP
# Inject another (single) job into the matrix for Coverity
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 RUN || travis_terminate 1
after_script:
- $CI_MANAGERS/debian.sh CLEANUP
include:
- stage: Coverity
language: bash
env:
- FEDORA_RELEASE="latest"
- TOOL_BASE="/var/tmp/coverity-scan-analysis"
- DOCKER_RUN="docker run -v $TOOL_BASE:$TOOL_BASE:rw --env-file .cov-env"
# Coverity env variables
- PLATFORM="$(uname)"
- TOOL_ARCHIVE="/var/tmp/cov-analysis-$PLATFORM.tgz"
- SCAN_URL="https://scan.coverity.com"
- UPLOAD_URL="https://scan.coverity.com/builds"
- COVERITY_SCAN_PROJECT_NAME="$TRAVIS_REPO_SLUG"
- COVERITY_SCAN_NOTIFICATION_EMAIL="${AUTHOR_EMAIL}"
- COVERITY_SCAN_BRANCH_PATTERN="$TRAVIS_BRANCH"
# Encrypted COVERITY_SCAN_TOKEN env variable
# Generated using `travis encrypt -r systemd/systemd COVERITY_SCAN_TOKEN=xxxx`
- secure: "jKSz+Y1Mv8xMpQHh7g5lzW7E6HQGndFz/vKDJQ1CVShwFoyjV3Zu+MFS3UYKlh1236zL0Z4dvsYFx/b3Hq8nxZWCrWeZs2NdXgy/wh8LZhxwzcGYigp3sIA/cYdP5rDjFJO0MasNkl25/rml8+eZWz+8/xQic98UQHjSco/EOWtssoRcg0J0c4eDM7bGLfIQWE73NNY1Q1UtWjKmx1kekVrM8dPmHXJ9aERka7bmcbJAcKd6vabs6DQ5AfWccUPIn/EsRYqIJTRxJrFYU6XizANZ1a7Vwk/DWHZUEn2msxcZw5BbAMDTMx0TbfrNkKSHMHuvQUCu6KCBAq414i+LgkMfmQ2SWwKiIUsud1kxXX3ZPl9bxDv1HkvVdcniC/EM7lNEEVwm4meOnjuhI2lhOyOjmP3FTSlMHGP7xlK8DS2k9fqL58vn0BaSjwWgd+2+HuL2+nJmxcK1eLGzKqaostFxrk2Xs2vPZkUdV2nWY/asUrcWHml6YlWDn2eP83pfwxHYsMiEHY/rTKvxeVY+iirO/AphoO+eaYu7LvjKZU1Yx5Z4u/SnGWAiCH0yhMis0bWmgi7SCbw+sDd2uya+aoiLIGiB2ChW7hXHXCue/dif6/gLU7b+L8R00pQwnWdvKUPoIJCmZJYCluTeib4jpW+EmARB2+nR8wms2K9FGKM="
before_install:
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
- docker --version
install:
# Install Coverity on the host
- $CI_TOOLS/get-coverity.sh
# Export necessary env variables for Coverity
- env | grep -E "TRAVIS|COV|TOOL|URL" > .cov-env
# Pull a Docker image and start a new container
- $CI_MANAGERS/fedora.sh SETUP
script:
- set -e
# Preconfigure with meson to prevent Coverity from capturing meson metadata
- $DOCKER_EXEC meson cov-build -Dman=false
# Run Coverity
- $DOCKER_EXEC tools/coverity.sh build
- $DOCKER_EXEC tools/coverity.sh upload
- 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
- 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
- PLATFORM="$(uname)"
- TOOL_ARCHIVE="/var/tmp/cov-analysis-$PLATFORM.tgz"
- SCAN_URL="https://scan.coverity.com"
- UPLOAD_URL="https://scan.coverity.com/builds"
- COVERITY_SCAN_PROJECT_NAME="$TRAVIS_REPO_SLUG"
- COVERITY_SCAN_NOTIFICATION_EMAIL="${AUTHOR_EMAIL}"
- COVERITY_SCAN_BRANCH_PATTERN="$TRAVIS_BRANCH"
# Encrypted COVERITY_SCAN_TOKEN env variable
# Generated using `travis encrypt -r systemd/systemd COVERITY_SCAN_TOKEN=xxxx`
- secure: "jKSz+Y1Mv8xMpQHh7g5lzW7E6HQGndFz/vKDJQ1CVShwFoyjV3Zu+MFS3UYKlh1236zL0Z4dvsYFx/b3Hq8nxZWCrWeZs2NdXgy/wh8LZhxwzcGYigp3sIA/cYdP5rDjFJO0MasNkl25/rml8+eZWz+8/xQic98UQHjSco/EOWtssoRcg0J0c4eDM7bGLfIQWE73NNY1Q1UtWjKmx1kekVrM8dPmHXJ9aERka7bmcbJAcKd6vabs6DQ5AfWccUPIn/EsRYqIJTRxJrFYU6XizANZ1a7Vwk/DWHZUEn2msxcZw5BbAMDTMx0TbfrNkKSHMHuvQUCu6KCBAq414i+LgkMfmQ2SWwKiIUsud1kxXX3ZPl9bxDv1HkvVdcniC/EM7lNEEVwm4meOnjuhI2lhOyOjmP3FTSlMHGP7xlK8DS2k9fqL58vn0BaSjwWgd+2+HuL2+nJmxcK1eLGzKqaostFxrk2Xs2vPZkUdV2nWY/asUrcWHml6YlWDn2eP83pfwxHYsMiEHY/rTKvxeVY+iirO/AphoO+eaYu7LvjKZU1Yx5Z4u/SnGWAiCH0yhMis0bWmgi7SCbw+sDd2uya+aoiLIGiB2ChW7hXHXCue/dif6/gLU7b+L8R00pQwnWdvKUPoIJCmZJYCluTeib4jpW+EmARB2+nR8wms2K9FGKM="
before_install:
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
- docker --version
install:
# Install Coverity on the host
- $CI_TOOLS/get-coverity.sh
# Export necessary env variables for Coverity
- env | grep -E "TRAVIS|COV|TOOL|URL" > .cov-env
# Pull a Docker image and start a new container
- $CI_MANAGERS/fedora.sh SETUP
script:
- set -e
# Preconfigure with meson to prevent Coverity from capturing meson metadata
- $DOCKER_EXEC meson cov-build -Dman=false
# Run Coverity
- $DOCKER_EXEC tools/coverity.sh build
- $DOCKER_EXEC tools/coverity.sh upload
- set +e
after_script:
- $CI_MANAGERS/fedora.sh CLEANUP
- set +e
after_script:
- $CI_MANAGERS/fedora.sh CLEANUP

View File

@ -19,7 +19,8 @@
<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"/>
@ -133,6 +134,15 @@
</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,7 +51,8 @@
<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>).</para>
each filesystem type (<filename>/sbin/mkfs.<replaceable>type</replaceable></filename>
or <filename>/sbin/mkswap</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
@ -61,8 +62,7 @@
number specific to each file system, so only certain types are supported.
Currently:
<citerefentry project='man-pages'><refentrytitle>ext4</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
btrfs (see
<citerefentry project='man-pages'><refentrytitle>btrfs-man5</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>,
<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,6 +145,43 @@
<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,7 +39,18 @@ 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(r, ...) log_full_errno(mac_selinux_enforcing() ? LOG_ERR : LOG_WARNING, r, __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; \
})
#endif
bool mac_selinux_use(void) {
@ -59,14 +70,15 @@ bool mac_selinux_enforcing(void) {
#if HAVE_SELINUX
if (_unlikely_(cached_enforcing < 0)) {
cached_enforcing = security_getenforce();
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");
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 */
}
log_debug("SELinux enforcing state cached to: %s", cached_enforcing ? "enforcing" : "permissive");
}
/* treat failure as enforcing mode */
return (cached_enforcing != 0);
return cached_enforcing > 0;
#else
return false;
#endif
@ -90,11 +102,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);
@ -109,25 +121,20 @@ int mac_selinux_init(void) {
before_timestamp = now(CLOCK_MONOTONIC);
label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
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;
if (!label_hnd)
return log_enforcing_errno(errno, "Failed to initialize SELinux context: %m");
after_timestamp = now(CLOCK_MONOTONIC);
after_mallinfo = mallinfo();
after_timestamp = now(CLOCK_MONOTONIC);
after_mallinfo = mallinfo();
l = after_mallinfo.uordblks > before_mallinfo.uordblks ? after_mallinfo.uordblks - before_mallinfo.uordblks : 0;
l = after_mallinfo.uordblks > before_mallinfo.uordblks ? after_mallinfo.uordblks - before_mallinfo.uordblks : 0;
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);
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 r;
return 0;
}
void mac_selinux_finish(void) {
@ -226,9 +233,7 @@ int mac_selinux_fix_container(const char *path, const char *inside_path, LabelFi
return 0;
fail:
log_enforcing_errno(r, "Unable to fix SELinux security context of %s (%s): %m", path, inside_path);
if (mac_selinux_enforcing())
return r;
return log_enforcing_errno(r, "Unable to fix SELinux security context of %s (%s): %m", path, inside_path);
#endif
return 0;
@ -243,21 +248,17 @@ int mac_selinux_apply(const char *path, const char *label) {
assert(path);
assert(label);
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;
}
if (setfilecon(path, label) < 0)
return log_enforcing_errno(errno, "Failed to set SELinux security context %s on path %s: %m", label, path);
#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);
@ -280,36 +281,39 @@ 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;
#endif
return r;
return 0;
#else
return -EOPNOTSUPP;
#endif
}
int mac_selinux_get_our_label(char **label) {
int r = -EOPNOTSUPP;
#if HAVE_SELINUX
int r;
assert(label);
#if HAVE_SELINUX
if (!mac_selinux_use())
return -EOPNOTSUPP;
r = getcon_raw(label);
if (r < 0)
return -errno;
#endif
return r;
return 0;
#else
return -EOPNOTSUPP;
#endif
}
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);
@ -362,9 +366,11 @@ 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;
#endif
return r;
return 0;
#else
return -EOPNOTSUPP;
#endif
}
char* mac_selinux_free(char *label) {
@ -399,26 +405,21 @@ static int selinux_create_file_prepare_abspath(const char *abspath, mode_t mode)
if (errno == ENOENT)
return 0;
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);
return log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", abspath);
}
if (mac_selinux_enforcing())
return -errno;
if (setfscreatecon_raw(filecon) < 0)
return log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", filecon, abspath);
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);
@ -440,15 +441,16 @@ int mac_selinux_create_file_prepare_at(int dirfd, const char *path, mode_t mode)
return -ENOMEM;
}
r = selinux_create_file_prepare_abspath(path, mode);
return selinux_create_file_prepare_abspath(path, mode);
#else
return 0;
#endif
return r;
}
int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
int r = 0;
#if HAVE_SELINUX
int r;
_cleanup_free_ char *abspath = NULL;
assert(path);
@ -460,9 +462,10 @@ int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
if (r < 0)
return r;
r = selinux_create_file_prepare_abspath(abspath, mode);
return selinux_create_file_prepare_abspath(abspath, mode);
#else
return 0;
#endif
return r;
}
void mac_selinux_create_file_clear(void) {
@ -480,17 +483,13 @@ 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;
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;
}
if (setsockcreatecon(label) < 0)
return log_enforcing_errno(errno, "Failed to set SELinux security context %s for sockets: %m", label);
#endif
return 0;
@ -561,15 +560,14 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
if (errno == ENOENT)
goto skipped;
log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", path);
if (mac_selinux_enforcing())
return -errno;
r = log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", path);
if (r < 0)
return r;
} else {
if (setfscreatecon_raw(fcon) < 0) {
log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", fcon, path);
if (mac_selinux_enforcing())
return -errno;
r = log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", fcon, path);
if (r < 0)
return r;
} else
context_changed = true;
}
@ -577,7 +575,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)
setfscreatecon_raw(NULL);
(void) setfscreatecon_raw(NULL);
return r;

View File

@ -746,6 +746,25 @@ 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),
@ -788,6 +807,9 @@ 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),
@ -1258,6 +1280,55 @@ 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,6 +54,7 @@
#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"
@ -2666,6 +2667,7 @@ 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);
@ -4195,6 +4197,10 @@ 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);
@ -4599,6 +4605,19 @@ 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,7 +155,9 @@ struct ExecContext {
char **unset_environment;
struct rlimit *rlimit[_RLIMIT_MAX];
char *working_directory, *root_directory, *root_image;
char *working_directory, *root_directory, *root_image, *root_verity, *root_hash_path;
void *root_hash;
size_t root_hash_size;
bool working_directory_missing_ok:1;
bool working_directory_home:1;

View File

@ -387,62 +387,25 @@ JobType job_type_lookup_merge(JobType a, JobType b) {
return job_merging_table[(a - 1) * a / 2 + b];
}
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(state, UNIT_INACTIVE, UNIT_FAILED) ||
job_later_link_matters(l->object, type, generation);
case JOB_STOP:
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) {
bool job_type_is_redundant(JobType a, UnitActiveState b) {
switch (a) {
case JOB_START:
return IN_SET(state, UNIT_ACTIVE, UNIT_RELOADING) && !job_later_link_matters(j, JOB_START, generation);
return IN_SET(b, UNIT_ACTIVE, UNIT_RELOADING);
case JOB_STOP:
return IN_SET(state, UNIT_INACTIVE, UNIT_FAILED) && !job_later_link_matters(j, JOB_STOP, generation);
return IN_SET(b, UNIT_INACTIVE, UNIT_FAILED);
case JOB_VERIFY_ACTIVE:
return IN_SET(state, UNIT_ACTIVE, UNIT_RELOADING);
return IN_SET(b, UNIT_ACTIVE, UNIT_RELOADING);
case JOB_RELOAD:
return
state == UNIT_RELOADING;
b == UNIT_RELOADING;
case JOB_RESTART:
return
state == UNIT_ACTIVATING;
b == UNIT_ACTIVATING;
case JOB_NOP:
return true;

View File

@ -196,8 +196,7 @@ _pure_ static inline bool job_type_is_superset(JobType a, JobType b) {
return a == job_type_lookup_merge(a, b);
}
bool job_later_link_matters(Job *j, JobType type, unsigned generation);
bool job_is_redundant(Job *j, unsigned generation);
bool job_type_is_redundant(JobType a, UnitActiveState b) _pure_;
/* 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,6 +23,8 @@ 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,6 +29,7 @@
#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"
@ -1413,6 +1414,64 @@ 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,6 +44,7 @@ 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,16 +1257,20 @@ 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 = NULL;
_cleanup_free_ void *root_hash_decoded = NULL;
_cleanup_free_ char *verity_data = NULL;
MountEntry *m = NULL, *mounts = NULL;
size_t n_mounts, root_hash_size = 0;
size_t n_mounts;
bool require_prefix = false;
const char *root;
int r = 0;
@ -1295,16 +1299,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, &root_hash_size, &verity_data);
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);
if (r < 0)
return log_debug_errno(r, "Failed to load root hash: %m");
dissect_image_flags |= verity_data ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0;
dissect_image_flags |= root_verity || verity_data ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0;
r = dissect_image(loop_device->fd, root_hash, root_hash_size, verity_data, dissect_image_flags, &dissected_image);
r = dissect_image(loop_device->fd, root_hash ?: root_hash_decoded, root_hash_size, root_verity ?: 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_size, verity_data, dissect_image_flags, &decrypted_image);
r = dissected_image_decrypt(dissected_image, NULL, root_hash ?: root_hash_decoded, root_hash_size, root_verity ?: verity_data, dissect_image_flags, &decrypted_image);
if (r < 0)
return log_debug_errno(r, "Failed to decrypt dissected image: %m");
}

View File

@ -88,6 +88,10 @@ 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, unsigned generation) {
static void transaction_drop_redundant(Transaction *tr) {
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, unsigned generation) {
LIST_FOREACH(transaction, k, j)
if (tr->anchor_job == k ||
!job_is_redundant(k, generation) ||
!job_type_is_redundant(k->type, unit_active_state(k->unit)) ||
(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, generation++);
transaction_drop_redundant(tr);
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, generation++);
transaction_drop_redundant(tr);
/* 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, arg_root_hash ? NULL : &arg_root_hash, &arg_root_hash_size,
r = verity_metadata_load(arg_image, NULL, 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,
0 }, /* Bind mount first */
MOUNT_MKDIR }, /* Bind mount first (mkdir/chown the mount point in case /sys/ is mounted as minimal skeleton tmpfs) */
{ NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT,
0 }, /* Then, make it r/o */
0 }, /* Then, make it r/o (don't mkdir/chown the mount point here, the previous entry already did that) */
#endif
};

View File

@ -5141,7 +5141,7 @@ static int run(int argc, char *argv[]) {
goto finish;
}
r = verity_metadata_load(arg_image, arg_root_hash ? NULL : &arg_root_hash, &arg_root_hash_size,
r = verity_metadata_load(arg_image, NULL, 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,6 +13,7 @@
#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"
@ -24,6 +25,7 @@
#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"
@ -849,6 +851,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
"ProtectHome",
"SELinuxContext",
"RootImage",
"RootVerity",
"RuntimeDirectoryPreserve",
"Personality",
"KeyringMode",
@ -1415,6 +1418,24 @@ 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, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data) {
int verity_metadata_load(const char *image, const char *root_hash_path, 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,24 +1465,31 @@ int verity_metadata_load(const char *image, void **ret_roothash, size_t *ret_roo
_cleanup_free_ char *text = NULL;
assert(ret_roothash_size);
r = getxattr_malloc(image, "user.verity.roothash", &text, true);
if (r < 0) {
char *fn, *e, *n;
if (!IN_SET(r, -ENODATA, -EOPNOTSUPP, -ENOENT))
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;
fn = newa(char, strlen(image) + STRLEN(".roothash") + 1);
n = stpcpy(fn, image);
e = endswith(fn, ".raw");
if (e)
n = e;
if (!IN_SET(r, -ENODATA, -EOPNOTSUPP, -ENOENT))
return r;
strcpy(n, ".roothash");
fn = newa(char, strlen(image) + STRLEN(".roothash") + 1);
n = stpcpy(fn, image);
e = endswith(fn, ".raw");
if (e)
n = e;
r = read_one_line_file(fn, &text);
if (r < 0 && r != -ENOENT)
return r;
strcpy(n, ".roothash");
r = read_one_line_file(fn, &text);
if (r < 0 && r != -ENOENT)
return r;
}
}
if (text) {

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, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data);
int verity_metadata_load(const char *image, const char *root_hash_path, 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,6 +152,10 @@ 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,6 +76,10 @@ 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,6 +196,8 @@ 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 /etc/nsswitch.conf
inst_any /etc/nsswitch.conf /usr/etc/nsswitch.conf
inst /etc/pam.conf || :
inst /etc/os-release
inst /etc/localtime

View File

@ -9,23 +9,25 @@
# export CONT_NAME="my-fancy-container"
# travis-ci/managers/debian.sh SETUP RUN CLEANUP
PHASES=(${@:-SETUP RUN RUN_ASAN CLEANUP})
PHASES=(${@:-SETUP RUN RUN_ASAN_UBSAN CLEANUP})
DEBIAN_RELEASE="${DEBIAN_RELEASE:-testing}"
CONT_NAME="${CONT_NAME:-debian-$DEBIAN_RELEASE-$RANDOM}"
CONT_NAME="${CONT_NAME:-systemd-debian-$DEBIAN_RELEASE}"
DOCKER_EXEC="${DOCKER_EXEC:-docker exec -it $CONT_NAME}"
DOCKER_RUN="${DOCKER_RUN:-docker run}"
REPO_ROOT="${REPO_ROOT:-$PWD}"
ADDITIONAL_DEPS=(python3-libevdev
python3-pyparsing
clang
perl
libpwquality-dev
fdisk
libfdisk-dev
libp11-kit-dev
libssl-dev
libzstd-dev
zstd)
ADDITIONAL_DEPS=(
clang
fdisk
libfdisk-dev
libp11-kit-dev
libpwquality-dev
libssl-dev
libzstd-dev
perl
python3-libevdev
python3-pyparsing
zstd
)
function info() {
echo -e "\033[33;1m$1\033[0m"
@ -54,7 +56,7 @@ for phase in "${PHASES[@]}"; do
$DOCKER_EXEC apt-get -y build-dep systemd
$DOCKER_EXEC apt-get -y install "${ADDITIONAL_DEPS[@]}"
;;
RUN|RUN_CLANG)
RUN|RUN_GCC|RUN_CLANG)
if [[ "$phase" = "RUN_CLANG" ]]; then
ENV_VARS="-e CC=clang -e CXX=clang++"
fi
@ -62,8 +64,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|RUN_CLANG_ASAN)
if [[ "$phase" = "RUN_CLANG_ASAN" ]]; then
RUN_ASAN_UBSAN|RUN_GCC_ASAN_UBSAN|RUN_CLANG_ASAN_UBSAN)
if [[ "$phase" = "RUN_CLANG_ASAN_UBSAN" ]]; 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,38 +9,32 @@
# export CONT_NAME="my-fancy-container"
# travis-ci/managers/fedora.sh SETUP RUN CLEANUP
PHASES=(${@:-SETUP RUN RUN_ASAN CLEANUP})
PHASES=(${@:-SETUP RUN RUN_ASAN_UBSAN CLEANUP})
FEDORA_RELEASE="${FEDORA_RELEASE:-rawhide}"
CONT_NAME="${CONT_NAME:-fedora-$FEDORA_RELEASE-$RANDOM}"
CONT_NAME="${CONT_NAME:-systemd-fedora-$FEDORA_RELEASE}"
DOCKER_EXEC="${DOCKER_EXEC:-docker exec -it $CONT_NAME}"
DOCKER_RUN="${DOCKER_RUN:-docker run}"
REPO_ROOT="${REPO_ROOT:-$PWD}"
ADDITIONAL_DEPS=(dnf-plugins-core
jq iputils
hostname libasan
python3-pyparsing
python3-evdev
libubsan
clang
llvm
perl
libfdisk-devel
libpwquality-devel
openssl-devel
p11-kit-devel)
ADDITIONAL_DEPS=(
clang
dnf-plugins-core
hostname libasan
jq iputils
libfdisk-devel
libpwquality-devel
libubsan
llvm
openssl-devel
p11-kit-devel
perl
python3-evdev
python3-pyparsing
)
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
@ -94,8 +88,8 @@ for phase in "${PHASES[@]}"; do
$DOCKER_EXEC ninja -v -C build
$DOCKER_EXEC ninja -C build test
;;
RUN_ASAN|RUN_CLANG_ASAN)
if [[ "$phase" = "RUN_CLANG_ASAN" ]]; then
RUN_ASAN|RUN_GCC_ASAN_UBSAN|RUN_CLANG_ASAN_UBSAN)
if [[ "$phase" = "RUN_CLANG_ASAN_UBSAN" ]]; then
ENV_VARS="-e CC=clang -e CXX=clang++"
MESON_ARGS="-Db_lundef=false" # See https://github.com/mesonbuild/meson/issues/764
fi
@ -110,46 +104,6 @@ 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