diff options
Diffstat (limited to '.github')
28 files changed, 1627 insertions, 0 deletions
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..b720b58 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +custom: ['https://spi-inc.org/projects/systemd/'] diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..a0dc872 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,183 @@ +name: Bug Report +description: A report of an error in a recent systemd version +labels: ["bug 🐛"] + +body: + - type: markdown + attributes: + value: Thanks for taking the time to fill out this bug report! + + - type: input + id: version + attributes: + label: systemd version the issue has been seen with + description: | + Do not submit bug reports about anything but the two most recently released *major* systemd versions upstream! + If there have been multiple stable releases for that major version, please consider updating to a recent one before reporting an issue. + When using a distro package, please make sure that the version reported is meaningful for upstream. + If a distro build is used, please just paste the package version, e.g. `systemd-250.7-1.fc36.x86_64`. + See https://github.com/systemd/systemd-stable/tags for the list of most recent releases. + For older version please use distribution trackers (see https://systemd.io/CONTRIBUTING#filing-issues). + placeholder: '251' + validations: + required: true + + - type: input + id: distro + attributes: + label: Used distribution + description: Used distribution and its version + placeholder: Fedora 36 + validations: + required: false + + - type: input + id: kernel + attributes: + label: Linux kernel version used + description: | + Please use `uname -r` to get linux kernel version. + placeholder: 5.17.12-300.fc36.ppc64le + validations: + required: false + + - type: dropdown + id: architecture + attributes: + label: CPU architectures issue was seen on + options: + - aarch64 + - alpha + - arm + - i686 + - ia64 + - loongarch + - mips + - parisc + - ppc (big endian) + - ppc64 (big endian) + - ppc64le + - riscv64 + - s390x + - sparc + - sparc64 + - x86_64 + - other + validations: + required: false + + - type: dropdown + id: component + attributes: + label: Component + description: Please chose components related to this issue. + multiple: true + # When updating list of components please also update labeling policy + # policy: `.github/advanced-issue-labeler.yml` + options: + - 'bootctl' + - 'coredumpctl' + - 'homectl' + - 'hostnamectl' + - 'hardware database files' + - 'journalctl' + - 'kernel-install' + - 'loginctl' + - 'machinectl' + - 'networkctl' + - 'nss-resolve' + - 'oomctl' + - 'pam_systemd' + - 'pam_systemd_home' + - 'portablectl' + - 'resolvectl' + - 'rpm scriptlets' + - 'systemctl' + - 'systemd' + - 'systemd-analyze' + - 'systemd-ask-password' + - 'systemd-binfmt' + - 'systemd-boot' + - 'systemd-cgtop' + - 'systemd-coredump' + - 'systemd-cryptsetup' + - 'systemd-delta' + - 'systemd-env-generator' + - 'systemd-fsck' + - 'systemd-gpt-auto-generator' + - 'systemd-growfs' + - 'systemd-homed' + - 'systemd-hostnamed' + - 'systemd-hwdb' + - 'systemd-import' + - 'systemd-journal-gatewayd' + - 'systemd-journal-remote' + - 'systemd-journal-upload' + - 'systemd-journald' + - 'systemd-logind' + - 'systemd-machined' + - 'systemd-modules-load' + - 'systemd-network-generator' + - 'systemd-networkd' + - 'systemd-networkd-wait-online' + - 'systemd-nspawn' + - 'systemd-oomd' + - 'systemd-portabled' + - 'systemd-pstore' + - 'systemd-repart' + - 'systemd-resolved' + - 'systemd-rfkill' + - 'systemd-run' + - 'systemd-stub' + - 'systemd-sysctl' + - 'systemd-sysext' + - 'systemd-sysusers' + - 'systemd-sysv-generator' + - 'systemd-timedate' + - 'systemd-timesync' + - 'systemd-tmpfiles' + - 'systemd-udevd' + - 'systemd-userdb' + - 'systemd-veritysetup' + - 'systemd-xdg-autostart-generator' + - 'timedatectl' + - 'udevadm' + - 'udev rule files' + - 'userdbctl' + - 'tests' + - 'other' + validations: + required: false + + - type: textarea + id: expected-behaviour + attributes: + label: Expected behaviour you didn't see + validations: + required: false + + - type: textarea + id: unexpected-behaviour + attributes: + label: Unexpected behaviour you saw + validations: + required: false + + - type: textarea + id: steps-to-reproduce + attributes: + label: Steps to reproduce the problem + validations: + required: false + + - type: textarea + id: additional-information + attributes: + label: Additional program output to the terminal or log subsystem illustrating the issue + description: | + Please paste relevant program terminal or journal output here, ideally when generated in debug mode (try setting the `SYSTEMD_LOG_LEVEL=debug` environment variable). + For very long copy/pasted data consider using a service like https://gist.github.com/. Where copy/paste is not possible (for example early boot or late shutdown), a photo of the screen might do too, but text is always much preferred. + placeholder: This will be automatically formatted into code, so no need for backticks. + render: sh + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..159187e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,9 @@ +--- +# vi: ts=2 sw=2 et: +# SPDX-License-Identifier: LGPL-2.1-or-later + +blank_issues_enabled: true +contact_links: + - name: systemd-devel mailing list + url: https://lists.freedesktop.org/mailman/listinfo/systemd-devel + about: Please ask (and answer) questions here, use the issue tracker only for issues. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..1f24851 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,124 @@ +name: Feature request +description: Suggest an improvement +labels: ["RFE 🎁"] + +body: + - type: markdown + attributes: + value: Thanks for taking the time to fill out this feature request! + + - type: dropdown + id: component + attributes: + label: Component + description: Please chose components related to this feature request. + multiple: true + # When updating list of components please also update labeling policy + # policy: `.github/advanced-issue-labeler.yml` + options: + - 'bootctl' + - 'coredumpctl' + - 'homectl' + - 'hostnamectl' + - 'hardware database files' + - 'journalctl' + - 'kernel-install' + - 'loginctl' + - 'machinectl' + - 'networkctl' + - 'nss-resolve' + - 'oomctl' + - 'pam_systemd' + - 'pam_systemd_home' + - 'portablectl' + - 'resolvectl' + - 'rpm scriptlets' + - 'systemctl' + - 'systemd' + - 'systemd-analyze' + - 'systemd-ask-password' + - 'systemd-binfmt' + - 'systemd-boot' + - 'systemd-cgtop' + - 'systemd-coredump' + - 'systemd-cryptsetup' + - 'systemd-delta' + - 'systemd-env-generator' + - 'systemd-fsck' + - 'systemd-gpt-auto-generator' + - 'systemd-growfs' + - 'systemd-homed' + - 'systemd-hostnamed' + - 'systemd-hwdb' + - 'systemd-import' + - 'systemd-journal-gatewayd' + - 'systemd-journal-remote' + - 'systemd-journal-upload' + - 'systemd-journald' + - 'systemd-logind' + - 'systemd-machined' + - 'systemd-modules-load' + - 'systemd-network-generator' + - 'systemd-networkd' + - 'systemd-networkd-wait-online' + - 'systemd-nspawn' + - 'systemd-oomd' + - 'systemd-portabled' + - 'systemd-pstore' + - 'systemd-repart' + - 'systemd-resolved' + - 'systemd-rfkill' + - 'systemd-run' + - 'systemd-stub' + - 'systemd-sysctl' + - 'systemd-sysext' + - 'systemd-sysusers' + - 'systemd-sysv-generator' + - 'systemd-timedate' + - 'systemd-timesync' + - 'systemd-tmpfiles' + - 'systemd-udevd' + - 'systemd-userdb' + - 'systemd-veritysetup' + - 'systemd-xdg-autostart-generator' + - 'timedatectl' + - 'udevadm' + - 'udev rule files' + - 'userdbctl' + - 'tests' + - 'other' + validations: + required: false + + - type: textarea + id: description + attributes: + label: Is your feature request related to a problem? Please describe + description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + validations: + required: false + + - type: textarea + id: solution + attributes: + label: Describe the solution you'd like + description: A clear and concise description of what you want to happen. + validations: + required: false + + - type: textarea + id: alternatives + attributes: + label: Describe alternatives you've considered + description: A clear and concise description of any alternative solutions or features you've considered. + validations: + required: false + + - type: input + id: version + attributes: + label: The systemd version you checked that didn't have the feature you are asking for + description: If this is not the most recently released upstream version, then please check first if it has that feature already. + placeholder: '251' + validations: + required: false diff --git a/.github/advanced-issue-labeler.yml b/.github/advanced-issue-labeler.yml new file mode 100644 index 0000000..38388fb --- /dev/null +++ b/.github/advanced-issue-labeler.yml @@ -0,0 +1,146 @@ +--- +# syntax - https://github.com/redhat-plumbers-in-action/advanced-issue-labeler#policy + +policy: + - template: [bug_report.yml, feature_request.yml] + section: + - id: [component] + block-list: [other] + label: + - name: analyze + keys: ['systemd-analyze'] + + - name: ask-password + keys: ['systemd-ask-password'] + + - name: binfmt + keys: ['systemd-binfmt'] + + - name: cgtop + keys: ['systemd-cgtop'] + + - name: coredump + keys: ['coredumpctl', 'systemd-coredump'] + + - name: cryptsetup + keys: ['systemd-cryptsetup'] + + - name: delta + keys: ['systemd-delta'] + + - name: env + keys: ['systemd-env-generator'] + + - name: fsck + keys: ['systemd-fsck'] + + - name: gpt-auto + keys: ['systemd-gpt-auto-generator'] + + - name: growfs + keys: ['systemd-growfs'] + + - name: homed + keys: ['systemd-homed', 'homectl', 'pam_systemd_home'] + + - name: hostname + keys: ['systemd-hostnamed', 'hostnamectl'] + + - name: hwdb + keys: ['systemd-hwdb', 'hardware database files'] + + - name: import + keys: ['systemd-import'] + + - name: journal + keys: ['systemd-journald', 'journalctl'] + + - name: journal-remote + keys: ['systemd-journal-remote', 'systemd-journal-upload', 'systemd-journal-gatewayd'] + + - name: kernel-install + keys: ['kernel-install'] + + - name: logind + keys: ['systemd-logind', 'loginctl', 'pam_systemd'] + + - name: machined + keys: ['systemd-machined', 'machinectl'] + + - name: modules-load + keys: ['systemd-modules-load'] + + - name: network + keys: ['systemd-networkd', 'networkctl', 'systemd-networkd-wait-online', 'systemd-network-generator'] + + - name: nspawn + keys: ['systemd-nspawn'] + + - name: oomd + keys: ['systemd-oomd', 'oomctl'] + + - name: pid1 + keys: ['systemd'] + + - name: portabled + keys: ['systemd-portabled', 'portablectl'] + + - name: pstore + keys: ['systemd-pstore'] + + - name: repart + keys: ['systemd-repart'] + + - name: resolve + keys: ['systemd-resolved', 'resolvectl', 'nss-resolve'] + + - name: rfkill + keys: ['systemd-rfkill'] + + - name: rpm + keys: ['rpm scriptlets'] + + - name: run + keys: ['systemd-run'] + + - name: sd-boot/sd-stub/bootctl + keys: ['bootctl', 'systemd-boot', 'systemd-stub'] + + - name: sysctl + keys: ['systemd-sysctl'] + + - name: sysext + keys: ['systemd-sysext'] + + - name: systemctl + keys: ['systemctl'] + + - name: sysusers + keys: ['systemd-sysusers'] + + - name: sysv + keys: ['systemd-sysv-generator'] + + - name: tests + keys: ['tests'] + + - name: timedate + keys: ['systemd-timedate', 'timedatectl'] + + - name: timesync + keys: ['systemd-timesync'] + + - name: tmpfiles + keys: ['systemd-tmpfiles'] + + - name: udev + keys: ['systemd-udevd', 'udevadm', 'udev rule files'] + + - name: userdb + keys: ['systemd-userdb', 'userdbctl'] + + - name: veritysetup + keys: ['systemd-veritysetup'] + + - name: xdg-autostart + keys: ['systemd-xdg-autostart-generator'] diff --git a/.github/codeql-config.yml b/.github/codeql-config.yml new file mode 100644 index 0000000..7c01d32 --- /dev/null +++ b/.github/codeql-config.yml @@ -0,0 +1,12 @@ +--- +# vi: ts=2 sw=2 et: +# SPDX-License-Identifier: LGPL-2.1-or-later +name: "CodeQL config" + +disable-default-queries: false + +queries: + - name: Enable possibly useful queries which are disabled by default + uses: ./.github/codeql-custom.qls + - name: systemd-specific CodeQL queries + uses: ./.github/codeql-queries/ diff --git a/.github/codeql-custom.qls b/.github/codeql-custom.qls new file mode 100644 index 0000000..d35fbe3 --- /dev/null +++ b/.github/codeql-custom.qls @@ -0,0 +1,44 @@ +--- +# vi: ts=2 sw=2 et syntax=yaml: +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Note: it is not recommended to directly reference the respective queries from +# the github/codeql repository, so we have to "dance" around it using +# a custom QL suite +# See: +# - https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#running-additional-queries +# - https://github.com/github/codeql-action/issues/430#issuecomment-806092120 +# - https://codeql.github.com/docs/codeql-cli/creating-codeql-query-suites/ + +# Note: the codeql/<lang>-queries pack name can be found in the CodeQL repo[0] +# in <lang>/ql/src/qlpack.yml. The respective codeql-suites are then +# under <lang>/ql/src/codeql-suites/. +# +# [0] https://github.com/github/codeql +- import: codeql-suites/cpp-lgtm.qls + from: codeql/cpp-queries +- import: codeql-suites/python-lgtm.qls + from: codeql/python-queries +- include: + id: + - cpp/bad-strncpy-size + - cpp/declaration-hides-variable + - cpp/include-non-header + - cpp/inconsistent-null-check + - cpp/mistyped-function-arguments + - cpp/nested-loops-with-same-variable + - cpp/sizeof-side-effect + - cpp/suspicious-pointer-scaling + - cpp/suspicious-pointer-scaling-void + - cpp/suspicious-sizeof + - cpp/unsafe-strcat + - cpp/unsafe-strncat + - cpp/unsigned-difference-expression-compared-zero + - cpp/unused-local-variable + tags: + - "security" + - "correctness" + severity: "error" +- exclude: + id: + - cpp/fixme-comment diff --git a/.github/codeql-queries/PotentiallyDangerousFunction.ql b/.github/codeql-queries/PotentiallyDangerousFunction.ql new file mode 100644 index 0000000..d5a5635 --- /dev/null +++ b/.github/codeql-queries/PotentiallyDangerousFunction.ql @@ -0,0 +1,59 @@ +/** + * vi: sw=2 ts=2 et syntax=ql: + * + * Borrowed from + * https://github.com/Semmle/ql/blob/master/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql + * + * @name Use of potentially dangerous function + * @description Certain standard library functions are dangerous to call. + * @id cpp/potentially-dangerous-function + * @kind problem + * @problem.severity error + * @precision high + * @tags reliability + * security + */ +import cpp + +predicate potentiallyDangerousFunction(Function f, string message) { + ( + f.getQualifiedName() = "fgets" and + message = "Call to fgets() is potentially dangerous. Use read_line() instead." + ) or ( + f.getQualifiedName() = "strtok" and + message = "Call to strtok() is potentially dangerous. Use extract_first_word() instead." + ) or ( + f.getQualifiedName() = "strsep" and + message = "Call to strsep() is potentially dangerous. Use extract_first_word() instead." + ) or ( + f.getQualifiedName() = "dup" and + message = "Call to dup() is potentially dangerous. Use fcntl(fd, FD_DUPFD_CLOEXEC, 3) instead." + ) or ( + f.getQualifiedName() = "htonl" and + message = "Call to htonl() is confusing. Use htobe32() instead." + ) or ( + f.getQualifiedName() = "htons" and + message = "Call to htons() is confusing. Use htobe16() instead." + ) or ( + f.getQualifiedName() = "ntohl" and + message = "Call to ntohl() is confusing. Use be32toh() instead." + ) or ( + f.getQualifiedName() = "ntohs" and + message = "Call to ntohs() is confusing. Use be16toh() instead." + ) or ( + f.getQualifiedName() = "strerror" and + message = "Call to strerror() is not thread-safe. Use printf()'s %m format string or STRERROR() instead." + ) or ( + f.getQualifiedName() = "accept" and + message = "Call to accept() is not O_CLOEXEC-safe. Use accept4() instead." + ) or ( + f.getQualifiedName() = "dirname" and + message = "Call dirname() is icky. Use path_extract_directory() instead." + ) +} + +from FunctionCall call, Function target, string message +where + call.getTarget() = target and + potentiallyDangerousFunction(target, message) +select call, message diff --git a/.github/codeql-queries/UninitializedVariableWithCleanup.ql b/.github/codeql-queries/UninitializedVariableWithCleanup.ql new file mode 100644 index 0000000..e514111 --- /dev/null +++ b/.github/codeql-queries/UninitializedVariableWithCleanup.ql @@ -0,0 +1,110 @@ +/** + * vi: sw=2 ts=2 et syntax=ql: + * + * Based on cpp/uninitialized-local. + * + * @name Potentially uninitialized local variable using the cleanup attribute + * @description Running the cleanup handler on a possibly uninitialized variable + * is generally a bad idea. + * @id cpp/uninitialized-local-with-cleanup + * @kind problem + * @problem.severity error + * @precision high + * @tags security + */ + +import cpp +import semmle.code.cpp.controlflow.StackVariableReachability + +/** Auxiliary predicate: List cleanup functions we want to explicitly ignore + * since they don't do anything illegal even when the variable is uninitialized + */ +predicate cleanupFunctionDenyList(string fun) { + fun = "erase_char" +} + +/** + * A declaration of a local variable using __attribute__((__cleanup__(x))) + * that leaves the variable uninitialized. + */ +DeclStmt declWithNoInit(LocalVariable v) { + result.getADeclaration() = v and + not v.hasInitializer() and + /* The variable has __attribute__((__cleanup__(...))) set */ + v.getAnAttribute().hasName("cleanup") and + /* Check if the cleanup function is not on a deny list */ + not cleanupFunctionDenyList(v.getAnAttribute().getAnArgument().getValueText()) +} + +class UninitialisedLocalReachability extends StackVariableReachability { + UninitialisedLocalReachability() { this = "UninitialisedLocal" } + + override predicate isSource(ControlFlowNode node, StackVariable v) { node = declWithNoInit(v) } + + /* Note: _don't_ use the `useOfVarActual()` predicate here (and a couple of lines + * below), as it assumes that the callee always modifies the variable if + * it's passed to the function. + * + * i.e.: + * _cleanup_free char *x; + * fun(&x); + * puts(x); + * + * `useOfVarActual()` won't treat this as an uninitialized read even if the callee + * doesn't modify the argument, however, `useOfVar()` will + */ + override predicate isSink(ControlFlowNode node, StackVariable v) { useOfVar(v, node) } + + override predicate isBarrier(ControlFlowNode node, StackVariable v) { + /* only report the _first_ possibly uninitialized use */ + useOfVar(v, node) or + ( + /* If there's a return statement somewhere between the variable declaration + * and a possible definition, don't accept is as a valid initialization. + * + * E.g.: + * _cleanup_free_ char *x; + * ... + * if (...) + * return; + * ... + * x = malloc(...); + * + * is not a valid initialization, since we might return from the function + * _before_ the actual initialization (emphasis on _might_, since we + * don't know if the return statement might ever evaluate to true). + */ + definitionBarrier(v, node) and + not exists(ReturnStmt rs | + /* The attribute check is "just" a complexity optimization */ + v.getFunction() = rs.getEnclosingFunction() and v.getAnAttribute().hasName("cleanup") | + rs.getLocation().isBefore(node.getLocation()) + ) + ) + } +} + +pragma[noinline] +predicate containsInlineAssembly(Function f) { exists(AsmStmt s | s.getEnclosingFunction() = f) } + +/** + * Auxiliary predicate: List common exceptions or false positives + * for this check to exclude them. + */ +VariableAccess commonException() { + /* If the uninitialized use we've found is in a macro expansion, it's + * typically something like va_start(), and we don't want to complain. */ + result.getParent().isInMacroExpansion() + or + result.getParent() instanceof BuiltInOperation + or + /* Finally, exclude functions that contain assembly blocks. It's + * anyone's guess what happens in those. */ + containsInlineAssembly(result.getEnclosingFunction()) +} + +from UninitialisedLocalReachability r, LocalVariable v, VariableAccess va +where + r.reaches(_, v, va) and + not va = commonException() +select va, "The variable $@ may not be initialized here, but has a cleanup handler.", v, v.getName() diff --git a/.github/codeql-queries/qlpack.yml b/.github/codeql-queries/qlpack.yml new file mode 100644 index 0000000..a1a2dec --- /dev/null +++ b/.github/codeql-queries/qlpack.yml @@ -0,0 +1,11 @@ +--- +# vi: ts=2 sw=2 et syntax=yaml: +# SPDX-License-Identifier: LGPL-2.1-or-later + +library: false +name: systemd/cpp-queries +version: 0.0.1 +dependencies: + codeql/cpp-all: "*" + codeql/suite-helpers: "*" +extractor: cpp diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..3e067c1 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" + open-pull-requests-limit: 2 + - package-ecosystem: "pip" + directory: "/.github/workflows" + schedule: + interval: "monthly" + open-pull-requests-limit: 2 + - package-ecosystem: "docker" + directory: "/.clusterfuzzlite" + schedule: + interval: "monthly" + open-pull-requests-limit: 2 diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000..7d128f4 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +hwdb: + - hwdb.d/**/* +units: + - units/**/* +documentation: + - NEWS + - docs/* +network: + - src/libsystemd-network/**/* + - src/network/**/* +udev: + - src/udev/**/* + - src/libudev/* +selinux: + - '**/*selinux*' +apparmor: + - '**/*apparmor*' +meson: + - meson_option.txt +mkosi: + - .mkosi/* + - mkosi.build +busctl: + - src/busctl/* +systemctl: + - src/systemctl/* +journal: + - src/journal/* +journal-remote: + - src/journal-remote/* +portable: + - src/portable/**/* +resolve: + - src/resolve/* +timedate: + - src/timedate/* +timesync: + - src/timesync/* diff --git a/.github/pull_request_template.md.disabled b/.github/pull_request_template.md.disabled new file mode 100644 index 0000000..a133346 --- /dev/null +++ b/.github/pull_request_template.md.disabled @@ -0,0 +1,5 @@ +# CODE FREEZE NOTICE + +An -rc1 tag has been created and a release is being prepared, so please note that +PRs introducing new features and APIs will be held back until the new version +has been released. diff --git a/.github/workflows/build_test.sh b/.github/workflows/build_test.sh new file mode 100755 index 0000000..e08f470 --- /dev/null +++ b/.github/workflows/build_test.sh @@ -0,0 +1,165 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: LGPL-2.1-or-later + +set -ex + +info() { echo -e "\033[33;1m$1\033[0m"; } +fatal() { echo >&2 -e "\033[31;1m$1\033[0m"; exit 1; } +success() { echo >&2 -e "\033[32;1m$1\033[0m"; } + +ARGS=( + "--optimization=0" + "--optimization=s -Dgnu-efi=true -Defi-cflags=-m32 -Defi-libdir=/usr/lib32" + "--optimization=3 -Db_lto=true -Ddns-over-tls=false" + "--optimization=3 -Db_lto=false -Dtpm2=false -Dlibfido2=false -Dp11kit=false" + "--optimization=3 -Ddns-over-tls=openssl" + "--optimization=3 -Dfexecve=true -Dstandalone-binaries=true -Dstatic-libsystemd=true -Dstatic-libudev=true" + "-Db_ndebug=true" +) +PACKAGES=( + cryptsetup-bin + expect + fdisk + gettext + iputils-ping + isc-dhcp-client + itstool + kbd + libblkid-dev + libbpf-dev + libc6-dev-i386 + libcap-dev + libcurl4-gnutls-dev + libfdisk-dev + libfido2-dev + libgpg-error-dev + liblz4-dev + liblzma-dev + libmicrohttpd-dev + libmount-dev + libp11-kit-dev + libpwquality-dev + libqrencode-dev + libssl-dev + libtss2-dev + libxkbcommon-dev + libxtables-dev + libzstd-dev + mold + mount + net-tools + perl + python3-evdev + python3-jinja2 + python3-lxml + python3-pip + python3-pyparsing + python3-setuptools + quota + strace + unifont + util-linux + zstd +) +COMPILER="${COMPILER:?}" +COMPILER_VERSION="${COMPILER_VERSION:?}" +LINKER="${LINKER:?}" +CRYPTOLIB="${CRYPTOLIB:?}" +RELEASE="$(lsb_release -cs)" + +bash -c "echo 'deb-src http://archive.ubuntu.com/ubuntu/ $RELEASE main restricted universe multiverse' >>/etc/apt/sources.list" + +# Note: As we use postfixed clang/gcc binaries, we need to override $AR +# as well, otherwise meson falls back to ar from binutils which +# doesn't work with LTO +if [[ "$COMPILER" == clang ]]; then + CC="clang-$COMPILER_VERSION" + CXX="clang++-$COMPILER_VERSION" + AR="llvm-ar-$COMPILER_VERSION" + + # Prefer the distro version if available + if ! apt install --dry-run "llvm-$COMPILER_VERSION" >/dev/null; then + # Latest LLVM stack deb packages provided by https://apt.llvm.org/ + # Following snippet was partly borrowed from https://apt.llvm.org/llvm.sh + wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | gpg --yes --dearmor --output /usr/share/keyrings/apt-llvm-org.gpg + printf "deb [signed-by=/usr/share/keyrings/apt-llvm-org.gpg] http://apt.llvm.org/%s/ llvm-toolchain-%s-%s main\n" \ + "$RELEASE" "$RELEASE" "$COMPILER_VERSION" >/etc/apt/sources.list.d/llvm-toolchain.list + fi + + PACKAGES+=("clang-$COMPILER_VERSION" "lldb-$COMPILER_VERSION" "lld-$COMPILER_VERSION" "clangd-$COMPILER_VERSION") +elif [[ "$COMPILER" == gcc ]]; then + CC="gcc-$COMPILER_VERSION" + CXX="g++-$COMPILER_VERSION" + AR="gcc-ar-$COMPILER_VERSION" + + if ! apt install --dry-run "gcc-$COMPILER_VERSION" >/dev/null; then + # Latest gcc stack deb packages provided by + # https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test + add-apt-repository -y ppa:ubuntu-toolchain-r/test + fi + + PACKAGES+=("gcc-$COMPILER_VERSION" "gcc-$COMPILER_VERSION-multilib") +else + fatal "Unknown compiler: $COMPILER" +fi + +# PPA with some newer build dependencies (like zstd) +add-apt-repository -y ppa:upstream-systemd-ci/systemd-ci +apt-get -y update +apt-get -y build-dep systemd +apt-get -y install "${PACKAGES[@]}" +# Install more or less recent meson and ninja with pip, since the distro versions don't +# always support all the features we need (like --optimization=). Since the build-dep +# command above installs the distro versions, let's install the pip ones just +# locally and add the local bin directory to the $PATH. +pip3 install --user -r .github/workflows/requirements.txt --require-hashes +export PATH="$HOME/.local/bin:$PATH" + +$CC --version +meson --version +ninja --version + +for args in "${ARGS[@]}"; do + SECONDS=0 + + # The install_tag feature introduced in 0.60 causes meson to fail with fatal-meson-warnings + # "Project targeting '>= 0.53.2' but tried to use feature introduced in '0.60.0': install_tag arg in custom_target" + # It can be safely removed from the CI since it isn't actually used anywhere to test anything. + find . -type f -name meson.build -exec sed -i '/install_tag/d' '{}' '+' + + # mold < 1.1 does not support LTO. + if dpkg --compare-versions "$(dpkg-query --showformat='${Version}' --show mold)" ge 1.1; then + fatal "Newer mold version detected, please remove this workaround." + elif [[ "$args" == *"-Db_lto=true"* ]]; then + LD="gold" + else + LD="$LINKER" + fi + + info "Checking build with $args" + # shellcheck disable=SC2086 + if ! AR="$AR" \ + CC="$CC" CC_LD="$LD" CFLAGS="-Werror" \ + CXX="$CXX" CXX_LD="$LD" CXXFLAGS="-Werror" \ + meson -Dtests=unsafe -Dslow-tests=true -Dfuzz-tests=true --werror \ + -Dnobody-group=nogroup -Dcryptolib="${CRYPTOLIB:?}" \ + $args build; then + + cat build/meson-logs/meson-log.txt + fatal "meson failed with $args" + fi + + if ! meson compile -C build -v; then + fatal "'meson compile' failed with $args" + fi + + for loader in build/src/boot/efi/*.efi; do + if sbverify --list "$loader" |& grep -q "gap in section table"; then + fatal "$loader: Gaps found in section table" + fi + done + + git clean -dxf + + success "Build with $args passed in $SECONDS seconds" +done diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml new file mode 100644 index 0000000..cd6937e --- /dev/null +++ b/.github/workflows/build_test.yml @@ -0,0 +1,38 @@ +--- +# vi: ts=2 sw=2 et: +# SPDX-License-Identifier: LGPL-2.1-or-later +# +name: Build test +on: + pull_request: + paths: + - '**/meson.build' + - '.github/workflows/**' + - 'meson_options.txt' + - 'src/**' + - 'test/fuzz/**' + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-22.04 + concurrency: + group: ${{ github.workflow }}-${{ toJSON(matrix.env) }}-${{ github.ref }} + cancel-in-progress: true + strategy: + fail-fast: false + matrix: + env: + - { COMPILER: "gcc", COMPILER_VERSION: "11", LINKER: "bfd", CRYPTOLIB: "gcrypt" } + - { COMPILER: "gcc", COMPILER_VERSION: "12", LINKER: "gold", CRYPTOLIB: "openssl" } + - { COMPILER: "clang", COMPILER_VERSION: "13", LINKER: "mold", CRYPTOLIB: "gcrypt" } + - { COMPILER: "clang", COMPILER_VERSION: "14", LINKER: "lld", CRYPTOLIB: "openssl" } + - { COMPILER: "clang", COMPILER_VERSION: "15", LINKER: "bfd", CRYPTOLIB: "auto" } + env: ${{ matrix.env }} + steps: + - name: Repository checkout + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + - name: ${{ format('Build check ({0}-{1}-{2}-{3})', env.COMPILER, env.COMPILER_VERSION, env.LINKER, env.CRYPTOLIB) }} + run: sudo -E .github/workflows/build_test.sh diff --git a/.github/workflows/cflite_pr.yml b/.github/workflows/cflite_pr.yml new file mode 100644 index 0000000..a35a97f --- /dev/null +++ b/.github/workflows/cflite_pr.yml @@ -0,0 +1,39 @@ +--- +# vi: ts=2 sw=2 et: +# SPDX-License-Identifier: LGPL-2.1-or-later +# +name: ClusterFuzzLite PR fuzzing +on: + pull_request: + branches: + - main + - v[0-9]+-stable + +permissions: read-all + +jobs: + PR: + runs-on: ubuntu-latest + if: github.repository != 'systemd/systemd' || github.event.pull_request.user.login == 'dependabot[bot]' + concurrency: + group: ${{ github.workflow }}-${{ matrix.sanitizer }}-${{ github.ref }} + cancel-in-progress: true + strategy: + fail-fast: false + matrix: + sanitizer: [address, undefined, memory] + steps: + - name: Build Fuzzers (${{ matrix.sanitizer }}) + id: build + uses: google/clusterfuzzlite/actions/build_fuzzers@v1 + with: + sanitizer: ${{ matrix.sanitizer }} + github-token: ${{ secrets.GITHUB_TOKEN }} + - name: Run Fuzzers (${{ matrix.sanitizer }}) + id: run + uses: google/clusterfuzzlite/actions/run_fuzzers@v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + fuzz-seconds: 1200 + mode: 'code-change' + sanitizer: ${{ matrix.sanitizer }} diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml new file mode 100644 index 0000000..25731ab --- /dev/null +++ b/.github/workflows/cifuzz.yml @@ -0,0 +1,62 @@ +--- +# vi: ts=2 sw=2 et: +# SPDX-License-Identifier: LGPL-2.1-or-later +# See: https://google.github.io/oss-fuzz/getting-started/continuous-integration/ + +name: CIFuzz + +permissions: + contents: read + +on: + pull_request: + paths: + - '**/meson.build' + - '.github/workflows/**' + - 'meson_options.txt' + - 'src/**' + - 'test/fuzz/**' + - 'tools/oss-fuzz.sh' + push: + branches: + - main +jobs: + Fuzzing: + runs-on: ubuntu-latest + if: github.repository == 'systemd/systemd' + concurrency: + group: ${{ github.workflow }}-${{ matrix.sanitizer }}-${{ matrix.architecture }}-${{ github.ref }} + cancel-in-progress: true + strategy: + fail-fast: false + matrix: + sanitizer: [address, undefined, memory] + architecture: [x86_64] + include: + - sanitizer: address + architecture: i386 + steps: + - name: Build Fuzzers (${{ matrix.sanitizer }}) + id: build + uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master + with: + oss-fuzz-project-name: 'systemd' + dry-run: false + allowed-broken-targets-percentage: 0 + # keep-unaffected-fuzz-targets should be removed once https://github.com/google/oss-fuzz/issues/7011 is fixed + keep-unaffected-fuzz-targets: true + sanitizer: ${{ matrix.sanitizer }} + architecture: ${{ matrix.architecture }} + - name: Run Fuzzers (${{ matrix.sanitizer }}) + uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master + with: + oss-fuzz-project-name: 'systemd' + fuzz-seconds: 600 + dry-run: false + sanitizer: ${{ matrix.sanitizer }} + - name: Upload Crash + uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 + if: failure() && steps.build.outcome == 'success' + with: + name: ${{ matrix.sanitizer }}-${{ matrix.architecture }}-artifacts + path: ./out/artifacts diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..b531753 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,58 @@ +--- +# vi: ts=2 sw=2 et: +# SPDX-License-Identifier: LGPL-2.1-or-later +# +name: "CodeQL" + +on: + pull_request: + branches: + - main + - v[0-9]+-stable + paths: + - '**/meson.build' + - '.github/**/codeql*' + - 'src/**' + - 'test/**' + - 'tools/**' + push: + branches: + - main + - v[0-9]+-stable + +permissions: + contents: read + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-22.04 + concurrency: + group: ${{ github.workflow }}-${{ matrix.language }}-${{ github.ref }} + cancel-in-progress: true + permissions: + actions: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: ['cpp', 'python'] + + steps: + - name: Checkout repository + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + + - name: Initialize CodeQL + uses: github/codeql-action/init@0c670bbf0414f39666df6ce8e718ec5662c21e03 + with: + languages: ${{ matrix.language }} + config-file: ./.github/codeql-config.yml + + - run: sudo -E .github/workflows/unit_tests.sh SETUP + + - name: Autobuild + uses: github/codeql-action/autobuild@0c670bbf0414f39666df6ce8e718ec5662c21e03 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@0c670bbf0414f39666df6ce8e718ec5662c21e03 diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml new file mode 100644 index 0000000..3fbebc6 --- /dev/null +++ b/.github/workflows/coverity.yml @@ -0,0 +1,30 @@ +--- +# vi: ts=2 sw=2 et: +# SPDX-License-Identifier: LGPL-2.1-or-later +# +name: Coverity + +on: + schedule: + # Run Coverity daily at midnight + - cron: '0 0 * * *' + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-22.04 + if: github.repository == 'systemd/systemd' + env: + # Set in repo settings -> secrets -> actions + COVERITY_SCAN_TOKEN: "${{ secrets.COVERITY_SCAN_TOKEN }}" + COVERITY_SCAN_NOTIFICATION_EMAIL: "${{ secrets.COVERITY_SCAN_NOTIFICATION_EMAIL }}" + steps: + - name: Repository checkout + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + # Reuse the setup phase of the unit test script to avoid code duplication + - name: Install build dependencies + run: sudo -E .github/workflows/unit_tests.sh SETUP + - name: Build & upload the results + run: tools/coverity.sh diff --git a/.github/workflows/differential-shellcheck.yml b/.github/workflows/differential-shellcheck.yml new file mode 100644 index 0000000..20ce681 --- /dev/null +++ b/.github/workflows/differential-shellcheck.yml @@ -0,0 +1,31 @@ +--- +# https://github.com/redhat-plumbers-in-action/differential-shellcheck#readme + +name: Differential ShellCheck +on: + pull_request: + branches: + - main + +permissions: + contents: read + +jobs: + lint: + if: github.event.repository.name != 'systemd-security' + runs-on: ubuntu-latest + + permissions: + security-events: write + pull-requests: write + + steps: + - name: Repository checkout + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + with: + fetch-depth: 0 + + - name: Differential ShellCheck + uses: redhat-plumbers-in-action/differential-shellcheck@1b1b75e42f0694c1012228513b21617a748c866e + with: + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/issue_labeler.yml b/.github/workflows/issue_labeler.yml new file mode 100644 index 0000000..0a97bf4 --- /dev/null +++ b/.github/workflows/issue_labeler.yml @@ -0,0 +1,36 @@ +--- + +name: Issue labeler +on: + issues: + types: [ opened ] + +permissions: + contents: read + +jobs: + label-component: + runs-on: ubuntu-22.04 + + permissions: + issues: write + + strategy: + matrix: + template: [ bug_report.yml, feature_request.yml ] + + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + + - name: Parse issue form + uses: stefanbuck/github-issue-parser@f80b14f78892a66d7a35bba44f0a7d63bee03602 + id: issue-parser + with: + template-path: .github/ISSUE_TEMPLATE/${{ matrix.template }} + + - name: Set labels based on component field + uses: redhat-plumbers-in-action/advanced-issue-labeler@fe9c43b7d77bd8bd7fbe86c2c217e74ebeea71f2 + with: + issue-form: ${{ steps.issue-parser.outputs.jsonString }} + template: ${{ matrix.template }} + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 0000000..35766df --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,24 @@ +--- +# vi: ts=2 sw=2 et: +# SPDX-License-Identifier: LGPL-2.1-or-later +# +name: "Pull Request Labeler" + +on: +- pull_request_target + +permissions: + contents: read + +jobs: + triage: + if: github.event.repository.name != 'systemd-security' + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - uses: actions/labeler@e54e5b338fbd6e6cdb5d60f51c22335fc57c401e + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" + configuration-path: .github/labeler.yml + sync-labels: "" # This is a workaround for issue 18671 diff --git a/.github/workflows/make_release.yml b/.github/workflows/make_release.yml new file mode 100644 index 0000000..9902a6c --- /dev/null +++ b/.github/workflows/make_release.yml @@ -0,0 +1,24 @@ +name: Make a Github release + +on: + push: + tags: + - "v*" + +permissions: + contents: read + +jobs: + release: + if: github.repository == 'systemd/systemd' || github.repository == 'systemd/systemd-stable' + runs-on: ubuntu-latest + + permissions: + contents: write + + steps: + - name: Release + uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 + with: + prerelease: ${{ contains(github.ref_name, '-rc') }} + draft: ${{ github.repository == 'systemd/systemd' }} diff --git a/.github/workflows/mkosi.yml b/.github/workflows/mkosi.yml new file mode 100644 index 0000000..4bb361b --- /dev/null +++ b/.github/workflows/mkosi.yml @@ -0,0 +1,95 @@ +--- +# vi: ts=2 sw=2 et: +# SPDX-License-Identifier: LGPL-2.1-or-later +# Simple boot tests that build and boot the mkosi images generated by the mkosi config files in mkosi.default.d/. +name: mkosi + +on: + push: + branches: + - main + - v[0-9]+-stable + pull_request: + branches: + - main + - v[0-9]+-stable + +permissions: + contents: read + +env: + # Enable debug logging in systemd, but keep udev's log level to info, + # since it's _very_ verbose in the QEMU task + # Disable the ISC DHCP servers, as they are failing in Ubuntu + KERNEL_CMDLINE: "systemd.unit=mkosi-check-and-shutdown.service !quiet systemd.log_level=debug systemd.log_target=console udev.log_level=info systemd.default_standard_output=journal+console systemd.mask=isc-dhcp-server6.service systemd.mask=isc-dhcp-server.service" + +jobs: + ci: + runs-on: ubuntu-22.04 + concurrency: + group: ${{ github.workflow }}-${{ matrix.distro }}-${{ matrix.release }}-${{ github.ref }} + cancel-in-progress: true + strategy: + fail-fast: false + matrix: + include: + - distro: arch + release: rolling + - distro: debian + release: testing + - distro: ubuntu + release: jammy + - distro: opensuse + release: tumbleweed + - distro: centos_epel + release: 9-stream + + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + - uses: systemd/mkosi@792cbc60eb2dc4a58d66bb3c212bf92f8d50f6ea + + # FIXME: temporary workaround for a file conflict between systemd (C9S) and + # systemd-boot (EPEL9). Drop this once systemd in C9S is updated to v252 + # (should be done by the end of 2022). + - name: Fix C9S/EPEL9 + if: ${{ matrix.release == '9-stream' }} + run: sudo sed -i '/add_packages/s/systemd-boot/systemd/g' /usr/local/lib/python3.10/dist-packages/mkosi/__init__.py + + - name: Install + run: sudo apt-get update && sudo apt-get install --no-install-recommends python3-pexpect python3-jinja2 + + - name: Configure + run: | + tee mkosi.default <<- EOF + [Distribution] + Distribution=${{ matrix.distro }} + Release=${{ matrix.release }} + + [Content] + Environment=CI_BUILD=1 + + [Output] + KernelCommandLine=${{ env.KERNEL_CMDLINE }} + + [Host] + # Sometimes we run on a host with /dev/kvm, but it is broken, so explicitly disable it + QemuKvm=no + EOF + + - name: Build ${{ matrix.distro }} + run: sudo python3 -m mkosi build + + - name: Show ${{ matrix.distro }} image summary + run: sudo python3 -m mkosi summary + + - name: Boot ${{ matrix.distro }} systemd-nspawn + run: sudo python3 -m mkosi boot ${{ env.KERNEL_CMDLINE }} + + - name: Check ${{ matrix.distro }} systemd-nspawn + run: sudo python3 -m mkosi shell bash -c "[[ -e /testok ]] || { cat /failed-services; exit 1; }" + + - name: Boot ${{ matrix.distro }} QEMU + run: sudo timeout -k 30 10m python3 -m mkosi qemu + + - name: Check ${{ matrix.distro }} QEMU + run: sudo python3 -m mkosi shell bash -c "[[ -e /testok ]] || { cat /failed-services; exit 1; }" diff --git a/.github/workflows/requirements.txt b/.github/workflows/requirements.txt new file mode 100644 index 0000000..edb1748 --- /dev/null +++ b/.github/workflows/requirements.txt @@ -0,0 +1,18 @@ +meson==0.63.2 \ + --hash=sha256:16222f17ef76be0542c91c07994f9676ae879f46fc21c0c786a21ef2cb518bbf \ + --hash=sha256:64a83ef257b2962b52c8b07ad9ec536c2de1b72fd9f14bcd9c21fe45730edd46 +ninja==1.10.2.4 \ + --hash=sha256:24e3bc4713667a9a1d15484ad2bb77bbaedb1e6d45254cb03f7964b8b497231a \ + --hash=sha256:251fb21cd6691accd0d95e28721ad8a50a6ec0ace97f9a8de3976f39301686f6 \ + --hash=sha256:327c319176c5a4af21908b727b776e9f5caf275680403da632821ba071fd6296 \ + --hash=sha256:3300f3f37d62dcc7bdd19284dff9eaed7d629f4ed2725019a6ce3291c655fb83 \ + --hash=sha256:34c8e44f6e2e35ff9444994bfc7bf451c8d4bf15e31ad1e3ef7b06f78647b35b \ + --hash=sha256:3fa6e69838613815c80abcaca34681c5b7cf15bf921543e518f5c918d7098bb7 \ + --hash=sha256:5b973b1ce7075e9091db290adbbf93ba9066a94f97c369d0ff631251c633e81b \ + --hash=sha256:685daebd1bc21480256351000a01dfb520636832fa65efc9f121474ff640e3df \ + --hash=sha256:b0350784b37c5080223ec1bedc507153cc714b502c17dd5a64552e930b0dca25 \ + --hash=sha256:b12cfed6382e510a597b3d08d7eec96664f7c8b8ee436eef645736c453d1c135 \ + --hash=sha256:b264085e409533aecb57040c5e90fbfb64db91a61575c7e637411780446412fa \ + --hash=sha256:b86a4e4ba2ed999d8b10f2b3f2ed56d7457ff647268f4098dd0b63dd145ede32 \ + --hash=sha256:da7a6d9b2ed2018165fbf90068e2c64da08f2568c700fdb8abea07a245dc4664 \ + --hash=sha256:ea245943a9849e5b1ebd74c1a4c1edd2c9801b62c0386165c7ac47623e353627 diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml new file mode 100644 index 0000000..911ac5a --- /dev/null +++ b/.github/workflows/scorecards.yml @@ -0,0 +1,70 @@ +--- +# vi: ts=2 sw=2 et: +# SPDX-License-Identifier: LGPL-2.1-or-later +name: Scorecards supply-chain security +on: + # Only the default branch is supported. + branch_protection_rule: + schedule: + - cron: '15 21 * * 6' + push: + branches: + - main + pull_request: + branches: + - main + paths: + - '.github/workflows/scorecards.yml' + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecards analysis + if: github.repository == 'systemd/systemd' + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Used to receive a badge. + id-token: write + + steps: + - name: Checkout code + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # tag=v3.0.0 + with: + persist-credentials: false + + - name: Run analysis + uses: ossf/scorecard-action@e363bfca00e752f91de7b7d2a77340e2e523cb18 # tag=v2.0.4 + with: + results_file: results.sarif + results_format: sarif + # (Optional) Read-only PAT token. Uncomment the `repo_token` line below if: + # - you want to enable the Branch-Protection check on a *public* repository, or + # - you are installing Scorecards on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. + # repo_token: ${{ secrets.SCORECARD_READ_TOKEN }} + + # Publish the results for public repositories to enable scorecard badges. For more details, see + # https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories, `publish_results` will automatically be set to `false`, regardless + # of the value entered here. + publish_results: ${{ github.event_name != 'pull_request' }} + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: Upload artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # tag=v3.0.0 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard. + - name: Upload to code-scanning + if: github.event_name != 'pull_request' + uses: github/codeql-action/upload-sarif@5f532563584d71fdef14ee64d17bafb34f751ce5 # tag=v1.0.26 + with: + sarif_file: results.sarif diff --git a/.github/workflows/unit_tests.sh b/.github/workflows/unit_tests.sh new file mode 100755 index 0000000..9a9fbb3 --- /dev/null +++ b/.github/workflows/unit_tests.sh @@ -0,0 +1,129 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: LGPL-2.1-or-later + +# shellcheck disable=SC2206 +PHASES=(${@:-SETUP RUN RUN_ASAN_UBSAN CLEANUP}) +RELEASE="$(lsb_release -cs)" +ADDITIONAL_DEPS=( + clang + expect + fdisk + jekyll + libbpf-dev + libfdisk-dev + libfido2-dev + libp11-kit-dev + libpwquality-dev + libqrencode-dev + libssl-dev + libtss2-dev + libxkbcommon-dev + libzstd-dev + perl + python3-libevdev + python3-pyparsing + rpm + zstd +) + +function info() { + echo -e "\033[33;1m$1\033[0m" +} + +function run_meson() { + if ! meson "$@"; then + find . -type f -name meson-log.txt -exec cat '{}' + + return 1 + fi +} + +set -ex + +MESON_ARGS=(-Dcryptolib=${CRYPTOLIB:-auto}) + +for phase in "${PHASES[@]}"; do + case $phase in + SETUP) + info "Setup phase" + bash -c "echo 'deb-src http://archive.ubuntu.com/ubuntu/ $RELEASE main restricted universe multiverse' >>/etc/apt/sources.list" + # PPA with some newer build dependencies + add-apt-repository -y ppa:upstream-systemd-ci/systemd-ci + apt-get -y update + apt-get -y build-dep systemd + apt-get -y install "${ADDITIONAL_DEPS[@]}" + pip3 install -r .github/workflows/requirements.txt --require-hashes + ;; + RUN|RUN_GCC|RUN_CLANG|RUN_CLANG_RELEASE) + if [[ "$phase" =~ ^RUN_CLANG ]]; then + export CC=clang + export CXX=clang++ + if [[ "$phase" == RUN_CLANG ]]; then + # The docs build is slow and is not affected by compiler/flags, so do it just once + MESON_ARGS+=(-Dman=true) + else + MESON_ARGS+=(-Dmode=release --optimization=2) + fi + + # Some variation: remove machine-id, like on Debian builders to ensure unit tests still work. + if [ -w /etc/machine-id ]; then + mv /etc/machine-id /etc/machine-id.bak + fi + fi + # The install_tag feature introduced in 0.60 causes meson to fail with fatal-meson-warnings + # "Project targeting '>= 0.53.2' but tried to use feature introduced in '0.60.0': install_tag arg in custom_target" + # It can be safely removed from the CI since it isn't actually used anywhere to test anything. + find . -type f -name meson.build -exec sed -i '/install_tag/d' '{}' '+' + MESON_ARGS+=(--fatal-meson-warnings) + run_meson -Dnobody-group=nogroup --werror -Dtests=unsafe -Dslow-tests=true -Dfuzz-tests=true "${MESON_ARGS[@]}" build + ninja -C build -v + meson test -C build --print-errorlogs + ;; + RUN_ASAN_UBSAN|RUN_GCC_ASAN_UBSAN|RUN_CLANG_ASAN_UBSAN|RUN_CLANG_ASAN_UBSAN_NO_DEPS) + MESON_ARGS=(--optimization=1) + + if [[ "$phase" =~ ^RUN_CLANG_ASAN_UBSAN ]]; then + export CC=clang + export CXX=clang++ + # Build fuzzer regression tests only with clang (for now), + # see: https://github.com/systemd/systemd/pull/15886#issuecomment-632689604 + # -Db_lundef=false: See https://github.com/mesonbuild/meson/issues/764 + MESON_ARGS+=(-Db_lundef=false -Dfuzz-tests=true) + + if [[ "$phase" == "RUN_CLANG_ASAN_UBSAN_NO_DEPS" ]]; then + MESON_ARGS+=(-Dskip-deps=true) + fi + fi + # The install_tag feature introduced in 0.60 causes meson to fail with fatal-meson-warnings + # "Project targeting '>= 0.53.2' but tried to use feature introduced in '0.60.0': install_tag arg in custom_target" + # It can be safely removed from the CI since it isn't actually used anywhere to test anything. + find . -type f -name meson.build -exec sed -i '/install_tag/d' '{}' '+' + MESON_ARGS+=(--fatal-meson-warnings) + run_meson -Dnobody-group=nogroup --werror -Dtests=unsafe -Db_sanitize=address,undefined "${MESON_ARGS[@]}" build + ninja -C build -v + + export ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1 + # Never remove halt_on_error from UBSAN_OPTIONS. See https://github.com/systemd/systemd/commit/2614d83aa06592aedb. + export UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1 + + # FIXME + # For some strange reason the GH Actions VM stops responding after + # executing first ~150 tests, _unless_ there's something producing + # output (either running `meson test` in verbose mode, or something + # else in background). Despite my efforts so far I haven't been able + # to identify the culprit (since the issue is not reproducible + # during debugging, wonderful), so let's at least keep a workaround + # here to make the builds stable for the time being. + (set +x; while :; do echo -ne "\n[WATCHDOG] $(date)\n"; sleep 30; done) & + meson test --timeout-multiplier=3 -C build --print-errorlogs + ;; + CLEANUP) + info "Cleanup phase" + if [ ! -f /etc/machine-id ] && [ -w /etc/machine-id.bak ]; then + mv /etc/machine-id.bak /etc/machine-id + fi + ;; + *) + echo >&2 "Unknown phase '$phase'" + exit 1 + esac +done diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml new file mode 100644 index 0000000..cd6c33e --- /dev/null +++ b/.github/workflows/unit_tests.yml @@ -0,0 +1,45 @@ +--- +# vi: ts=2 sw=2 et: +# SPDX-License-Identifier: LGPL-2.1-or-later +# +name: Unit tests +on: + pull_request: + branches: + - main + - v[0-9]+-stable + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-22.04 + concurrency: + group: ${{ github.workflow }}-${{ matrix.run_phase }}-${{ matrix.cryptolib }}-${{ github.ref }} + cancel-in-progress: true + strategy: + fail-fast: false + matrix: + run_phase: [GCC, GCC_ASAN_UBSAN, CLANG, CLANG_RELEASE, CLANG_ASAN_UBSAN, CLANG_ASAN_UBSAN_NO_DEPS] + cryptolib: [auto] + include: + - run_phase: GCC + cryptolib: openssl + - run_phase: CLANG + cryptolib: gcrypt + steps: + - name: Repository checkout + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + - name: Install build dependencies + run: | + # Drop XDG_* stuff from /etc/environment, so we don't get the user + # XDG_* variables when running under sudo + sudo sed -i '/^XDG_/d' /etc/environment + # Pass only specific env variables through sudo, to avoid having + # the already existing XDG_* stuff on the "other side" + sudo --preserve-env=CRYPTOLIB,GITHUB_ACTIONS,CI .github/workflows/unit_tests.sh SETUP + - name: Build & test (${{ matrix.run_phase }}-${{ matrix.cryptolib }}) + run: sudo --preserve-env=CRYPTOLIB,GITHUB_ACTIONS,CI .github/workflows/unit_tests.sh RUN_${{ matrix.run_phase }} + env: + CRYPTOLIB: ${{ matrix.cryptolib }} |