diff options
73 files changed, 772 insertions, 329 deletions
diff --git a/.github/workflows/mkosi.yml b/.github/workflows/mkosi.yml index 5842158..d76a935 100644 --- a/.github/workflows/mkosi.yml +++ b/.github/workflows/mkosi.yml @@ -10,36 +10,36 @@ on: - main - v[0-9]+-stable paths: - - '**' - - '!README*' - - '!LICENSE*' - - '!LICENSES/**' - - '!TODO' - - '!docs/**' - - '!man/**' - - '!catalog/**' - - '!shell-completion/**' - - '!po/**' - - '!.**' - - '.github/**' + - "**" + - "!README*" + - "!LICENSE*" + - "!LICENSES/**" + - "!TODO" + - "!docs/**" + - "!man/**" + - "!catalog/**" + - "!shell-completion/**" + - "!po/**" + - "!.**" + - ".github/**" pull_request: branches: - main - v[0-9]+-stable paths: - - '**' - - '!README*' - - '!LICENSE*' - - '!LICENSES/**' - - '!TODO' - - '!docs/**' - - '!man/**' - - '!catalog/**' - - '!shell-completion/**' - - '!po/**' - - '!.**' - - '.github/**' + - "**" + - "!README*" + - "!LICENSE*" + - "!LICENSES/**" + - "!TODO" + - "!docs/**" + - "!man/**" + - "!catalog/**" + - "!shell-completion/**" + - "!po/**" + - "!.**" + - ".github/**" permissions: contents: read @@ -104,126 +104,126 @@ jobs: relabel: yes steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - - uses: systemd/mkosi@4eba736412c702bbbe2c6d4a58a92fa977219249 - - # Freeing up disk space with rm -rf can take multiple minutes. Since we don't need the extra free space - # immediately, we remove the files in the background. However, we first move them to a different location - # so that nothing tries to use anything in these directories anymore while we're busy deleting them. - - name: Free disk space - run: | - sudo mv /usr/local /usr/local.trash - sudo mv /opt/hostedtoolcache /opt/hostedtoolcache.trash - sudo systemd-run rm -rf /usr/local.trash /opt/hostedtoolcache.trash - - - name: Btrfs - run: | - truncate --size=100G btrfs.raw - mkfs.btrfs btrfs.raw - sudo mkdir /mnt/mkosi - LOOP="$(sudo losetup --find --show --direct-io=on btrfs.raw)" - sudo mount "$LOOP" /mnt/mkosi --options compress=zstd:1,user_subvol_rm_allowed,noatime,discard=async,space_cache=v2 - sudo chown "$(id -u):$(id -g)" /mnt/mkosi - mkdir /mnt/mkosi/tmp - echo "TMPDIR=/mnt/mkosi/tmp" >>"$GITHUB_ENV" - ln -s /mnt/mkosi/build build - - - name: Configure - run: | - # XXX: drop after the HyperV bug that breaks secure boot KVM guests is solved - sed -i "s/'firmware'\s*:\s*'auto'/'firmware' : 'uefi'/g" test/*/meson.build - tee mkosi.local.conf <<EOF - [Distribution] - Distribution=${{ matrix.distro }} - Release=${{ matrix.release }} - - [Output] - # Build a disk image in CI as this logic is much more prone to breakage. - Format=disk - UseSubvolumes=yes - - WorkspaceDirectory=$TMPDIR - PackageCacheDirectory=$TMPDIR/cache - - [Content] - Environment= - # Build debuginfo packages since we'll be publishing the packages as artifacts. - WITH_DEBUG=1 - CFLAGS="${{ matrix.cflags }}" - SANITIZERS=${{ matrix.sanitizers }} - MESON_OPTIONS=--werror - LLVM=${{ matrix.llvm }} - SYSEXT=1 - - SELinuxRelabel=${{ matrix.relabel }} - - [Host] - QemuMem=4G - EOF - - - name: Generate secure boot key - run: mkosi --debug genkey - - - name: Show image summary - run: mkosi summary - - - name: Install dependencies - run: | - mkosi dependencies | - xargs -d '\n' sudo apt-get install \ - gperf \ - libblkid-dev \ - libcap-dev \ - libcryptsetup-dev \ - libcurl4-openssl-dev \ - libfdisk-dev \ - libmicrohttpd-dev \ - libmount-dev \ - libtss2-dev \ - meson - - - name: Configure meson - run: | - meson setup build \ - --buildtype=debugoptimized \ - -Dintegration-tests=true \ - -Dremote=enabled \ - -Dopenssl=enabled \ - -Dblkid=enabled \ - -Dtpm2=enabled \ - -Dlibcryptsetup=enabled \ - -Dlibcurl=enabled \ - -Drepart=enabled \ - -Dfirstboot=true \ - -Dsysusers=true \ - -Dtmpfiles=true \ - -Dhwdb=true \ - -Dvmspawn=enabled - - - name: Build image - run: sudo meson compile -C build mkosi - - - name: Run integration tests - run: sudo --preserve-env meson test -C build --no-rebuild --suite integration-tests --print-errorlogs --no-stdsplit --num-processes "$(($(nproc) - 1))" - - - name: Archive failed test journals - uses: actions/upload-artifact@v4 - if: failure() && (github.repository == 'systemd/systemd' || github.repository == 'systemd/systemd-stable') - with: - name: ci-mkosi-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.distro }}-${{ matrix.release }}-failed-test-journals - path: | - build/test/journal/*.journal - build/meson-logs/* - retention-days: 7 - - - name: Archive packages - uses: actions/upload-artifact@v4 - if: (success() || failure()) && (github.repository == 'systemd/systemd' || github.repository == 'systemd/systemd-stable') - with: - name: ci-mkosi-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.distro }}-${{ matrix.release }}-packages - path: | - build/mkosi.output/*.rpm - build/mkosi.output/*.deb - build/mkosi.output/*.ddeb - build/mkosi.output/*.pkg.tar - retention-days: 4 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: systemd/mkosi@31b4e756c1484c302435653da5d3b9bdfae38518 + + # Freeing up disk space with rm -rf can take multiple minutes. Since we don't need the extra free space + # immediately, we remove the files in the background. However, we first move them to a different location + # so that nothing tries to use anything in these directories anymore while we're busy deleting them. + - name: Free disk space + run: | + sudo mv /usr/local /usr/local.trash + sudo mv /opt/hostedtoolcache /opt/hostedtoolcache.trash + sudo systemd-run rm -rf /usr/local.trash /opt/hostedtoolcache.trash + + - name: Btrfs + run: | + truncate --size=100G btrfs.raw + mkfs.btrfs btrfs.raw + sudo mkdir /mnt/mkosi + LOOP="$(sudo losetup --find --show --direct-io=on btrfs.raw)" + sudo mount "$LOOP" /mnt/mkosi --options compress=zstd:1,user_subvol_rm_allowed,noatime,discard=async,space_cache=v2 + sudo chown "$(id -u):$(id -g)" /mnt/mkosi + mkdir /mnt/mkosi/tmp + echo "TMPDIR=/mnt/mkosi/tmp" >>"$GITHUB_ENV" + ln -s /mnt/mkosi/build build + + - name: Configure + run: | + # XXX: drop after the HyperV bug that breaks secure boot KVM guests is solved + sed -i "s/'firmware'\s*:\s*'auto'/'firmware' : 'uefi'/g" test/*/meson.build + tee mkosi.local.conf <<EOF + [Distribution] + Distribution=${{ matrix.distro }} + Release=${{ matrix.release }} + + [Output] + # Build a disk image in CI as this logic is much more prone to breakage. + Format=disk + UseSubvolumes=yes + + WorkspaceDirectory=$TMPDIR + PackageCacheDirectory=$TMPDIR/cache + + [Content] + Environment= + # Build debuginfo packages since we'll be publishing the packages as artifacts. + WITH_DEBUG=1 + CFLAGS="${{ matrix.cflags }}" + SANITIZERS=${{ matrix.sanitizers }} + MESON_OPTIONS=--werror + LLVM=${{ matrix.llvm }} + SYSEXT=1 + + SELinuxRelabel=${{ matrix.relabel }} + + [Host] + QemuMem=4G + EOF + + - name: Generate secure boot key + run: mkosi --debug genkey + + - name: Show image summary + run: mkosi summary + + - name: Install dependencies + run: | + mkosi dependencies | + xargs -d '\n' sudo apt-get install \ + gperf \ + libblkid-dev \ + libcap-dev \ + libcryptsetup-dev \ + libcurl4-openssl-dev \ + libfdisk-dev \ + libmicrohttpd-dev \ + libmount-dev \ + libtss2-dev \ + meson + + - name: Configure meson + run: | + meson setup build \ + --buildtype=debugoptimized \ + -Dintegration-tests=true \ + -Dremote=enabled \ + -Dopenssl=enabled \ + -Dblkid=enabled \ + -Dtpm2=enabled \ + -Dlibcryptsetup=enabled \ + -Dlibcurl=enabled \ + -Drepart=enabled \ + -Dfirstboot=true \ + -Dsysusers=true \ + -Dtmpfiles=true \ + -Dhwdb=true \ + -Dvmspawn=enabled + + - name: Build image + run: sudo meson compile -C build mkosi + + - name: Run integration tests + run: sudo --preserve-env meson test -C build --no-rebuild --suite integration-tests --print-errorlogs --no-stdsplit --num-processes "$(($(nproc) - 1))" + + - name: Archive failed test journals + uses: actions/upload-artifact@v4 + if: failure() && (github.repository == 'systemd/systemd' || github.repository == 'systemd/systemd-stable') + with: + name: ci-mkosi-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.distro }}-${{ matrix.release }}-failed-test-journals + path: | + build/test/journal/*.journal + build/meson-logs/* + retention-days: 7 + + - name: Archive packages + uses: actions/upload-artifact@v4 + if: (success() || failure()) && (github.repository == 'systemd/systemd' || github.repository == 'systemd/systemd-stable') + with: + name: ci-mkosi-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.distro }}-${{ matrix.release }}-packages + path: | + build/mkosi.output/*.rpm + build/mkosi.output/*.deb + build/mkosi.output/*.ddeb + build/mkosi.output/*.pkg.tar + retention-days: 4 diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index c8b75ac..6081351 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -23,17 +23,17 @@ All tools: * `$SYSTEMD_OFFLINE=[0|1]` — if set to `1`, then `systemctl` will refrain from talking to PID 1; this has the same effect as the historical detection of `chroot()`. Setting this variable to `0` instead has a similar effect as - `$SYSTEMD_IGNORE_CHROOT=1`; i.e. tools will try to communicate with PID 1 + `$SYSTEMD_IN_CHROOT=0`; i.e. tools will try to communicate with PID 1 even if a `chroot()` environment is detected. You almost certainly want to set this to `1` if you maintain a package build system or similar and are trying to use a modern container system and not plain `chroot()`. -* `$SYSTEMD_IGNORE_CHROOT=1` — if set, don't check whether being invoked in a - `chroot()` environment. This is particularly relevant for systemctl, as it - will not alter its behaviour for `chroot()` environments if set. Normally it - refrains from talking to PID 1 in such a case; turning most operations such - as `start` into no-ops. If that's what's explicitly desired, you might - consider setting `$SYSTEMD_OFFLINE=1`. +* `$SYSTEMD_IN_CHROOT=0|1` — takes a boolean. If set, overrides chroot detection. + This is particularly relevant for systemctl, as it will not alter its behaviour + for `chroot()` environments if `SYSTEMD_IN_CHROOT=0`. Normally it refrains from + talking to PID 1 in such a case; turning most operations such as `start` into + no-ops. If that's what's explicitly desired, you might consider setting + `$SYSTEMD_OFFLINE=1`. * `$SYSTEMD_FIRST_BOOT=0|1` — if set, assume "first boot" condition to be false or true, instead of checking the flag file created by PID 1. diff --git a/hwdb.d/60-evdev.hwdb b/hwdb.d/60-evdev.hwdb index 0b70a82..372ae68 100644 --- a/hwdb.d/60-evdev.hwdb +++ b/hwdb.d/60-evdev.hwdb @@ -255,6 +255,13 @@ evdev:input:b0003v0ED1p7821* # Dell ######################################### +# Dell AlpsPS/2 ALPS DualPoint TouchPad +evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:*:svnDellInc.*:pnLatitudeE7440*: + EVDEV_ABS_00=:::28 + EVDEV_ABS_01=:::28 + EVDEV_ABS_35=:::28 + EVDEV_ABS_36=:::28 + # Dell Vostro 1510 evdev:name:AlpsPS/2 ALPS GlidePoint*:dmi:bvn*:bvr*:bd*:svnDellInc.:pnVostro1510:* EVDEV_ABS_00=::14 diff --git a/hwdb.d/60-keyboard.hwdb b/hwdb.d/60-keyboard.hwdb index 15c0d4c..5a08931 100644 --- a/hwdb.d/60-keyboard.hwdb +++ b/hwdb.d/60-keyboard.hwdb @@ -223,7 +223,7 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPackard*Bell*:pn*:* # Swift SF314-511 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnSwiftSF314-511:pvr* - KEYBOARD_KEY_8a=f20 # Fn+F12, microphone mute + KEYBOARD_KEY_8a=f20 # Fn+F12, microphone mute # Predator PHN16-71 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnPredatorPHN16-71:* @@ -231,6 +231,10 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnPredatorPHN16-71:* KEYBOARD_KEY_f5=prog1 # "predator sense" button KEYBOARD_KEY_66=micmute # Microphone mute button +# Predator PHN16-72 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnPredatorPHN16-72:* + KEYBOARD_KEY_66=micmute # Microphone mute button + # Nitro AN515-58 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnNitro*AN*515-58:pvr* KEYBOARD_KEY_8a=f20 # Microphone mute button @@ -259,7 +263,7 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAlienware*:pnM17xR3:* # Aquarius Cmp NS483 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAquarius*:pnCmp*NS483*:* KEYBOARD_KEY_56=backslash - KEYBOARD_KEY_76=f21 # Touchpad Toggle + KEYBOARD_KEY_76=f21 # Touchpad Toggle ########################################################### # Asus @@ -341,6 +345,9 @@ evdev:atkbd:dmi:bvn*:bvr*:svnNotebook:pnV54x_6x_TU:* KEYBOARD_KEY_f7=f21 # Touchpad Toggle KEYBOARD_KEY_f8=f21 # Touchpad Toggle +evdev:atkbd:dmi:bvn*:bvr*:svnNotebook:pnV5xTNC_TND_TNE:* + KEYBOARD_KEY_81=f20 # Fn+4; Mic Mute + ########################################################### # Compal ########################################################### @@ -973,7 +980,7 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnJP-IK:pnLEAPW502:pvr* # LE14U/LE15U evdev:atkbd:dmi:bvn*:bvr*:bd*:svnKVADRA*:pn*LE1*U*:* - KEYBOARD_KEY_76=f21 # Fn+F1 Toggle touchpad, sends meta+ctrl+toggle + KEYBOARD_KEY_76=f21 # Fn+F1 Toggle touchpad, sends meta+ctrl+toggle ########################################################### # Lenovo @@ -1901,9 +1908,9 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700T*:* # Galaxy Book (2021) NP750XDA-KD4SE evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn750XDA:pvr* KEYBOARD_KEY_81=!esc - KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings - KEYBOARD_KEY_ae=!volumedown # Fn+F7 volume down - KEYBOARD_KEY_b0=!volumeup # Fn+F8 volume up + KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings + KEYBOARD_KEY_ae=!volumedown # Fn+F7 volume down + KEYBOARD_KEY_b0=!volumeup # Fn+F8 volume up ########################################################### @@ -2028,13 +2035,13 @@ evdev:name:Toshiba*input*device:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*P75-A: # Portege Z830 ACPI quickstart buttons evdev:name:Quickstart Button 1:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnPORTEGEZ830:* - KEYBOARD_KEY_1=prog1 # TOSHIBA eco button + KEYBOARD_KEY_1=prog1 # TOSHIBA eco button evdev:name:Quickstart Button 2:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnPORTEGEZ830:* - KEYBOARD_KEY_1=prog2 # TOSHIBA Presentation button + KEYBOARD_KEY_1=prog2 # TOSHIBA Presentation button evdev:name:Quickstart Button 3:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnPORTEGEZ830:* - KEYBOARD_KEY_1=f21 # Touchpad toggle + KEYBOARD_KEY_1=f21 # Touchpad toggle ########################################################### # VIA @@ -2067,11 +2074,11 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnINET:pnP325J:* # Home: LeftCtrl + Esc -> LeftMeta (ignore LeftCtrl, map Esc to LeftMeta) # Back: Backspace -> back (map backspace to back) evdev:name:FTSC1000:00 2808:509C Keyboard:dmi:*:svnXiaomiInc:pnMipad2:* - KEYBOARD_KEY_700e0=unknown # LeftCtrl -> ignore - KEYBOARD_KEY_700e3=unknown # LeftMeta -> ignore - KEYBOARD_KEY_70016=menu # S -> menu - KEYBOARD_KEY_70029=leftmeta # Esc -> LeftMeta (Windows key / Win8 tablets home) - KEYBOARD_KEY_7002a=back # Backspace -> back + KEYBOARD_KEY_700e0=unknown # LeftCtrl -> ignore + KEYBOARD_KEY_700e3=unknown # LeftMeta -> ignore + KEYBOARD_KEY_70016=menu # S -> menu + KEYBOARD_KEY_70029=leftmeta # Esc -> LeftMeta (Windows key / Win8 tablets home) + KEYBOARD_KEY_7002a=back # Backspace -> back ########################################################### # Zepto @@ -2183,7 +2190,7 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnViewSonic:pnVPAD10:* evdev:name:AT Translated Set 2 keyboard:dmi:bvn*:bvr*:bd*:svnPositivoBahia-VAIO:pnVJPW1[12]F11X*:pvr*:* # Vaio FE14 (VJFE41F11X, VJE42F11X, VJFE44F11X, VJFE54F11X) evdev:name:AT Translated Set 2 keyboard:dmi:bvn*:bvr*:bd*:svnPositivoBahia-VAIO:pnVJFE*:pvr*:* - KEYBOARD_KEY_76=f21 # Fn+F1 toggle touchpad + KEYBOARD_KEY_76=f21 # Fn+F1 toggle touchpad ########################################################### # Positivo @@ -2288,6 +2295,18 @@ evdev:input:b0003v05FEp1010* # # Presence of a LED is implicit when the property is absent. +# Apple Wireless keyboards +evdev:input:b0005v05aCp022C* +evdev:input:b0005v05aCp022D* +evdev:input:b0005v05aCp022E* +evdev:input:b0005v05aCp0239* +evdev:input:b0005v05aCp023A* +evdev:input:b0005v05aCp023B* +evdev:input:b0005v05aCp0255* +evdev:input:b0005v05aCp0256* +evdev:input:b0005v05aCp0257* + KEYBOARD_LED_NUMLOCK=0 + # Logitech K750 evdev:input:b0003v046Dp4002* KEYBOARD_LED_NUMLOCK=0 diff --git a/hwdb.d/60-sensor.hwdb b/hwdb.d/60-sensor.hwdb index 21f4380..8054783 100644 --- a/hwdb.d/60-sensor.hwdb +++ b/hwdb.d/60-sensor.hwdb @@ -152,6 +152,7 @@ sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnM80TA:* sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnT100TA:* sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnT100TAF:* sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnT100TAM:* +sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnT100TAS:* sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:pnT200TA:* ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 @@ -163,6 +164,7 @@ sensor:modalias:acpi:INVN6500*:dmi:*svn*ASUSTeK*:*pn*TP300LA:* sensor:modalias:acpi:INVN6500*:dmi:*svn*ASUSTeK*:*pn*TP300LD:* ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 +sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pn*Q551LB:* sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pn*Q551LN:* ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1 diff --git a/man/networkd.conf.xml b/man/networkd.conf.xml index cac1d3b..9daa125 100644 --- a/man/networkd.conf.xml +++ b/man/networkd.conf.xml @@ -131,6 +131,12 @@ for more details about the sysctl options. Defaults to unset and the sysctl options will not be changed.</para> + <para>If an interface is configured with a .network file that enables <varname>IPMasquerade=</varname> + for IPv4 (that is, <literal>ipv4</literal> or <literal>both</literal>), this setting is implied + unless explicitly specified. See <varname>IPMasquerade=</varname> in + <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry> + for more details.</para> + <xi:include href="version-info.xml" xpointer="v256"/> </listitem> </varlistentry> @@ -145,6 +151,12 @@ for more details about the sysctl options. Defaults to unset and the sysctl options will not be changed.</para> + <para>If an interface is configured with a .network file that enables <varname>IPMasquerade=</varname> + for IPv6 (that is, <literal>ipv6</literal> or <literal>both</literal>), this setting is implied + unless explicitly specified. See <varname>IPMasquerade=</varname> in + <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry> + for more details.</para> + <xi:include href="version-info.xml" xpointer="v256"/> </listitem> </varlistentry> diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 1e3f244..708c37d 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -888,15 +888,15 @@ DuplicateAddressDetection=none</programlisting></para> <literal>ipv6</literal>, <literal>both</literal>, or <literal>no</literal>. Defaults to <literal>no</literal>. Note. Any positive boolean values such as <literal>yes</literal> or <literal>true</literal> are now deprecated. Please use one of the values above. Specifying - <literal>ipv4</literal> or <literal>both</literal> implies <varname>IPv4Forwarding=</varname>, - unless it is explicitly specified. Similarly for <varname>IPv6Forwarding=</varname> when - <literal>ipv6</literal> or <literal>both</literal> is specified. These implications are only on - this interface. Hence, to make the IP packet forwarding works, - <varname>IPv4Forwarding=</varname>/<varname>IPv6Forwarding=</varname> need to be enabled on an - upstream interface, or globally enabled by specifying them in - <citerefentry><refentrytitle>networkd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>. - See <varname>IPv4Forwarding=</varname>/<varname>IPv6Forwarding=</varname> in the above for more - details.</para> + <literal>ipv4</literal> or <literal>both</literal> implies <varname>IPv4Forwarding=</varname> + settings in both .network file for this interface and the global + <citerefentry><refentrytitle>networkd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> + unless they are explicitly specified. Similarly for <varname>IPv6Forwarding=</varname> when + <literal>ipv6</literal> or <literal>both</literal> is specified. See + <varname>IPv4Forwarding=</varname>/<varname>IPv6Forwarding=</varname> in the above for the per-link + settings, and + <citerefentry><refentrytitle>networkd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> + for the global settings.</para> <xi:include href="version-info.xml" xpointer="v219"/> </listitem> diff --git a/meson.version b/meson.version index e162ee4..9516687 100644 --- a/meson.version +++ b/meson.version @@ -1 +1 @@ -256.5 +256.6 diff --git a/mkosi.conf.d/10-arch/mkosi.prepare b/mkosi.conf.d/10-arch/mkosi.prepare index aac7b3d..76f67c1 100755 --- a/mkosi.conf.d/10-arch/mkosi.prepare +++ b/mkosi.conf.d/10-arch/mkosi.prepare @@ -6,9 +6,11 @@ if [[ "$1" == "build" ]]; then exit 0 fi +mapfile -t PACKAGES < <(jq --raw-output .VolatilePackages[] <"$MKOSI_CONFIG") + DEPS="" -while read -r PACKAGE; do +for PACKAGE in "${PACKAGES[@]}"; do DEPS="$DEPS $( pacman --sync --info "$PACKAGE" | sed '1,/^$/d' | # Only keep result from first repository (delete everything after first blank line). @@ -23,11 +25,11 @@ while read -r PACKAGE; do sed 's/ *\(.*\):.*/\1/' | # Drop descriptions (everything after first colon for all lines). tr '\n' ' ' # Transform newlines to whitespace. )" -done < <(jq --raw-output .VolatilePackages[] <"$MKOSI_CONFIG") +done echo "$DEPS" | xargs | # Remove extra whitespace. tr ' ' '\n' | - grep --invert-match --regexp systemd --regexp None | # systemd packages will be installed later on. + grep --extended-regexp --invert-match --regexp "$(IFS=\| ; echo "${PACKAGES[*]}")" --regexp None | # systemd packages will be installed later on. sort --unique | xargs --delimiter '\n' --no-run-if-empty mkosi-install diff --git a/mkosi.conf.d/10-centos-fedora/mkosi.prepare b/mkosi.conf.d/10-centos-fedora/mkosi.prepare index 2a890bc..9aca009 100755 --- a/mkosi.conf.d/10-centos-fedora/mkosi.prepare +++ b/mkosi.conf.d/10-centos-fedora/mkosi.prepare @@ -11,9 +11,9 @@ mapfile -t PACKAGES < <(jq --raw-output .VolatilePackages[] <"$MKOSI_CONFIG") for DEPS in --requires --recommends --suggests; do # We need --latest-limit=1 to only consider the newest version of the packages. # --latest-limit=1 is per <name>.<arch> so we have to pass --arch= explicitly to make sure i686 packages - # are not considerd on x86-64. - dnf repoquery --arch="$DISTRIBUTION_ARCHITECTURE" --latest-limit=1 --quiet "$DEPS" "${PACKAGES[@]}" | - grep --invert-match --regexp systemd --regexp udev --regexp /bin/sh --regexp grubby --regexp sdubby --regexp libcurl-minimal | + # are not considered on x86-64. + dnf repoquery --arch="$DISTRIBUTION_ARCHITECTURE,noarch" --latest-limit=1 --quiet "$DEPS" "${PACKAGES[@]}" | + grep --extended-regexp --invert-match --regexp "$(IFS=\| ; echo "${PACKAGES[*]}")" --regexp /bin/sh --regexp grubby --regexp sdubby --regexp libcurl-minimal | sort --unique | xargs --delimiter '\n' --no-run-if-empty mkosi-install done diff --git a/mkosi.conf.d/10-debian-ubuntu/mkosi.conf b/mkosi.conf.d/10-debian-ubuntu/mkosi.conf index d14746f..472064e 100644 --- a/mkosi.conf.d/10-debian-ubuntu/mkosi.conf +++ b/mkosi.conf.d/10-debian-ubuntu/mkosi.conf @@ -8,10 +8,6 @@ Distribution=|ubuntu PackageManagerTrees=mkosi-pinning.pref:/etc/apt/preferences.d/mkosi-pinning.pref [Content] -# Debian ships /usr/bin/login from shadow instead of util-linux which doesn't support credentials so we -# enable autologin the old-fashioned way. -Autologin=yes - VolatilePackages= libnss-myhostname libnss-mymachines @@ -58,6 +54,7 @@ Packages= knot libcap-ng-utils locales + login man-db multipath-tools ncat diff --git a/mkosi.conf.d/10-debian-ubuntu/mkosi.prepare b/mkosi.conf.d/10-debian-ubuntu/mkosi.prepare index acab113..bf2c5eb 100755 --- a/mkosi.conf.d/10-debian-ubuntu/mkosi.prepare +++ b/mkosi.conf.d/10-debian-ubuntu/mkosi.prepare @@ -8,9 +8,23 @@ fi mapfile -t PACKAGES < <(jq --raw-output .VolatilePackages[] <"$MKOSI_CONFIG") -apt-cache depends "${PACKAGES[@]}" | - grep --invert-match --regexp "<" --regexp "|" --regexp systemd | # Remove e.g. <python3:any> and |dbus-broker like results - grep --extended-regexp "Depends|Suggests|Recommends" | - sed --quiet 's/.*: //p' | # Get every line with ": " in it and strip it at the same time. - sort --unique | - xargs --delimiter '\n' --no-run-if-empty mkosi-install +PATTERNS=() + +# The ?reverse-depends() pattern for some weird reason lists all the packages providing systemd-sysusers +# instead of just excluding it, so we add another pattern to filter out anything that conflicts with +# any other systemd packages so we filter out both opensysusers and systemd-sysusers-standalone. We also +# exclude packages that belong to the systemd source package as we'll install these later. Finally, we +# exclude virtual packages as trying to install these makes apt fail with an error saying we need to install +# a specific implementation even if one is already installed. +COMMON="?not(?virtual), ?not(?reverse-conflicts(?source-package(^systemd$))), ?not(?reverse-breaks(?source-package(^systemd$))), ?not(?source-package(^systemd$))" + +for PACKAGE in "${PACKAGES[@]}"; do + # Get all the dependencies of the systemd packages including recommended and suggested dependencies. + PATTERNS+=( + "?and(?reverse-depends(?exact-name($PACKAGE)), $COMMON)" + "?and(?reverse-recommends(?exact-name($PACKAGE)), $COMMON)" + "?and(?reverse-suggests(?exact-name($PACKAGE)), $COMMON)" + ) +done + +mkosi-install "${PATTERNS[@]}" diff --git a/mkosi.conf.d/10-fedora/mkosi.conf.d/rawhide.conf b/mkosi.conf.d/10-fedora/mkosi.conf.d/rawhide.conf new file mode 100644 index 0000000..f657b3d --- /dev/null +++ b/mkosi.conf.d/10-fedora/mkosi.conf.d/rawhide.conf @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +[Match] +Release=rawhide + +[Content] +Packages=util-linux-script diff --git a/mkosi.conf.d/10-opensuse/mkosi.prepare b/mkosi.conf.d/10-opensuse/mkosi.prepare index 6ee0af2..728b502 100755 --- a/mkosi.conf.d/10-opensuse/mkosi.prepare +++ b/mkosi.conf.d/10-opensuse/mkosi.prepare @@ -6,18 +6,20 @@ if [[ "$1" == "build" ]]; then exit 0 fi +mapfile -t PACKAGES < <(jq --raw-output .VolatilePackages[] <"$MKOSI_CONFIG") + DEPS="" -while read -r PACKAGE; do +for PACKAGE in "${PACKAGES[@]}"; do # zypper's output is not machine readable so we make do with sed instead. DEPS="$DEPS\n$( zypper info --requires --recommends --suggests "$PACKAGE" | sed '/Requires/,$!d' | # Remove everything before Requires line sed --quiet 's/^ //p' # All indented lines have dependencies )" -done < <(jq --raw-output .VolatilePackages[] <"$MKOSI_CONFIG") +done echo -e "$DEPS" | - grep --invert-match --regexp systemd --regexp udev --regexp qemu | + grep --extended-regexp --invert-match --regexp "$(IFS=\| ; echo "${PACKAGES[*]}")" --regexp qemu | sort --unique | xargs --delimiter '\n' --no-run-if-empty mkosi-install diff --git a/mkosi.conf.d/10-ubuntu/mkosi.conf b/mkosi.conf.d/10-ubuntu/mkosi.conf index 1ffa3ab..73faafe 100644 --- a/mkosi.conf.d/10-ubuntu/mkosi.conf +++ b/mkosi.conf.d/10-ubuntu/mkosi.conf @@ -8,6 +8,9 @@ Release=noble Repositories=universe [Content] +# Ubuntu ships /usr/bin/login from shadow instead of util-linux which doesn't support credentials so we +# enable autologin the old-fashioned way. +Autologin=yes Packages= linux-image-generic linux-tools-common diff --git a/mkosi.images/build/mkosi.conf.d/arch/mkosi.build.chroot b/mkosi.images/build/mkosi.conf.d/arch/mkosi.build.chroot index 3ffde85..8d501ec 100755 --- a/mkosi.images/build/mkosi.conf.d/arch/mkosi.build.chroot +++ b/mkosi.images/build/mkosi.conf.d/arch/mkosi.build.chroot @@ -61,22 +61,23 @@ EOF # Linting the PKGBUILD takes multiple seconds every build so avoid that by nuking all the linting functions. rm /usr/share/makepkg/lint_pkgbuild/* -if [[ -d .git/ ]] && [[ -z "$(git status --porcelain)" ]]; then - TS="$(git show --no-patch --format=%ct HEAD)" -else - TS="${SOURCE_DATE_EPOCH:-$(date +%s)}" -fi +TS="${SOURCE_DATE_EPOCH:-$(date +%s)}" sed --in-place "pkg/$PKG_SUBDIR/PKGBUILD" \ --expression "s/^_tag=.*/_tag=$(cat meson.version)/" \ --expression "s/^pkgrel=.*/pkgrel=$(date "+%Y%m%d%H%M%S" --date "@$TS")/" +# Replace cdrom/dialout/tape groups with optical/uucp/storage. We apply this patch manually because we run +# with --noprepare. +patch -Np1 -i pkg/arch/0001-Use-Arch-Linux-device-access-groups.patch + # We get around makepkg's root check by setting EUID to something else. # shellcheck disable=SC2046 env --chdir="pkg/$PKG_SUBDIR" \ EUID=123 \ makepkg \ --noextract \ + --noprepare \ $( ((WITH_TESTS)) || echo --nocheck) \ --force \ _systemd_UPSTREAM=1 \ diff --git a/mkosi.images/build/mkosi.conf.d/arch/mkosi.conf b/mkosi.images/build/mkosi.conf.d/arch/mkosi.conf index c071468..91a4d17 100644 --- a/mkosi.images/build/mkosi.conf.d/arch/mkosi.conf +++ b/mkosi.images/build/mkosi.conf.d/arch/mkosi.conf @@ -7,7 +7,7 @@ Distribution=arch Environment= GIT_URL=https://gitlab.archlinux.org/archlinux/packaging/packages/systemd.git GIT_BRANCH=main - GIT_COMMIT=1d577a62688419ee4af01b847e55845cd9780301 + GIT_COMMIT=ea5f086275aeba40d878507fba8b22308c3fac01 PKG_SUBDIR=arch Packages= diff --git a/mkosi.images/build/mkosi.conf.d/centos-fedora/mkosi.build.chroot b/mkosi.images/build/mkosi.conf.d/centos-fedora/mkosi.build.chroot index 466699c..9cacff6 100755 --- a/mkosi.images/build/mkosi.conf.d/centos-fedora/mkosi.build.chroot +++ b/mkosi.images/build/mkosi.conf.d/centos-fedora/mkosi.build.chroot @@ -9,11 +9,7 @@ if [[ ! -f "pkg/$PKG_SUBDIR/systemd.spec" ]]; then exit 1 fi -if [[ -d .git/ ]] && [[ -z "$(git status --porcelain)" ]]; then - TS="$(git show --no-patch --format=%ct HEAD)" -else - TS="${SOURCE_DATE_EPOCH:-$(date +%s)}" -fi +TS="${SOURCE_DATE_EPOCH:-$(date +%s)}" if [[ "$(rpm --eval "%{lua:print(rpm.vercmp('$(rpm --version | cut -d ' ' -f3)', '4.19.91'))}")" == "-1" ]]; then # Fix the %install override so debuginfo packages are generated even when --build-in-place is used. @@ -57,6 +53,12 @@ if ((WIPE)) && [[ -d "$BUILDDIR/meson-private" ]]; then MKOSI_MESON_OPTIONS="$MKOSI_MESON_OPTIONS --wipe" fi +# Hack to work around https://github.com/rpm-software-management/rpm/issues/3216. +# TODO: Remove when rpm 4.20 gets into Rawhide. +mkdir -p "/var/tmp/BUILD/systemd-${VERSION/\~/_}-build" +mkdir -p "/var/tmp/BUILD/systemd-${VERSION/\~/_}-build/SPECPARTS" +ln -s /work/src "/var/tmp/BUILD/systemd-${VERSION/\~/_}-build/systemd-$VERSION" + IFS= # TODO: Replace meson_build and meson_install overrides with "--undefine __meson_verbose" once # https://github.com/mesonbuild/meson/pull/12835 is available. @@ -70,12 +72,13 @@ CC_LD="$( ((LLVM)) && echo lld)" \ CXX_LD="$( ((LLVM)) && echo lld)" \ rpmbuild \ -bb \ + --noprep \ --build-in-place \ --with upstream \ $( ((WITH_TESTS)) || echo "--nocheck") \ $( ((WITH_DOCS)) || echo "--without=docs") \ --define "_topdir /var/tmp" \ - --define "_sourcedir pkg/$PKG_SUBDIR" \ + --define "_sourcedir $PWD/pkg/$PKG_SUBDIR" \ --define "_rpmdir $OUTPUTDIR" \ ${BUILDDIR:+"--define=_vpath_builddir $BUILDDIR"} \ --define "_build_name_fmt %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm" \ @@ -100,7 +103,6 @@ CXX_LD="$( ((LLVM)) && echo lld)" \ --define "__script_requires %{nil}" \ --define "_find_debuginfo_opts --unique-debug-src-base \"%{name}\"" \ --define "_find_debuginfo_dwz_opts %{nil}" \ - --define "_fixperms true" \ --undefine _package_note_flags \ --noclean \ "pkg/$PKG_SUBDIR/systemd.spec" diff --git a/mkosi.images/build/mkosi.conf.d/centos-fedora/mkosi.conf b/mkosi.images/build/mkosi.conf.d/centos-fedora/mkosi.conf index f3afd55..1efca6d 100644 --- a/mkosi.images/build/mkosi.conf.d/centos-fedora/mkosi.conf +++ b/mkosi.images/build/mkosi.conf.d/centos-fedora/mkosi.conf @@ -8,7 +8,7 @@ Distribution=|fedora Environment= GIT_URL=https://src.fedoraproject.org/rpms/systemd.git GIT_BRANCH=rawhide - GIT_COMMIT=00babccdea1576d96edfdb7ab12958564cc4f1b6 + GIT_COMMIT=a67221c3f0d0b81b9b5b3230a71d09044342f1a4 PKG_SUBDIR=fedora Packages= diff --git a/mkosi.images/build/mkosi.conf.d/centos-fedora/mkosi.prepare b/mkosi.images/build/mkosi.conf.d/centos-fedora/mkosi.prepare index 6028dc3..4fef26f 100755 --- a/mkosi.images/build/mkosi.conf.d/centos-fedora/mkosi.prepare +++ b/mkosi.images/build/mkosi.conf.d/centos-fedora/mkosi.prepare @@ -17,7 +17,7 @@ mkosi-chroot \ --query \ --buildrequires \ --define "_topdir /var/tmp" \ - --define "_sourcedir pkg/$PKG_SUBDIR" \ + --define "_sourcedir $PWD/pkg/$PKG_SUBDIR" \ "pkg/$PKG_SUBDIR/systemd.spec" | grep --invert-match --regexp systemd --regexp /bin/sh --regexp "rpmlib(" --regexp udev --regexp grubby --regexp sdubby | sort --unique | @@ -32,10 +32,11 @@ sed '/Source0/d' --in-place "pkg/$PKG_SUBDIR/systemd.spec" until mkosi-chroot \ rpmbuild \ -br \ + --noprep \ --build-in-place \ --with upstream \ --define "_topdir /var/tmp" \ - --define "_sourcedir pkg/$PKG_SUBDIR" \ + --define "_sourcedir $PWD/pkg/$PKG_SUBDIR" \ --define "_build_name_fmt %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm" \ "pkg/$PKG_SUBDIR/systemd.spec" do diff --git a/mkosi.images/build/mkosi.conf.d/debian-ubuntu/mkosi.build.chroot b/mkosi.images/build/mkosi.conf.d/debian-ubuntu/mkosi.build.chroot index 03b3b04..0d33b10 100755 --- a/mkosi.images/build/mkosi.conf.d/debian-ubuntu/mkosi.build.chroot +++ b/mkosi.images/build/mkosi.conf.d/debian-ubuntu/mkosi.build.chroot @@ -18,11 +18,7 @@ rm -rf "$SRCDIR"/debian/patches/* DEB_HOST_GNU_TYPE="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)" mount --mkdir --bind "$BUILDDIR" "$SRCDIR/obj-$DEB_HOST_GNU_TYPE" -if [[ -d .git/ ]] && [[ -z "$(git status --porcelain)" ]]; then - TS="$(git show --no-patch --format=%ct HEAD)" -else - TS="${SOURCE_DATE_EPOCH:-$(date +%s)}" -fi +TS="${SOURCE_DATE_EPOCH:-$(date +%s)}" # Add a new changelog entry to update the version. We use a fixed date since a dynamic one causes a full # rebuild every time. diff --git a/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.build.chroot b/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.build.chroot index a1fb83c..0a5b47b 100755 --- a/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.build.chroot +++ b/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.build.chroot @@ -9,11 +9,7 @@ if [[ ! -f "pkg/$PKG_SUBDIR/systemd.spec" ]]; then exit 1 fi -if [[ -d .git/ ]] && [[ -z "$(git status --porcelain)" ]]; then - TS="$(git show --no-patch --format=%ct HEAD)" -else - TS="${SOURCE_DATE_EPOCH:-$(date +%s)}" -fi +TS="${SOURCE_DATE_EPOCH:-$(date +%s)}" # The openSUSE filelists hardcode the manpage compression extension. This causes rpmbuild errors since we # disable manpage compression as the files cannot be found. Fix the issue by removing the compression @@ -73,11 +69,12 @@ build() { CXX_LD="$( ((LLVM)) && echo lld)" \ rpmbuild \ -bb \ + --noprep \ --build-in-place \ --with upstream \ $( ((WITH_TESTS)) || echo "--nocheck") \ --define "_topdir /var/tmp" \ - --define "_sourcedir pkg/$PKG_SUBDIR" \ + --define "_sourcedir $PWD/pkg/$PKG_SUBDIR" \ --define "_rpmdir $OUTPUTDIR" \ ${BUILDDIR:+"--define=_vpath_builddir $BUILDDIR"} \ --define "_build_name_fmt %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm" \ @@ -97,7 +94,6 @@ build() { --define "__script_requires %{nil}" \ --define "_find_debuginfo_dwz_opts %{nil}" \ --define "_find_debuginfo_opts --unique-debug-src-base \"%{name}\"" \ - --define "_fixperms true" \ --noclean \ "$@" \ "pkg/$PKG_SUBDIR/systemd.spec" diff --git a/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.conf b/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.conf index a941457..0b17435 100644 --- a/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.conf +++ b/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.conf @@ -5,9 +5,9 @@ Distribution=opensuse [Content] Environment= - GIT_URL=https://code.opensuse.org/package/systemd - GIT_BRANCH=master - GIT_COMMIT=6812406e52a474568744c267e7bade1496bb26a5 + GIT_URL=https://src.opensuse.org/pool/systemd + GIT_BRANCH=factory + GIT_COMMIT=612bc16021b28ab99002fa1069f1ec97124397a25c7a207d013213b5cfb86055 PKG_SUBDIR=opensuse Packages= diff --git a/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.prepare b/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.prepare index 24f07fd..c4a9580 100755 --- a/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.prepare +++ b/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.prepare @@ -20,7 +20,7 @@ mkosi-chroot \ --query \ --buildrequires \ --define "_topdir /var/tmp" \ - --define "_sourcedir pkg/$PKG_SUBDIR" \ + --define "_sourcedir $PWD/pkg/$PKG_SUBDIR" \ "pkg/$PKG_SUBDIR/systemd.spec" | grep --invert-match --regexp systemd --regexp /bin/sh --regexp "rpmlib(" --regexp udev | sort --unique | @@ -30,10 +30,11 @@ mkosi-chroot \ until mkosi-chroot \ rpmbuild \ -bd \ + --noprep \ --build-in-place \ --with upstream \ --define "_topdir /var/tmp" \ - --define "_sourcedir pkg/$PKG_SUBDIR" \ + --define "_sourcedir $PWD/pkg/$PKG_SUBDIR" \ --define "_build_name_fmt %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm" \ "pkg/$PKG_SUBDIR/systemd.spec" do diff --git a/mkosi.images/build/mkosi.sync b/mkosi.images/build/mkosi.sync index febe893..4cb2b41 100755 --- a/mkosi.images/build/mkosi.sync +++ b/mkosi.images/build/mkosi.sync @@ -43,7 +43,7 @@ if [[ ! -e "pkg/$PKG_SUBDIR" ]] || [[ -z "$(ls --almost-all "pkg/$PKG_SUBDIR")" # --no-cone is needed to check out only one top-level directory git -C "pkg/$PKG_SUBDIR" sparse-checkout set --no-cone "${GIT_SUBDIR:-}" fi -else +elif ! git -C "pkg/$PKG_SUBDIR" cat-file -e "$GIT_COMMIT^{commit}"; then git -C "pkg/$PKG_SUBDIR" remote set-url origin "$GIT_URL" git -C "pkg/$PKG_SUBDIR" fetch origin "$GIT_BRANCH" fi diff --git a/mkosi.presets/20-final/mkosi.extra/root/.gdbinit b/mkosi.presets/20-final/mkosi.extra/root/.gdbinit new file mode 100644 index 0000000..1a2163e --- /dev/null +++ b/mkosi.presets/20-final/mkosi.extra/root/.gdbinit @@ -0,0 +1,3 @@ +set debuginfod enabled off +set build-id-verbose 0 +set substitute-path ../src /root/src diff --git a/mkosi.sanitizers/mkosi.postinst b/mkosi.sanitizers/mkosi.postinst index e0ad422..593a8f9 100755 --- a/mkosi.sanitizers/mkosi.postinst +++ b/mkosi.sanitizers/mkosi.postinst @@ -73,12 +73,7 @@ wrap=( lvm mdadm mkfs.btrfs - mkfs.erofs - mkfs.ext4 - mkfs.vfat - mkfs.xfs mksquashfs - mkswap multipath multipathd nvme diff --git a/src/basic/audit-util.c b/src/basic/audit-util.c index bf96e08..7f86f84 100644 --- a/src/basic/audit-util.c +++ b/src/basic/audit-util.c @@ -99,7 +99,7 @@ static int try_audit_request(int fd) { n = recvmsg_safe(fd, &mh, 0); if (n < 0) - return -errno; + return n; if (n != NLMSG_LENGTH(sizeof(struct nlmsgerr))) return -EIO; diff --git a/src/basic/missing_loop.h b/src/basic/missing_loop.h index b88501d..f83a14c 100644 --- a/src/basic/missing_loop.h +++ b/src/basic/missing_loop.h @@ -29,3 +29,7 @@ assert_cc(LOOP_SET_DIRECT_IO == 0x4C08); #ifndef LOOP_SET_STATUS_SETTABLE_FLAGS # define LOOP_SET_STATUS_SETTABLE_FLAGS (LO_FLAGS_AUTOCLEAR | LO_FLAGS_PARTSCAN) #endif + +#ifndef LOOP_SET_BLOCK_SIZE +# define LOOP_SET_BLOCK_SIZE 0x4C09 +#endif diff --git a/src/basic/process-util.c b/src/basic/process-util.c index c9d968d..de5a146 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -2066,9 +2066,10 @@ int posix_spawn_wrapper( _unused_ _cleanup_(posix_spawnattr_destroyp) posix_spawnattr_t *attr_destructor = &attr; #if HAVE_PIDFD_SPAWN + static bool setcgroup_supported = true; _cleanup_close_ int cgroup_fd = -EBADF; - if (cgroup) { + if (cgroup && setcgroup_supported) { _cleanup_free_ char *resolved_cgroup = NULL; r = cg_get_path_and_check( @@ -2102,6 +2103,19 @@ int posix_spawn_wrapper( _cleanup_close_ int pidfd = -EBADF; r = pidfd_spawn(&pidfd, path, NULL, &attr, argv, envp); + if (r == E2BIG && FLAGS_SET(flags, POSIX_SPAWN_SETCGROUP)) { + /* Some kernels (e.g., 5.4) support clone3 but they do not support CLONE_INTO_CGROUP. + * Retry pidfd_spawn() after removing the flag. */ + flags &= ~POSIX_SPAWN_SETCGROUP; + r = posix_spawnattr_setflags(&attr, flags); + if (r != 0) + return -r; + r = pidfd_spawn(&pidfd, path, NULL, &attr, argv, envp); + /* if pidfd_spawn was successful after removing SPAWN_CGROUP, + * mark setcgroup_supported as false so that we do not retry every time */ + if (r == 0) + setcgroup_supported = false; + } if (r == 0) { r = pidref_set_pidfd_consume(ret_pidref, TAKE_FD(pidfd)); if (r < 0) @@ -2120,10 +2134,12 @@ int posix_spawn_wrapper( /* Compiled on a newer host, or seccomp&friends blocking clone3()? Fallback, but need to change the * flags to remove the cgroup one, which is what redirects to clone3() */ - flags &= ~POSIX_SPAWN_SETCGROUP; - r = posix_spawnattr_setflags(&attr, flags); - if (r != 0) - return -r; + if (FLAGS_SET(flags, POSIX_SPAWN_SETCGROUP)) { + flags &= ~POSIX_SPAWN_SETCGROUP; + r = posix_spawnattr_setflags(&attr, flags); + if (r != 0) + return -r; + } #endif pid_t pid; diff --git a/src/basic/virt.c b/src/basic/virt.c index 0970350..2cb3a08 100644 --- a/src/basic/virt.c +++ b/src/basic/virt.c @@ -896,6 +896,13 @@ int running_in_chroot(void) { * mount /proc, so all other programs can assume that if /proc is *not* available, we're in some * chroot. */ + r = getenv_bool("SYSTEMD_IN_CHROOT"); + if (r >= 0) + return r > 0; + if (r != -ENXIO) + log_debug_errno(r, "Failed to parse $SYSTEMD_IN_CHROOT, ignoring: %m"); + + /* Deprecated but kept for backwards compatibility. */ if (getenv_bool("SYSTEMD_IGNORE_CHROOT") > 0) return 0; diff --git a/src/boot/bootctl-install.c b/src/boot/bootctl-install.c index dc46d30..fd26b43 100644 --- a/src/boot/bootctl-install.c +++ b/src/boot/bootctl-install.c @@ -45,7 +45,7 @@ static int load_etc_machine_info(void) { _cleanup_free_ char *p = NULL, *s = NULL, *layout = NULL; int r; - p = path_join(arg_root, "etc/machine-info"); + p = path_join(arg_root, "/etc/machine-info"); if (!p) return log_oom(); diff --git a/src/core/namespace.c b/src/core/namespace.c index a9b98bc..b92bb01 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -1565,12 +1565,24 @@ static int apply_one_mount( if (r < 0) return log_debug_errno(r, "Failed to extract extension name from %s: %m", mount_entry_source(m)); - r = load_extension_release_pairs(mount_entry_source(m), IMAGE_SYSEXT, extension_name, /* relax_extension_release_check= */ false, &extension_release); + r = load_extension_release_pairs( + mount_entry_source(m), + IMAGE_SYSEXT, + extension_name, + /* relax_extension_release_check= */ false, + &extension_release); if (r == -ENOENT) { - r = load_extension_release_pairs(mount_entry_source(m), IMAGE_CONFEXT, extension_name, /* relax_extension_release_check= */ false, &extension_release); + r = load_extension_release_pairs( + mount_entry_source(m), + IMAGE_CONFEXT, + extension_name, + /* relax_extension_release_check= */ false, + &extension_release); if (r >= 0) class = IMAGE_CONFEXT; } + if (r == -ENOENT && m->ignore) + return 0; if (r < 0) return log_debug_errno(r, "Failed to acquire 'extension-release' data of extension tree %s: %m", mount_entry_source(m)); @@ -1585,12 +1597,6 @@ static int apply_one_mount( if (isempty(host_os_release_id)) return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "'ID' field not found or empty in 'os-release' data of OS tree '%s'.", empty_to_root(root_directory)); - r = load_extension_release_pairs(mount_entry_source(m), class, extension_name, /* relax_extension_release_check= */ false, &extension_release); - if (r == -ENOENT && m->ignore) - return 0; - if (r < 0) - return log_debug_errno(r, "Failed to parse directory %s extension-release metadata: %m", extension_name); - r = extension_release_validate( extension_name, host_os_release_id, diff --git a/src/home/homectl.c b/src/home/homectl.c index d9321a2..5c454f7 100644 --- a/src/home/homectl.c +++ b/src/home/homectl.c @@ -1243,6 +1243,8 @@ static int acquire_new_password( if (r < 0) return log_error_errno(r, "Failed to acquire password: %m"); + assert(!strv_isempty(first)); + question = mfree(question); if (asprintf(&question, "Please enter new password for user %s (repeat):", user_name) < 0) return log_oom(); diff --git a/src/libsystemd-network/sd-lldp-tx.c b/src/libsystemd-network/sd-lldp-tx.c index 2b822af..01c476e 100644 --- a/src/libsystemd-network/sd-lldp-tx.c +++ b/src/libsystemd-network/sd-lldp-tx.c @@ -590,6 +590,7 @@ int sd_lldp_tx_stop(sd_lldp_tx *lldp_tx) { return 1; } + int sd_lldp_tx_start(sd_lldp_tx *lldp_tx) { usec_t delay; int r; diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c index ecd030e..228b166 100644 --- a/src/libsystemd-network/test-dhcp-server.c +++ b/src/libsystemd-network/test-dhcp-server.c @@ -127,6 +127,7 @@ static void test_message_handler(void) { .s_addr = htobe32(INADDR_LOOPBACK + 42), }; static uint8_t static_lease_client_id[7] = {0x01, 'A', 'B', 'C', 'D', 'E', 'G' }; + int r; log_debug("/* %s */", __func__); @@ -137,7 +138,10 @@ static void test_message_handler(void) { assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0); assert_se(sd_dhcp_server_start(server) >= 0); - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == DHCP_OFFER); + r = dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL); + if (r == -ENETDOWN) + return (void) log_tests_skipped("Network is not available"); + assert_se(r == DHCP_OFFER); test.end = 0; /* TODO, shouldn't this fail? */ diff --git a/src/libsystemd/sd-netlink/test-netlink.c b/src/libsystemd/sd-netlink/test-netlink.c index cf19c48..c58cfc0 100644 --- a/src/libsystemd/sd-netlink/test-netlink.c +++ b/src/libsystemd/sd-netlink/test-netlink.c @@ -92,18 +92,24 @@ TEST(message_address) { struct in_addr in_data; struct ifa_cacheinfo cache; const char *label; + int r; assert_se(sd_netlink_open(&rtnl) >= 0); ifindex = (int) if_nametoindex("lo"); assert_se(sd_rtnl_message_new_addr(rtnl, &message, RTM_GETADDR, ifindex, AF_INET) >= 0); assert_se(sd_netlink_message_set_request_dump(message, true) >= 0); - assert_se(sd_netlink_call(rtnl, message, 0, &reply) == 1); - assert_se(sd_netlink_message_read_in_addr(reply, IFA_LOCAL, &in_data) >= 0); - assert_se(sd_netlink_message_read_in_addr(reply, IFA_ADDRESS, &in_data) >= 0); - assert_se(sd_netlink_message_read_string(reply, IFA_LABEL, &label) >= 0); - assert_se(sd_netlink_message_read_cache_info(reply, IFA_CACHEINFO, &cache) == 0); + r = sd_netlink_call(rtnl, message, 0, &reply); + assert_se(r >= 0); + + /* If the loopback device is down we won't get any results. */ + if (r > 0) { + assert_se(sd_netlink_message_read_in_addr(reply, IFA_LOCAL, &in_data) >= 0); + assert_se(sd_netlink_message_read_in_addr(reply, IFA_ADDRESS, &in_data) >= 0); + assert_se(sd_netlink_message_read_string(reply, IFA_LABEL, &label) >= 0); + assert_se(sd_netlink_message_read_cache_info(reply, IFA_CACHEINFO, &cache) == 0); + } } TEST(message_route) { diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index ceff268..b0c4896 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -4264,6 +4264,7 @@ int manager_start_scope( const char *slice, const char *description, const char * const *requires, + const char * const *wants, const char * const *extra_after, const char *requires_mounts_for, sd_bus_message *more_properties, @@ -4313,6 +4314,16 @@ int manager_start_scope( return r; } + STRV_FOREACH(i, wants) { + r = sd_bus_message_append(m, "(sv)", "Wants", "as", 1, *i); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "(sv)", "After", "as", 1, *i); + if (r < 0) + return r; + } + STRV_FOREACH(i, extra_after) { r = sd_bus_message_append(m, "(sv)", "After", "as", 1, *i); if (r < 0) @@ -4375,6 +4386,7 @@ int manager_start_scope( slice, description, requires, + wants, extra_after, requires_mounts_for, more_properties, diff --git a/src/login/logind-dbus.h b/src/login/logind-dbus.h index 8459d04..d965ba9 100644 --- a/src/login/logind-dbus.h +++ b/src/login/logind-dbus.h @@ -32,6 +32,7 @@ int manager_start_scope( const char *slice, const char *description, const char * const *requires, + const char * const *wants, const char * const *extra_after, const char *requires_mounts_for, sd_bus_message *more_properties, diff --git a/src/login/logind-session.c b/src/login/logind-session.c index 4713aa0..4758cb9 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -746,15 +746,15 @@ static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_er s->user->slice, description, /* These should have been pulled in explicitly in user_start(). Just to be sure. */ - STRV_MAKE_CONST(s->user->runtime_dir_unit, - SESSION_CLASS_WANTS_SERVICE_MANAGER(s->class) ? s->user->service_manager_unit : NULL), + /* requires = */ STRV_MAKE_CONST(s->user->runtime_dir_unit), + /* wants = */ STRV_MAKE_CONST(SESSION_CLASS_WANTS_SERVICE_MANAGER(s->class) ? s->user->service_manager_unit : NULL), /* We usually want to order session scopes after systemd-user-sessions.service * since the unit is used as login session barrier for unprivileged users. However * the barrier doesn't apply for root as sysadmin should always be able to log in * (and without waiting for any timeout to expire) in case something goes wrong * during the boot process. */ - STRV_MAKE_CONST("systemd-logind.service", - SESSION_CLASS_IS_EARLY(s->class) ? NULL : "systemd-user-sessions.service"), + /* extra_after = */ STRV_MAKE_CONST("systemd-logind.service", + SESSION_CLASS_IS_EARLY(s->class) ? NULL : "systemd-user-sessions.service"), user_record_home_directory(s->user->user_record), properties, error, diff --git a/src/network/networkd-lldp-tx.c b/src/network/networkd-lldp-tx.c index f48781e..cc22fbf 100644 --- a/src/network/networkd-lldp-tx.c +++ b/src/network/networkd-lldp-tx.c @@ -86,6 +86,36 @@ int link_lldp_tx_configure(Link *link) { return 0; } +int link_lldp_tx_update_capabilities(Link *link) { + int r; + + assert(link); + + if (!link->lldp_tx) + return 0; /* disabled, or not configured yet. */ + + r = sd_lldp_tx_set_capabilities(link->lldp_tx, + SD_LLDP_SYSTEM_CAPABILITIES_STATION | + SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE | + SD_LLDP_SYSTEM_CAPABILITIES_ROUTER, + (link_get_ip_forwarding(link, AF_INET) > 0 || link_get_ip_forwarding(link, AF_INET6) > 0) ? + SD_LLDP_SYSTEM_CAPABILITIES_ROUTER : SD_LLDP_SYSTEM_CAPABILITIES_STATION); + if (r < 0) + return r; + + if (sd_lldp_tx_is_running(link->lldp_tx)) { + r = sd_lldp_tx_stop(link->lldp_tx); + if (r < 0) + return r; + + r = sd_lldp_tx_start(link->lldp_tx); + if (r < 0) + return r; + } + + return 0; +} + static const char * const lldp_multicast_mode_table[_SD_LLDP_MULTICAST_MODE_MAX] = { [SD_LLDP_MULTICAST_MODE_NEAREST_BRIDGE] = "nearest-bridge", [SD_LLDP_MULTICAST_MODE_NON_TPMR_BRIDGE] = "non-tpmr-bridge", diff --git a/src/network/networkd-lldp-tx.h b/src/network/networkd-lldp-tx.h index 73757f1..346eb5c 100644 --- a/src/network/networkd-lldp-tx.h +++ b/src/network/networkd-lldp-tx.h @@ -6,5 +6,6 @@ typedef struct Link Link; int link_lldp_tx_configure(Link *link); +int link_lldp_tx_update_capabilities(Link *link); CONFIG_PARSER_PROTOTYPE(config_parse_lldp_multicast_mode); diff --git a/src/network/networkd-sysctl.c b/src/network/networkd-sysctl.c index 68c23e0..a454322 100644 --- a/src/network/networkd-sysctl.c +++ b/src/network/networkd-sysctl.c @@ -7,7 +7,9 @@ #include "af-list.h" #include "missing_network.h" #include "networkd-link.h" +#include "networkd-lldp-tx.h" #include "networkd-manager.h" +#include "networkd-ndisc.h" #include "networkd-network.h" #include "networkd-sysctl.h" #include "socket-util.h" @@ -130,7 +132,7 @@ int link_get_ip_forwarding(Link *link, int family) { return link->manager->ip_forwarding[family == AF_INET6]; } -static int link_set_ip_forwarding(Link *link, int family) { +static int link_set_ip_forwarding_impl(Link *link, int family) { int r, t; assert(link); @@ -151,6 +153,65 @@ static int link_set_ip_forwarding(Link *link, int family) { return 0; } +static int link_reapply_ip_forwarding(Link *link, int family) { + int r, ret = 0; + + assert(link); + assert(IN_SET(family, AF_INET, AF_INET6)); + + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + return 0; + + (void) link_set_ip_forwarding_impl(link, family); + + r = link_lldp_tx_update_capabilities(link); + if (r < 0) + RET_GATHER(ret, log_link_warning_errno(link, r, "Could not update LLDP capabilities, ignoring: %m")); + + if (family == AF_INET6 && !link_ndisc_enabled(link)) { + r = ndisc_stop(link); + if (r < 0) + RET_GATHER(ret, log_link_warning_errno(link, r, "Could not stop IPv6 Router Discovery, ignoring: %m")); + + ndisc_flush(link); + } + + return ret; +} + +static int link_set_ip_forwarding(Link *link, int family) { + int r; + + assert(link); + assert(link->manager); + assert(link->network); + assert(IN_SET(family, AF_INET, AF_INET6)); + + if (!link_is_configured_for_family(link, family)) + return 0; + + /* When IPMasquerade= is enabled and the global setting is unset, enable _global_ IP forwarding, and + * re-apply per-link setting for all links. */ + if (FLAGS_SET(link->network->ip_masquerade, family == AF_INET ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6) && + link->manager->ip_forwarding[family == AF_INET6] < 0) { + + link->manager->ip_forwarding[family == AF_INET6] = true; + manager_set_ip_forwarding(link->manager, family); + + Link *other; + HASHMAP_FOREACH(other, link->manager->links_by_index) { + r = link_reapply_ip_forwarding(other, family); + if (r < 0) + link_enter_failed(other); + } + + return 0; + } + + /* Otherwise, apply per-link setting for _this_ link. */ + return link_set_ip_forwarding_impl(link, family); +} + static int link_set_ipv4_rp_filter(Link *link) { assert(link); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 7d87116..c6ce36b 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -2207,7 +2207,7 @@ static int copy_devnodes(const char *dest) { /* Explicitly warn the user when /dev is already populated. */ if (errno == EEXIST) log_notice("%s/dev/ is pre-mounted and pre-populated. If a pre-mounted /dev/ is provided it needs to be an unpopulated file system.", dest); - if (errno != EPERM) + if (!ERRNO_IS_PRIVILEGE(errno) || arg_uid_shift != 0) return log_error_errno(errno, "mknod(%s) failed: %m", to); /* Some systems abusively restrict mknod but allow bind mounts. */ @@ -2217,12 +2217,12 @@ static int copy_devnodes(const char *dest) { r = mount_nofollow_verbose(LOG_DEBUG, from, to, NULL, MS_BIND, NULL); if (r < 0) return log_error_errno(r, "Both mknod and bind mount (%s) failed: %m", to); + } else { + r = userns_lchown(to, 0, 0); + if (r < 0) + return log_error_errno(r, "chown() of device node %s failed: %m", to); } - r = userns_lchown(to, 0, 0); - if (r < 0) - return log_error_errno(r, "chown() of device node %s failed: %m", to); - dn = path_join("/dev", S_ISCHR(st.st_mode) ? "char" : "block"); if (!dn) return log_oom(); diff --git a/src/partition/repart.c b/src/partition/repart.c index 8a5ce7e..3b7c165 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -4925,14 +4925,14 @@ static int do_copy_files(Context *context, Partition *p, const char *root) { sfd, ".", pfd, fn, UID_INVALID, GID_INVALID, - COPY_REFLINK|COPY_HOLES|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS|COPY_GRACEFUL_WARN|COPY_TRUNCATE, + COPY_REFLINK|COPY_HOLES|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS|COPY_GRACEFUL_WARN|COPY_TRUNCATE|COPY_RESTORE_DIRECTORY_TIMESTAMPS, denylist, subvolumes_by_source_inode); } else r = copy_tree_at( sfd, ".", tfd, ".", UID_INVALID, GID_INVALID, - COPY_REFLINK|COPY_HOLES|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS|COPY_GRACEFUL_WARN|COPY_TRUNCATE, + COPY_REFLINK|COPY_HOLES|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS|COPY_GRACEFUL_WARN|COPY_TRUNCATE|COPY_RESTORE_DIRECTORY_TIMESTAMPS, denylist, subvolumes_by_source_inode); if (r < 0) return log_error_errno(r, "Failed to copy '%s%s' to '%s%s': %m", @@ -8155,6 +8155,10 @@ static int run(int argc, char *argv[]) { if (!context) return log_oom(); + r = context_read_seed(context, arg_root); + if (r < 0) + return r; + r = context_copy_from(context); if (r < 0) return r; @@ -8232,10 +8236,6 @@ static int run(int argc, char *argv[]) { return r; } - r = context_read_seed(context, arg_root); - if (r < 0) - return r; - /* Make sure each partition has a unique UUID and unique label */ r = context_acquire_partition_uuids_and_labels(context); if (r < 0) diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h index 1b649af..a43571a 100644 --- a/src/resolve/resolved-dns-packet.h +++ b/src/resolve/resolved-dns-packet.h @@ -111,6 +111,7 @@ static inline uint8_t* DNS_PACKET_DATA(const DnsPacket *p) { #define DNS_PACKET_AD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 5) & 1) #define DNS_PACKET_CD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 4) & 1) +#define DNS_PACKET_FLAG_AD (UINT16_C(1) << 5) #define DNS_PACKET_FLAG_TC (UINT16_C(1) << 9) static inline uint16_t DNS_PACKET_RCODE(DnsPacket *p) { diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index 23d4db9..c604a51 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -685,7 +685,8 @@ static int dns_stub_send_failure( static int dns_stub_patch_bypass_reply_packet( DnsPacket **ret, /* Where to place the patched packet */ DnsPacket *original, /* The packet to patch */ - DnsPacket *request) { /* The packet the patched packet shall look like a reply to */ + DnsPacket *request, /* The packet the patched packet shall look like a reply to */ + bool authenticated) { _cleanup_(dns_packet_unrefp) DnsPacket *c = NULL; int r; @@ -725,6 +726,10 @@ static int dns_stub_patch_bypass_reply_packet( DNS_PACKET_HEADER(c)->flags = htobe16(be16toh(DNS_PACKET_HEADER(c)->flags) | DNS_PACKET_FLAG_TC); } + /* Ensure we don't pass along an untrusted ad flag for bypass packets */ + if (!authenticated) + DNS_PACKET_HEADER(c)->flags = htobe16(be16toh(DNS_PACKET_HEADER(c)->flags) & ~DNS_PACKET_FLAG_AD); + *ret = TAKE_PTR(c); return 0; } @@ -745,7 +750,8 @@ static void dns_stub_query_complete(DnsQuery *query) { q->answer_full_packet->protocol == DNS_PROTOCOL_DNS) { _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL; - r = dns_stub_patch_bypass_reply_packet(&reply, q->answer_full_packet, q->request_packet); + r = dns_stub_patch_bypass_reply_packet(&reply, q->answer_full_packet, q->request_packet, + FLAGS_SET(q->answer_query_flags, SD_RESOLVED_AUTHENTICATED)); if (r < 0) log_debug_errno(r, "Failed to patch bypass reply packet: %m"); else diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index bf79dc2..042c0ad 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -167,7 +167,16 @@ static int ask_password_keyring(const AskPasswordRequest *req, AskPasswordFlags if (r < 0) return r; - return retrieve_key(serial, ret); + _cleanup_strv_free_erase_ char **l = NULL; + r = retrieve_key(serial, &l); + if (r < 0) + return r; + + if (strv_isempty(l)) + return log_debug_errno(SYNTHETIC_ERRNO(ENOKEY), "Found an empty password from keyring."); + + *ret = TAKE_PTR(l); + return 0; } static int backspace_chars(int ttyfd, size_t p) { @@ -322,8 +331,8 @@ int ask_password_plymouth( return -ENOENT; } else if (IN_SET(buffer[0], 2, 9)) { + _cleanup_strv_free_erase_ char **l = NULL; uint32_t size; - char **l; /* One or more answers */ if (p < 5) @@ -341,15 +350,16 @@ int ask_password_plymouth( if (!l) return -ENOMEM; - *ret = l; - break; + if (strv_isempty(l)) + return log_debug_errno(SYNTHETIC_ERRNO(ECANCELED), "Received an empty password."); + + *ret = TAKE_PTR(l); + return 0; } else /* Unknown packet */ return -EIO; } - - return 0; } #define NO_ECHO "(no echo) " @@ -949,8 +959,8 @@ finish: static int ask_password_credential(const AskPasswordRequest *req, AskPasswordFlags flags, char ***ret) { _cleanup_(erase_and_freep) char *buffer = NULL; + _cleanup_strv_free_erase_ char **l = NULL; size_t size; - char **l; int r; assert(req); @@ -965,7 +975,10 @@ static int ask_password_credential(const AskPasswordRequest *req, AskPasswordFla if (!l) return -ENOMEM; - *ret = l; + if (strv_isempty(l)) + return log_debug_errno(SYNTHETIC_ERRNO(ENOKEY), "Found an empty password in credential."); + + *ret = TAKE_PTR(l); return 0; } diff --git a/src/shared/copy.c b/src/shared/copy.c index 8389774..9b90afa 100644 --- a/src/shared/copy.c +++ b/src/shared/copy.c @@ -982,6 +982,7 @@ static int fd_copy_directory( _cleanup_close_ int fdf = -EBADF, fdt = -EBADF; _cleanup_closedir_ DIR *d = NULL; + struct stat dt_st; bool exists; int r; @@ -1026,6 +1027,9 @@ static int fd_copy_directory( if (fdt < 0) return fdt; + if (exists && FLAGS_SET(copy_flags, COPY_RESTORE_DIRECTORY_TIMESTAMPS) && fstat(fdt, &dt_st) < 0) + return -errno; + r = 0; if (PTR_TO_INT(hashmap_get(denylist, st)) == DENY_CONTENTS) { @@ -1125,7 +1129,9 @@ finish: (void) copy_xattr(dirfd(d), NULL, fdt, NULL, copy_flags); (void) futimens(fdt, (struct timespec[]) { st->st_atim, st->st_mtim }); - } + } else if (FLAGS_SET(copy_flags, COPY_RESTORE_DIRECTORY_TIMESTAMPS)) + /* If the directory already exists, make sure the timestamps stay the same as before. */ + (void) futimens(fdt, (struct timespec[]) { dt_st.st_atim, dt_st.st_mtim }); if (copy_flags & COPY_FSYNC_FULL) { if (fsync(fdt) < 0) diff --git a/src/shared/copy.h b/src/shared/copy.h index b8fb28a..db95738 100644 --- a/src/shared/copy.h +++ b/src/shared/copy.h @@ -12,25 +12,26 @@ #include "set.h" typedef enum CopyFlags { - COPY_REFLINK = 1 << 0, /* Try to reflink */ - COPY_MERGE = 1 << 1, /* Merge existing trees with our new one to copy */ - COPY_REPLACE = 1 << 2, /* Replace an existing file if there's one */ - COPY_SAME_MOUNT = 1 << 3, /* Don't descend recursively into other file systems, across mount point boundaries */ - COPY_MERGE_EMPTY = 1 << 4, /* Merge an existing, empty directory with our new tree to copy */ - COPY_CRTIME = 1 << 5, /* Generate a user.crtime_usec xattr off the source crtime if there is one, on copying */ - COPY_SIGINT = 1 << 6, /* Check for SIGINT regularly and return EINTR if seen (caller needs to block SIGINT) */ - COPY_SIGTERM = 1 << 7, /* ditto, but for SIGTERM */ - COPY_MAC_CREATE = 1 << 8, /* Create files with the correct MAC label (currently SELinux only) */ - COPY_HARDLINKS = 1 << 9, /* Try to reproduce hard links */ - COPY_FSYNC = 1 << 10, /* fsync() after we are done */ - COPY_FSYNC_FULL = 1 << 11, /* fsync_full() after we are done */ - COPY_SYNCFS = 1 << 12, /* syncfs() the *top-level* dir after we are done */ - COPY_ALL_XATTRS = 1 << 13, /* Preserve all xattrs when copying, not just those in the user namespace */ - COPY_HOLES = 1 << 14, /* Copy holes */ - COPY_GRACEFUL_WARN = 1 << 15, /* Skip copying file types that aren't supported by the target filesystem */ - COPY_TRUNCATE = 1 << 16, /* Truncate to current file offset after copying */ - COPY_LOCK_BSD = 1 << 17, /* Return a BSD exclusively locked file descriptor referring to the copied image/directory. */ - COPY_VERIFY_LINKED = 1 << 18, /* Check the source file is still linked after copying. */ + COPY_REFLINK = 1 << 0, /* Try to reflink */ + COPY_MERGE = 1 << 1, /* Merge existing trees with our new one to copy */ + COPY_REPLACE = 1 << 2, /* Replace an existing file if there's one */ + COPY_SAME_MOUNT = 1 << 3, /* Don't descend recursively into other file systems, across mount point boundaries */ + COPY_MERGE_EMPTY = 1 << 4, /* Merge an existing, empty directory with our new tree to copy */ + COPY_CRTIME = 1 << 5, /* Generate a user.crtime_usec xattr off the source crtime if there is one, on copying */ + COPY_SIGINT = 1 << 6, /* Check for SIGINT regularly and return EINTR if seen (caller needs to block SIGINT) */ + COPY_SIGTERM = 1 << 7, /* ditto, but for SIGTERM */ + COPY_MAC_CREATE = 1 << 8, /* Create files with the correct MAC label (currently SELinux only) */ + COPY_HARDLINKS = 1 << 9, /* Try to reproduce hard links */ + COPY_FSYNC = 1 << 10, /* fsync() after we are done */ + COPY_FSYNC_FULL = 1 << 11, /* fsync_full() after we are done */ + COPY_SYNCFS = 1 << 12, /* syncfs() the *top-level* dir after we are done */ + COPY_ALL_XATTRS = 1 << 13, /* Preserve all xattrs when copying, not just those in the user namespace */ + COPY_HOLES = 1 << 14, /* Copy holes */ + COPY_GRACEFUL_WARN = 1 << 15, /* Skip copying file types that aren't supported by the target filesystem */ + COPY_TRUNCATE = 1 << 16, /* Truncate to current file offset after copying */ + COPY_LOCK_BSD = 1 << 17, /* Return a BSD exclusively locked file descriptor referring to the copied image/directory. */ + COPY_VERIFY_LINKED = 1 << 18, /* Check the source file is still linked after copying. */ + COPY_RESTORE_DIRECTORY_TIMESTAMPS = 1 << 19, /* Make sure existing directory timestamps don't change during copying. */ } CopyFlags; typedef enum DenyType { diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index a9e211f..6a39010 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -3077,6 +3077,7 @@ int dissected_image_decrypt_interactively( if (r < 0) return log_error_errno(r, "Failed to query for passphrase: %m"); + assert(!strv_isempty(z)); passphrase = z[0]; } } diff --git a/src/shared/tests.c b/src/shared/tests.c index 9169513..a919212 100644 --- a/src/shared/tests.c +++ b/src/shared/tests.c @@ -29,6 +29,7 @@ #include "strv.h" #include "tests.h" #include "tmpfile-util.h" +#include "uid-range.h" char* setup_fake_runtime_dir(void) { char t[] = "/tmp/fake-xdg-runtime-XXXXXX", *p; @@ -166,6 +167,24 @@ bool have_namespaces(void) { assert_not_reached(); } +bool userns_has_single_user(void) { + _cleanup_(uid_range_freep) UIDRange *uidrange = NULL, *gidrange = NULL; + + /* Check if we're in a user namespace with only a single user mapped in. We special case this + * scenario in a few tests because it's the only kind of namespace that can be created unprivileged + * and as such happens more often than not, so we make sure to deal with it so that all tests pass + * in such environments. */ + + if (uid_range_load_userns(NULL, UID_RANGE_USERNS_INSIDE, &uidrange) < 0) + return false; + + if (uid_range_load_userns(NULL, GID_RANGE_USERNS_INSIDE, &gidrange) < 0) + return false; + + return uidrange->n_entries == 1 && uidrange->entries[0].nr == 1 && + gidrange->n_entries == 1 && gidrange->entries[0].nr == 1; +} + bool can_memlock(void) { /* Let's see if we can mlock() a larger blob of memory. BPF programs are charged against * RLIMIT_MEMLOCK, hence let's first make sure we can lock memory at all, and skip the test if we diff --git a/src/shared/tests.h b/src/shared/tests.h index 21f00db..f904c0d 100644 --- a/src/shared/tests.h +++ b/src/shared/tests.h @@ -76,6 +76,7 @@ void test_setup_logging(int level); int write_tmpfile(char *pattern, const char *contents); bool have_namespaces(void); +bool userns_has_single_user(void); /* We use the small but non-trivial limit here */ #define CAN_MEMLOCK_SIZE (512 * 1024U) @@ -217,6 +218,39 @@ static inline int run_test_table(void) { } \ }) +/* For funtions that return a boolean on success and a negative errno on failure. */ +#define ASSERT_OK_POSITIVE(expr) \ + ({ \ + typeof(expr) _result = (expr); \ + if (_result < 0) { \ + log_error_errno(_result, "%s:%i: Assertion failed: expected \"%s\" to succeed but got the following error: %m", \ + PROJECT_FILE, __LINE__, #expr); \ + abort(); \ + } \ + if (_result == 0) { \ + log_error("%s:%i: Assertion failed: expected \"%s\" to be positive, but it is zero.", \ + PROJECT_FILE, __LINE__, #expr); \ + abort(); \ + } \ + }) + +#define ASSERT_OK_ZERO(expr) \ + ({ \ + typeof(expr) _result = (expr); \ + if (_result < 0) { \ + log_error_errno(_result, "%s:%i: Assertion failed: expected \"%s\" to succeed but got the following error: %m", \ + PROJECT_FILE, __LINE__, #expr); \ + abort(); \ + } \ + if (_result != 0) { \ + char _sexpr[DECIMAL_STR_MAX(typeof(expr))]; \ + xsprintf(_sexpr, DECIMAL_STR_FMT(_result), _result); \ + log_error("%s:%i: Assertion failed: expected \"%s\" to be zero, but it is %s.", \ + PROJECT_FILE, __LINE__, #expr, _sexpr); \ + abort(); \ + } \ + }) + #define ASSERT_OK_ERRNO(expr) \ ({ \ typeof(expr) _result = (expr); \ diff --git a/src/test/test-acl-util.c b/src/test/test-acl-util.c index 0cc9afc..daab75e 100644 --- a/src/test/test-acl-util.c +++ b/src/test/test-acl-util.c @@ -41,7 +41,7 @@ TEST_RET(add_acls_for_user) { cmd = strjoina("getfacl -p ", fn); assert_se(system(cmd) == 0); - if (getuid() == 0) { + if (getuid() == 0 && !userns_has_single_user()) { const char *nobody = NOBODY_USER_NAME; r = get_user_creds(&nobody, &uid, NULL, NULL, NULL, 0); if (r < 0) diff --git a/src/test/test-capability.c b/src/test/test-capability.c index 34f3a91..51bd806 100644 --- a/src/test/test-capability.c +++ b/src/test/test-capability.c @@ -318,10 +318,13 @@ int main(int argc, char *argv[]) { show_capabilities(); - test_drop_privileges(); + if (!userns_has_single_user()) + test_drop_privileges(); + test_update_inherited_set(); - fork_test(test_have_effective_cap); + if (!userns_has_single_user()) + fork_test(test_have_effective_cap); if (run_ambient) fork_test(test_apply_ambient_caps); diff --git a/src/test/test-chase.c b/src/test/test-chase.c index 13ee702..c7ca3fd 100644 --- a/src/test/test-chase.c +++ b/src/test/test-chase.c @@ -183,7 +183,7 @@ TEST(chase) { /* Paths underneath the "root" with different UIDs while using CHASE_SAFE */ - if (geteuid() == 0) { + if (geteuid() == 0 && !userns_has_single_user()) { p = strjoina(temp, "/user"); ASSERT_OK(mkdir(p, 0755)); ASSERT_OK(chown(p, UID_NOBODY, GID_NOBODY)); @@ -313,7 +313,7 @@ TEST(chase) { r = chase(p, NULL, 0, &result, NULL); assert_se(r == -ENOENT); - if (geteuid() == 0) { + if (geteuid() == 0 && !userns_has_single_user()) { p = strjoina(temp, "/priv1"); ASSERT_OK(mkdir(p, 0755)); diff --git a/src/test/test-chown-rec.c b/src/test/test-chown-rec.c index 5d83f59..7558de7 100644 --- a/src/test/test-chown-rec.c +++ b/src/test/test-chown-rec.c @@ -153,8 +153,8 @@ TEST(chown_recursive) { } static int intro(void) { - if (geteuid() != 0) - return log_tests_skipped("not running as root"); + if (geteuid() != 0 || userns_has_single_user()) + return log_tests_skipped("not running as root or in userns with single user"); return EXIT_SUCCESS; } diff --git a/src/test/test-condition.c b/src/test/test-condition.c index be83690..76b2af9 100644 --- a/src/test/test-condition.c +++ b/src/test/test-condition.c @@ -1003,6 +1003,13 @@ TEST(condition_test_group) { condition_free(condition); free(gid); + /* In an unprivileged user namespace with the current user mapped to root, all the auxiliary groups + * of the user will be mapped to the nobody group, which means the user in the user namespace is in + * both the root and the nobody group, meaning the next test can't work, so let's skip it in that + * case. */ + if (in_group(NOBODY_GROUP_NAME) && in_group("root")) + return (void) log_tests_skipped("user is in both root and nobody group"); + groupname = (char*)(getegid() == 0 ? NOBODY_GROUP_NAME : "root"); condition = condition_new(CONDITION_GROUP, groupname, false, false); assert_se(condition); diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index f2fa51f..09fd995 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -368,8 +368,8 @@ TEST(chmod_and_chown) { struct stat st; const char *p; - if (geteuid() != 0) - return; + if (geteuid() != 0 || userns_has_single_user()) + return (void) log_tests_skipped("not running as root or in userns with single user"); BLOCK_WITH_UMASK(0000); diff --git a/src/test/test-macro.c b/src/test/test-macro.c index 3d5b0cf..b56f5b8 100644 --- a/src/test/test-macro.c +++ b/src/test/test-macro.c @@ -1117,6 +1117,18 @@ TEST(ASSERT) { ASSERT_SIGNAL(ASSERT_OK(-1), SIGABRT); ASSERT_SIGNAL(ASSERT_OK(-ENOANO), SIGABRT); + ASSERT_OK_POSITIVE(1); + ASSERT_OK_POSITIVE(255); + ASSERT_SIGNAL(ASSERT_OK_POSITIVE(0), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_POSITIVE(-1), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_POSITIVE(-ENOANO), SIGABRT); + + ASSERT_OK_ZERO(0); + ASSERT_SIGNAL(ASSERT_OK_ZERO(1), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_ZERO(255), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_ZERO(-1), SIGABRT); + ASSERT_SIGNAL(ASSERT_OK_ZERO(-ENOANO), SIGABRT); + ASSERT_OK_ERRNO(0 >= 0); ASSERT_OK_ERRNO(255 >= 0); ASSERT_OK_ERRNO(printf("Hello world\n")); diff --git a/src/test/test-rm-rf.c b/src/test/test-rm-rf.c index 4c69bd2..e4a4263 100644 --- a/src/test/test-rm-rf.c +++ b/src/test/test-rm-rf.c @@ -89,6 +89,9 @@ static void test_rm_rf_chmod_inner(void) { TEST(rm_rf_chmod) { int r; + if (getuid() == 0 && userns_has_single_user()) + return (void) log_tests_skipped("running as root or in userns with single user"); + if (getuid() == 0) { /* This test only works unpriv (as only then the access mask for the owning user matters), * hence drop privs here */ diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c index e34aa10..967ba9d 100644 --- a/src/test/test-socket-util.c +++ b/src/test/test-socket-util.c @@ -170,7 +170,7 @@ TEST(getpeercred_getpeergroups) { struct ucred ucred; int pair[2] = EBADF_PAIR; - if (geteuid() == 0) { + if (geteuid() == 0 && !userns_has_single_user()) { test_uid = 1; test_gid = 2; test_gids = (gid_t*) gids; diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c index 31b284b..4e62b84 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -265,9 +265,7 @@ static int process_one_password_file(const char *filename) { return log_error_errno(r, "Failed to query password: %m"); } - if (strv_isempty(passwords)) - return -ECANCELED; - + assert(!strv_isempty(passwords)); r = send_passwords(socket_name, passwords); if (r < 0) return log_error_errno(r, "Failed to send: %m"); diff --git a/src/udev/udevadm-test-builtin.c b/src/udev/udevadm-test-builtin.c index 322f627..5815f2c 100644 --- a/src/udev/udevadm-test-builtin.c +++ b/src/udev/udevadm-test-builtin.c @@ -79,6 +79,7 @@ int builtin_main(int argc, char *argv[], void *userdata) { UdevBuiltinCommand cmd; int r; + log_set_max_level(LOG_DEBUG); log_setup(); r = parse_argv(argc, argv); diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c index c8c23e8..58964b9 100644 --- a/src/udev/udevadm-test.c +++ b/src/udev/udevadm-test.c @@ -96,6 +96,7 @@ int test_main(int argc, char *argv[], void *userdata) { sigset_t mask, sigmask_orig; int r; + log_set_max_level(LOG_DEBUG); log_setup(); r = parse_argv(argc, argv); diff --git a/src/ukify/test/test_ukify.py b/src/ukify/test/test_ukify.py index e3d49d4..bab0b24 100755 --- a/src/ukify/test/test_ukify.py +++ b/src/ukify/test/test_ukify.py @@ -45,6 +45,13 @@ except ImportError as e: sys.path.append(os.path.dirname(__file__) + '/..') import ukify +# Skip if we're running on an architecture that does not use UEFI. +try: + ukify.guess_efi_arch() +except ValueError as e: + print(str(e), file=sys.stderr) + sys.exit(77) + build_root = os.getenv('PROJECT_BUILD_ROOT') try: slow_tests = bool(int(os.getenv('SYSTEMD_SLOW_TESTS', '1'))) diff --git a/test/TEST-13-NSPAWN/test.sh b/test/TEST-13-NSPAWN/test.sh index 5c85b0c..3ab52d0 100755 --- a/test/TEST-13-NSPAWN/test.sh +++ b/test/TEST-13-NSPAWN/test.sh @@ -17,6 +17,8 @@ test_append_files() { # For virtual wlan interface. instmods mac80211_hwsim + # for IPMasquerade= + instmods "=net/netfilter" generate_module_dependencies # Create a dummy container "template" with a minimal toolset, which we can diff --git a/test/integration-test-wrapper.py b/test/integration-test-wrapper.py index 0931043..e0a4b6e 100755 --- a/test/integration-test-wrapper.py +++ b/test/integration-test-wrapper.py @@ -149,7 +149,7 @@ def main(): '--runtime-scratch=no', *args.mkosi_args, '--qemu-firmware', args.firmware, - '--qemu-kvm', "auto" if not bool(int(os.getenv("TEST_NO_KVM", "0"))) else "no", + *(['--qemu-kvm', 'no'] if int(os.getenv("TEST_NO_KVM", "0")) else []), '--kernel-command-line-extra', ' '.join([ 'systemd.hostname=H', diff --git a/test/test-functions b/test/test-functions index 04fe20f..69a0e58 100644 --- a/test/test-functions +++ b/test/test-functions @@ -1453,10 +1453,31 @@ install_missing_libraries() { [[ -e "$libgcc_s" ]] && inst_library "$libgcc_s" done < <(ldconfig -p | awk '/\/libgcc_s.so.1$/ { print $4 }') - local lib path + local lib path libs # A number of dependencies is now optional via dlopen, so the install # script will not pick them up, since it looks at linkage. - for lib in libcryptsetup libidn libidn2 pwquality libqrencode tss2-esys tss2-rc tss2-mu tss2-tcti-device libfido2 libbpf libelf libdw xkbcommon p11-kit-1 libarchive libgcrypt libkmod; do + libs=( + libarchive + libbpf + libcryptsetup + libdw + libelf + libfido2 + libgcrypt + libidn + libidn2 + libip4tc + libkmod + libqrencode + p11-kit-1 + pwquality + tss2-esys + tss2-mu + tss2-rc + tss2-tcti-device + xkbcommon + ) + for lib in "${libs[@]}"; do ddebug "Searching for $lib via pkg-config" if pkg-config --exists "$lib"; then path="$(pkg-config --variable=libdir "$lib")" diff --git a/test/test-systemctl-enable.sh b/test/test-systemctl-enable.sh index 5615c90..3fc59f6 100644 --- a/test/test-systemctl-enable.sh +++ b/test/test-systemctl-enable.sh @@ -3,7 +3,7 @@ set -ex # Silence warning from running_in_chroot_or_offline() -export SYSTEMD_IGNORE_CHROOT=1 +export SYSTEMD_IN_CHROOT=0 systemctl=${1:-systemctl} systemd_id128=${2:-systemd-id128} diff --git a/test/units/TEST-13-NSPAWN.nspawn.sh b/test/units/TEST-13-NSPAWN.nspawn.sh index ee0fef8..ad11468 100755 --- a/test/units/TEST-13-NSPAWN.nspawn.sh +++ b/test/units/TEST-13-NSPAWN.nspawn.sh @@ -943,6 +943,17 @@ matrix_run_one() { return 0 } +testcase_api_vfs() { + local api_vfs_writable + + for api_vfs_writable in yes no network; do + matrix_run_one no no $api_vfs_writable + matrix_run_one yes no $api_vfs_writable + matrix_run_one no yes $api_vfs_writable + matrix_run_one yes yes $api_vfs_writable + done +} + testcase_check_os_release() { # https://github.com/systemd/systemd/issues/29185 local base common_opts root @@ -973,11 +984,46 @@ testcase_check_os_release() { rm -fr "$root" "$base" } -run_testcases +testcase_ip_masquerade() { + local root + + if ! command -v networkctl >/dev/null; then + echo "This test requires systemd-networkd, skipping..." + return 0 + fi + + systemctl unmask systemd-networkd.service + systemctl edit --runtime --stdin systemd-networkd.service --drop-in=debug.conf <<EOF +[Service] +Environment=SYSTEMD_LOG_LEVEL=debug +EOF + systemctl start systemd-networkd.service -for api_vfs_writable in yes no network; do - matrix_run_one no no $api_vfs_writable - matrix_run_one yes no $api_vfs_writable - matrix_run_one no yes $api_vfs_writable - matrix_run_one yes yes $api_vfs_writable -done + root="$(mktemp -d /var/lib/machines/TEST-13-NSPAWN.ip_masquerade.XXX)" + create_dummy_container "$root" + + systemd-run --unit=nspawn-hoge.service \ + systemd-nspawn \ + --register=no \ + --directory="$root" \ + --ephemeral \ + --machine=hoge \ + --network-veth \ + bash -x -c "ip link set host0 up; sleep 30s" + + /usr/lib/systemd/systemd-networkd-wait-online -i ve-hoge --timeout 30s + + # Check IPMasquerade= for ve-* and friends enabled IP forwarding. + [[ "$(cat /proc/sys/net/ipv4/conf/all/forwarding)" == "1" ]] + [[ "$(cat /proc/sys/net/ipv4/conf/default/forwarding)" == "1" ]] + [[ "$(cat /proc/sys/net/ipv6/conf/all/forwarding)" == "1" ]] + [[ "$(cat /proc/sys/net/ipv6/conf/default/forwarding)" == "1" ]] + + systemctl stop nspawn-hoge.service || : + systemctl stop systemd-networkd.service + systemctl mask systemd-networkd.service + + rm -fr "$root" +} + +run_testcases diff --git a/test/units/TEST-58-REPART.sh b/test/units/TEST-58-REPART.sh index f8c22ab..e5f9c1f 100755 --- a/test/units/TEST-58-REPART.sh +++ b/test/units/TEST-58-REPART.sh @@ -161,7 +161,7 @@ $imgs/zzz1 : start= 2048, size= 1775576, type=933AC7E1-2EB4-4F13-B844 $imgs/zzz2 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\"" systemd-repart --offline="$OFFLINE" \ - --definitions="$defs" \ + --definitions="$defs" \ --empty=create \ --size=50M \ --seed="$seed" \ @@ -1288,6 +1288,49 @@ testcase_dropped_partitions() { [[ "$(sfdisk -q -l "$image" | grep -c "$image")" -eq 2 ]] } +testcase_random_seed() { + local defs imgs output + + # For issue #34257 + + defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")" + imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")" + # shellcheck disable=SC2064 + trap "rm -rf '$defs' '$imgs'" RETURN + chmod 0755 "$defs" + + tee "$defs/root.conf" <<EOF +[Partition] +Type=root +EOF + + tee "$defs/home.conf" <<EOF +[Partition] +Type=home +Label=home-first +EOF + + tee "$defs/swap.conf" <<EOF +[Partition] +Type=swap +SizeMaxBytes=64M +PaddingMinBytes=92M +EOF + + systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --empty=create \ + --size=1G \ + --dry-run=no \ + --seed=random \ + --offline="$OFFLINE" \ + --json=pretty \ + "$imgs/zzz" + + sfdisk -d "$imgs/zzz" + [[ "$(sfdisk -d "$imgs/zzz" | grep -F 'uuid=' | awk '{ print $8 }' | sort -u | wc -l)" == "3" ]] +} + OFFLINE="yes" run_testcases diff --git a/test/units/TEST-74-AUX-UTILS.detect-virt.sh b/test/units/TEST-74-AUX-UTILS.detect-virt.sh new file mode 100755 index 0000000..fe1db4d --- /dev/null +++ b/test/units/TEST-74-AUX-UTILS.detect-virt.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: LGPL-2.1-or-later +set -eux +set -o pipefail + +SYSTEMD_IN_CHROOT=1 systemd-detect-virt --chroot +(! SYSTEMD_IN_CHROOT=0 systemd-detect-virt --chroot) |