--- /dev/null
+/**
+ * @name Use of potentially dangerous function
+ * @description Certain standard library functions are dangerous to call.
+ * @kind problem
+ * @problem.severity error
+ * @precision high
+ * @id cpp/potentially-dangerous-function
+ * @tags reliability
+ * security
+ *
+ * Borrowed from
+ * https://github.com/Semmle/ql/blob/master/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql
+ */
+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."
+ )
+}
+
+from FunctionCall call, Function target, string message
+where
+ call.getTarget() = target and
+ potentiallyDangerousFunction(target, message)
+select call, message
+++ /dev/null
-/**
- * @name Use of fgets()
- * @description fgets() is dangerous to call. Use read_line() instead.
- * @kind problem
- * @problem.severity error
- * @precision high
- * @id cpp/fgets
- * @tags reliability
- * security
- */
-import cpp
-
-predicate dangerousFunction(Function function) {
- exists (string name | name = function.getQualifiedName() |
- name = "fgets")
-}
-
-from FunctionCall call, Function target
-where call.getTarget() = target
- and dangerousFunction(target)
-select call, target.getQualifiedName() + " is potentially dangerous"
* paranoia: whenever we process passwords, call mlock() on the memory
first. i.e. look for all places we use string_erase()/string_free_erase() and
- augment them with mlock()
+ augment them with mlock(). Also use MADV_DONTDUMP
* whenever oom_kill memory.event event is triggered print a nice log message
show state of these flags, and optionally trigger such a factory reset on
next boot by setting the flag.
-* sd-boot: add "oneshot boot timeout" variable support
-
* sd-boot: automatically load EFI modules from some drop-in dir, so that people
can add in file system drivers and such
* sd-boot: optionally, show boot menu when previous default boot item has
non-zero "tries done" count
-* logind: add "boot into bootmenu" API, and possibly even "boot into windows"
- and "boot into macos".
-
* maybe set a special xattr on cgroups that have delegate=yes set, to make it
easy to mark cut points
print the initial transaction it would execute during boot-up.
This will also inform you about ordering loops and suchlike.
+## Compilation options
+
+The default configuration does not enable any optimization or hardening
+options. This is suitable for development and testing, but not for end-user
+installations.
+
+For deployment, optimization (`-O2` or `-O3` compiler options), link time
+optimization (`-Db_lto=true` meson option), and hardening (e.g.
+`-D_FORTIFY_SOURCE=2`, `-fstack-protector-strong`, `-fstack-clash-protection`,
+`-fcf-protection`, `-pie` compiler options, and `-z relro`, `-z now`,
+`--as-needed` linker options) are recommended. The most appropriate set of
+options depends on the architecture and distribution specifics so no default is
+provided.
+
## NTP Pool
By default, systemd-timesyncd uses the Google Public NTP servers
with `:` in which case the kernel command line option takes precedence, if it
is specified as well.
+* `$SYSTEMD_REBOOT_TO_FIRMWARE_SETUP` — if set overrides systemd-logind's
+ built-in EFI logic of requesting a reboot into the firmware. Takes a
+ boolean. If set to false the functionality is turned off entirely. If set to
+ true instead of requesting a reboot into the firmware setup UI through EFI a
+ file `/run/systemd/reboot-to-firmware-setup` is created whenever this is
+ requested. This file may be checked for by services run during system
+ shutdown in order to request the appropriate operation from the firmware in
+ an alternative fashion.
+
+* `$SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU` — similar to the above, allows
+ overriding of systemd-logind's built-in EFI logic of requesting a reboot into
+ the boot loader menu. Takes a boolean. If set to false the functionality is
+ turned off entirely. If set to true instead of requesting a reboot into the
+ boot loader menu through EFI a file `/run/systemd/reboot-to-boot-loader-menu`
+ is created whenever this is requested. The file contains the requested boot
+ loader menu timeout in µs, formatted in ASCII decimals, or zero in case no
+ time-out is requested. This file may be checked for by services run during
+ system shutdown in order to request the appropriate operation from the boot
+ loader in an alternative fashion.
+
+* `$SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY` — similar to the above, allows
+ overriding of systemd-logind's built-in EFI logic of requesting a reboot into
+ a specific boot loader entry. Takes a boolean. If set to false the
+ functionality is turned off entirely. If set to true instead of requesting a
+ reboot into a specific boot loader entry through EFI a file
+ `/run/systemd/reboot-to-boot-loader-entry` is created whenever this is
+ requested. The file contains the requested boot loader entry identifier. This
+ file may be checked for by services run during system shutdown in order to
+ request the appropriate operation from the boot loader in an alternative
+ fashion. Note that by default only boot loader entries which follow the [Boot
+ Loader Specification](https://systemd.io/BOOT_LOADER_SPECIFICATION) and are
+ placed in the ESP or the Extended Boot Loader partition may be selected this
+ way. However, if a directory `/run/boot-loader-entries/` exists, the entries
+ are loaded from there instead. The directory should contain the usual
+ directory hierarchy mandated by the Boot Loader Specification, i.e. the entry
+ drop-ins should be placed in
+ `/run/boot-loader-entries/loader/entries/*.conf`, and the files referenced by
+ the drop-ins (including the kernels and initrds) somewhere else below
+ `/run/boot-loader-entries/`. Note that all these files may be (and are
+ supposed to be) symlinks. systemd-logind will load these files on-demand,
+ these files can hence be updated (ideally atomically) whenever the boot
+ loader configuration changes. A foreign boot loader installer script should
+ hence synthesize drop-in snippets and symlinks for all boot entries at boot
+ or whenever they change if it wants to integrate with systemd-logind's APIs.
+
installed systemd tests:
* `$SYSTEMD_TEST_DATA` — override the location of test data. This is useful if
EVDEV_ABS_35=::94
EVDEV_ABS_36=::92
+# MacBook8,1 (2015), MacBook9,1 (2016), MacBook10,1 (2017)
+evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBook8,1:*
+evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBook9,1:*
+evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBook10,1:*
+ EVDEV_ABS_00=::95
+ EVDEV_ABS_01=::90
+ EVDEV_ABS_35=::95
+ EVDEV_ABS_36=::90
+
+# MacBookPro13,* (Late 2016), MacBookPro14,* (Mid 2017)
+evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBookPro13,1:*
+evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBookPro13,2:*
+evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBookPro14,1:*
+evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBookPro14,2:*
+ EVDEV_ABS_00=::96
+ EVDEV_ABS_01=::94
+ EVDEV_ABS_35=::96
+ EVDEV_ABS_36=::94
+
+evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBookPro13,3:*
+evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBookPro14,3:*
+ EVDEV_ABS_00=::96
+ EVDEV_ABS_01=::95
+ EVDEV_ABS_35=::96
+ EVDEV_ABS_36=::95
+
#########################################
# ASUS
#########################################
# XP-PEN STAR 06
id-input:modalias:input:b0003v28bdp0078*
ID_INPUT_TABLET=1
+
+# Lite-On Tech IBM USB Travel Keyboard with Ultra Nav Mouse
+id-input:modalias:input:b0003v04B3p301Ee0100-e0,1,2,4*
+ ID_INPUT_POINTINGSTICK=1
###########################################################
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAlienware*:pn*
+ KEYBOARD_KEY_81=f21 # Touchpad toggle
KEYBOARD_KEY_8a=ejectcd
# Alienware/Dell reserves these keys; safe to apply on all their devices
KEYBOARD_KEY_ae=!volumedown
KEYBOARD_KEY_b0=!volumeup
+# Lenovo Y50-70
+evdev:atkbd:dmi:bvn*:bvr*:svnLENOVO*:pn*20378*:pvr*
+ KEYBOARD_KEY_f3=f21 # Fn+F6 (toggle touchpad)
+
# V480
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*Lenovo*V480*:pvr*
KEYBOARD_KEY_f1=f21
<term><option>--firmware-setup</option></term>
<listitem>
- <para>When used with the <command>reboot</command> command,
- indicate to the system's firmware to boot into setup
- mode. Note that this is currently only supported on some EFI
- systems and only if the system was booted in EFI
- mode.</para>
+ <para>When used with the <command>reboot</command> command, indicate to the system's firmware to reboot into
+ the firmware setup interface. Note that this functionality is not available on all systems.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--boot-loader-menu=</option></term>
+
+ <listitem>
+ <para>When used with the <command>reboot</command> command, indicate to the system's boot loader to show the
+ boot loader menu on the following boot. Takes a time value as parameter — indicating the menu time-out. Pass
+ zero in order to disable the menu time-out. Note that not all boot loaders support this
+ functionality.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--boot-loader-entry=</option></term>
+
+ <listitem>
+ <para>When used with the <command>reboot</command> command, indicate to the system's boot loader to boot into
+ a specific boot loader entry on the following boot. Takes a boot loader entry identifier as argument, or
+ <literal>help</literal> in order to list available entries. Note that not all boot loaders support this
+ functionality.</para>
</listitem>
</varlistentry>
<listitem><para>Takes a boolean argument. When set, sets up a new UTS namespace for the executed
processes. In addition, changing hostname or domainname is prevented. Defaults to off.</para>
- <para>Note that the implementation of this setting might be impossible (for example if UTS namespaces are not
- available), and the unit should be written in a way that does not solely rely on this setting for
- security.</para></listitem>
+ <para>Note that the implementation of this setting might be impossible (for example if UTS namespaces
+ are not available), and the unit should be written in a way that does not solely rely on this setting
+ for security.</para>
+
+ <para>Note that when this option is enabled for a service hostname changes no longer propagate from
+ the system into the service, it is hence not suitable for services that need to take notice of system
+ hostname changes dynamically.</para></listitem>
</varlistentry>
<varlistentry>
<varlistentry>
<term><varname>DHCPServer=</varname></term>
<listitem>
- <para>Takes a boolean. If set to <literal>yes</literal>, DHCPv4 server will be start. Defaults
+ <para>Takes a boolean. If set to <literal>yes</literal>, DHCPv4 server will be started. Defaults
to <literal>no</literal>. Further settings for the DHCP
server may be set in the <literal>[DHCPServer]</literal>
section described below.</para>
specified more than once.
</para>
- <para>If the specified address is 0.0.0.0 (for IPv4) or
- [::] (for IPv6), a new address range of the requested size
- is automatically allocated from a system-wide pool of
- unused ranges. The allocated range is checked against all
- current network interfaces and all known network
- configuration files to avoid address range conflicts. The
- default system-wide pool consists of 192.168.0.0/16,
- 172.16.0.0/12 and 10.0.0.0/8 for IPv4, and fc00::/7 for
- IPv6. This functionality is useful to manage a large
- number of dynamically created network interfaces with the
- same network configuration and automatic address range
- assignment.</para>
+ <para>If the specified address is <literal>0.0.0.0</literal> (for IPv4) or <literal>::</literal>
+ (for IPv6), a new address range of the requested size is automatically allocated from a
+ system-wide pool of unused ranges. Note that the prefix length must be equal or larger than 8 for
+ IPv4, and 64 for IPv6. The allocated range is checked against all current network interfaces and
+ all known network configuration files to avoid address range conflicts. The default system-wide
+ pool consists of 192.168.0.0/16, 172.16.0.0/12 and 10.0.0.0/8 for IPv4, and fd00::/8 for IPv6.
+ This functionality is useful to manage a large number of dynamically created network interfaces
+ with the same network configuration and automatic address range assignment.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Address=</varname></term>
<listitem>
- <para>As in the <literal>[Network]</literal> section. This
- key is mandatory.</para>
+ <para>As in the <literal>[Network]</literal> section. This key is mandatory. Each
+ <literal>[Address]</literal> section can contain one <varname>Address=</varname> setting.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Peer=</varname></term>
<listitem>
<para>The peer address in a point-to-point connection.
- Accepts the same format as the <literal>Address</literal>
+ Accepts the same format as the <varname>Address=</varname>
key.</para>
</listitem>
</varlistentry>
described in
<citerefentry project='man-pages'><refentrytitle>inet_pton</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
This key only applies to IPv4 addresses. If it is not
- given, it is derived from the <literal>Address</literal>
+ given, it is derived from the <varname>Address=</varname>
key.</para>
</listitem>
</varlistentry>
automatic restart off. By default automatic restart is disabled.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>TripleSampling=</varname></term>
+ <listitem>
+ <para>Takes a boolean. When <literal>yes</literal>, three samples (instead of one) are used to determine
+ the value of a received bit by majority rule. When unset, the kernel's default will be used.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
<term><option>-c</option></term>
<term><option>--action=<replaceable>ACTION</replaceable></option></term>
<listitem>
- <para>Type of event to be triggered. The default value is
- <command>change</command>.</para>
+ <para>Type of event to be triggered. Possible actions are <literal>add</literal>,
+ <literal>remove</literal>, <literal>change</literal>, <literal>move</literal>,
+ <literal>online</literal>, <literal>offline</literal>, <literal>bind</literal>,
+ and <literal>unbind</literal>. The default value is <literal>change</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>
if rootprefixdir == ''
rootprefixdir = rootprefix_default
endif
+rootprefixdir_noslash = rootprefixdir == '/' ? '' : rootprefixdir
sysvinit_path = get_option('sysvinit-path')
sysvrcnd_path = get_option('sysvrcnd-path')
conf.set10('BUMP_PROC_SYS_FS_NR_OPEN', get_option('bump-proc-sys-fs-nr-open'))
conf.set('HIGH_RLIMIT_NOFILE', 512*1024)
-# join_paths ignore the preceding arguments if an absolute component is
+# join_paths ignores the preceding arguments if an absolute component is
# encountered, so this should canonicalize various paths when they are
# absolute or relative.
prefixdir = get_option('prefix')
substs.set('prefix', prefixdir)
substs.set('rootprefix', rootprefixdir)
+substs.set('rootprefix_noslash', rootprefixdir_noslash)
substs.set('exec_prefix', prefixdir)
substs.set('libdir', libdir)
substs.set('rootlibdir', rootlibdir)
'-Wno-missing-field-initializers',
'-Wno-unused-result',
'-Wno-format-signedness',
- '-Wno-error=#warnings',
+ '-Wno-error=#warnings', # clang
+ '-Wno-string-plus-int', # clang
# work-around for gcc 7.1 turning this on on its own.
'-Wno-error=nonnull',
'src/udev',
'src/libudev',
'src/core',
+ 'src/shutdown',
'src/libsystemd/sd-bus',
'src/libsystemd/sd-device',
'src/libsystemd/sd-event',
subdir('src/libudev')
subdir('src/shared')
subdir('src/core')
+subdir('src/shutdown')
subdir('src/udev')
subdir('src/network')
executable('systemd-fstab-generator',
'src/fstab-generator/fstab-generator.c',
- 'src/core/mount-setup.c',
include_directories : includes,
- link_with : [libshared],
+ link_with : [libcore_shared,
+ libshared],
install_rpath : rootlibexecdir,
install : true,
install_dir : systemgeneratordir)
executable('systemd-remount-fs',
'src/remount-fs/remount-fs.c',
- 'src/core/mount-setup.c',
- 'src/core/mount-setup.h',
include_directories : includes,
- link_with : [libshared],
+ link_with : [libcore_shared,
+ libshared],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootlibexecdir)
executable('systemd-machine-id-setup',
'src/machine-id-setup/machine-id-setup-main.c',
- 'src/core/machine-id-setup.c',
- 'src/core/machine-id-setup.h',
include_directories : includes,
- link_with : [libshared],
+ link_with : [libcore_shared,
+ libshared],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootbindir)
executable('systemd-shutdown',
systemd_shutdown_sources,
include_directories : includes,
- link_with : [libshared],
+ link_with : [libcore_shared,
+ libshared],
dependencies : [libmount],
install_rpath : rootlibexecdir,
install : true,
exe = executable('systemd-nspawn',
systemd_nspawn_sources,
- 'src/core/mount-setup.c', # FIXME: use a variable?
- 'src/core/mount-setup.h',
- 'src/core/loopback-setup.c',
- 'src/core/loopback-setup.h',
include_directories : includes,
- link_with : [libnspawn_core,
+ link_with : [libcore_shared,
+ libnspawn_core,
libshared],
dependencies : [libblkid],
install_rpath : rootlibexecdir,
msgstr ""
"Project-Id-Version: systemd\n"
"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
-"POT-Creation-Date: 2018-10-26 19:14+0000\n"
-"PO-Revision-Date: 2018-10-26 21:15+0200\n"
+"POT-Creation-Date: 2019-03-06 17:54+0000\n"
+"PO-Revision-Date: 2019-03-06 18:58+0100\n"
"Last-Translator: Piotr DrÄ…g <piotrdrag@gmail.com>\n"
"Language-Team: Polish <trans-pl@lists.fedoraproject.org>\n"
"Language: pl\n"
"Wymagane jest uwierzytelnienie, aby zablokować lub odblokować aktywne sesje."
#: src/login/org.freedesktop.login1.policy:341
-msgid "Allow indication to the firmware to boot to setup interface"
+msgid "Indicate to the firmware to boot to setup interface"
msgstr "Wskazanie oprogramowaniu sprzętowemu, aby uruchomić interfejs ustawień"
#: src/login/org.freedesktop.login1.policy:342
"Wymagane jest uwierzytelnienie, aby wskazać oprogramowaniu sprzętowemu, że "
"należy uruchomić interfejs ustawień."
-#: src/login/org.freedesktop.login1.policy:351
+#: src/login/org.freedesktop.login1.policy:352
+msgid "Indicate to the boot loader to boot to the boot loader menu"
+msgstr "Wskazanie programowi startowemu, aby uruchomić jego menu"
+
+#: src/login/org.freedesktop.login1.policy:353
+msgid ""
+"Authentication is required to indicate to the boot loader to boot to the "
+"boot loader menu."
+msgstr ""
+"Wymagane jest uwierzytelnienie, aby wskazać programowi startowemu, że należy "
+"uruchomić jego menu."
+
+#: src/login/org.freedesktop.login1.policy:363
+msgid "Indicate to the boot loader to boot a specific entry"
+msgstr "Wskazanie programowi startowemu, aby uruchomić podany wpis"
+
+#: src/login/org.freedesktop.login1.policy:364
+msgid ""
+"Authentication is required to indicate to the boot loader to boot into a "
+"specific boot loader entry."
+msgstr ""
+"Wymagane jest uwierzytelnienie, aby wskazać programowi startowemu, że należy "
+"uruchomić podany wpis."
+
+#: src/login/org.freedesktop.login1.policy:374
msgid "Set a wall message"
msgstr "Ustawienie komunikatu wall"
-#: src/login/org.freedesktop.login1.policy:352
+#: src/login/org.freedesktop.login1.policy:375
msgid "Authentication is required to set a wall message"
msgstr "Wymagane jest uwierzytelnienie, aby ustawić komunikat wall"
RELEASE=${RELEASE:-buster}
ARCH=${ARCH:-amd64}
CONTAINER=${RELEASE}-${ARCH}
+MAX_CACHE_AGE=604800 # one week
+CACHE=${SEMAPHORE_CACHE_DIR:=/tmp}/${CONTAINER}.img.tar.gz
+
+create_container() {
+ # create autopkgtest LXC image; this sometimes fails with "Unable to fetch
+ # GPG key from keyserver", so retry a few times
+ for retry in $(seq 5); do
+ sudo lxc-create -n $CONTAINER -t download -- -d $DISTRO -r $RELEASE -a $ARCH && break
+ sleep $((retry*retry))
+ done
+
+ # unconfine the container, otherwise some tests fail
+ echo 'lxc.apparmor.profile = unconfined' | sudo tee -a /var/lib/lxc/$CONTAINER/config
+
+ sudo lxc-start -n $CONTAINER
+
+ # enable source repositories so that apt-get build-dep works
+ sudo lxc-attach -n $CONTAINER -- sh -ex <<EOF
+sed 's/^deb/deb-src/' /etc/apt/sources.list >> /etc/apt/sources.list.d/sources.list
+# wait until online
+while [ -z "\$(ip route list 0/0)" ]; do sleep 1; done
+apt-get -q update
+apt-get -y dist-upgrade
+apt-get install -y eatmydata
+EOF
+ sudo lxc-stop -n $CONTAINER
+
+ # cache it
+ sudo tar cpzf "$CACHE" /var/lib/lxc/$CONTAINER
+}
# remove semaphore repos, some of them don't work and cause error messages
sudo rm -f /etc/apt/sources.list.d/*
sudo apt-get install -y -t xenial-backports lxc
sudo apt-get install -y python3-debian git dpkg-dev fakeroot
-AUTOPKGTESTDIR=${SEMAPHORE_CACHE_DIR:-/tmp}/autopkgtest
+AUTOPKGTESTDIR=$SEMAPHORE_CACHE_DIR/autopkgtest
[ -d $AUTOPKGTESTDIR ] || git clone --quiet --depth=1 https://salsa.debian.org/ci-team/autopkgtest.git "$AUTOPKGTESTDIR"
-# TODO: cache container image (though downloading/building it takes < 1 min)
-# create autopkgtest LXC image
-sudo lxc-create -n $CONTAINER -t download -- -d $DISTRO -r $RELEASE -a $ARCH
-
-# unconfine the container, otherwise some tests fail
-echo 'lxc.apparmor.profile = unconfined' | sudo tee -a /var/lib/lxc/$CONTAINER/config
-
-sudo lxc-start -n $CONTAINER
-
-# enable source repositories so that apt-get build-dep works
-sudo lxc-attach -n $CONTAINER -- sh -ex <<EOF
-sed 's/^deb/deb-src/' /etc/apt/sources.list >> /etc/apt/sources.list.d/sources.list
-# wait until online
-while [ -z "\$(ip route list 0/0)" ]; do sleep 1; done
-apt-get -q update
-apt-get -y dist-upgrade
-apt-get install -y eatmydata
-EOF
-sudo lxc-stop -n $CONTAINER
+# use cached container image, unless older than a week
+if [ -e "$CACHE" ] && [ $(( $(date +%s) - $(stat -c %Y "$CACHE") )) -le $MAX_CACHE_AGE ]; then
+ sudo tar -C / -xpzf "$CACHE"
+else
+ create_container
+fi
if (fstat(child, &st) < 0)
return -errno;
if ((flags & CHASE_SAFE) &&
+ (empty_or_root(root) || (size_t)(todo - buffer) > strlen(root)) &&
unsafe_transition(&previous_stat, &st))
return log_unsafe_transition(fd, child, path, flags);
#include "in-addr-util.h"
#include "macro.h"
#include "parse-util.h"
+#include "random-util.h"
+#include "strxcpyx.h"
#include "util.h"
bool in4_addr_is_null(const struct in_addr *a) {
return -EAFNOSUPPORT;
}
+int in_addr_random_prefix(
+ int family,
+ union in_addr_union *u,
+ unsigned prefixlen_fixed_part,
+ unsigned prefixlen) {
+
+ assert(u);
+
+ /* Random network part of an address by one. */
+
+ if (prefixlen <= 0)
+ return 0;
+
+ if (family == AF_INET) {
+ uint32_t c, n;
+
+ if (prefixlen_fixed_part > 32)
+ prefixlen_fixed_part = 32;
+ if (prefixlen > 32)
+ prefixlen = 32;
+ if (prefixlen_fixed_part >= prefixlen)
+ return -EINVAL;
+
+ c = be32toh(u->in.s_addr);
+ c &= ((UINT32_C(1) << prefixlen_fixed_part) - 1) << (32 - prefixlen_fixed_part);
+
+ random_bytes(&n, sizeof(n));
+ n &= ((UINT32_C(1) << (prefixlen - prefixlen_fixed_part)) - 1) << (32 - prefixlen);
+
+ u->in.s_addr = htobe32(n | c);
+ return 1;
+ }
+
+ if (family == AF_INET6) {
+ struct in6_addr n;
+ unsigned i, j;
+
+ if (prefixlen_fixed_part > 128)
+ prefixlen_fixed_part = 128;
+ if (prefixlen > 128)
+ prefixlen = 128;
+ if (prefixlen_fixed_part >= prefixlen)
+ return -EINVAL;
+
+ random_bytes(&n, sizeof(n));
+
+ for (i = 0; i < 16; i++) {
+ uint8_t mask_fixed_part = 0, mask = 0;
+
+ if (i < (prefixlen_fixed_part + 7) / 8) {
+ if (i < prefixlen_fixed_part / 8)
+ mask_fixed_part = 0xffu;
+ else {
+ j = prefixlen_fixed_part % 8;
+ mask_fixed_part = ((UINT8_C(1) << (j + 1)) - 1) << (8 - j);
+ }
+ }
+
+ if (i < (prefixlen + 7) / 8) {
+ if (i < prefixlen / 8)
+ mask = 0xffu ^ mask_fixed_part;
+ else {
+ j = prefixlen % 8;
+ mask = (((UINT8_C(1) << (j + 1)) - 1) << (8 - j)) ^ mask_fixed_part;
+ }
+ }
+
+ u->in6.s6_addr[i] &= mask_fixed_part;
+ u->in6.s6_addr[i] |= n.s6_addr[i] & mask;
+ }
+
+ return 1;
+ }
+
+ return -EAFNOSUPPORT;
+}
+
int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
- char *x;
+ _cleanup_free_ char *x = NULL;
size_t l;
assert(u);
return -ENOMEM;
errno = 0;
- if (!inet_ntop(family, u, x, l)) {
- free(x);
+ if (!inet_ntop(family, u, x, l))
+ return errno > 0 ? -errno : -EINVAL;
+
+ *ret = TAKE_PTR(x);
+ return 0;
+}
+
+int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret) {
+ _cleanup_free_ char *x = NULL;
+ char *p;
+ size_t l;
+
+ assert(u);
+ assert(ret);
+
+ if (family == AF_INET)
+ l = INET_ADDRSTRLEN + 3;
+ else if (family == AF_INET6)
+ l = INET6_ADDRSTRLEN + 4;
+ else
+ return -EAFNOSUPPORT;
+
+ if (prefixlen > FAMILY_ADDRESS_SIZE(family) * 8)
+ return -EINVAL;
+
+ x = new(char, l);
+ if (!x)
+ return -ENOMEM;
+
+ errno = 0;
+ if (!inet_ntop(family, u, x, l))
return errno > 0 ? -errno : -EINVAL;
- }
- *ret = x;
+ p = x + strlen(x);
+ l -= strlen(x);
+ (void) strpcpyf(&p, l, "/%u", prefixlen);
+
+ *ret = TAKE_PTR(x);
return 0;
}
int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) {
+ _cleanup_free_ char *x = NULL;
size_t l;
- char *x;
int r;
assert(u);
return -ENOMEM;
errno = 0;
- if (!inet_ntop(family, u, x, l)) {
- free(x);
+ if (!inet_ntop(family, u, x, l))
return errno > 0 ? -errno : -EINVAL;
- }
sprintf(strchr(x, 0), "%%%i", ifindex);
- *ret = x;
+ *ret = TAKE_PTR(x);
return 0;
fallback:
int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b);
int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen);
int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen);
+int in_addr_random_prefix(int family, union in_addr_union *u, unsigned prefixlen_fixed_part, unsigned prefixlen);
int in_addr_to_string(int family, const union in_addr_union *u, char **ret);
+int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret);
int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret);
int in_addr_from_string(int family, const char *s, union in_addr_union *ret);
int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret);
ratelimit.h
raw-clone.h
raw-reboot.h
- refcnt.h
replace-var.c
replace-var.h
rlimit-util.c
+++ /dev/null
-/* SPDX-License-Identifier: LGPL-2.1+ */
-#pragma once
-
-/* A type-safe atomic refcounter.
- *
- * DO NOT USE THIS UNLESS YOU ACTUALLY CARE ABOUT THREAD SAFETY! */
-
-typedef struct {
- volatile unsigned _value;
-} RefCount;
-
-#define REFCNT_GET(r) ((r)._value)
-#define REFCNT_INC(r) (__sync_add_and_fetch(&(r)._value, 1))
-#define REFCNT_DEC(r) (__sync_sub_and_fetch(&(r)._value, 1))
-
-#define REFCNT_INIT ((RefCount) { ._value = 1 })
-
-#define _DEFINE_ATOMIC_REF_FUNC(type, name, scope) \
- scope type *name##_ref(type *p) { \
- if (!p) \
- return NULL; \
- \
- assert_se(REFCNT_INC(p->n_ref) >= 2); \
- return p; \
- }
-
-#define _DEFINE_ATOMIC_UNREF_FUNC(type, name, free_func, scope) \
- scope type *name##_unref(type *p) { \
- if (!p) \
- return NULL; \
- \
- if (REFCNT_DEC(p->n_ref) > 0) \
- return NULL; \
- \
- return free_func(p); \
- }
-
-#define DEFINE_ATOMIC_REF_FUNC(type, name) \
- _DEFINE_ATOMIC_REF_FUNC(type, name,)
-#define DEFINE_PUBLIC_ATOMIC_REF_FUNC(type, name) \
- _DEFINE_ATOMIC_REF_FUNC(type, name, _public_)
-
-#define DEFINE_ATOMIC_UNREF_FUNC(type, name, free_func) \
- _DEFINE_ATOMIC_UNREF_FUNC(type, name, free_func,)
-#define DEFINE_PUBLIC_ATOMIC_UNREF_FUNC(type, name, free_func) \
- _DEFINE_ATOMIC_UNREF_FUNC(type, name, free_func, _public_)
-
-#define DEFINE_ATOMIC_REF_UNREF_FUNC(type, name, free_func) \
- DEFINE_ATOMIC_REF_FUNC(type, name); \
- DEFINE_ATOMIC_UNREF_FUNC(type, name, free_func);
-
-#define DEFINE_PUBLIC_ATOMIC_REF_UNREF_FUNC(type, name, free_func) \
- DEFINE_PUBLIC_ATOMIC_REF_FUNC(type, name); \
- DEFINE_PUBLIC_ATOMIC_UNREF_FUNC(type, name, free_func);
static int boot_entry_show(const BootEntry *e, bool show_as_default) {
assert(e);
- printf(" title: %s%s%s%s%s%s\n",
+ printf(" title: %s%s%s%s%s%s\n"
+ " type: %s\n",
ansi_highlight(),
boot_entry_title(e),
ansi_normal(),
ansi_highlight_green(),
show_as_default ? " (default)" : "",
- ansi_normal());
+ ansi_normal(),
+ boot_entry_type_to_string(e->type));
if (e->id)
printf(" id: %s\n", e->id);
static int verb_list(int argc, char *argv[], void *userdata) {
_cleanup_(boot_config_free) BootConfig config = {};
- _cleanup_free_ char **found_by_loader = NULL;
int r;
/* If we lack privileges we invoke find_esp_and_warn() in "unprivileged mode" here, which does two things: turn
if (r < 0)
return r;
- r = efi_loader_get_entries(&found_by_loader);
- if (r < 0 && !IN_SET(r, -ENOENT, -EOPNOTSUPP))
- log_debug_errno(r, "Failed to acquire boot loader discovered entries: %m");
+ (void) boot_entries_augment_from_loader(&config, false);
if (config.n_entries == 0)
log_info("No boot loader entries found.");
if (r < 0)
return r;
- puts("");
-
- strv_remove(found_by_loader, config.entries[n].id);
+ if (n+1 < config.n_entries)
+ putchar('\n');
}
}
- if (!strv_isempty(found_by_loader)) {
- char **i;
-
- printf("Automatic/Other Entries Found by Boot Loader:\n\n");
-
- STRV_FOREACH(i, found_by_loader)
- puts(*i);
- }
-
return 0;
}
return r;
SET_FOREACH(id, status_set->status, i) {
- int val = PTR_TO_INT(id);
+ int32_t val = PTR_TO_INT(id);
if (val < 0 || val > 255)
continue;
return r;
SET_FOREACH(id, status_set->signal, i) {
- int val = PTR_TO_INT(id);
+ int32_t val = PTR_TO_INT(id);
const char *str;
- str = signal_to_string(val);
+ str = signal_to_string((int) val);
if (!str)
continue;
UnitWriteFlags flags,
sd_bus_error *error) {
- const int *status, *signal;
+ const int32_t *status, *signal;
size_t sz_status, sz_signal, i;
int r;
if (r < 0)
return r;
+ sz_status /= sizeof(int32_t);
+ sz_signal /= sizeof(int32_t);
+
if (sz_status == 0 && sz_signal == 0 && !UNIT_WRITE_FLAGS_NOOP(flags)) {
exit_status_set_free(status_set);
unit_write_settingf(u, flags, name, "%s=", name);
for (i = 0; i < sz_status; i++) {
if (status[i] < 0 || status[i] > 255)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid status code in %s: %i", name, status[i]);
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid status code in %s: %"PRIi32, name, status[i]);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
r = set_ensure_allocated(&status_set->status, NULL);
if (r < 0)
return r;
- r = set_put(status_set->status, INT_TO_PTR(status[i]));
+ r = set_put(status_set->status, INT_TO_PTR((int) status[i]));
if (r < 0)
return r;
- unit_write_settingf(u, flags, name, "%s=%i", name, status[i]);
+ unit_write_settingf(u, flags, name, "%s=%"PRIi32, name, status[i]);
}
}
for (i = 0; i < sz_signal; i++) {
const char *str;
- str = signal_to_string(signal[i]);
+ str = signal_to_string((int) signal[i]);
if (!str)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal in %s: %i", name, signal[i]);
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal in %s: %"PRIi32, name, signal[i]);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
r = set_ensure_allocated(&status_set->signal, NULL);
if (r < 0)
return r;
- r = set_put(status_set->signal, INT_TO_PTR(signal[i]));
+ r = set_put(status_set->signal, INT_TO_PTR((int) signal[i]));
if (r < 0)
return r;
return r;
STRV_FOREACH(p, l) {
+ path_simplify(*p, true);
+
if (!path_is_absolute(*p))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s is not absolute: %s", name, *p);
+ if (!path_is_valid(*p))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s has invalid length: %s", name, *p);
+
+ if (!path_is_normalized(*p))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s is not normalized: %s", name, *p);
+
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
r = unit_require_mounts_for(u, *p, UNIT_DEPENDENCY_FILE);
if (r < 0)
#include "stat-util.h"
#include "string-util.h"
#include "swap.h"
+#include "udev-util.h"
#include "unit-name.h"
#include "unit.h"
assert(dev);
+ if (device_is_renaming(dev) > 0)
+ return false;
+
if (sd_device_get_property_value(dev, "SYSTEMD_READY", &ready) < 0)
return true;
else
fprintf(f, "%d\n", c->syscall_errno);
}
-
- if (c->apparmor_profile)
- fprintf(f,
- "%sAppArmorProfile: %s%s\n",
- prefix, c->apparmor_profile_ignore ? "-" : "", c->apparmor_profile);
}
bool exec_context_maintains_privileges(const ExecContext *c) {
assert(rvalue);
assert(data);
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "%s= is deprecated, please do not use.", lvalue);
+
if (isempty(rvalue)) {
/* Empty assignment resets the list */
*list = condition_free_list(*list);
# SPDX-License-Identifier: LGPL-2.1+
-libcore_la_sources = '''
+libcore_shared_sources = '''
+ killall.c
+ killall.h
+ loopback-setup.c
+ loopback-setup.h
+ machine-id-setup.c
+ machine-id-setup.h
+ mount-setup.c
+ mount-setup.h
+'''.split()
+
+libcore_sources = '''
audit-fd.c
audit-fd.h
automount.c
job.h
kill.c
kill.h
- killall.c
- killall.h
kmod-setup.c
kmod-setup.h
load-dropin.c
load-fragment.h
locale-setup.c
locale-setup.h
- loopback-setup.c
- loopback-setup.h
- machine-id-setup.c
- machine-id-setup.h
manager.c
manager.h
- mount-setup.c
- mount-setup.h
mount.c
mount.h
namespace.c
command : [awk, '-f', '@INPUT0@', '@INPUT1@'],
capture : true)
+# A convenience library to share code with other binaries:
+# systemd-shutdown, systemd-remount-fs, systemd-machine-id-setup, …
+libcore_shared = static_library(
+ 'core-shared',
+ libcore_shared_sources,
+ include_directories : includes,
+ dependencies : [versiondep,
+ libmount])
+
libcore = static_library(
'core',
- libcore_la_sources,
+ libcore_sources,
load_fragment_gperf_c,
load_fragment_gperf_nulstr_c,
include_directories : includes,
+ link_whole : libcore_shared,
dependencies : [versiondep,
threads,
librt,
systemd_sources = files('main.c')
-systemd_shutdown_sources = files('''
- shutdown.c
- umount.c
- umount.h
- mount-setup.c
- mount-setup.h
- killall.c
- killall.h
-'''.split())
-
in_files = [['macros.systemd', rpmmacrosdir],
['system.conf', pkgsysconfdir],
['systemd.pc', pkgconfigdatadir],
# (at your option) any later version.
prefix=@prefix@
-rootprefix=@rootprefix@
+rootprefix=@rootprefix_noslash@
sysconfdir=@sysconfdir@
systemdutildir=${rootprefix}/lib/systemd
systemdsystemunitdir=${rootprefix}/lib/systemd/system
if (!p)
return -ENOMEM;
- path = path_simplify(p, false);
+ path = path_simplify(p, true);
if (!path_is_normalized(path))
return -EPERM;
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+
+#include "alloc-util.h"
+#include "bus-label.h"
+#include "fuzz.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ _cleanup_free_ char *unescaped = NULL, *escaped = NULL;
+
+ unescaped = bus_label_unescape_n((const char*)data, size);
+ assert_se(unescaped != NULL);
+ escaped = bus_label_escape(unescaped);
+ assert_se(escaped != NULL);
+
+ return 0;
+}
}
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size > 65536)
+ return 0;
+
/* This triggers client_receive_advertise */
fuzz_client(data, size, false);
--- /dev/null
+[libfuzzer]
+max_len = 65536
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+
+#include "alloc-util.h"
+#include "env-file.h"
+#include "fd-util.h"
+#include "fuzz.h"
+#include "strv.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_strv_free_ char **rl = NULL, **rlp = NULL;
+
+ if (size == 0)
+ return 0;
+
+ f = fmemopen((char*) data, size, "re");
+ assert_se(f);
+
+ /* We don't want to fill the logs with messages about parse errors.
+ * Disable most logging if not running standalone */
+ if (!getenv("SYSTEMD_LOG_LEVEL"))
+ log_set_max_level(LOG_CRIT);
+
+ (void) load_env_file(f, NULL, &rl);
+ assert_se(fseek(f, 0, SEEK_SET) == 0);
+ (void) load_env_file_pairs(f, NULL, &rlp);
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fuzz.h"
+#include "hostname-util.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *ret = NULL;
+
+ if (size == 0)
+ return 0;
+
+ f = fmemopen((char*) data, size, "re");
+ assert_se(f);
+
+ /* We don't want to fill the logs with messages about parse errors.
+ * Disable most logging if not running standalone */
+ if (!getenv("SYSTEMD_LOG_LEVEL"))
+ log_set_max_level(LOG_CRIT);
+
+ (void) read_etc_hostname_stream(f, &ret);
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fuzz.h"
+#include "nspawn-settings.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_(settings_freep) Settings *s = NULL;
+
+ if (size == 0)
+ return 0;
+
+ f = fmemopen((char*) data, size, "re");
+ assert_se(f);
+
+ /* We don't want to fill the logs with messages about parse errors.
+ * Disable most logging if not running standalone */
+ if (!getenv("SYSTEMD_LOG_LEVEL"))
+ log_set_max_level(LOG_CRIT);
+
+ (void) settings_load(f, "/dev/null", &s);
+
+ return 0;
+}
[['src/fuzz/fuzz-compress.c'],
[libshared],
[]],
+
+ [['src/fuzz/fuzz-bus-label.c'],
+ [libshared],
+ []],
+
+ [['src/fuzz/fuzz-env-file.c'],
+ [libshared],
+ []],
+
+ [['src/fuzz/fuzz-hostname-util.c'],
+ [libshared],
+ []],
+
+ [['src/fuzz/fuzz-nspawn-settings.c'],
+ [libshared,
+ libnspawn_core],
+ []],
]
#include "import-common.h"
#include "os-util.h"
#include "process-util.h"
+#include "selinux-util.h"
#include "signal-util.h"
#include "tmpfile-util.h"
#include "util.h"
int import_fork_tar_x(const char *path, pid_t *ret) {
_cleanup_close_pair_ int pipefd[2] = { -1, -1 };
+ bool use_selinux;
pid_t pid;
int r;
if (pipe2(pipefd, O_CLOEXEC) < 0)
return log_error_errno(errno, "Failed to create pipe for tar: %m");
+ use_selinux = mac_selinux_use();
+
r = safe_fork("(tar)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
if (r < 0)
return r;
if (r < 0)
log_error_errno(r, "Failed to drop capabilities, ignoring: %m");
- execlp("tar", "tar", "--numeric-owner", "-C", path, "-px", "--xattrs", "--xattrs-include=*", NULL);
+ execlp("tar", "tar", "--numeric-owner", "-C", path, "-px", "--xattrs", "--xattrs-include=*",
+ use_selinux ? "--selinux" : "--no-selinux", NULL);
log_error_errno(errno, "Failed to execute tar: %m");
_exit(EXIT_FAILURE);
}
int import_fork_tar_c(const char *path, pid_t *ret) {
_cleanup_close_pair_ int pipefd[2] = { -1, -1 };
+ bool use_selinux;
pid_t pid;
int r;
if (pipe2(pipefd, O_CLOEXEC) < 0)
return log_error_errno(errno, "Failed to create pipe for tar: %m");
+ use_selinux = mac_selinux_use();
+
r = safe_fork("(tar)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
if (r < 0)
return r;
if (r < 0)
log_error_errno(r, "Failed to drop capabilities, ignoring: %m");
- execlp("tar", "tar", "-C", path, "-c", "--xattrs", "--xattrs-include=*", ".", NULL);
+ execlp("tar", "tar", "-C", path, "-c", "--xattrs", "--xattrs-include=*",
+ use_selinux ? "--selinux" : "--no-selinux", ".", NULL);
log_error_errno(errno, "Failed to execute tar: %m");
_exit(EXIT_FAILURE);
}
const char *header;
int r, code, fd;
_cleanup_free_ char *hostname = NULL;
+ bool chunked = false;
size_t len;
assert(connection);
return mhd_respond(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE,
"Content-Type: application/vnd.fdo.journal is required.");
+ header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Transfer-Encoding");
+ if (header) {
+ if (!strcaseeq(header, "chunked"))
+ return mhd_respondf(connection, 0, MHD_HTTP_BAD_REQUEST,
+ "Unsupported Transfer-Encoding type: %s", header);
+
+ chunked = true;
+ }
+
header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Length");
- if (!header)
- return mhd_respond(connection, MHD_HTTP_LENGTH_REQUIRED,
- "Content-Length header is required.");
- r = safe_atozu(header, &len);
- if (r < 0)
- return mhd_respondf(connection, r, MHD_HTTP_LENGTH_REQUIRED,
- "Content-Length: %s cannot be parsed: %m", header);
-
- if (len > ENTRY_SIZE_MAX)
- /* When serialized, an entry of maximum size might be slightly larger,
- * so this does not correspond exactly to the limit in journald. Oh well.
- */
- return mhd_respondf(connection, 0, MHD_HTTP_PAYLOAD_TOO_LARGE,
- "Payload larger than maximum size of %u bytes", ENTRY_SIZE_MAX);
+ if (header) {
+ if (chunked)
+ return mhd_respond(connection, MHD_HTTP_BAD_REQUEST,
+ "Content-Length must not specified when Transfer-Encoding type is 'chuncked'");
+
+ r = safe_atozu(header, &len);
+ if (r < 0)
+ return mhd_respondf(connection, r, MHD_HTTP_LENGTH_REQUIRED,
+ "Content-Length: %s cannot be parsed: %m", header);
+
+ if (len > ENTRY_SIZE_MAX)
+ /* When serialized, an entry of maximum size might be slightly larger,
+ * so this does not correspond exactly to the limit in journald. Oh well.
+ */
+ return mhd_respondf(connection, 0, MHD_HTTP_PAYLOAD_TOO_LARGE,
+ "Payload larger than maximum size of %u bytes", ENTRY_SIZE_MAX);
+ }
{
const union MHD_ConnectionInfo *ci;
NULL
};
-#define CATALOG_SIGNATURE (uint8_t[]) { 'R', 'H', 'H', 'H', 'K', 'S', 'L', 'P' }
+#define CATALOG_SIGNATURE { 'R', 'H', 'H', 'H', 'K', 'S', 'L', 'P' }
typedef struct CatalogHeader {
uint8_t signature[8]; /* "RHHHKSLP" */
return 1;
}
-static int catalog_entry_lang(const char* filename, int line,
- const char* t, const char* deflang, char **lang) {
+static int catalog_entry_lang(
+ const char* filename,
+ unsigned line,
+ const char* t,
+ const char* deflang,
+ char **ret) {
+
size_t c;
+ char *z;
c = strlen(t);
if (c < 2)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "[%s:%u] Language too short.",
- filename, line);
+ "[%s:%u] Language too short.", filename, line);
if (c > 31)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "[%s:%u] language too long.", filename,
- line);
+ "[%s:%u] language too long.", filename, line);
if (deflang) {
if (streq(t, deflang)) {
- log_warning("[%s:%u] language specified unnecessarily",
- filename, line);
+ log_warning("[%s:%u] language specified unnecessarily", filename, line);
return 0;
- } else
- log_warning("[%s:%u] language differs from default for file",
- filename, line);
+ }
+
+ log_warning("[%s:%u] language differs from default for file", filename, line);
}
- *lang = strdup(t);
- if (!*lang)
- return -ENOMEM;
+ z = strdup(t);
+ if (!z)
+ return -ENOMEM;
+ *ret = z;
return 0;
}
return 0;
}
-static int64_t write_catalog(const char *database, struct strbuf *sb,
- CatalogItem *items, size_t n) {
- CatalogHeader header;
+static int64_t write_catalog(
+ const char *database,
+ struct strbuf *sb,
+ CatalogItem *items,
+ size_t n) {
+
_cleanup_fclose_ FILE *w = NULL;
- int r;
- _cleanup_free_ char *d, *p = NULL;
+ _cleanup_free_ char *p = NULL;
+ CatalogHeader header;
size_t k;
+ int r;
- d = dirname_malloc(database);
- if (!d)
- return log_oom();
-
- r = mkdir_p(d, 0775);
+ r = mkdir_parents(database, 0755);
if (r < 0)
- return log_error_errno(r, "Recursive mkdir %s: %m", d);
+ return log_error_errno(r, "Failed to create parent directories of %s: %m", database);
r = fopen_temporary(database, &w, &p);
if (r < 0)
return log_error_errno(r, "Failed to open database for writing: %s: %m",
database);
- zero(header);
- memcpy(header.signature, CATALOG_SIGNATURE, sizeof(header.signature));
- header.header_size = htole64(ALIGN_TO(sizeof(CatalogHeader), 8));
- header.catalog_item_size = htole64(sizeof(CatalogItem));
- header.n_items = htole64(n);
+ header = (CatalogHeader) {
+ .signature = CATALOG_SIGNATURE,
+ .header_size = htole64(ALIGN_TO(sizeof(CatalogHeader), 8)),
+ .catalog_item_size = htole64(sizeof(CatalogItem)),
+ .n_items = htole64(n),
+ };
r = -EIO;
goto error;
}
- fchmod(fileno(w), 0644);
+ (void) fchmod(fileno(w), 0644);
if (rename(p, database) < 0) {
r = log_error_errno(errno, "rename (%s -> %s) failed: %m", p, database);
}
static int open_mmap(const char *database, int *_fd, struct stat *_st, void **_p) {
+ _cleanup_close_ int fd = -1;
const CatalogHeader *h;
- int fd;
- void *p;
struct stat st;
+ void *p;
assert(_fd);
assert(_st);
if (fd < 0)
return -errno;
- if (fstat(fd, &st) < 0) {
- safe_close(fd);
+ if (fstat(fd, &st) < 0)
return -errno;
- }
- if (st.st_size < (off_t) sizeof(CatalogHeader)) {
- safe_close(fd);
+ if (st.st_size < (off_t) sizeof(CatalogHeader))
return -EINVAL;
- }
p = mmap(NULL, PAGE_ALIGN(st.st_size), PROT_READ, MAP_SHARED, fd, 0);
- if (p == MAP_FAILED) {
- safe_close(fd);
+ if (p == MAP_FAILED)
return -errno;
- }
h = p;
- if (memcmp(h->signature, CATALOG_SIGNATURE, sizeof(h->signature)) != 0 ||
+ if (memcmp(h->signature, (const uint8_t[]) CATALOG_SIGNATURE, sizeof(h->signature)) != 0 ||
le64toh(h->header_size) < sizeof(CatalogHeader) ||
le64toh(h->catalog_item_size) < sizeof(CatalogItem) ||
h->incompatible_flags != 0 ||
le64toh(h->n_items) <= 0 ||
st.st_size < (off_t) (le64toh(h->header_size) + le64toh(h->catalog_item_size) * le64toh(h->n_items))) {
- safe_close(fd);
munmap(p, st.st_size);
return -EBADMSG;
}
- *_fd = fd;
+ *_fd = TAKE_FD(fd);
*_st = st;
*_p = p;
#include "siphash24.h"
#include "sparse-endian.h"
#include "stdio-util.h"
+#include "udev-util.h"
#include "virt.h"
#define SYSTEMD_PEN 43793
/* not yet ready */
return -EBUSY;
+ r = device_is_renaming(device);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ /* device is under renaming */
+ return -EBUSY;
+
name = net_get_name(device);
}
}
#include "lldp-network.h"
#include "macro.h"
#include "string-util.h"
+#include "tests.h"
#define TEST_LLDP_PORT "em1"
#define TEST_LLDP_TYPE_SYSTEM_NAME "systemd-lldp"
int main(int argc, char *argv[]) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
- log_set_max_level(LOG_DEBUG);
+ test_setup_logging(LOG_DEBUG);
/* LLDP reception tests */
assert_se(sd_event_new(&e) == 0);
#include "hashmap.h"
#include "list.h"
#include "prioq.h"
-#include "refcnt.h"
#include "socket-util.h"
#include "util.h"
};
struct sd_bus {
- /* We use atomic ref counting here since sd_bus_message
- objects retain references to their originating sd_bus but
- we want to allow them to be processed in a different
- thread. We won't provide full thread safety, but only the
- bare minimum that makes it possible to use sd_bus and
- sd_bus_message objects independently and on different
- threads as long as each object is used only once at the
- same time. */
- RefCount n_ref;
+ unsigned n_ref;
enum bus_state state;
int input_fd, output_fd;
return -ENOMEM;
*b = (sd_bus) {
- .n_ref = REFCNT_INIT,
+ .n_ref = 1,
.input_fd = -1,
.output_fd = -1,
.inotify_fd = -1,
bus_set_state(bus, BUS_CLOSING);
}
-DEFINE_PUBLIC_ATOMIC_REF_UNREF_FUNC(sd_bus, sd_bus, bus_free);
+DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_bus, sd_bus, bus_free);
_public_ int sd_bus_is_open(sd_bus *bus) {
assert_return(bus, -EINVAL);
#include "log.h"
#include "string-util.h"
#include "strv.h"
+#include "tests.h"
static void test_one_address(sd_bus *b,
const char *host,
}
int main(int argc, char *argv[]) {
- log_set_max_level(LOG_INFO);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_INFO);
test_bus_set_address_system_remote(argv + 1);
#include "bus-internal.h"
#include "bus-message.h"
#include "bus-util.h"
-#include "refcnt.h"
#include "tests.h"
static bool use_system_bus = false;
_cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
assert_se(sd_bus_new(&bus) == 0);
- printf("after new: refcount %u\n", REFCNT_GET(bus->n_ref));
+ assert_se(bus->n_ref == 1);
}
static int test_bus_open(void) {
}
assert_se(r >= 0);
- printf("after open: refcount %u\n", REFCNT_GET(bus->n_ref));
+ assert_se(bus->n_ref >= 1); /* we send a hello message when opening, so the count is above 1 */
return 0;
}
assert_se(sd_bus_message_new_method_call(bus, &m, "a.service.name", "/an/object/path", "an.interface.name", "AMethodName") >= 0);
- printf("after message_new_method_call: refcount %u\n", REFCNT_GET(bus->n_ref));
-
+ assert_se(m->n_ref == 1); /* We hold the only reference to the message */
+ assert_se(bus->n_ref >= 2);
sd_bus_flush_close_unref(bus);
- printf("after bus_flush_close_unref: refcount %u\n", m->n_ref);
+ assert_se(m->n_ref == 1);
}
static void test_bus_new_signal(void) {
assert_se(sd_bus_message_new_signal(bus, &m, "/an/object/path", "an.interface.name", "Name") >= 0);
- printf("after message_new_signal: refcount %u\n", REFCNT_GET(bus->n_ref));
-
+ assert_se(m->n_ref == 1); /* We hold the only reference to the message */
+ assert_se(bus->n_ref >= 2);
sd_bus_flush_close_unref(bus);
- printf("after bus_flush_close_unref: refcount %u\n", m->n_ref);
+ assert_se(m->n_ref == 1);
}
int main(int argc, char **argv) {
#include "bus-introspect.h"
#include "log.h"
+#include "tests.h"
static int prop_get(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
return -EINVAL;
int main(int argc, char *argv[]) {
struct introspect intro;
- log_set_max_level(LOG_DEBUG);
+ test_setup_logging(LOG_DEBUG);
assert_se(introspect_begin(&intro, false) >= 0);
/* SPDX-License-Identifier: LGPL-2.1+ */
+#include "sd-bus.h"
#include "main-func.h"
-#include "sd-bus.h"
#include "tests.h"
-static int run(int argc, char *argv[]) {
+static int test_ref_unref(void) {
sd_bus_message *m = NULL;
sd_bus *bus = NULL;
int r;
return 0;
}
+static int run(int argc, char *argv[]) {
+ int r;
+
+ test_setup_logging(LOG_INFO);
+
+ r = test_ref_unref();
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
DEFINE_MAIN_FUNCTION(run);
#include "socket-util.h"
#include "string-util.h"
#include "tmpfile-util.h"
+#include "tests.h"
static int method_foobar(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
log_info("Got Foobar() call.");
pthread_t server, client1, client2;
char *path;
- log_set_max_level(LOG_DEBUG);
+ test_setup_logging(LOG_DEBUG);
/* We use /dev/shm here rather than /tmp, since some weird distros might set up /tmp as some weird fs that
* doesn't support inotify properly. */
bool db_persist:1; /* don't clean up the db when switching from initrd to real root */
};
-typedef enum DeviceAction {
- DEVICE_ACTION_ADD,
- DEVICE_ACTION_REMOVE,
- DEVICE_ACTION_CHANGE,
- DEVICE_ACTION_MOVE,
- DEVICE_ACTION_ONLINE,
- DEVICE_ACTION_OFFLINE,
- DEVICE_ACTION_BIND,
- DEVICE_ACTION_UNBIND,
- _DEVICE_ACTION_MAX,
- _DEVICE_ACTION_INVALID = -1,
-} DeviceAction;
-
int device_new_aux(sd_device **ret);
int device_add_property_aux(sd_device *device, const char *key, const char *value, bool db);
int device_add_property_internal(sd_device *device, const char *key, const char *value);
int device_set_subsystem(sd_device *device, const char *_subsystem);
int device_set_driver(sd_device *device, const char *_driver);
int device_set_usec_initialized(sd_device *device, usec_t when);
-
-DeviceAction device_action_from_string(const char *s) _pure_;
-const char *device_action_to_string(DeviceAction a) _const_;
#include "mkdir.h"
#include "parse-util.h"
#include "path-util.h"
-#include "refcnt.h"
#include "set.h"
#include "string-table.h"
#include "string-util.h"
#include "sd-device.h"
+#include "macro.h"
+
int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len);
int device_new_from_strv(sd_device **ret, char **strv);
int device_new_from_stat_rdev(sd_device **ret, const struct stat *st);
static inline int device_read_db(sd_device *device) {
return device_read_db_internal(device, false);
}
+
+typedef enum DeviceAction {
+ DEVICE_ACTION_ADD,
+ DEVICE_ACTION_REMOVE,
+ DEVICE_ACTION_CHANGE,
+ DEVICE_ACTION_MOVE,
+ DEVICE_ACTION_ONLINE,
+ DEVICE_ACTION_OFFLINE,
+ DEVICE_ACTION_BIND,
+ DEVICE_ACTION_UNBIND,
+ _DEVICE_ACTION_MAX,
+ _DEVICE_ACTION_INVALID = -1,
+} DeviceAction;
+
+DeviceAction device_action_from_string(const char *s) _pure_;
+const char *device_action_to_string(DeviceAction a) _const_;
#include "hashmap.h"
#include "hwdb-internal.h"
#include "hwdb-util.h"
-#include "refcnt.h"
#include "string-util.h"
#include "util.h"
struct sd_hwdb {
- RefCount n_ref;
+ unsigned n_ref;
FILE *f;
struct stat st;
if (!hwdb)
return -ENOMEM;
- hwdb->n_ref = REFCNT_INIT;
+ hwdb->n_ref = 1;
/* find hwdb.bin in hwdb_bin_paths */
NULSTR_FOREACH(hwdb_bin_path, hwdb_bin_paths) {
+ log_debug("Trying to open \"%s\"...", hwdb_bin_path);
hwdb->f = fopen(hwdb_bin_path, "re");
if (hwdb->f)
break;
- else if (errno == ENOENT)
- continue;
- else
+ if (errno != ENOENT)
return log_debug_errno(errno, "Failed to open %s: %m", hwdb_bin_path);
}
- if (!hwdb->f) {
- log_debug("hwdb.bin does not exist, please run 'systemd-hwdb update'");
- return -ENOENT;
- }
+ if (!hwdb->f)
+ return log_debug_errno(SYNTHETIC_ERRNO(ENOENT),
+ "hwdb.bin does not exist, please run 'systemd-hwdb update'");
- if (fstat(fileno(hwdb->f), &hwdb->st) < 0 ||
- (size_t) hwdb->st.st_size < offsetof(struct trie_header_f, strings_len) + 8)
- return log_debug_errno(errno, "Failed to read %s: %m", hwdb_bin_path);
+ if (fstat(fileno(hwdb->f), &hwdb->st) < 0)
+ return log_debug_errno(errno, "Failed to stat %s: %m", hwdb_bin_path);
+ if (hwdb->st.st_size < (off_t) offsetof(struct trie_header_f, strings_len) + 8)
+ return log_debug_errno(SYNTHETIC_ERRNO(EIO),
+ "File %s is too short: %m", hwdb_bin_path);
hwdb->map = mmap(0, hwdb->st.st_size, PROT_READ, MAP_SHARED, fileno(hwdb->f), 0);
if (hwdb->map == MAP_FAILED)
return mfree(hwdb);
}
-DEFINE_PUBLIC_ATOMIC_REF_UNREF_FUNC(sd_hwdb, sd_hwdb, hwdb_free)
+DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_hwdb, sd_hwdb, hwdb_free)
bool hwdb_validate(sd_hwdb *hwdb) {
bool found = false;
return false;
/* if hwdb.bin doesn't exist anywhere, we need to update */
- NULSTR_FOREACH(p, hwdb_bin_paths) {
+ NULSTR_FOREACH(p, hwdb_bin_paths)
if (stat(p, &st) >= 0) {
found = true;
break;
}
- }
if (!found)
return true;
#include "list.h"
#include "netlink-types.h"
#include "prioq.h"
-#include "refcnt.h"
#define RTNL_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
};
struct sd_netlink {
- RefCount n_ref;
+ unsigned n_ref;
int fd;
};
struct sd_netlink_message {
- RefCount n_ref;
+ unsigned n_ref;
sd_netlink *rtnl;
#include "netlink-internal.h"
#include "netlink-types.h"
#include "netlink-util.h"
-#include "refcnt.h"
#include "socket-util.h"
#include "util.h"
if (!m)
return -ENOMEM;
- m->n_ref = REFCNT_INIT;
+ m->n_ref = 1;
m->protocol = rtnl->protocol;
m->sealed = false;
return 0;
}
-DEFINE_ATOMIC_REF_FUNC(sd_netlink_message, sd_netlink_message);
+DEFINE_TRIVIAL_REF_FUNC(sd_netlink_message, sd_netlink_message);
sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m) {
- sd_netlink_message *t;
-
- while (m && REFCNT_DEC(m->n_ref) == 0) {
+ while (m && --m->n_ref == 0) {
unsigned i;
free(m->hdr);
for (i = 0; i <= m->n_containers; i++)
free(m->containers[i].attributes);
- t = m;
+ sd_netlink_message *t = m;
m = m->next;
free(t);
}
#include "netlink-internal.h"
#include "netlink-types.h"
#include "netlink-util.h"
-#include "refcnt.h"
#include "socket-util.h"
#include "util.h"
static const NLType rtnl_link_info_data_can_types[] = {
[IFLA_CAN_BITTIMING] = { .size = sizeof(struct can_bittiming) },
[IFLA_CAN_RESTART_MS] = { .type = NETLINK_TYPE_U32 },
+ [IFLA_CAN_CTRLMODE] = { .size = sizeof(struct can_ctrlmode) },
};
/* these strings must match the .kind entries in the kernel */
assert(ifindex > 0);
assert(name);
+ if (!ifname_valid(name))
+ return -EINVAL;
+
if (!*rtnl) {
r = sd_netlink_open(rtnl);
if (r < 0)
#include "netlink-internal.h"
#include "netlink-types.h"
#include "netlink-util.h"
-#include "refcnt.h"
#include "socket-util.h"
#include "util.h"
return -ENOMEM;
*rtnl = (sd_netlink) {
- .n_ref = REFCNT_INIT,
+ .n_ref = 1,
.fd = -1,
.sockaddr.nl.nl_family = AF_NETLINK,
.original_pid = getpid_cached(),
return mfree(rtnl);
}
-DEFINE_ATOMIC_REF_UNREF_FUNC(sd_netlink, sd_netlink, netlink_free);
+DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_netlink, sd_netlink, netlink_free);
static void rtnl_seal_message(sd_netlink *rtnl, sd_netlink_message *m) {
assert(rtnl);
#include "keymap-util.h"
#include "log.h"
#include "string-util.h"
+#include "tests.h"
static void test_find_language_fallback(void) {
_cleanup_free_ char *ans = NULL, *ans2 = NULL;
}
int main(int argc, char **argv) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
+ test_setup_logging(LOG_DEBUG);
test_find_language_fallback();
test_find_converted_keymap();
SUBSYSTEM=="sound", KERNEL=="card*", TAG+="seat"
SUBSYSTEM=="input", KERNEL=="input*", TAG+="seat"
SUBSYSTEM=="graphics", KERNEL=="fb[0-9]*", TAG+="seat"
+
+# HyperV currently doesn't do DRM, hence we need to synthesize for HyperV's fb device instead
+SUBSYSTEM=="graphics", KERNEL=="fb[0-9]", DRIVERS=="hyperv_fb", TAG+="master-of-seat"
+
SUBSYSTEM=="drm", KERNEL=="card[0-9]*", TAG+="seat", TAG+="master-of-seat"
SUBSYSTEM=="usb", ATTR{bDeviceClass}=="09", TAG+="seat"
return bus_log_parse_error(r);
if (all || !isempty(s))
- bus_print_property_value(name, expected_value, value, "%s", s);
+ bus_print_property_value(name, expected_value, value, s);
return 1;
"Invalid user ID: " UID_FMT,
uid);
- bus_print_property_value(name, expected_value, value, UID_FMT, uid);
+ bus_print_property_valuef(name, expected_value, value, UID_FMT, uid);
return 1;
}
break;
#include "alloc-util.h"
#include "audit-util.h"
+#include "bootspec.h"
#include "bus-common-errors.h"
#include "bus-error.h"
#include "bus-unit-util.h"
#include "device-util.h"
#include "dirent-util.h"
#include "efivars.h"
+#include "env-util.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio-label.h"
#include "logind.h"
#include "missing_capability.h"
#include "mkdir.h"
+#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "selinux-util.h"
#include "sleep-config.h"
#include "special.h"
+#include "stdio-util.h"
#include "strv.h"
#include "terminal-util.h"
#include "tmpfile-util.h"
assert(reply);
assert(userdata);
- r = efi_get_reboot_to_firmware();
- if (r < 0 && r != -EOPNOTSUPP)
- log_warning_errno(r, "Failed to determine reboot-to-firmware state: %m");
+ r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP");
+ if (r == -ENXIO) {
+ /* EFI case: let's see what is currently configured in the EFI variables */
+ r = efi_get_reboot_to_firmware();
+ if (r < 0 && r != -EOPNOTSUPP)
+ log_warning_errno(r, "Failed to determine reboot-to-firmware-setup state: %m");
+ } else if (r < 0)
+ log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
+ else if (r > 0) {
+ /* Non-EFI case: let's see whether /run/systemd/reboot-to-firmware-setup exists. */
+ if (access("/run/systemd/reboot-to-firmware-setup", F_OK) < 0) {
+ if (errno != ENOENT)
+ log_warning_errno(errno, "Failed to check whether /run/systemd/reboot-to-firmware-setup exists: %m");
+
+ r = false;
+ } else
+ r = true;
+ }
return sd_bus_message_append(reply, "b", r > 0);
}
void *userdata,
sd_bus_error *error) {
- int b, r;
Manager *m = userdata;
+ bool use_efi;
+ int b, r;
assert(message);
assert(m);
if (r < 0)
return r;
+ r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP");
+ if (r == -ENXIO) {
+ /* EFI case: let's see what the firmware supports */
+
+ r = efi_reboot_to_firmware_supported();
+ if (r == -EOPNOTSUPP)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Firmware does not support boot into firmware.");
+ if (r < 0)
+ return r;
+
+ use_efi = true;
+
+ } else if (r <= 0) {
+ /* non-EFI case: $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP is set to off */
+
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
+
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Firmware does not support boot into firmware.");
+ } else
+ /* non-EFI case: $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP is set to on */
+ use_efi = false;
+
r = bus_verify_polkit_async(message,
CAP_SYS_ADMIN,
"org.freedesktop.login1.set-reboot-to-firmware-setup",
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
- r = efi_set_reboot_to_firmware(b);
+ if (use_efi) {
+ r = efi_set_reboot_to_firmware(b);
+ if (r < 0)
+ return r;
+ } else {
+ if (b) {
+ r = touch("/run/systemd/reboot-to-firmware-setup");
+ if (r < 0)
+ return r;
+ } else {
+ if (unlink("/run/systemd/reboot-to-firmware-setup") < 0 && errno != ENOENT)
+ return -errno;
+ }
+ }
+
+ return sd_bus_reply_method_return(message, NULL);
+}
+
+static int return_test_polkit(
+ sd_bus_message *message,
+ int capability,
+ const char *action,
+ const char **details,
+ uid_t good_user,
+ sd_bus_error *e) {
+
+ const char *result;
+ bool challenge;
+ int r;
+
+ r = bus_test_polkit(message, capability, action, details, good_user, &challenge, e);
if (r < 0)
return r;
- return sd_bus_reply_method_return(message, NULL);
+ if (r > 0)
+ result = "yes";
+ else if (challenge)
+ result = "challenge";
+ else
+ result = "no";
+
+ return sd_bus_reply_method_return(message, "s", result);
}
static int method_can_reboot_to_firmware_setup(
void *userdata,
sd_bus_error *error) {
+ Manager *m = userdata;
int r;
- bool challenge;
- const char *result;
+
+ assert(message);
+ assert(m);
+
+ r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP");
+ if (r == -ENXIO) {
+ /* EFI case: let's see what the firmware supports */
+
+ r = efi_reboot_to_firmware_supported();
+ if (r < 0) {
+ if (r != -EOPNOTSUPP)
+ log_warning_errno(r, "Failed to determine whether reboot to firmware is supported: %m");
+
+ return sd_bus_reply_method_return(message, "s", "na");
+ }
+
+ } else if (r <= 0) {
+ /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP */
+
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
+
+ return sd_bus_reply_method_return(message, "s", "na");
+ }
+
+ return return_test_polkit(
+ message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.set-reboot-to-firmware-setup",
+ NULL,
+ UID_INVALID,
+ error);
+}
+
+static int property_get_reboot_to_boot_loader_menu(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ uint64_t x = UINT64_MAX;
+ int r;
+
+ assert(bus);
+ assert(reply);
+ assert(userdata);
+
+ r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU");
+ if (r == -ENXIO) {
+ _cleanup_free_ char *v = NULL;
+
+ /* EFI case: returns the current value of LoaderConfigTimeoutOneShot. Three cases are distuingished:
+ *
+ * 1. Variable not set, boot into boot loader menu is not enabled (we return UINT64_MAX to the user)
+ * 2. Variable set to "0", boot into boot loader menu is enabled with no timeout (we return 0 to the user)
+ * 3. Variable set to numeric value formatted in ASCII, boot into boot loader menu with the specified timeout in seconds
+ */
+
+ r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", &v);
+ if (r < 0) {
+ if (r != -ENOENT)
+ log_warning_errno(r, "Failed to read LoaderConfigTimeoutOneShot variable: %m");
+ } else {
+ uint64_t sec;
+
+ r = safe_atou64(v, &sec);
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse LoaderConfigTimeoutOneShot value '%s': %m", v);
+ else if (sec > (USEC_INFINITY / USEC_PER_SEC))
+ log_warning("LoaderConfigTimeoutOneShot too large, ignoring: %m");
+ else
+ x = sec * USEC_PER_SEC; /* return in µs */
+ }
+
+ } else if (r < 0)
+ log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m");
+ else if (r > 0) {
+ _cleanup_free_ char *v = NULL;
+
+ /* Non-EFI case, let's process /run/systemd/reboot-to-boot-loader-menu. */
+
+ r = read_one_line_file("/run/systemd/reboot-to-boot-loader-menu", &v);
+ if (r < 0) {
+ if (r != -ENOENT)
+ log_warning_errno(r, "Failed to read /run/systemd/reboot-to-boot-loader-menu: %m");
+ } else {
+ r = safe_atou64(v, &x);
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse /run/systemd/reboot-to-boot-loader-menu: %m");
+ }
+ }
+
+ return sd_bus_message_append(reply, "t", x);
+}
+
+static int method_set_reboot_to_boot_loader_menu(
+ sd_bus_message *message,
+ void *userdata,
+ sd_bus_error *error) {
+
Manager *m = userdata;
+ bool use_efi;
+ uint64_t x;
+ int r;
assert(message);
assert(m);
- r = efi_reboot_to_firmware_supported();
- if (r < 0) {
- if (r != -EOPNOTSUPP)
- log_warning_errno(r, "Failed to determine whether reboot to firmware is supported: %m");
+ r = sd_bus_message_read(message, "t", &x);
+ if (r < 0)
+ return r;
+
+ r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU");
+ if (r == -ENXIO) {
+ uint64_t features;
+
+ /* EFI case: let's see if booting into boot loader menu is supported. */
+
+ r = efi_loader_get_features(&features);
+ if (r < 0)
+ log_warning_errno(r, "Failed to determine whether reboot to boot loader menu is supported: %m");
+ if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader does not support boot into boot loader menu.");
+
+ use_efi = true;
+
+ } else if (r <= 0) {
+ /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU is set to off */
+
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m");
+
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader does not support boot into boot loader menu.");
+ } else
+ /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU is set to on */
+ use_efi = false;
+
+ r = bus_verify_polkit_async(message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.set-reboot-to-boot-loader-menu",
+ NULL,
+ false,
+ UID_INVALID,
+ &m->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+
+ if (use_efi) {
+ if (x == UINT64_MAX)
+ r = efi_set_variable(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", NULL, 0);
+ else {
+ char buf[DECIMAL_STR_MAX(uint64_t) + 1];
+ xsprintf(buf, "%" PRIu64, DIV_ROUND_UP(x, USEC_PER_SEC)); /* second granularity */
+
+ r = efi_set_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", buf);
+ }
+ if (r < 0)
+ return r;
+ } else {
+ if (x == UINT64_MAX) {
+ if (unlink("/run/systemd/reboot-to-loader-menu") < 0 && errno != ENOENT)
+ return -errno;
+ } else {
+ char buf[DECIMAL_STR_MAX(uint64_t) + 1];
+
+ xsprintf(buf, "%" PRIu64, x); /* µs granularity */
+
+ r = write_string_file_atomic_label("/run/systemd/reboot-to-loader-menu", buf);
+ if (r < 0)
+ return r;
+ }
+ }
+
+ return sd_bus_reply_method_return(message, NULL);
+}
+
+static int method_can_reboot_to_boot_loader_menu(
+ sd_bus_message *message,
+ void *userdata,
+ sd_bus_error *error) {
+
+ Manager *m = userdata;
+ int r;
+
+
+ assert(message);
+ assert(m);
+
+ r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU");
+ if (r == -ENXIO) {
+ uint64_t features = 0;
+
+ /* EFI case, let's see if booting into boot loader menu is supported. */
+
+ r = efi_loader_get_features(&features);
+ if (r < 0)
+ log_warning_errno(r, "Failed to determine whether reboot to boot loader menu is supported: %m");
+ if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT))
+ return sd_bus_reply_method_return(message, "s", "na");
+
+ } else if (r <= 0) {
+ /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU */
+
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m");
return sd_bus_reply_method_return(message, "s", "na");
}
- r = bus_test_polkit(message,
- CAP_SYS_ADMIN,
- "org.freedesktop.login1.set-reboot-to-firmware-setup",
- NULL,
- UID_INVALID,
- &challenge,
- error);
+ return return_test_polkit(
+ message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.set-reboot-to-boot-loader-menu",
+ NULL,
+ UID_INVALID,
+ error);
+}
+
+static int property_get_reboot_to_boot_loader_entry(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ _cleanup_free_ char *v = NULL;
+ int r;
+
+ assert(bus);
+ assert(reply);
+ assert(userdata);
+
+ r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY");
+ if (r == -ENXIO) {
+ /* EFI case: let's read the LoaderEntryOneShot variable */
+
+ r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", &v);
+ if (r < 0) {
+ if (r != -ENOENT)
+ log_warning_errno(r, "Failed to read LoaderEntryOneShot variable: %m");
+ } else if (!efi_loader_entry_name_valid(v)) {
+ log_warning("LoaderEntryOneShot contains invalid entry name '%s', ignoring.", v);
+ v = mfree(v);
+ }
+ } else if (r < 0)
+ log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m");
+ else if (r > 0) {
+
+ /* Non-EFI case, let's process /run/systemd/reboot-to-boot-loader-entry. */
+
+ r = read_one_line_file("/run/systemd/reboot-to-boot-loader-entry", &v);
+ if (r < 0) {
+ if (r != -ENOENT)
+ log_warning_errno(r, "Failed to read /run/systemd/reboot-to-boot-loader-entry: %m");
+ } else if (!efi_loader_entry_name_valid(v)) {
+ log_warning("/run/systemd/reboot-to-boot-loader-entry is not valid, ignoring.");
+ v = mfree(v);
+ }
+ }
+
+ return sd_bus_message_append(reply, "s", v);
+}
+
+static int boot_loader_entry_exists(const char *id) {
+ _cleanup_(boot_config_free) BootConfig config = {};
+ int r;
+
+ assert(id);
+
+ r = boot_entries_load_config_auto(NULL, NULL, &config);
if (r < 0)
return r;
- if (r > 0)
- result = "yes";
- else if (challenge)
- result = "challenge";
- else
- result = "no";
+ (void) boot_entries_augment_from_loader(&config, true);
- return sd_bus_reply_method_return(message, "s", result);
+ return boot_config_has_entry(&config, id);
+}
+
+static int method_set_reboot_to_boot_loader_entry(
+ sd_bus_message *message,
+ void *userdata,
+ sd_bus_error *error) {
+
+ Manager *m = userdata;
+ bool use_efi;
+ const char *v;
+ int r;
+
+ assert(message);
+ assert(m);
+
+ r = sd_bus_message_read(message, "s", &v);
+ if (r < 0)
+ return r;
+
+ if (isempty(v))
+ v = NULL;
+ else if (efi_loader_entry_name_valid(v)) {
+ r = boot_loader_entry_exists(v);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader entry '%s' is not known.", v);
+ } else
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Boot loader entry name '%s' is not valid, refusing.", v);
+
+ r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY");
+ if (r == -ENXIO) {
+ uint64_t features;
+
+ /* EFI case: let's see if booting into boot loader entry is supported. */
+
+ r = efi_loader_get_features(&features);
+ if (r < 0)
+ log_warning_errno(r, "Failed to determine whether reboot into boot loader entry is supported: %m");
+ if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_ENTRY_ONESHOT))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Loader does not support boot into boot loader entry.");
+
+ use_efi = true;
+
+ } else if (r <= 0) {
+ /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY is set to off */
+
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m");
+
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Loader does not support boot into boot loader entry.");
+ } else
+ /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY is set to on */
+ use_efi = false;
+
+ r = bus_verify_polkit_async(message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.set-reboot-to-boot-loader-entry",
+ NULL,
+ false,
+ UID_INVALID,
+ &m->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+
+ if (use_efi) {
+ if (isempty(v))
+ /* Delete item */
+ r = efi_set_variable(EFI_VENDOR_LOADER, "LoaderEntryOneShot", NULL, 0);
+ else
+ r = efi_set_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", v);
+ if (r < 0)
+ return r;
+ } else {
+ if (isempty(v)) {
+ if (unlink("/run/systemd/reboot-to-boot-loader-entry") < 0 && errno != ENOENT)
+ return -errno;
+ } else {
+ r = write_string_file_atomic_label("/run/systemd/reboot-boot-to-loader-entry", v);
+ if (r < 0)
+ return r;
+ }
+ }
+
+ return sd_bus_reply_method_return(message, NULL);
+}
+
+static int method_can_reboot_to_boot_loader_entry(
+ sd_bus_message *message,
+ void *userdata,
+ sd_bus_error *error) {
+
+ Manager *m = userdata;
+ int r;
+
+ assert(message);
+ assert(m);
+
+ r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY");
+ if (r == -ENXIO) {
+ uint64_t features = 0;
+
+ /* EFI case, let's see if booting into boot loader entry is supported. */
+
+ r = efi_loader_get_features(&features);
+ if (r < 0)
+ log_warning_errno(r, "Failed to determine whether reboot to boot loader entry is supported: %m");
+ if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_ENTRY_ONESHOT))
+ return sd_bus_reply_method_return(message, "s", "na");
+
+ } else if (r <= 0) {
+ /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY */
+
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m");
+
+ return sd_bus_reply_method_return(message, "s", "na");
+ }
+
+ return return_test_polkit(
+ message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.set-reboot-to-boot-loader-entry",
+ NULL,
+ UID_INVALID,
+ error);
+}
+
+static int property_get_boot_loader_entries(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ _cleanup_(boot_config_free) BootConfig config = {};
+ size_t i;
+ int r;
+
+ assert(bus);
+ assert(reply);
+ assert(userdata);
+
+ r = boot_entries_load_config_auto(NULL, NULL, &config);
+ if (r < 0)
+ return r;
+
+ (void) boot_entries_augment_from_loader(&config, true);
+
+ r = sd_bus_message_open_container(reply, 'a', "s");
+ if (r < 0)
+ return r;
+
+ for (i = 0; i < config.n_entries; i++) {
+ BootEntry *e = config.entries + i;
+
+ r = sd_bus_message_append(reply, "s", e->id);
+ if (r < 0)
+ return r;
+ }
+
+ return sd_bus_message_close_container(reply);
}
static int method_set_wall_message(
SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, 0),
+ SD_BUS_PROPERTY("RebootToBootLoaderMenu", "t", property_get_reboot_to_boot_loader_menu, 0, 0),
+ SD_BUS_PROPERTY("RebootToBootLoaderEntry", "s", property_get_reboot_to_boot_loader_entry, 0, 0),
+ SD_BUS_PROPERTY("BootLoaderEntries", "as", property_get_boot_loader_entries, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("CanRebootToBootLoaderMenu", NULL, "s", method_can_reboot_to_boot_loader_menu, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("SetRebootToBootLoaderMenu", "t", NULL, method_set_reboot_to_boot_loader_menu, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("CanRebootToBootLoaderEntry", NULL, "s", method_can_reboot_to_boot_loader_entry, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("SetRebootToBootLoaderEntry", "s", NULL, method_set_reboot_to_boot_loader_entry, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_SIGNAL("SessionNew", "so", 0),
send_interface="org.freedesktop.login1.Manager"
send_member="SetRebootToFirmwareSetup"/>
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="CanRebootToBootLoaderMenu"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="SetRebootToBootLoaderMenu"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="CanRebootToBootLoaderEntry"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="SetRebootToBootLoaderEntry"/>
+
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
send_member="SetWallMessage"/>
</action>
<action id="org.freedesktop.login1.set-reboot-to-firmware-setup">
- <description gettext-domain="systemd">Allow indication to the firmware to boot to setup interface</description>
+ <description gettext-domain="systemd">Indicate to the firmware to boot to setup interface</description>
<message gettext-domain="systemd">Authentication is required to indicate to the firmware to boot to setup interface.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.reboot</annotate>
</action>
+ <action id="org.freedesktop.login1.set-reboot-to-boot-loader-menu">
+ <description gettext-domain="systemd">Indicate to the boot loader to boot to the boot loader menu</description>
+ <message gettext-domain="systemd">Authentication is required to indicate to the boot loader to boot to the boot loader menu.</message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>yes</allow_active>
+ </defaults>
+ <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.reboot</annotate>
+ </action>
+
+ <action id="org.freedesktop.login1.set-reboot-to-boot-loader-entry">
+ <description gettext-domain="systemd">Indicate to the boot loader to boot a specific entry</description>
+ <message gettext-domain="systemd">Authentication is required to indicate to the boot loader to boot into a specific boot loader entry.</message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>yes</allow_active>
+ </defaults>
+ <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.reboot</annotate>
+ </action>
+
<action id="org.freedesktop.login1.set-wall-message">
<description gettext-domain="systemd">Set a wall message</description>
<message gettext-domain="systemd">Authentication is required to set a wall message</message>
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(reply, "(st)", &name, &usage)) > 0) {
- log_info("Removed image '%s'. Freed exclusive disk space: %s",
- name, format_bytes(fb, sizeof(fb), usage));
-
- total += usage;
+ if (usage == UINT64_MAX) {
+ log_info("Removed image '%s'", name);
+ total = UINT64_MAX;
+ } else {
+ log_info("Removed image '%s'. Freed exclusive disk space: %s",
+ name, format_bytes(fb, sizeof(fb), usage));
+ if (total != UINT64_MAX)
+ total += usage;
+ }
c++;
}
if (r < 0)
return bus_log_parse_error(r);
- log_info("Removed %u images in total. Total freed exclusive disk space %s.",
- c, format_bytes(fb, sizeof(fb), total));
+ if (total == UINT64_MAX)
+ log_info("Removed %u images in total.", c);
+ else
+ log_info("Removed %u images in total. Total freed exclusive disk space: %s.",
+ c, format_bytes(fb, sizeof(fb), total));
return 0;
}
#include "set.h"
#include "string-util.h"
-int address_pool_new(
+#define RANDOM_PREFIX_TRIAL_MAX 1024
+
+static int address_pool_new(
Manager *m,
AddressPool **ret,
int family,
int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found) {
union in_addr_union u;
+ unsigned i;
+ int r;
assert(p);
assert(prefixlen > 0);
assert(found);
- if (p->prefixlen > prefixlen)
+ if (p->prefixlen >= prefixlen)
return 0;
u = p->in_addr;
- for (;;) {
- if (!address_pool_prefix_is_taken(p, &u, prefixlen)) {
- _cleanup_free_ char *s = NULL;
- int r;
- r = in_addr_to_string(p->family, &u, &s);
- if (r < 0)
- return r;
+ for (i = 0; i < RANDOM_PREFIX_TRIAL_MAX; i++) {
+ r = in_addr_random_prefix(p->family, &u, p->prefixlen, prefixlen);
+ if (r <= 0)
+ return r;
- log_debug("Found range %s/%u", strna(s), prefixlen);
+ if (!address_pool_prefix_is_taken(p, &u, prefixlen)) {
+ if (DEBUG_LOGGING) {
+ _cleanup_free_ char *s = NULL;
+
+ (void) in_addr_to_string(p->family, &u, &s);
+ log_debug("Found range %s/%u", strna(s), prefixlen);
+ }
*found = u;
return 1;
}
-
- if (!in_addr_prefix_next(p->family, &u, prefixlen))
- return 0;
-
- if (!in_addr_prefix_intersect(p->family, &p->in_addr, p->prefixlen, &u, prefixlen))
- return 0;
}
return 0;
LIST_FIELDS(AddressPool, address_pools);
};
-int address_pool_new(Manager *m, AddressPool **ret, int family, const union in_addr_union *u, unsigned prefixlen);
int address_pool_new_from_string(Manager *m, AddressPool **ret, int family, const char *p, unsigned prefixlen);
void address_pool_free(AddressPool *p);
r = fw_add_masquerade(masq, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
if (r < 0)
- log_link_warning_errno(link, r, "Could not enable IP masquerading: %m");
+ return r;
address->ip_masquerade_done = masq;
}
r = fw_add_masquerade(false, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
if (r < 0)
- log_link_warning_errno(address->link, r, "Failed to disable IP masquerading: %m");
+ return r;
address->ip_masquerade_done = false;
}
int address_drop(Address *address) {
Link *link;
bool ready;
+ int r;
assert(address);
ready = address_is_ready(address);
link = address->link;
- address_release(address);
+ r = address_release(address);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Failed to disable IP masquerading, ignoring: %m");
+
address_free(address);
link_update_operstate(link, true);
link_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
- _cleanup_free_ char *b = NULL;
int r;
assert(address);
assert(link->manager->rtnl);
if (DEBUG_LOGGING) {
- if (in_addr_to_string(address->family, &address->in_addr, &b) >= 0)
- log_link_debug(link, "Removing address %s", b);
+ _cleanup_free_ char *b = NULL;
+
+ (void) in_addr_to_string(address->family, &address->in_addr, &b);
+ log_link_debug(link, "Removing address %s", strna(b));
}
r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR,
link->ifindex, address->family);
if (r < 0)
- return log_error_errno(r, "Could not allocate RTM_DELADDR message: %m");
+ return log_link_error_errno(link, r, "Could not allocate RTM_DELADDR message: %m");
r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
if (r < 0)
- return log_error_errno(r, "Could not set prefixlen: %m");
+ return log_link_error_errno(link, r, "Could not set prefixlen: %m");
r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
if (r < 0)
- return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m");
+ return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
r = netlink_call_async(link->manager->rtnl, NULL, req,
callback ?: address_remove_handler,
link_netlink_destroy_callback, link);
if (r < 0)
- return log_error_errno(r, "Could not send rtnetlink message: %m");
+ return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
link_ref(link);
assert(ret);
/* Something useful was configured? just use it */
- if (in_addr_is_null(original->family, &original->in_addr) <= 0)
- return 0;
+ r = in_addr_is_null(original->family, &original->in_addr);
+ if (r <= 0)
+ return r;
/* The address is configured to be 0.0.0.0 or [::] by the user?
* Then let's acquire something more useful from the pool. */
r = manager_address_pool_acquire(link->manager, original->family, original->prefixlen, &in_addr);
if (r < 0)
- return log_link_error_errno(link, r, "Failed to acquire address from pool: %m");
- if (r == 0) {
- log_link_error(link, "Couldn't find free address for interface, all taken.");
+ return r;
+ if (r == 0)
return -EBUSY;
- }
if (original->family == AF_INET) {
/* Pick first address in range for ourselves ... */
/* If this is a new address, then refuse adding more than the limit */
if (address_get(link, address->family, &address->in_addr, address->prefixlen, NULL) <= 0 &&
set_size(link->addresses) >= ADDRESSES_PER_LINK_MAX)
- return -E2BIG;
+ return log_link_error_errno(link, SYNTHETIC_ERRNO(E2BIG),
+ "Too many addresses are configured, refusing: %m");
r = address_acquire(link, address, &address);
if (r < 0)
- return r;
+ return log_link_error_errno(link, r, "Failed to acquire an address from pool: %m");
if (update)
r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req,
r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_NEWADDR,
link->ifindex, address->family);
if (r < 0)
- return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m");
+ return log_link_error_errno(link, r, "Could not allocate RTM_NEWADDR message: %m");
r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
if (r < 0)
- return log_error_errno(r, "Could not set prefixlen: %m");
+ return log_link_error_errno(link, r, "Could not set prefixlen: %m");
address->flags |= IFA_F_PERMANENT;
r = sd_rtnl_message_addr_set_flags(req, (address->flags & 0xff));
if (r < 0)
- return log_error_errno(r, "Could not set flags: %m");
+ return log_link_error_errno(link, r, "Could not set flags: %m");
if (address->flags & ~0xff) {
r = sd_netlink_message_append_u32(req, IFA_FLAGS, address->flags);
if (r < 0)
- return log_error_errno(r, "Could not set extended flags: %m");
+ return log_link_error_errno(link, r, "Could not set extended flags: %m");
}
r = sd_rtnl_message_addr_set_scope(req, address->scope);
if (r < 0)
- return log_error_errno(r, "Could not set scope: %m");
+ return log_link_error_errno(link, r, "Could not set scope: %m");
r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
if (r < 0)
- return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m");
+ return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
if (in_addr_is_null(address->family, &address->in_addr_peer) == 0) {
r = netlink_message_append_in_addr_union(req, IFA_ADDRESS, address->family, &address->in_addr_peer);
if (r < 0)
- return log_error_errno(r, "Could not append IFA_ADDRESS attribute: %m");
+ return log_link_error_errno(link, r, "Could not append IFA_ADDRESS attribute: %m");
} else if (address->family == AF_INET && address->prefixlen <= 30) {
r = sd_netlink_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
if (r < 0)
- return log_error_errno(r, "Could not append IFA_BROADCAST attribute: %m");
+ return log_link_error_errno(link, r, "Could not append IFA_BROADCAST attribute: %m");
}
if (address->label) {
r = sd_netlink_message_append_string(req, IFA_LABEL, address->label);
if (r < 0)
- return log_error_errno(r, "Could not append IFA_LABEL attribute: %m");
+ return log_link_error_errno(link, r, "Could not append IFA_LABEL attribute: %m");
}
r = sd_netlink_message_append_cache_info(req, IFA_CACHEINFO, &address->cinfo);
if (r < 0)
- return log_error_errno(r, "Could not append IFA_CACHEINFO attribute: %m");
+ return log_link_error_errno(link, r, "Could not append IFA_CACHEINFO attribute: %m");
r = address_establish(address, link);
if (r < 0)
- return r;
+ log_link_warning_errno(link, r, "Could not enable IP masquerading, ignoring: %m");
r = netlink_call_async(link->manager->rtnl, NULL, req, callback, link_netlink_destroy_callback, link);
if (r < 0) {
address_release(address);
- return log_error_errno(r, "Could not send rtnetlink message: %m");
+ return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
}
link_ref(link);
r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL);
if (r < 0) {
address_release(address);
- return log_error_errno(r, "Could not add address: %m");
+ return log_link_error_errno(link, r, "Could not add address: %m");
}
return 0;
return 0;
}
+ if (in_addr_is_null(f, &buffer)) {
+ /* Will use address from address pool. Note that for ipv6 case, prefix of the address
+ * pool is 8, but 40 bit is used by the global ID and 16 bit by the subnet ID. So,
+ * let's limit the prefix length to 64 or larger. See RFC4193. */
+ if ((f == AF_INET && prefixlen < 8) ||
+ (f == AF_INET6 && prefixlen < 64)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Null address with invalid prefixlen='%u', ignoring assignment: %s",
+ prefixlen, rvalue);
+ return 0;
+ }
+ }
+
n->family = f;
n->prefixlen = prefixlen;
#include "strv.h"
#include "sysctl-util.h"
#include "tmpfile-util.h"
+#include "udev-util.h"
#include "util.h"
#include "virt.h"
return log_link_error_errno(link, r, "Could not append IFLA_CAN_RESTART_MS attribute: %m");
}
+ if (link->network->can_triple_sampling >= 0) {
+ struct can_ctrlmode cm = {
+ .mask = CAN_CTRLMODE_3_SAMPLES,
+ .flags = link->network->can_triple_sampling ? CAN_CTRLMODE_3_SAMPLES : 0,
+ };
+
+ log_link_debug(link, "%sabling triple-sampling", link->network->can_triple_sampling ? "En" : "Dis");
+
+ r = sd_netlink_message_append_data(m, IFLA_CAN_CTRLMODE, &cm, sizeof(cm));
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_CAN_CTRLMODE attribute: %m");
+ }
+
r = sd_netlink_message_close_container(m);
if (r < 0)
return log_link_error_errno(link, r, "Failed to close netlink container: %m");
return 0;
}
+ r = device_is_renaming(device);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to determine the device is renamed or not: %m");
+ goto failed;
+ }
+ if (r > 0) {
+ log_link_debug(link, "Interface is under renaming, pending initialization.");
+ return 0;
+ }
+
r = link_initialized(link, device);
if (r < 0)
goto failed;
r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname);
if (r >= 0 && !streq(ifname, link->ifname)) {
- log_link_info(link, "Interface name change detected, %s has been renamed to %s.", link->ifname, ifname);
+ Manager *manager = link->manager;
- if (link->state == LINK_STATE_PENDING) {
- r = free_and_strdup(&link->ifname, ifname);
- if (r < 0)
- return r;
- } else {
- Manager *manager = link->manager;
+ log_link_info(link, "Interface name change detected, %s has been renamed to %s.", link->ifname, ifname);
- link_drop(link);
- r = link_add(manager, m, &link);
- if (r < 0)
- return r;
- }
+ link_drop(link);
+ r = link_add(manager, m, &link);
+ if (r < 0)
+ return r;
}
r = sd_netlink_message_read_u32(m, IFLA_MTU, &mtu);
#include "strv.h"
#include "sysctl-util.h"
#include "tmpfile-util.h"
+#include "udev-util.h"
#include "virt.h"
/* use 8 MB for receive socket kernel queue. */
/* Add in the well-known private address ranges. */
- r = address_pool_new_from_string(m, &p, AF_INET6, "fc00::", 7);
+ r = address_pool_new_from_string(m, &p, AF_INET6, "fd00::", 8);
if (r < 0)
return r;
- r = address_pool_new_from_string(m, &p, AF_INET, "192.168.0.0", 16);
+ r = address_pool_new_from_string(m, &p, AF_INET, "10.0.0.0", 8);
if (r < 0)
return r;
if (r < 0)
return r;
- r = address_pool_new_from_string(m, &p, AF_INET, "10.0.0.0", 8);
+ r = address_pool_new_from_string(m, &p, AF_INET, "192.168.0.0", 16);
if (r < 0)
return r;
return 0;
}
- if (!STR_IN_SET(action, "add", "change")) {
+ if (!STR_IN_SET(action, "add", "change", "move")) {
log_device_debug(device, "Ignoring udev %s event for device.", action);
return 0;
}
return 0;
}
+ r = device_is_renaming(device);
+ if (r < 0) {
+ log_device_error_errno(device, r, "Failed to determine the device is renamed or not, ignoring '%s' uevent: %m", action);
+ return 0;
+ }
+ if (r > 0) {
+ log_device_debug(device, "Interface is under renaming, wait for the interface to be renamed: %m");
+ return 0;
+ }
+
r = link_get(m, ifindex, &link);
if (r < 0) {
if (r != -ENODEV)
CAN.BitRate, config_parse_si_size, 0, offsetof(Network, can_bitrate)
CAN.SamplePoint, config_parse_permille, 0, offsetof(Network, can_sample_point)
CAN.RestartSec, config_parse_sec, 0, offsetof(Network, can_restart_us)
+CAN.TripleSampling, config_parse_tristate, 0, offsetof(Network, can_triple_sampling)
/* backwards compatibility: do not add new entries to this section */
Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local)
DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_use_dns)
.ipv6_accept_ra_use_onlink_prefix = true,
.ipv6_accept_ra_route_table = RT_TABLE_MAIN,
.ipv6_accept_ra_route_table_set = false,
+
+ .can_triple_sampling = -1,
};
r = config_parse_many(filename, NETWORK_DIRS, dropin_dirname,
size_t can_bitrate;
unsigned can_sample_point;
usec_t can_restart_us;
+ int can_triple_sampling;
AddressFamilyBoolean ip_forward;
bool ip_masquerade;
RTM_DELROUTE, route->family,
route->protocol);
if (r < 0)
- return log_error_errno(r, "Could not create RTM_DELROUTE message: %m");
+ return log_link_error_errno(link, r, "Could not create RTM_DELROUTE message: %m");
if (in_addr_is_null(route->family, &route->gw) == 0) {
r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->family, &route->gw);
if (r < 0)
- return log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTA_GATEWAY attribute: %m");
}
if (route->dst_prefixlen) {
r = netlink_message_append_in_addr_union(req, RTA_DST, route->family, &route->dst);
if (r < 0)
- return log_error_errno(r, "Could not append RTA_DST attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTA_DST attribute: %m");
r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
if (r < 0)
- return log_error_errno(r, "Could not set destination prefix length: %m");
+ return log_link_error_errno(link, r, "Could not set destination prefix length: %m");
}
if (route->src_prefixlen) {
r = netlink_message_append_in_addr_union(req, RTA_SRC, route->family, &route->src);
if (r < 0)
- return log_error_errno(r, "Could not append RTA_SRC attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTA_SRC attribute: %m");
r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen);
if (r < 0)
- return log_error_errno(r, "Could not set source prefix length: %m");
+ return log_link_error_errno(link, r, "Could not set source prefix length: %m");
}
if (in_addr_is_null(route->family, &route->prefsrc) == 0) {
r = netlink_message_append_in_addr_union(req, RTA_PREFSRC, route->family, &route->prefsrc);
if (r < 0)
- return log_error_errno(r, "Could not append RTA_PREFSRC attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTA_PREFSRC attribute: %m");
}
r = sd_rtnl_message_route_set_scope(req, route->scope);
if (r < 0)
- return log_error_errno(r, "Could not set scope: %m");
+ return log_link_error_errno(link, r, "Could not set scope: %m");
r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority);
if (r < 0)
- return log_error_errno(r, "Could not append RTA_PRIORITY attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTA_PRIORITY attribute: %m");
if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW)) {
r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
if (r < 0)
- return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTA_OIF attribute: %m");
}
r = netlink_call_async(link->manager->rtnl, NULL, req,
callback ?: route_remove_handler,
link_netlink_destroy_callback, link);
if (r < 0)
- return log_error_errno(r, "Could not send rtnetlink message: %m");
+ return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
link_ref(link);
if (route_get(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL) <= 0 &&
set_size(link->routes) >= routes_max())
- return -E2BIG;
+ return log_link_error_errno(link, SYNTHETIC_ERRNO(E2BIG),
+ "Too many routes are configured, refusing: %m");
if (DEBUG_LOGGING) {
_cleanup_free_ char *dst = NULL, *dst_prefixlen = NULL, *src = NULL, *gw = NULL, *prefsrc = NULL;
RTM_NEWROUTE, route->family,
route->protocol);
if (r < 0)
- return log_error_errno(r, "Could not create RTM_NEWROUTE message: %m");
+ return log_link_error_errno(link, r, "Could not create RTM_NEWROUTE message: %m");
if (in_addr_is_null(route->family, &route->gw) == 0) {
r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->family, &route->gw);
if (r < 0)
- return log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTA_GATEWAY attribute: %m");
r = sd_rtnl_message_route_set_family(req, route->family);
if (r < 0)
- return log_error_errno(r, "Could not set route family: %m");
+ return log_link_error_errno(link, r, "Could not set route family: %m");
}
if (route->dst_prefixlen) {
r = netlink_message_append_in_addr_union(req, RTA_DST, route->family, &route->dst);
if (r < 0)
- return log_error_errno(r, "Could not append RTA_DST attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTA_DST attribute: %m");
r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
if (r < 0)
- return log_error_errno(r, "Could not set destination prefix length: %m");
+ return log_link_error_errno(link, r, "Could not set destination prefix length: %m");
}
if (route->src_prefixlen) {
r = netlink_message_append_in_addr_union(req, RTA_SRC, route->family, &route->src);
if (r < 0)
- return log_error_errno(r, "Could not append RTA_SRC attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTA_SRC attribute: %m");
r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen);
if (r < 0)
- return log_error_errno(r, "Could not set source prefix length: %m");
+ return log_link_error_errno(link, r, "Could not set source prefix length: %m");
}
if (in_addr_is_null(route->family, &route->prefsrc) == 0) {
r = netlink_message_append_in_addr_union(req, RTA_PREFSRC, route->family, &route->prefsrc);
if (r < 0)
- return log_error_errno(r, "Could not append RTA_PREFSRC attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTA_PREFSRC attribute: %m");
}
r = sd_rtnl_message_route_set_scope(req, route->scope);
if (r < 0)
- return log_error_errno(r, "Could not set scope: %m");
+ return log_link_error_errno(link, r, "Could not set scope: %m");
if (route->gateway_onlink >= 0)
SET_FLAG(route->flags, RTNH_F_ONLINK, route->gateway_onlink);
r = sd_rtnl_message_route_set_flags(req, route->flags);
if (r < 0)
- return log_error_errno(r, "Could not set flags: %m");
+ return log_link_error_errno(link, r, "Could not set flags: %m");
if (route->table != RT_TABLE_MAIN) {
if (route->table < 256) {
r = sd_rtnl_message_route_set_table(req, route->table);
if (r < 0)
- return log_error_errno(r, "Could not set route table: %m");
+ return log_link_error_errno(link, r, "Could not set route table: %m");
} else {
r = sd_rtnl_message_route_set_table(req, RT_TABLE_UNSPEC);
if (r < 0)
- return log_error_errno(r, "Could not set route table: %m");
+ return log_link_error_errno(link, r, "Could not set route table: %m");
/* Table attribute to allow more than 256. */
r = sd_netlink_message_append_data(req, RTA_TABLE, &route->table, sizeof(route->table));
if (r < 0)
- return log_error_errno(r, "Could not append RTA_TABLE attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTA_TABLE attribute: %m");
}
}
r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority);
if (r < 0)
- return log_error_errno(r, "Could not append RTA_PRIORITY attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTA_PRIORITY attribute: %m");
r = sd_netlink_message_append_u8(req, RTA_PREF, route->pref);
if (r < 0)
- return log_error_errno(r, "Could not append RTA_PREF attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTA_PREF attribute: %m");
if (route->lifetime != USEC_INFINITY && kernel_route_expiration_supported()) {
r = sd_netlink_message_append_u32(req, RTA_EXPIRES,
DIV_ROUND_UP(usec_sub_unsigned(route->lifetime, now(clock_boottime_or_monotonic())), USEC_PER_SEC));
if (r < 0)
- return log_error_errno(r, "Could not append RTA_EXPIRES attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTA_EXPIRES attribute: %m");
}
r = sd_rtnl_message_route_set_type(req, route->type);
if (r < 0)
- return log_error_errno(r, "Could not set route type: %m");
+ return log_link_error_errno(link, r, "Could not set route type: %m");
if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW)) {
r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
if (r < 0)
- return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTA_OIF attribute: %m");
}
r = sd_netlink_message_open_container(req, RTA_METRICS);
if (r < 0)
- return log_error_errno(r, "Could not append RTA_METRICS attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
if (route->mtu > 0) {
r = sd_netlink_message_append_u32(req, RTAX_MTU, route->mtu);
if (r < 0)
- return log_error_errno(r, "Could not append RTAX_MTU attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTAX_MTU attribute: %m");
}
if (route->initcwnd > 0) {
r = sd_netlink_message_append_u32(req, RTAX_INITCWND, route->initcwnd);
if (r < 0)
- return log_error_errno(r, "Could not append RTAX_INITCWND attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTAX_INITCWND attribute: %m");
}
if (route->initrwnd > 0) {
r = sd_netlink_message_append_u32(req, RTAX_INITRWND, route->initrwnd);
if (r < 0)
- return log_error_errno(r, "Could not append RTAX_INITRWND attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTAX_INITRWND attribute: %m");
}
if (route->quickack != -1) {
r = sd_netlink_message_append_u32(req, RTAX_QUICKACK, route->quickack);
if (r < 0)
- return log_error_errno(r, "Could not append RTAX_QUICKACK attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTAX_QUICKACK attribute: %m");
}
r = sd_netlink_message_close_container(req);
if (r < 0)
- return log_error_errno(r, "Could not append RTA_METRICS attribute: %m");
+ return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
link_netlink_destroy_callback, link);
if (r < 0)
- return log_error_errno(r, "Could not send rtnetlink message: %m");
+ return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
link_ref(link);
r = route_add(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, &route);
if (r < 0)
- return log_error_errno(r, "Could not add route: %m");
+ return log_link_error_errno(link, r, "Could not add route: %m");
/* TODO: drop expiration handling once it can be pushed into the kernel */
route->lifetime = lifetime;
r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(),
route->lifetime, 0, route_expire_handler, route);
if (r < 0)
- return log_error_errno(r, "Could not arm expiration timer: %m");
+ return log_link_error_errno(link, r, "Could not arm expiration timer: %m");
}
sd_event_source_unref(route->expire);
}
if (isempty(source))
- source = NULL;
+ source = mfree(source);
else if (!source_path_is_valid(source))
return -EINVAL;
if (!m)
return -ENOMEM;
- m->source = source;
- m->destination = destination;
+ m->source = TAKE_PTR(source);
+ m->destination = TAKE_PTR(destination);
m->read_only = read_only;
- m->options = opts;
-
- source = destination = opts = NULL;
+ m->options = TAKE_PTR(opts);
return 0;
}
} else if (arg_slice || arg_property)
log_notice("Machine and scope registration turned off, --slice= and --property= settings will have no effect.");
- r = sync_cgroup(*pid, arg_unified_cgroup_hierarchy, arg_uid_shift);
+ r = create_subcgroup(*pid, arg_keep_unit, arg_unified_cgroup_hierarchy);
if (r < 0)
return r;
- r = create_subcgroup(*pid, arg_keep_unit, arg_unified_cgroup_hierarchy);
+ r = sync_cgroup(*pid, arg_unified_cgroup_hierarchy, arg_uid_shift);
if (r < 0)
return r;
if (buf_size < POOL_SIZE_MIN)
buf_size = POOL_SIZE_MIN;
- r = mkdir_parents_label(RANDOM_SEED, 0755);
+ r = mkdir_parents(RANDOM_SEED, 0755);
if (r < 0)
return log_error_errno(r, "Failed to create directory " RANDOM_SEED_DIR ": %m");
if (a->items[i].ifindex != ifindex)
continue;
- r = dns_resource_record_equal(a->items[i].rr, rr);
+ r = dns_resource_key_equal(a->items[i].rr->key, rr->key);
if (r < 0)
return r;
- if (r > 0) {
- /* Don't mix contradicting TTLs (see below) */
- if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0))
- return -EINVAL;
-
- /* Entry already exists, keep the entry with
- * the higher RR. */
- if (rr->ttl > a->items[i].rr->ttl) {
- dns_resource_record_ref(rr);
- dns_resource_record_unref(a->items[i].rr);
- a->items[i].rr = rr;
- }
+ if (r == 0)
+ continue;
- a->items[i].flags |= flags;
- return 0;
- }
+ /* There's already an RR of the same RRset in place! Let's see if the TTLs more or less
+ * match. We don't really care if they match precisely, but we do care whether one is 0 and
+ * the other is not. See RFC 2181, Section 5.2. */
+ if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0))
+ return -EINVAL;
- r = dns_resource_key_equal(a->items[i].rr->key, rr->key);
+ r = dns_resource_record_payload_equal(a->items[i].rr, rr);
if (r < 0)
return r;
- if (r > 0) {
- /* There's already an RR of the same RRset in
- * place! Let's see if the TTLs more or less
- * match. We don't really care if they match
- * precisely, but we do care whether one is 0
- * and the other is not. See RFC 2181, Section
- * 5.2. */
-
- if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0))
- return -EINVAL;
+ if (r == 0)
+ continue;
+
+ /* Entry already exists, keep the entry with the higher RR. */
+ if (rr->ttl > a->items[i].rr->ttl) {
+ dns_resource_record_ref(rr);
+ dns_resource_record_unref(a->items[i].rr);
+ a->items[i].rr = rr;
}
+
+ a->items[i].flags |= flags;
+ return 0;
}
return dns_answer_add_raw(a, rr, ifindex, flags);
#include "alloc-util.h"
#include "dns-domain.h"
#include "resolved-dns-packet.h"
+#include "set.h"
#include "string-table.h"
#include "strv.h"
#include "unaligned.h"
if (!question)
return -ENOMEM;
+ _cleanup_set_free_ Set *keys = NULL; /* references to keys are kept by Question */
+
+ keys = set_new(&dns_resource_key_hash_ops);
+ if (!keys)
+ return log_oom();
+
+ r = set_reserve(keys, n * 2); /* Higher multipliers give slightly higher efficiency through
+ * hash collisions, but the gains quickly drop of after 2. */
+ if (r < 0)
+ return r;
+
for (i = 0; i < n; i++) {
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
bool cache_flush;
if (!dns_type_is_valid_query(key->type))
return -EBADMSG;
- r = dns_question_add(question, key);
+ r = set_put(keys, key);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ /* Already in the Question, let's skip */
+ continue;
+
+ r = dns_question_add_raw(question, key);
if (r < 0)
return r;
}
* be contained in questions, never in replies. Crappy
* Belkin routers copy the OPT data for example, hence let's
* detect this so that we downgrade early. */
- log_debug("OPT RR contained RFC6975 data, ignoring.");
+ log_debug("OPT RR contains RFC6975 data, ignoring.");
bad_opt = true;
continue;
}
DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsQuestion, dns_question, dns_question_free);
+int dns_question_add_raw(DnsQuestion *q, DnsResourceKey *key) {
+ /* Insert without checking for duplicates. */
+
+ assert(key);
+ assert(q);
+
+ if (q->n_keys >= q->n_allocated)
+ return -ENOSPC;
+
+ q->keys[q->n_keys++] = dns_resource_key_ref(key);
+ return 0;
+}
+
int dns_question_add(DnsQuestion *q, DnsResourceKey *key) {
- size_t i;
int r;
assert(key);
if (!q)
return -ENOSPC;
- for (i = 0; i < q->n_keys; i++) {
+ for (size_t i = 0; i < q->n_keys; i++) {
r = dns_resource_key_equal(q->keys[i], key);
if (r < 0)
return r;
return 0;
}
- if (q->n_keys >= q->n_allocated)
- return -ENOSPC;
-
- q->keys[q->n_keys++] = dns_resource_key_ref(key);
- return 0;
+ return dns_question_add_raw(q, key);
}
int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) {
int dns_question_new_reverse(DnsQuestion **ret, int family, const union in_addr_union *a);
int dns_question_new_service(DnsQuestion **ret, const char *service, const char *type, const char *domain, bool with_txt, bool convert_idna);
+int dns_question_add_raw(DnsQuestion *q, DnsResourceKey *key);
int dns_question_add(DnsQuestion *q, DnsResourceKey *key);
int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain);
((a).field ## _size == (b).field ## _size && \
memcmp((a).field, (b).field, (a).field ## _size) == 0)
-int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
+int dns_resource_record_payload_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
int r;
- assert(a);
- assert(b);
-
- if (a == b)
- return 1;
-
- r = dns_resource_key_equal(a->key, b->key);
- if (r <= 0)
- return r;
+ /* Check if a and b are the same, but don't look at their keys */
if (a->unparseable != b->unparseable)
return 0;
}
}
+int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
+ int r;
+
+ assert(a);
+ assert(b);
+
+ if (a == b)
+ return 1;
+
+ r = dns_resource_key_equal(a->key, b->key);
+ if (r <= 0)
+ return r;
+
+ return dns_resource_record_payload_equal(a, b);
+}
+
static char* format_location(uint32_t latitude, uint32_t longitude, uint32_t altitude,
uint8_t size, uint8_t horiz_pre, uint8_t vert_pre) {
char *s;
int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name);
int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name);
int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b);
+int dns_resource_record_payload_equal(const DnsResourceRecord *a, const DnsResourceRecord *b);
+
const char* dns_resource_record_to_string(DnsResourceRecord *rr);
DnsResourceRecord *dns_resource_record_copy(DnsResourceRecord *rr);
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceRecord*, dns_resource_record_unref);
#include "log.h"
#include "resolved-etc-hosts.h"
#include "strv.h"
+#include "tests.h"
#include "tmpfile-util.h"
static void test_parse_etc_hosts_system(void) {
}
int main(int argc, char **argv) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
if (argc == 1) {
test_parse_etc_hosts_system();
#include "log.h"
#include "resolved-dns-packet.h"
+#include "tests.h"
static void test_dns_packet_new(void) {
size_t i;
}
int main(int argc, char **argv) {
-
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
test_dns_packet_new();
#include "path-util.h"
#include "pe-header.h"
#include "stat-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "unaligned.h"
const char *path,
BootEntry *entry) {
- _cleanup_(boot_entry_free) BootEntry tmp = {};
+ _cleanup_(boot_entry_free) BootEntry tmp = {
+ .type = BOOT_ENTRY_CONF,
+ };
+
_cleanup_fclose_ FILE *f = NULL;
unsigned line = 1;
char *b, *c;
c = endswith_no_case(path, ".conf");
if (!c)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry filename: %s", path);
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry file suffix: %s", path);
b = basename(path);
tmp.id = strndup(b, c - b);
if (!tmp.id)
return log_oom();
+ if (!efi_loader_entry_name_valid(tmp.id))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry filename: %s", path);
+
tmp.path = strdup(path);
if (!tmp.path)
return log_oom();
BootEntry *ret) {
_cleanup_free_ char *os_pretty_name = NULL, *os_id = NULL, *version_id = NULL, *build_id = NULL;
- _cleanup_(boot_entry_free) BootEntry tmp = {};
+ _cleanup_(boot_entry_free) BootEntry tmp = {
+ .type = BOOT_ENTRY_UNIFIED,
+ };
_cleanup_fclose_ FILE *f = NULL;
const char *k;
int r;
if (!tmp.id)
return log_oom();
+ if (!efi_loader_entry_name_valid(tmp.id))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry: %s", tmp.id);
+
tmp.path = strdup(path);
if (!tmp.path)
return log_oom();
r = fd_verify_regular(fd);
if (r < 0) {
- log_warning_errno(errno, "File %s/%s is not regular, ignoring: %m", dir, de->d_name);
+ log_warning_errno(r, "File %s/%s is not regular, ignoring: %m", dir, de->d_name);
continue;
}
if (is_efi_boot()) {
r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", &config->entry_oneshot);
- if (r < 0 && r != -ENOENT)
- return log_error_errno(r, "Failed to read EFI var \"LoaderEntryOneShot\": %m");
+ if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
+ log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryOneShot\": %m");
+ if (r == -ENOMEM)
+ return r;
+ }
r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryDefault", &config->entry_default);
- if (r < 0 && r != -ENOENT)
- return log_error_errno(r, "Failed to read EFI var \"LoaderEntryDefault\": %m");
+ if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
+ log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryDefault\": %m");
+ if (r == -ENOMEM)
+ return r;
+ }
}
config->default_entry = boot_entries_select_default(config);
return 0;
}
+int boot_entries_load_config_auto(
+ const char *override_esp_path,
+ const char *override_xbootldr_path,
+ BootConfig *config) {
+
+ _cleanup_free_ char *esp_where = NULL, *xbootldr_where = NULL;
+ int r;
+
+ assert(config);
+
+ /* This function is similar to boot_entries_load_config(), however we automatically search for the
+ * ESP and the XBOOTLDR partition unless it is explicitly specified. Also, if the user did not pass
+ * an ESP or XBOOTLDR path directly, let's see if /run/boot-loader-entries/ exists. If so, let's
+ * read data from there, as if it was an ESP (i.e. loading both entries and loader.conf data from
+ * it). This allows other boot loaders to pass boot loader entry information to our tools if they
+ * want to. */
+
+ if (!override_esp_path && !override_xbootldr_path) {
+ if (access("/run/boot-loader-entries/", F_OK) >= 0)
+ return boot_entries_load_config("/run/boot-loader-entries/", NULL, config);
+
+ if (errno != ENOENT)
+ return log_error_errno(errno,
+ "Failed to determine whether /run/boot-loader-entries/ exists: %m");
+ }
+
+ r = find_esp_and_warn(override_esp_path, false, &esp_where, NULL, NULL, NULL, NULL);
+ if (r == -ENOKEY) /* find_esp_and_warn() doesn't warn about this case */
+ return log_error_errno(r, "Cannot find the ESP partition mount point.");
+ if (r < 0) /* But it logs about all these cases, hence don't log here again */
+ return r;
+
+ r = find_xbootldr_and_warn(override_xbootldr_path, false, &xbootldr_where, NULL);
+ if (r < 0 && r != -ENOKEY)
+ return r; /* It's fine if the XBOOTLDR partition doesn't exist, hence we ignore ENOKEY here */
+
+ return boot_entries_load_config(esp_where, xbootldr_where, config);
+}
+
+int boot_entries_augment_from_loader(BootConfig *config, bool only_auto) {
+
+ static const char * const title_table[] = {
+ /* Pretty names for a few well-known automatically discovered entries. */
+ "auto-osx", "macOS",
+ "auto-windows", "Windows Boot Manager",
+ "auto-efi-shell", "EFI Shell",
+ "auto-efi-default", "EFI Default Loader",
+ "auto-reboot-to-firmware-setup", "Reboot Into Firmware Interface",
+ };
+
+ _cleanup_free_ char **found_by_loader = NULL;
+ size_t n_allocated;
+ char **i;
+ int r;
+
+ assert(config);
+
+ /* Let's add the entries discovered by the boot loader to the end of our list, unless they are
+ * already included there. */
+
+ r = efi_loader_get_entries(&found_by_loader);
+ if (IN_SET(r, -ENOENT, -EOPNOTSUPP))
+ return log_debug_errno(r, "Boot loader reported no entries.");
+ if (r < 0)
+ return log_error_errno(r, "Failed to determine entries reported by boot loader: %m");
+
+ n_allocated = config->n_entries;
+
+ STRV_FOREACH(i, found_by_loader) {
+ _cleanup_free_ char *c = NULL, *t = NULL;
+ char **a, **b;
+
+ if (boot_config_has_entry(config, *i))
+ continue;
+
+ if (only_auto && !startswith(*i, "auto-"))
+ continue;
+
+ c = strdup(*i);
+ if (!c)
+ return log_oom();
+
+ STRV_FOREACH_PAIR(a, b, (char**) title_table)
+ if (streq(*a, *i)) {
+ t = strdup(*b);
+ if (!t)
+ return log_oom();
+ break;
+ }
+
+ if (!GREEDY_REALLOC0(config->entries, n_allocated, config->n_entries + 1))
+ return log_oom();
+
+ config->entries[config->n_entries++] = (BootEntry) {
+ .type = BOOT_ENTRY_LOADER,
+ .id = TAKE_PTR(c),
+ .title = TAKE_PTR(t),
+ };
+ }
+
+ return 0;
+}
+
/********************************************************************************/
static int verify_esp_blkid(
return 0;
}
-int find_default_boot_entry(
- const char *esp_path,
- const char *xbootldr_path,
- BootConfig *config,
- const BootEntry **e) {
+static const char* const boot_entry_type_table[_BOOT_ENTRY_MAX] = {
+ [BOOT_ENTRY_CONF] = "conf",
+ [BOOT_ENTRY_UNIFIED] = "unified",
+ [BOOT_ENTRY_LOADER] = "loader",
+};
- _cleanup_free_ char *esp_where = NULL, *xbootldr_where = NULL;
- int r;
-
- assert(config);
- assert(e);
-
- r = find_esp_and_warn(esp_path, false, &esp_where, NULL, NULL, NULL, NULL);
- if (r < 0)
- return r;
-
- r = find_xbootldr_and_warn(xbootldr_path, false, &xbootldr_where, NULL);
- if (r < 0 && r != -ENOKEY)
- return r;
-
- r = boot_entries_load_config(esp_where, xbootldr_where, config);
- if (r < 0)
- return log_error_errno(r, "Failed to load boot loader entries: %m");
-
- if (config->default_entry < 0)
- return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
- "No boot loader entry suitable as default, refusing to guess.");
-
- *e = &config->entries[config->default_entry];
- log_debug("Found default boot loader entry in file \"%s\"", (*e)->path);
-
- return 0;
-}
+DEFINE_STRING_TABLE_LOOKUP(boot_entry_type, BootEntryType);
#include "sd-id128.h"
+#include "string-util.h"
+
+typedef enum BootEntryType {
+ BOOT_ENTRY_CONF, /* Type #1 entries: *.conf files */
+ BOOT_ENTRY_UNIFIED, /* Type #2 entries: *.efi files */
+ BOOT_ENTRY_LOADER, /* Additional entries augmented from LoaderEntries EFI var */
+ _BOOT_ENTRY_MAX,
+ _BOOT_ENTRY_INVALID = -1,
+} BootEntryType;
+
typedef struct BootEntry {
+ BootEntryType type;
char *id; /* This is the file basename without extension */
char *path; /* This is the full path to the drop-in file */
char *root; /* The root path in which the drop-in was found, i.e. to which 'kernel', 'efi' and 'initrd' are relative */
ssize_t default_entry;
} BootConfig;
+static inline bool boot_config_has_entry(BootConfig *config, const char *id) {
+ size_t j;
+
+ for (j = 0; j < config->n_entries; j++)
+ if (streq(config->entries[j].id, id))
+ return true;
+
+ return false;
+}
+
+static inline BootEntry* boot_config_default_entry(BootConfig *config) {
+ if (config->default_entry < 0)
+ return NULL;
+
+ return config->entries + config->default_entry;
+}
+
void boot_config_free(BootConfig *config);
int boot_entries_load_config(const char *esp_path, const char *xbootldr_path, BootConfig *config);
+int boot_entries_load_config_auto(const char *override_esp_path, const char *override_xbootldr_path, BootConfig *config);
+int boot_entries_augment_from_loader(BootConfig *config, bool only_auto);
static inline const char* boot_entry_title(const BootEntry *entry) {
return entry->show_title ?: entry->title ?: entry->id;
int find_esp_and_warn(const char *path, bool unprivileged_mode, char **ret_path, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid);
int find_xbootldr_and_warn(const char *path, bool unprivileged_mode, char **ret_path,sd_id128_t *ret_uuid);
-int find_default_boot_entry(const char *esp_path, const char *xbootldr_path, BootConfig *config, const BootEntry **e);
+const char* boot_entry_type_to_string(BootEntryType t) _const_;
+BootEntryType boot_entry_type_from_string(const char *s) _pure_;
return 0;
}
-int bus_print_property_value(const char *name, const char *expected_value, bool only_value, const char *fmt, ...) {
+int bus_print_property_value(const char *name, const char *expected_value, bool only_value, const char *value) {
+ assert(name);
+
+ if (expected_value && !streq_ptr(expected_value, value))
+ return 0;
+
+ if (only_value)
+ puts(value);
+ else
+ printf("%s=%s\n", name, value);
+
+ return 0;
+}
+
+int bus_print_property_valuef(const char *name, const char *expected_value, bool only_value, const char *fmt, ...) {
va_list ap;
int r;
/* This property has a single value, so we need to take
* care not to print a new line, everything else is OK. */
good = !strchr(s, '\n');
- bus_print_property_value(name, expected_value, value, "%s", good ? s : "[unprintable]");
+ bus_print_property_value(name, expected_value, value, good ? s : "[unprintable]");
}
return 1;
if (expected_value && parse_boolean(expected_value) != b)
return 1;
- bus_print_property_value(name, NULL, value, "%s", yes_no(b));
+ bus_print_property_value(name, NULL, value, yes_no(b));
return 1;
}
t = format_timestamp(timestamp, sizeof(timestamp), u);
if (t || all)
- bus_print_property_value(name, expected_value, value, "%s", strempty(t));
+ bus_print_property_value(name, expected_value, value, strempty(t));
} else if (strstr(name, "USec")) {
char timespan[FORMAT_TIMESPAN_MAX];
(void) format_timespan(timespan, sizeof(timespan), u, 0);
- bus_print_property_value(name, expected_value, value, "%s", timespan);
+ bus_print_property_value(name, expected_value, value, timespan);
} else if (streq(name, "RestrictNamespaces")) {
_cleanup_free_ char *s = NULL;
result = s;
}
- bus_print_property_value(name, expected_value, value, "%s", result);
+ bus_print_property_value(name, expected_value, value, result);
} else if (streq(name, "MountFlags")) {
const char *result;
if (!result)
return -EINVAL;
- bus_print_property_value(name, expected_value, value, "%s", result);
+ bus_print_property_value(name, expected_value, value, result);
} else if (STR_IN_SET(name, "CapabilityBoundingSet", "AmbientCapabilities")) {
_cleanup_free_ char *s = NULL;
if (r < 0)
return r;
- bus_print_property_value(name, expected_value, value, "%s", s);
+ bus_print_property_value(name, expected_value, value, s);
} else if ((STR_IN_SET(name, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight") && u == CGROUP_WEIGHT_INVALID) ||
(STR_IN_SET(name, "CPUShares", "StartupCPUShares") && u == CGROUP_CPU_SHARES_INVALID) ||
(STR_IN_SET(name, "MemoryCurrent", "TasksCurrent") && u == (uint64_t) -1) ||
(endswith(name, "NSec") && u == (uint64_t) -1))
- bus_print_property_value(name, expected_value, value, "%s", "[not set]");
+ bus_print_property_value(name, expected_value, value, "[not set]");
else if ((STR_IN_SET(name, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit") && u == CGROUP_LIMIT_MAX) ||
(STR_IN_SET(name, "TasksMax", "DefaultTasksMax") && u == (uint64_t) -1) ||
(startswith(name, "Limit") && u == (uint64_t) -1) ||
(startswith(name, "DefaultLimit") && u == (uint64_t) -1))
- bus_print_property_value(name, expected_value, value, "%s", "infinity");
+ bus_print_property_value(name, expected_value, value, "infinity");
+ else if (STR_IN_SET(name, "IPIngressBytes", "IPIngressPackets", "IPEgressBytes", "IPEgressPackets") && u == (uint64_t) -1)
+ bus_print_property_value(name, expected_value, value, "[no data]");
else
- bus_print_property_value(name, expected_value, value, "%"PRIu64, u);
+ bus_print_property_valuef(name, expected_value, value, "%"PRIu64, u);
return 1;
}
if (r < 0)
return r;
- bus_print_property_value(name, expected_value, value, "%"PRIi64, i);
+ bus_print_property_valuef(name, expected_value, value, "%"PRIi64, i);
return 1;
}
return r;
if (strstr(name, "UMask") || strstr(name, "Mode"))
- bus_print_property_value(name, expected_value, value, "%04o", u);
+ bus_print_property_valuef(name, expected_value, value, "%04o", u);
else if (streq(name, "UID")) {
if (u == UID_INVALID)
- bus_print_property_value(name, expected_value, value, "%s", "[not set]");
+ bus_print_property_value(name, expected_value, value, "[not set]");
else
- bus_print_property_value(name, expected_value, value, "%"PRIu32, u);
+ bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
} else if (streq(name, "GID")) {
if (u == GID_INVALID)
- bus_print_property_value(name, expected_value, value, "%s", "[not set]");
+ bus_print_property_value(name, expected_value, value, "[not set]");
else
- bus_print_property_value(name, expected_value, value, "%"PRIu32, u);
+ bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
} else
- bus_print_property_value(name, expected_value, value, "%"PRIu32, u);
+ bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
return 1;
}
if (r < 0)
return r;
- bus_print_property_value(name, expected_value, value, "%"PRIi32, i);
+ bus_print_property_valuef(name, expected_value, value, "%"PRIi32, i);
return 1;
}
if (r < 0)
return r;
- bus_print_property_value(name, expected_value, value, "%g", d);
+ bus_print_property_valuef(name, expected_value, value, "%g", d);
return 1;
}
typedef int (*bus_message_print_t) (const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all);
-int bus_print_property_value(const char *name, const char *expected_value, bool only_value, const char *fmt, ...) _printf_(4,5);
+int bus_print_property_value(const char *name, const char *expected_value, bool only_value, const char *value);
+int bus_print_property_valuef(const char *name, const char *expected_value, bool only_value, const char *fmt, ...) _printf_(4,5);
int bus_message_print_all_properties(sd_bus_message *m, bus_message_print_t func, char **filter, bool value, bool all, Set **found_properties);
int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, bus_message_print_t func, char **filter, bool value, bool all, Set **found_properties);
if (fstat(fd, &st) < 0)
return -errno;
if (st.st_size < 4)
- return -EIO;
+ return -ENODATA;
if (st.st_size > 4*1024*1024 + 4)
return -E2BIG;
return 0;
}
-bool efi_loader_entry_name_valid(const char *s) {
- if (isempty(s))
- return false;
-
- if (strlen(s) > FILENAME_MAX) /* Make sure entry names fit in filenames */
- return false;
-
- return in_charset(s, ALPHANUMERICAL "-");
-}
-
int efi_loader_get_entries(char ***ret) {
_cleanup_free_ char16_t *entries = NULL;
_cleanup_strv_free_ char **l = NULL;
#endif
+bool efi_loader_entry_name_valid(const char *s) {
+ if (isempty(s))
+ return false;
+
+ if (strlen(s) > FILENAME_MAX) /* Make sure entry names fit in filenames */
+ return false;
+
+ return in_charset(s, ALPHANUMERICAL "-_.");
+}
+
char *efi_tilt_backslashes(char *s) {
char *p;
int efi_loader_get_entries(char ***ret);
-bool efi_loader_entry_name_valid(const char *s);
-
int efi_loader_get_features(uint64_t *ret);
#else
#endif
+bool efi_loader_entry_name_valid(const char *s);
+
char *efi_tilt_backslashes(char *s);
"CONFIG_FILE=%s", source,
"CONFIG_LINE=%u", source_line,
"CONFIG_COLUMN=%u", source_column,
- LOG_MESSAGE("%s:%u: %s", source, line, buffer),
+ LOG_MESSAGE("%s:%u:%u: %s", source, source_line, source_column, buffer),
NULL);
else
return log_struct_internal(
*ret = TAKE_PTR(data.device);
return 0;
}
+
+int device_is_renaming(sd_device *dev) {
+ int r;
+
+ assert(dev);
+
+ r = sd_device_get_property_value(dev, "ID_RENAMING", NULL);
+ if (r < 0 && r != -ENOENT)
+ return r;
+
+ return r >= 0;
+}
}
int device_wait_for_initialization(sd_device *device, const char *subsystem, sd_device **ret);
+int device_is_renaming(sd_device *dev);
--- /dev/null
+systemd_shutdown_sources = files('''
+ shutdown.c
+ umount.c
+ umount.h
+'''.split())
* value input. For all other issues, report the failure and indicate that
* the sync is not making progress.
*/
-static bool sync_making_progress(unsigned long long *prev_dirty) {
+static int sync_making_progress(unsigned long long *prev_dirty) {
_cleanup_fclose_ FILE *f = NULL;
unsigned long long val = 0;
- bool r = false;
+ int ret;
f = fopen("/proc/meminfo", "re");
if (!f)
val += ull;
}
- r = *prev_dirty > val;
-
+ ret = *prev_dirty > val;
*prev_dirty = val;
-
- return r;
+ return ret;
}
static void sync_with_progress(void) {
else if (r == -ETIMEDOUT) {
/* Reset the check counter if the "Dirty" value is
* decreasing */
- if (sync_making_progress(&dirty))
+ if (sync_making_progress(&dirty) > 0)
checks = 0;
} else {
log_error_errno(r, "Failed to sync filesystems and block devices: %m");
bool changed = false;
if (use_watchdog)
- watchdog_ping();
+ (void) watchdog_ping();
/* Let's trim the cgroup tree on each iteration so
that we leave an empty cgroup tree around, so that
container managers get a nice notify event when we
are down */
if (cgroup)
- cg_trim(SYSTEMD_CGROUP_CONTROLLER, cgroup, false);
+ (void) cg_trim(SYSTEMD_CGROUP_CONTROLLER, cgroup, false);
if (need_umount) {
log_info("Unmounting file systems.");
arguments[0] = NULL;
arguments[1] = arg_verb;
arguments[2] = NULL;
- execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
+ (void) execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
(void) rlimit_nofile_safe();
#include <stddef.h>
#include <stdio.h>
#include <string.h>
+#include <sys/mount.h>
#include <sys/prctl.h>
#include <sys/reboot.h>
#include <sys/socket.h>
#include "hostname-util.h"
#include "initreq.h"
#include "install.h"
+#include "in-addr-util.h"
#include "io-util.h"
+#include "journal-util.h"
#include "list.h"
#include "locale-util.h"
#include "log.h"
#include "unit-def.h"
#include "unit-name.h"
#include "user-util.h"
+#include "utf8.h"
#include "util.h"
#include "utmp-wtmp.h"
#include "verbs.h"
static OutputMode arg_output = OUTPUT_SHORT;
static bool arg_plain = false;
static bool arg_firmware_setup = false;
+static usec_t arg_boot_loader_menu = USEC_INFINITY;
+static const char *arg_boot_loader_entry = NULL;
static bool arg_now = false;
static bool arg_jobs_before = false;
static bool arg_jobs_after = false;
#endif
}
-static int logind_prepare_firmware_setup(void) {
+static int prepare_firmware_setup(void) {
+
+ if (!arg_firmware_setup)
+ return 0;
+
#if ENABLE_LOGIND
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus;
return 0;
#else
- log_error("Cannot remotely indicate to EFI to boot into setup mode.");
+ log_error("Booting into firmware setup not supported.");
return -ENOSYS;
#endif
}
-static int prepare_firmware_setup(void) {
+static int prepare_boot_loader_menu(void) {
+
+ if (arg_boot_loader_menu == USEC_INFINITY)
+ return 0;
+
+#if ENABLE_LOGIND
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus;
int r;
- if (!arg_firmware_setup)
+ r = acquire_bus(BUS_FULL, &bus);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ "SetRebootToBootLoaderMenu",
+ &error,
+ NULL,
+ "t", arg_boot_loader_menu);
+ if (r < 0)
+ return log_error_errno(r, "Cannot indicate to boot loader to enter boot loader entry menu: %s", bus_error_message(&error, r));
+
+ return 0;
+#else
+ log_error("Booting into boot loader menu not supported.");
+ return -ENOSYS;
+#endif
+}
+
+static int prepare_boot_loader_entry(void) {
+
+ if (!arg_boot_loader_entry)
return 0;
- if (arg_transport == BUS_TRANSPORT_LOCAL) {
+#if ENABLE_LOGIND
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus;
+ int r;
+
+ r = acquire_bus(BUS_FULL, &bus);
+ if (r < 0)
+ return r;
- r = efi_set_reboot_to_firmware(true);
- if (r < 0)
- log_debug_errno(r, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
- else
- return r;
- }
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ "SetRebootToBootLoaderEntry",
+ &error,
+ NULL,
+ "s", arg_boot_loader_entry);
+ if (r < 0)
+ return log_error_errno(r, "Cannot set boot into loader entry '%s': %s", arg_boot_loader_entry, bus_error_message(&error, r));
- return logind_prepare_firmware_setup();
+ return 0;
+#else
+ log_error("Booting into boot loader entry not supported.");
+ return -ENOSYS;
+#endif
}
static int load_kexec_kernel(void) {
if (access(KEXEC, X_OK) < 0)
return log_error_errno(errno, KEXEC" is not available: %m");
- r = find_default_boot_entry(NULL, NULL, &config, &e);
- if (r == -ENOKEY) /* find_default_boot_entry() doesn't warn about this case */
- return log_error_errno(r, "Cannot find the ESP partition mount point.");
+ r = boot_entries_load_config_auto(NULL, NULL, &config);
if (r < 0)
- /* But it logs about all these cases, hence don't log here again */
return r;
+ e = boot_config_default_entry(&config);
+ if (!e)
+ return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
+ "No boot loader entry suitable as default, refusing to guess.");
+
+ log_debug("Found default boot loader entry in file \"%s\"", e->path);
+
+ if (!e->kernel)
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "Boot entry does not refer to Linux kernel, which is not supported currently.");
if (strv_length(e->initrd) > 1)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Boot entry specifies multiple initrds, which is not supported currently.");
kernel = path_join(e->root, e->kernel);
return log_oom();
if (!strv_isempty(e->initrd)) {
- initrd = path_join(e->root, *e->initrd);
+ initrd = path_join(e->root, e->initrd[0]);
if (!initrd)
return log_oom();
}
if (arg_dry_run)
return 0;
- r = safe_fork("(kexec)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
+ r = safe_fork("(kexec)", FORK_WAIT|FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
"--load", kernel,
"--append", options,
initrd ? "--initrd" : NULL, initrd,
- NULL };
+ NULL
+ };
/* Child */
execv(args[0], (char * const *) args);
_exit(EXIT_FAILURE);
}
- r = wait_for_terminate_and_check("kexec", pid, WAIT_LOG);
- if (r < 0)
- return r;
- if (r > 0)
- /* Command failed */
- return -EPROTO;
return 0;
}
if (r < 0)
return r;
+ r = prepare_boot_loader_menu();
+ if (r < 0)
+ return r;
+
+ r = prepare_boot_loader_entry();
+ if (r < 0)
+ return r;
+
if (a == ACTION_REBOOT && argc > 1) {
r = update_reboot_parameter_and_warn(argv[1]);
if (r < 0)
switch (bus_type) {
+ case SD_BUS_TYPE_INT32:
+ if (endswith(name, "ActionExitStatus")) {
+ int32_t i;
+
+ r = sd_bus_message_read_basic(m, bus_type, &i);
+ if (r < 0)
+ return r;
+
+ if (i >= 0 && i <= 255)
+ bus_print_property_valuef(name, expected_value, value, "%"PRIi32, i);
+ else if (all)
+ bus_print_property_value(name, expected_value, value, "[not set]");
+
+ return 1;
+ }
+ break;
+
case SD_BUS_TYPE_STRUCT:
if (contents[0] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
return bus_log_parse_error(r);
if (u > 0)
- bus_print_property_value(name, expected_value, value, "%"PRIu32, u);
+ bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
else if (all)
- bus_print_property_value(name, expected_value, value, "%s", "");
+ bus_print_property_value(name, expected_value, value, "");
return 1;
return bus_log_parse_error(r);
if (all || !isempty(s))
- bus_print_property_value(name, expected_value, value, "%s", s);
+ bus_print_property_value(name, expected_value, value, s);
return 1;
if (r < 0)
return bus_log_parse_error(r);
- if (all || !isempty(a) || !isempty(b))
- bus_print_property_value(name, expected_value, value, "%s \"%s\"", strempty(a), strempty(b));
+ if (!isempty(a) || !isempty(b))
+ bus_print_property_valuef(name, expected_value, value, "%s \"%s\"", strempty(a), strempty(b));
+ else if (all)
+ bus_print_property_value(name, expected_value, value, "");
return 1;
- } else if (streq_ptr(name, "SystemCallFilter")) {
+
+ } else if (STR_IN_SET(name, "SystemCallFilter", "RestrictAddressFamilies")) {
_cleanup_strv_free_ char **l = NULL;
int whitelist;
}
return 1;
+
+ } else if (STR_IN_SET(name, "SELinuxContext", "AppArmorProfile", "SmackProcessLabel")) {
+ int ignore;
+ const char *s;
+
+ r = sd_bus_message_read(m, "(bs)", &ignore, &s);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (!isempty(s))
+ bus_print_property_valuef(name, expected_value, value, "%s%s", ignore ? "-" : "", s);
+ else if (all)
+ bus_print_property_value(name, expected_value, value, "");
+
+ return 1;
+
+ } else if (endswith(name, "ExitStatus") && streq(contents, "aiai")) {
+ const int32_t *status, *signal;
+ size_t sz_status, sz_signal, i;
+
+ r = sd_bus_message_enter_container(m, 'r', "aiai");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_read_array(m, 'i', (const void **) &status, &sz_status);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_read_array(m, 'i', (const void **) &signal, &sz_signal);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ sz_status /= sizeof(int32_t);
+ sz_signal /= sizeof(int32_t);
+
+ if (all || sz_status > 0 || sz_signal > 0) {
+ bool first = true;
+
+ if (!value) {
+ fputs(name, stdout);
+ fputc('=', stdout);
+ }
+
+ for (i = 0; i < sz_status; i++) {
+ if (status[i] < 0 || status[i] > 255)
+ continue;
+
+ if (first)
+ first = false;
+ else
+ fputc(' ', stdout);
+
+ printf("%"PRIi32, status[i]);
+ }
+
+ for (i = 0; i < sz_signal; i++) {
+ const char *str;
+
+ str = signal_to_string((int) signal[i]);
+ if (!str)
+ continue;
+
+ if (first)
+ first = false;
+ else
+ fputc(' ', stdout);
+
+ fputs(str, stdout);
+ }
+
+ fputc('\n', stdout);
+ }
+ return 1;
}
break;
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
- bus_print_property_value(name, expected_value, value, "%s (ignore_errors=%s)", path, yes_no(ignore));
+ bus_print_property_valuef(name, expected_value, value, "%s (ignore_errors=%s)", path, yes_no(ignore));
if (r < 0)
return bus_log_parse_error(r);
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
- bus_print_property_value(name, expected_value, value, "%s (%s)", path, type);
+ bus_print_property_valuef(name, expected_value, value, "%s (%s)", path, type);
if (r < 0)
return bus_log_parse_error(r);
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
- bus_print_property_value(name, expected_value, value, "%s (%s)", path, type);
+ bus_print_property_valuef(name, expected_value, value, "%s (%s)", path, type);
if (r < 0)
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(stt)", &base, &v, &next_elapse)) > 0) {
char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
- bus_print_property_value(name, expected_value, value, "{ %s=%s ; next_elapse=%s }", base,
- format_timespan(timespan1, sizeof(timespan1), v, 0),
- format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
+ bus_print_property_valuef(name, expected_value, value, "{ %s=%s ; next_elapse=%s }", base,
+ format_timespan(timespan1, sizeof(timespan1), v, 0),
+ format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
}
if (r < 0)
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(sst)", &base, &spec, &next_elapse)) > 0) {
char timestamp[FORMAT_TIMESTAMP_MAX];
- bus_print_property_value(name, expected_value, value, "{ %s=%s ; next_elapse=%s }", base, spec,
- format_timestamp(timestamp, sizeof(timestamp), next_elapse));
+ bus_print_property_valuef(name, expected_value, value, "{ %s=%s ; next_elapse=%s }", base, spec,
+ format_timestamp(timestamp, sizeof(timestamp), next_elapse));
}
if (r < 0)
return bus_log_parse_error(r);
tt = strv_join(info.argv, " ");
- bus_print_property_value(name, expected_value, value,
- "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }",
- strna(info.path),
- strna(tt),
- yes_no(info.ignore),
- strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
- strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
- info.pid,
- sigchld_code_to_string(info.code),
- info.status,
- info.code == CLD_EXITED ? "" : "/",
- strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
+ bus_print_property_valuef(name, expected_value, value,
+ "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }",
+ strna(info.path),
+ strna(tt),
+ yes_no(info.ignore),
+ strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
+ strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
+ info.pid,
+ sigchld_code_to_string(info.code),
+ info.status,
+ info.code == CLD_EXITED ? "" : "/",
+ strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
free(info.path);
strv_free(info.argv);
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
- bus_print_property_value(name, expected_value, value, "%s %s", strna(path), strna(rwm));
+ bus_print_property_valuef(name, expected_value, value, "%s %s", strna(path), strna(rwm));
if (r < 0)
return bus_log_parse_error(r);
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
- bus_print_property_value(name, expected_value, value, "%s %"PRIu64, strna(path), weight);
+ bus_print_property_valuef(name, expected_value, value, "%s %"PRIu64, strna(path), weight);
if (r < 0)
return bus_log_parse_error(r);
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
- bus_print_property_value(name, expected_value, value, "%s %"PRIu64, strna(path), bandwidth);
+ bus_print_property_valuef(name, expected_value, value, "%s %"PRIu64, strna(path), bandwidth);
if (r < 0)
return bus_log_parse_error(r);
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(st)", &path, &target)) > 0)
- bus_print_property_value(name, expected_value, value, "%s %s", strna(path),
- format_timespan(ts, sizeof(ts), target, 1));
+ bus_print_property_valuef(name, expected_value, value, "%s %s", strna(path),
+ format_timespan(ts, sizeof(ts), target, 1));
if (r < 0)
return bus_log_parse_error(r);
if (n < 0)
return log_oom();
- bus_print_property_value(name, expected_value, value, "%s", h);
+ bus_print_property_value(name, expected_value, value, h);
+
+ return 1;
+
+ } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) {
+ _cleanup_free_ char *addresses = NULL;
+
+ r = sd_bus_message_enter_container(m, 'a', "(iayu)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ for (;;) {
+ _cleanup_free_ char *str = NULL;
+ uint32_t prefixlen;
+ int32_t family;
+ const void *ap;
+ size_t an;
+
+ r = sd_bus_message_enter_container(m, 'r', "iayu");
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
+
+ r = sd_bus_message_read(m, "i", &family);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_read_array(m, 'y', &ap, &an);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_read(m, "u", &prefixlen);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (!IN_SET(family, AF_INET, AF_INET6))
+ continue;
+
+ if (an != FAMILY_ADDRESS_SIZE(family))
+ continue;
+
+ if (prefixlen > FAMILY_ADDRESS_SIZE(family) * 8)
+ continue;
+
+ if (in_addr_prefix_to_string(family, (union in_addr_union *) ap, prefixlen, &str) < 0)
+ continue;
+
+ if (!strextend_with_separator(&addresses, " ", str, NULL))
+ return log_oom();
+ }
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (all || !isempty(addresses))
+ bus_print_property_value(name, expected_value, value, strempty(addresses));
+
+ return 1;
+
+ } else if (STR_IN_SET(name, "BindPaths", "BindReadOnlyPaths")) {
+ _cleanup_free_ char *paths = NULL;
+ const char *source, *dest;
+ int ignore_enoent;
+ uint64_t rbind;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ssbt)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(m, "(ssbt)", &source, &dest, &ignore_enoent, &rbind)) > 0) {
+ _cleanup_free_ char *str = NULL;
+
+ if (isempty(source))
+ continue;
+
+ if (asprintf(&str, "%s%s%s%s%s",
+ ignore_enoent ? "-" : "",
+ source,
+ isempty(dest) ? "" : ":",
+ strempty(dest),
+ rbind == MS_REC ? ":rbind" : "") < 0)
+ return log_oom();
+
+ if (!strextend_with_separator(&paths, " ", str, NULL))
+ return log_oom();
+ }
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (all || !isempty(paths))
+ bus_print_property_value(name, expected_value, value, strempty(paths));
+
+ return 1;
+
+ } else if (streq(name, "TemporaryFileSystem")) {
+ _cleanup_free_ char *paths = NULL;
+ const char *target, *option;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(m, "(ss)", &target, &option)) > 0) {
+ _cleanup_free_ char *str = NULL;
+
+ if (isempty(target))
+ continue;
+
+ if (asprintf(&str, "%s%s%s", target, isempty(option) ? "" : ":", strempty(option)) < 0)
+ return log_oom();
+
+ if (!strextend_with_separator(&paths, " ", str, NULL))
+ return log_oom();
+ }
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (all || !isempty(paths))
+ bus_print_property_value(name, expected_value, value, strempty(paths));
+
+ return 1;
+
+ } else if (streq(name, "LogExtraFields")) {
+ _cleanup_free_ char *fields = NULL;
+ const void *p;
+ size_t sz;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "ay");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read_array(m, 'y', &p, &sz)) > 0) {
+ _cleanup_free_ char *str = NULL;
+ const char *eq;
+
+ if (memchr(p, 0, sz))
+ continue;
+
+ eq = memchr(p, '=', sz);
+ if (!eq)
+ continue;
+
+ if (!journal_field_valid(p, eq - (const char*) p, false))
+ continue;
+
+ str = malloc(sz + 1);
+ if (!str)
+ return log_oom();
+
+ memcpy(str, p, sz);
+ str[sz] = '\0';
+
+ if (!utf8_is_valid(str))
+ continue;
+
+ if (!strextend_with_separator(&fields, " ", str, NULL))
+ return log_oom();
+ }
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (all || !isempty(fields))
+ bus_print_property_value(name, expected_value, value, strempty(fields));
return 1;
}
" short-monotonic, short-unix,\n"
" verbose, export, json, json-pretty, json-sse, cat)\n"
" --firmware-setup Tell the firmware to show the setup menu on next boot\n"
+ " --boot-loader-menu=TIME\n"
+ " Boot into boot loader menu on next boot\n"
+ " --boot-loader-entry=NAME\n"
+ " Boot into a specific boot loader entry on next boot\n"
" --plain Print unit dependencies as a list instead of a tree\n\n"
"Unit Commands:\n"
" list-units [PATTERN...] List units currently in memory\n"
DUMP_STRING_TABLE(timer_state, TimerState, _TIMER_STATE_MAX);
}
+static int help_boot_loader_entry(void) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char **l = NULL;
+ sd_bus *bus;
+ char **i;
+ int r;
+
+ r = acquire_bus(BUS_FULL, &bus);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_get_property_strv(
+ bus,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ "BootLoaderEntries",
+ &error,
+ &l);
+ if (r < 0)
+ return log_error_errno(r, "Failed to enumerate boot loader entries: %s", bus_error_message(&error, r));
+
+ if (strv_isempty(l)) {
+ log_error("No boot loader entries discovered.");
+ return -ENODATA;
+ }
+
+ STRV_FOREACH(i, l)
+ puts(*i);
+
+ return 0;
+}
+
static int systemctl_parse_argv(int argc, char *argv[]) {
enum {
ARG_FAIL = 0x100,
ARG_JOB_MODE,
ARG_PRESET_MODE,
ARG_FIRMWARE_SETUP,
+ ARG_BOOT_LOADER_MENU,
+ ARG_BOOT_LOADER_ENTRY,
ARG_NOW,
ARG_MESSAGE,
ARG_WAIT,
{ "recursive", no_argument, NULL, 'r' },
{ "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
{ "firmware-setup", no_argument, NULL, ARG_FIRMWARE_SETUP },
+ { "boot-loader-menu", required_argument, NULL, ARG_BOOT_LOADER_MENU },
+ { "boot-loader-entry", required_argument, NULL, ARG_BOOT_LOADER_ENTRY },
{ "now", no_argument, NULL, ARG_NOW },
{ "message", required_argument, NULL, ARG_MESSAGE },
{}
arg_firmware_setup = true;
break;
+ case ARG_BOOT_LOADER_MENU:
+
+ r = parse_sec(optarg, &arg_boot_loader_menu);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --boot-loader-menu= argument '%s': %m", optarg);
+
+ break;
+
+ case ARG_BOOT_LOADER_ENTRY:
+
+ if (streq(optarg, "help")) { /* Yes, this means, "help" is not a valid boot loader entry name we can deal with */
+ r = help_boot_loader_entry();
+ if (r < 0)
+ return r;
+
+ return 0;
+ }
+
+ arg_boot_loader_entry = empty_to_null(optarg);
+ break;
+
case ARG_STATE: {
if (isempty(optarg))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
'ENABLE_NSS', 'manual'],
[['src/test/test-umount.c',
- 'src/core/mount-setup.c',
- 'src/core/mount-setup.h',
- 'src/core/umount.c',
- 'src/core/umount.h'],
- [],
+ 'src/shutdown/umount.c',
+ 'src/shutdown/umount.h'],
+ [libcore_shared,
+ libshared],
[libmount]],
[['src/test/test-bus-util.c'],
_cleanup_(rm_rf_physical_and_freep) char *t = NULL;
struct stat st;
const char *p;
+ const uid_t uid = getuid();
+ const gid_t gid = getgid();
umask(022);
assert_se(mkdtemp_malloc(NULL, &t) >= 0);
assert_se(lstat(p, &st) >= 0);
assert_se(S_ISDIR(st.st_mode));
assert_se((st.st_mode & 07777) == 0755);
- assert_se(st.st_uid == 0);
- assert_se(st.st_gid == 0);
+ assert_se(st.st_uid == uid);
+ assert_se(st.st_gid == gid);
assert_se(!has_xattr(p));
p = strjoina(t, "/dir/symlink");
assert_se(lstat(p, &st) >= 0);
assert_se(S_ISLNK(st.st_mode));
assert_se((st.st_mode & 07777) == 0777);
- assert_se(st.st_uid == 0);
- assert_se(st.st_gid == 0);
+ assert_se(st.st_uid == uid);
+ assert_se(st.st_gid == gid);
assert_se(!has_xattr(p));
p = strjoina(t, "/dir/reg");
assert_se(lstat(p, &st) >= 0);
assert_se(S_ISREG(st.st_mode));
assert_se((st.st_mode & 07777) == 0755);
- assert_se(st.st_uid == 0);
- assert_se(st.st_gid == 0);
+ assert_se(st.st_uid == uid);
+ assert_se(st.st_gid == gid);
assert_se(!has_xattr(p));
p = strjoina(t, "/dir/sock");
assert_se(lstat(p, &st) >= 0);
assert_se(S_ISSOCK(st.st_mode));
assert_se((st.st_mode & 07777) == 0755);
- assert_se(st.st_uid == 0);
- assert_se(st.st_gid == 0);
+ assert_se(st.st_uid == uid);
+ assert_se(st.st_gid == gid);
assert_se(!has_xattr(p));
p = strjoina(t, "/dir/fifo");
assert_se(lstat(p, &st) >= 0);
assert_se(S_ISFIFO(st.st_mode));
assert_se((st.st_mode & 07777) == 0755);
- assert_se(st.st_uid == 0);
- assert_se(st.st_gid == 0);
+ assert_se(st.st_uid == uid);
+ assert_se(st.st_gid == gid);
assert_se(!has_xattr(p));
/* We now apply an xattr to the dir, and check it again */
assert_se(lstat(p, &st) >= 0);
assert_se(S_ISDIR(st.st_mode));
assert_se((st.st_mode & 07777) == 0775); /* acl change changed the mode too */
- assert_se(st.st_uid == 0);
- assert_se(st.st_gid == 0);
+ assert_se(st.st_uid == uid);
+ assert_se(st.st_gid == gid);
assert_se(has_xattr(p));
assert_se(path_chown_recursive(t, 1, 2) >= 0);
int main(int argc, char *argv[]) {
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
_cleanup_free_ char *test_execute_path = NULL;
- _cleanup_hashmap_free_ Hashmap *s = NULL;
static const test_function_t user_tests[] = {
test_exec_basic,
test_exec_ambientcapabilities,
return 0;
}
+ _cleanup_hashmap_free_ Hashmap *s = NULL;
assert_se(s = hashmap_new(NULL));
r = seccomp_syscall_resolve_name("unshare");
assert_se(r != __NR_SCMP_ERROR);
assert_se(path_equal(result, q));
result = mfree(result);
+ /* Paths underneath the "root" with different UIDs while using CHASE_SAFE */
+
+ if (geteuid() == 0) {
+ p = strjoina(temp, "/user");
+ assert_se(mkdir(p, 0755) >= 0);
+ assert_se(chown(p, UID_NOBODY, GID_NOBODY) >= 0);
+
+ q = strjoina(temp, "/user/root");
+ assert_se(mkdir(q, 0755) >= 0);
+
+ p = strjoina(q, "/link");
+ assert_se(symlink("/", p) >= 0);
+
+ /* Fail when user-owned directories contain root-owned subdirectories. */
+ r = chase_symlinks(p, temp, CHASE_SAFE, &result);
+ assert_se(r == -ENOLINK);
+ result = mfree(result);
+
+ /* Allow this when the user-owned directories are all in the "root". */
+ r = chase_symlinks(p, q, CHASE_SAFE, &result);
+ assert_se(r > 0);
+ result = mfree(result);
+ }
+
/* Paths using . */
r = chase_symlinks("/etc/./.././", NULL, 0, &result);
/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <fnmatch.h>
#include <netinet/in.h>
#include "log.h"
+#include "strv.h"
#include "in-addr-util.h"
-static void test_in_addr_prefix_from_string(
+static void test_in_addr_prefix_from_string_one(
const char *p,
int family,
int ret,
}
}
+static void test_in_addr_prefix_from_string(void) {
+ test_in_addr_prefix_from_string_one("", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+ test_in_addr_prefix_from_string_one("/", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+ test_in_addr_prefix_from_string_one("/8", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+ test_in_addr_prefix_from_string_one("1.2.3.4", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, -ENOANO, 0, 0, 8);
+ test_in_addr_prefix_from_string_one("1.2.3.4/0", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 0, 0, 0, 0, 0);
+ test_in_addr_prefix_from_string_one("1.2.3.4/1", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 1, 0, 1, 0, 1);
+ test_in_addr_prefix_from_string_one("1.2.3.4/2", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 2, 0, 2, 0, 2);
+ test_in_addr_prefix_from_string_one("1.2.3.4/32", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, 0, 32, 0, 32);
+ test_in_addr_prefix_from_string_one("1.2.3.4/33", AF_INET, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
+ test_in_addr_prefix_from_string_one("1.2.3.4/-1", AF_INET, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
+ test_in_addr_prefix_from_string_one("::1", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+
+ test_in_addr_prefix_from_string_one("", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+ test_in_addr_prefix_from_string_one("/", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+ test_in_addr_prefix_from_string_one("/8", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+ test_in_addr_prefix_from_string_one("::1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, -ENOANO, 0, 0, 0);
+ test_in_addr_prefix_from_string_one("::1/0", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0, 0, 0, 0, 0);
+ test_in_addr_prefix_from_string_one("::1/1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 1, 0, 1, 0, 1);
+ test_in_addr_prefix_from_string_one("::1/2", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 2, 0, 2, 0, 2);
+ test_in_addr_prefix_from_string_one("::1/32", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 32, 0, 32, 0, 32);
+ test_in_addr_prefix_from_string_one("::1/33", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 33, 0, 33, 0, 33);
+ test_in_addr_prefix_from_string_one("::1/64", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 64, 0, 64, 0, 64);
+ test_in_addr_prefix_from_string_one("::1/128", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, 0, 128, 0, 128);
+ test_in_addr_prefix_from_string_one("::1/129", AF_INET6, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
+ test_in_addr_prefix_from_string_one("::1/-1", AF_INET6, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
+}
+
+static void test_in_addr_prefix_to_string_valid(int family, const char *p) {
+ _cleanup_free_ char *str = NULL;
+ union in_addr_union u;
+ unsigned char l;
+
+ log_info("/* %s */", p);
+
+ assert_se(in_addr_prefix_from_string(p, family, &u, &l) >= 0);
+ assert_se(in_addr_prefix_to_string(family, &u, l, &str) >= 0);
+ assert_se(streq(str, p));
+}
+
+static void test_in_addr_prefix_to_string_unoptimized(int family, const char *p) {
+ _cleanup_free_ char *str1 = NULL, *str2 = NULL;
+ union in_addr_union u1, u2;
+ unsigned char len1, len2;
+
+ log_info("/* %s */", p);
+
+ assert_se(in_addr_prefix_from_string(p, family, &u1, &len1) >= 0);
+ assert_se(in_addr_prefix_to_string(family, &u1, len1, &str1) >= 0);
+ assert_se(in_addr_prefix_from_string(str1, family, &u2, &len2) >= 0);
+ assert_se(in_addr_prefix_to_string(family, &u2, len2, &str2) >= 0);
+
+ assert_se(streq(str1, str2));
+ assert_se(len1 == len2);
+ assert_se(in_addr_equal(family, &u1, &u2) > 0);
+}
+
+static void test_in_addr_prefix_to_string(void) {
+ test_in_addr_prefix_to_string_valid(AF_INET, "0.0.0.0/32");
+ test_in_addr_prefix_to_string_valid(AF_INET, "1.2.3.4/0");
+ test_in_addr_prefix_to_string_valid(AF_INET, "1.2.3.4/24");
+ test_in_addr_prefix_to_string_valid(AF_INET, "1.2.3.4/32");
+ test_in_addr_prefix_to_string_valid(AF_INET, "255.255.255.255/32");
+
+ test_in_addr_prefix_to_string_valid(AF_INET6, "::1/128");
+ test_in_addr_prefix_to_string_valid(AF_INET6, "fd00:abcd::1/64");
+ test_in_addr_prefix_to_string_valid(AF_INET6, "fd00:abcd::1234:1/64");
+ test_in_addr_prefix_to_string_valid(AF_INET6, "1111:2222:3333:4444:5555:6666:7777:8888/128");
+
+ test_in_addr_prefix_to_string_unoptimized(AF_INET, "0.0.0.0");
+ test_in_addr_prefix_to_string_unoptimized(AF_INET, "192.168.0.1");
+
+ test_in_addr_prefix_to_string_unoptimized(AF_INET6, "fd00:0000:0000:0000:0000:0000:0000:0001/64");
+ test_in_addr_prefix_to_string_unoptimized(AF_INET6, "fd00:1111::0000:2222:3333:4444:0001/64");
+}
+
+static void test_in_addr_random_prefix(void) {
+ _cleanup_free_ char *str = NULL;
+ union in_addr_union a;
+
+ assert_se(in_addr_from_string(AF_INET, "192.168.10.1", &a) >= 0);
+
+ assert_se(in_addr_random_prefix(AF_INET, &a, 31, 32) >= 0);
+ assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
+ assert_se(STR_IN_SET(str, "192.168.10.0", "192.168.10.1"));
+ str = mfree(str);
+
+ assert_se(in_addr_random_prefix(AF_INET, &a, 24, 26) >= 0);
+ assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
+ assert_se(startswith(str, "192.168.10."));
+ str = mfree(str);
+
+ assert_se(in_addr_random_prefix(AF_INET, &a, 16, 24) >= 0);
+ assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
+ assert_se(fnmatch("192.168.[0-9]*.0", str, 0) == 0);
+ str = mfree(str);
+
+ assert_se(in_addr_random_prefix(AF_INET, &a, 8, 24) >= 0);
+ assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
+ assert_se(fnmatch("192.[0-9]*.[0-9]*.0", str, 0) == 0);
+ str = mfree(str);
+
+ assert_se(in_addr_random_prefix(AF_INET, &a, 8, 16) >= 0);
+ assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
+ assert_se(fnmatch("192.[0-9]*.0.0", str, 0) == 0);
+ str = mfree(str);
+
+ assert_se(in_addr_from_string(AF_INET6, "fd00::1", &a) >= 0);
+
+ assert_se(in_addr_random_prefix(AF_INET6, &a, 16, 64) >= 0);
+ assert_se(in_addr_to_string(AF_INET6, &a, &str) >= 0);
+ assert_se(startswith(str, "fd00:"));
+ str = mfree(str);
+
+ assert_se(in_addr_random_prefix(AF_INET6, &a, 8, 16) >= 0);
+ assert_se(in_addr_to_string(AF_INET6, &a, &str) >= 0);
+ assert_se(fnmatch("fd??::", str, 0) == 0);
+ str = mfree(str);
+}
+
int main(int argc, char *argv[]) {
- test_in_addr_prefix_from_string("", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
- test_in_addr_prefix_from_string("/", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
- test_in_addr_prefix_from_string("/8", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
- test_in_addr_prefix_from_string("1.2.3.4", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, -ENOANO, 0, 0, 8);
- test_in_addr_prefix_from_string("1.2.3.4/0", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 0, 0, 0, 0, 0);
- test_in_addr_prefix_from_string("1.2.3.4/1", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 1, 0, 1, 0, 1);
- test_in_addr_prefix_from_string("1.2.3.4/2", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 2, 0, 2, 0, 2);
- test_in_addr_prefix_from_string("1.2.3.4/32", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, 0, 32, 0, 32);
- test_in_addr_prefix_from_string("1.2.3.4/33", AF_INET, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
- test_in_addr_prefix_from_string("1.2.3.4/-1", AF_INET, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
- test_in_addr_prefix_from_string("::1", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
-
- test_in_addr_prefix_from_string("", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
- test_in_addr_prefix_from_string("/", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
- test_in_addr_prefix_from_string("/8", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
- test_in_addr_prefix_from_string("::1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, -ENOANO, 0, 0, 0);
- test_in_addr_prefix_from_string("::1/0", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0, 0, 0, 0, 0);
- test_in_addr_prefix_from_string("::1/1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 1, 0, 1, 0, 1);
- test_in_addr_prefix_from_string("::1/2", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 2, 0, 2, 0, 2);
- test_in_addr_prefix_from_string("::1/32", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 32, 0, 32, 0, 32);
- test_in_addr_prefix_from_string("::1/33", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 33, 0, 33, 0, 33);
- test_in_addr_prefix_from_string("::1/64", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 64, 0, 64, 0, 64);
- test_in_addr_prefix_from_string("::1/128", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, 0, 128, 0, 128);
- test_in_addr_prefix_from_string("::1/129", AF_INET6, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
- test_in_addr_prefix_from_string("::1/-1", AF_INET6, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
+ test_in_addr_prefix_from_string();
+ test_in_addr_random_prefix();
+ test_in_addr_prefix_to_string();
return 0;
}
#include "in-addr-util.h"
#include "local-addresses.h"
#include "log.h"
+#include "main-func.h"
#include "nss-util.h"
#include "path-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
+#include "tests.h"
static const char* nss_status_to_string(enum nss_status status, char *buf, size_t buf_len) {
switch (status) {
return 0;
}
-int main(int argc, char **argv) {
+static int run(int argc, char **argv) {
_cleanup_free_ char *dir = NULL;
_cleanup_strv_free_ char **modules = NULL, **names = NULL;
_cleanup_free_ struct local_address *addresses = NULL;
char **module;
int r;
- log_set_max_level(LOG_INFO);
- log_parse_environment();
+ test_setup_logging(LOG_INFO);
r = parse_argv(argc, argv, &modules, &names, &addresses, &n_addresses);
if (r < 0) {
dir = dirname_malloc(argv[0]);
if (!dir)
- return EXIT_FAILURE;
+ return log_oom();
STRV_FOREACH(module, modules) {
r = test_one_module(dir, *module, names, addresses, n_addresses);
if (r < 0)
- return EXIT_FAILURE;
+ return r;
}
- return EXIT_SUCCESS;
+ return 0;
}
+
+DEFINE_MAIN_FUNCTION(run);
#include "cgroup.h"
#include "compress.h"
#include "condition.h"
-#include "device-internal.h"
+#include "device-private.h"
#include "device.h"
#include "execute.h"
#include "import-util.h"
return r;
if (arg_all || !isempty(str))
- bus_print_property_value(name, expected_value, value, "%s", str);
+ bus_print_property_value(name, expected_value, value, str);
return 1;
}
n += !!u->path;
if (n == 0) {
- (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL);
-
c->slot_job_removed = sd_bus_slot_unref(c->slot_job_removed);
+
+ (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL);
}
return 0;
if (!dn)
return log_oom();
- fd = chase_symlinks(dn, NULL, CHASE_OPEN|CHASE_SAFE|CHASE_WARN, NULL);
+ fd = chase_symlinks(dn, arg_root, CHASE_OPEN|CHASE_SAFE|CHASE_WARN, NULL);
if (fd < 0 && fd != -ENOLINK)
return log_error_errno(fd, "Failed to validate path %s: %m", path);
"Failed to open invalid path '%s'.",
path);
- fd = chase_symlinks(path, NULL, CHASE_OPEN|CHASE_SAFE|CHASE_WARN|CHASE_NOFOLLOW, NULL);
+ fd = chase_symlinks(path, arg_root, CHASE_OPEN|CHASE_SAFE|CHASE_WARN|CHASE_NOFOLLOW, NULL);
if (fd < 0 && fd != -ENOLINK)
return log_error_errno(fd, "Failed to validate path %s: %m", path);
i->done |= operation;
- r = chase_symlinks(i->path, NULL, CHASE_NO_AUTOFS|CHASE_WARN, NULL);
+ r = chase_symlinks(i->path, arg_root, CHASE_NO_AUTOFS|CHASE_WARN, NULL);
if (r == -EREMOTE) {
log_notice_errno(r, "Skipping %s", i->path);
return 0;
sd_device_unref(event->dev);
sd_device_unref(event->dev_db_clone);
sd_netlink_unref(event->rtnl);
- hashmap_free_free_key(event->run_list);
- hashmap_free_free_free(event->seclabel_list);
+ ordered_hashmap_free_free_key(event->run_list);
+ ordered_hashmap_free_free_free(event->seclabel_list);
free(event->program_result);
free(event->name);
static int rename_netif(UdevEvent *event) {
sd_device *dev = event->dev;
const char *action, *oldname;
- char name[IFNAMSIZ];
int ifindex, r;
if (!event->name)
if (r < 0)
return log_device_error_errno(dev, r, "Failed to get ifindex: %m");
- strscpy(name, IFNAMSIZ, event->name);
- r = rtnl_set_link_name(&event->rtnl, ifindex, name);
+ r = rtnl_set_link_name(&event->rtnl, ifindex, event->name);
if (r < 0)
- return log_device_error_errno(dev, r, "Failed to rename network interface %i from '%s' to '%s': %m", ifindex, oldname, name);
+ return log_device_error_errno(dev, r, "Failed to rename network interface %i from '%s' to '%s': %m",
+ ifindex, oldname, event->name);
+
+ /* Set ID_RENAMING boolean property here, and drop it in the corresponding move uevent later. */
+ r = device_add_property(dev, "ID_RENAMING", "1");
+ if (r < 0)
+ log_device_warning_errno(dev, r, "Failed to add 'ID_RENAMING' property: %m");
r = device_rename(dev, event->name);
if (r < 0)
- return log_warning_errno(r, "Network interface %i is renamed from '%s' to '%s', but could not update sd_device object: %m", ifindex, oldname, name);
+ log_device_warning_errno(dev, r, "Failed to update properties with new name '%s': %m", event->name);
- log_device_debug(dev, "Network interface %i is renamed from '%s' to '%s'", ifindex, oldname, name);
+ log_device_debug(dev, "Network interface %i is renamed from '%s' to '%s'", ifindex, oldname, event->name);
return 1;
}
(void) udev_node_remove(dev);
}
+static int udev_event_on_move(UdevEvent *event) {
+ sd_device *dev = event->dev;
+ int r;
+
+ if (event->dev_db_clone &&
+ sd_device_get_devnum(dev, NULL) < 0) {
+ r = device_copy_properties(dev, event->dev_db_clone);
+ if (r < 0)
+ log_device_debug_errno(dev, r, "Failed to copy properties from cloned sd_device object, ignoring: %m");
+ }
+
+ /* Drop previously added property */
+ r = device_add_property(dev, "ID_RENAMING", NULL);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to remove 'ID_RENAMING' property, ignoring: %m");
+
+ return 0;
+}
+
int udev_event_execute_rules(UdevEvent *event,
usec_t timeout_usec,
Hashmap *properties_list,
UdevRules *rules) {
- sd_device *dev = event->dev;
const char *subsystem, *action;
+ sd_device *dev;
int r;
assert(event);
assert(rules);
+ dev = event->dev;
+
r = sd_device_get_subsystem(dev, &subsystem);
if (r < 0)
return log_device_error_errno(dev, r, "Failed to get subsystem: %m");
if (r < 0)
log_device_debug_errno(dev, r, "Failed to clone sd_device object, ignoring: %m");
- if (event->dev_db_clone) {
- r = sd_device_get_devnum(dev, NULL);
- if (r < 0) {
- if (r != -ENOENT)
- log_device_debug_errno(dev, r, "Failed to get devnum, ignoring: %m");
+ if (event->dev_db_clone && sd_device_get_devnum(dev, NULL) >= 0)
+ /* Disable watch during event processing. */
+ (void) udev_watch_end(event->dev_db_clone);
- if (streq(action, "move")) {
- r = device_copy_properties(dev, event->dev_db_clone);
- if (r < 0)
- log_device_debug_errno(dev, r, "Failed to copy properties from cloned device, ignoring: %m");
- }
- } else
- /* Disable watch during event processing. */
- (void) udev_watch_end(event->dev_db_clone);
- }
+ if (streq(action, "move"))
+ (void) udev_event_on_move(event);
(void) udev_rules_apply_to_event(rules, event, timeout_usec, properties_list);
void *val;
Iterator i;
- HASHMAP_FOREACH_KEY(val, cmd, event->run_list, i) {
+ ORDERED_HASHMAP_FOREACH_KEY(val, cmd, event->run_list, i) {
enum udev_builtin_cmd builtin_cmd = PTR_TO_INT(val);
char command[UTIL_PATH_SIZE];
static int node_permissions_apply(sd_device *dev, bool apply,
mode_t mode, uid_t uid, gid_t gid,
- Hashmap *seclabel_list) {
+ OrderedHashmap *seclabel_list) {
const char *devnode, *subsystem, *id_filename = NULL;
struct stat stats;
dev_t devnum;
log_device_debug(dev, "Preserve permissions of %s, %#o, uid=%u, gid=%u", devnode, mode, uid, gid);
/* apply SECLABEL{$module}=$label */
- HASHMAP_FOREACH_KEY(label, name, seclabel_list, i) {
+ ORDERED_HASHMAP_FOREACH_KEY(label, name, seclabel_list, i) {
int q;
if (streq(name, "selinux")) {
int udev_node_add(sd_device *dev, bool apply,
mode_t mode, uid_t uid, gid_t gid,
- Hashmap *seclabel_list) {
+ OrderedHashmap *seclabel_list) {
const char *devnode, *devlink;
_cleanup_free_ char *filename = NULL;
int r;
int udev_node_add(sd_device *dev, bool apply,
mode_t mode, uid_t uid, gid_t gid,
- Hashmap *seclabel_list);
+ OrderedHashmap *seclabel_list);
int udev_node_remove(sd_device *dev);
int udev_node_update_old_links(sd_device *dev, sd_device *dev_old);
char *line;
int r;
- r = udev_event_spawn(event, timeout_usec, false, program, result, sizeof result);
+ r = udev_event_spawn(event, timeout_usec, true, program, result, sizeof result);
if (r < 0)
return r;
if (r > 0)
return log_oom();
if (IN_SET(cur->key.op, OP_ASSIGN, OP_ASSIGN_FINAL))
- hashmap_clear_free_free(event->seclabel_list);
+ ordered_hashmap_clear_free_free(event->seclabel_list);
- r = hashmap_ensure_allocated(&event->seclabel_list, NULL);
+ r = ordered_hashmap_ensure_allocated(&event->seclabel_list, NULL);
if (r < 0)
return log_oom();
- r = hashmap_put(event->seclabel_list, name, label);
+ r = ordered_hashmap_put(event->seclabel_list, name, label);
if (r < 0)
return log_oom();
log_device_debug(dev, "SECLABEL{%s}='%s' %s:%u",
_cleanup_free_ char *cmd = NULL;
if (IN_SET(cur->key.op, OP_ASSIGN, OP_ASSIGN_FINAL))
- hashmap_clear_free_key(event->run_list);
+ ordered_hashmap_clear_free_key(event->run_list);
- r = hashmap_ensure_allocated(&event->run_list, NULL);
+ r = ordered_hashmap_ensure_allocated(&event->run_list, NULL);
if (r < 0)
return log_oom();
if (!cmd)
return log_oom();
- r = hashmap_put(event->run_list, cmd, INT_TO_PTR(cur->key.builtin_cmd));
+ r = ordered_hashmap_put(event->run_list, cmd, INT_TO_PTR(cur->key.builtin_cmd));
if (r < 0)
return log_oom();
mode_t mode;
uid_t uid;
gid_t gid;
- Hashmap *seclabel_list;
- Hashmap *run_list;
+ OrderedHashmap *seclabel_list;
+ OrderedHashmap *run_list;
usec_t exec_delay_usec;
usec_t birth_usec;
sd_netlink *rtnl;
FOREACH_DEVICE_PROPERTY(dev, key, value)
printf("%s=%s\n", key, value);
- HASHMAP_FOREACH_KEY(val, cmd, event->run_list, i) {
+ ORDERED_HASHMAP_FOREACH_KEY(val, cmd, event->run_list, i) {
char program[UTIL_PATH_SIZE];
udev_event_apply_format(event, cmd, program, sizeof(program), false);
#include "sd-event.h"
#include "device-enumerator-private.h"
+#include "device-private.h"
#include "fd-util.h"
#include "fileio.h"
#include "path-util.h"
}
static int device_monitor_handler(sd_device_monitor *m, sd_device *dev, void *userdata) {
+ _cleanup_free_ char *val = NULL;
Set *settle_set = userdata;
const char *syspath;
if (arg_verbose)
printf("settle %s\n", syspath);
- if (!set_remove(settle_set, syspath))
+ val = set_remove(settle_set, syspath);
+ if (!val)
log_debug("Got epoll event on syspath %s not present in syspath set", syspath);
if (set_isempty(settle_set))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown type --type=%s", optarg);
break;
case 'c':
- if (STR_IN_SET(optarg, "add", "remove", "change"))
- action = optarg;
- else
- log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown action '%s'", optarg);
+ if (device_action_from_string(optarg) < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown action '%s'", optarg);
+ action = optarg;
break;
case 's':
r = sd_device_enumerator_add_match_subsystem(e, optarg, true);
--- /dev/null
+#! /bin/bash
+#
+# Verify tmpfiles can run in a root directory under a path prefix that contains
+# directories owned by unprivileged users, for example when a root file system
+# is mounted in a regular user's home directory.
+#
+# https://github.com/systemd/systemd/pull/11820
+#
+
+set -e
+
+rm -fr /tmp/root /tmp/user
+mkdir -p /tmp/root /tmp/user/root
+chown daemon:daemon /tmp/user
+
+# Verify the command works as expected with no prefix or a root-owned prefix.
+echo 'd /tmp/root/test1' | systemd-tmpfiles --create -
+test -d /tmp/root/test1
+echo 'd /test2' | systemd-tmpfiles --root=/tmp/root --create -
+test -d /tmp/root/test2
+
+# Verify the command fails to write to a root-owned subdirectory under an
+# unprivileged user's directory when it's not part of the prefix, as expected
+# by the unsafe_transition function.
+! echo 'd /tmp/user/root/test' | systemd-tmpfiles --create -
+! test -e /tmp/user/root/test
+! echo 'd /user/root/test' | systemd-tmpfiles --root=/tmp --create -
+! test -e /tmp/user/root/test
+
+# Verify the above works when all user-owned directories are in the prefix.
+echo 'd /test' | systemd-tmpfiles --root=/tmp/user/root --create -
+test -d /tmp/user/root/test
--- /dev/null
+../TEST-01-BASIC/Makefile
\ No newline at end of file
--- /dev/null
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+set -e
+TEST_DESCRIPTION="UDEV ID_RENAMING property"
+TEST_NO_NSPAWN=1
+
+. $TEST_BASE_DIR/test-functions
+QEMU_TIMEOUT=300
+
+test_setup() {
+ create_empty_image
+ mkdir -p $TESTDIR/root
+ mount ${LOOPDEV}p1 $TESTDIR/root
+
+ (
+ LOG_LEVEL=5
+ eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
+
+ setup_basic_environment
+
+ # mask some services that we do not want to run in these tests
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.service
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.socket
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-resolved.service
+
+ # setup the testsuite service
+ cat >$initdir/etc/systemd/system/testsuite.service <<EOF
+[Unit]
+Description=Testsuite service
+
+[Service]
+ExecStart=/bin/bash -x /testsuite.sh
+Type=oneshot
+StandardOutput=tty
+StandardError=tty
+EOF
+ cp testsuite.sh $initdir/
+
+ setup_testsuite
+ ) || return 1
+
+ ddebug "umount $TESTDIR/root"
+ umount $TESTDIR/root
+}
+
+do_test "$@"
--- /dev/null
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+set -ex
+set -o pipefail
+
+mkdir -p /run/udev/rules.d/
+
+cat > /run/udev/rules.d/50-testsuite.rules <<EOF
+ACTION=="remove", GOTO="lo_end"
+
+SUBSYSTEM=="net", KERNEL=="lo", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/net/devices/lo"
+
+ACTION!="change", GOTO="lo_end"
+
+SUBSYSTEM=="net", KERNEL=="lo", ENV{ID_RENAMING}="1"
+
+LABEL="lo_end"
+EOF
+
+udevadm control --log-priority=debug --reload
+udevadm trigger --action=add --settle /sys/devices/virtual/net/lo
+udevadm info /sys/devices/virtual/net/lo
+
+STATE=$(systemctl show --property=ActiveState --value sys-devices-virtual-net-lo.device)
+[[ $STATE == "active" ]] || exit 1
+
+udevadm trigger --action=change --settle /sys/devices/virtual/net/lo
+udevadm info /sys/devices/virtual/net/lo
+
+STATE=$(systemctl show --property=ActiveState --value sys-devices-virtual-net-lo.device)
+[[ $STATE == "inactive" ]] || exit 1
+
+udevadm trigger --action=move --settle /sys/devices/virtual/net/lo
+udevadm info /sys/devices/virtual/net/lo
+
+STATE=$(systemctl show --property=ActiveState --value sys-devices-virtual-net-lo.device)
+[[ $STATE == "active" ]] || exit 1
+
+rm -f /run/udev/rules.d/50-testsuite.rules
+udevadm control --reload
+
+echo OK > /testok
+
+exit 0
--- /dev/null
+VARIABLE="value"
+OPTION="--option=1234"
+NUMBER=1
+EMPTY=""
+PATH=/var/lib/xxx
SamplePoint=
BitRate=
RestartSec=
+TripleSampling=
[Address]
DuplicateAddressDetection=
AutoJoin=
--- /dev/null
+[Exec]
+Boot=off
+ProcessTwo=off
+Parameters=/sbin/init -x=1
+Environment=THIS=that
+User=user
+WorkingDirectory=/cwd
+PivotRoot=/newroot
+Capability=CAP_NET
+DropCapability=CAP_ADMIN
+KillSignal=SIGTERM
+Personality=shy
+MachineID=edbfea3309ba41ea83e2318c58a8d498
+PrivateUser=1:2
+NotifyReady=no
+SystemCallFilters=write
+
+[Files]
+ReadOnly=no
+Volatile=no
+Bind=/bindthis
+BindReadOnly=/bindthisro
+TemporaryFileSystem=/thisismytmpfs:rw
+Overlay=/thisisanoverlay:/thisisanoverlaytoo
+PrivateUsersChown=no
+
+[Network]
+Private=off
+VirtualEthernet=yes
+VirtualEthernetExtra=veth1:veth2
+Interface=eth1 enp0s1
+MacVLAN=eno1 eno2
+IPVLAN=eno3 enp2s124
+Bridge=bridge123 bridge125
+Zone=myzone
+Port=1234 156 -1
--- /dev/null
+[Match]
+Name=test1
--- /dev/null
+[Network]
+VLAN=vlan99
+Address=192.168.24.5/24
+Address=192.168.25.5/24
+IPv6AcceptRA=false
[Match]
-Name=test1
+Name=vlan99
+
+[Network]
+IPv6AcceptRA=false
+Address=192.168.23.5/24
+++ /dev/null
-[Network]
-VLAN=vlan99
[Address]
Address=2001:db8::20
Peer=2001:db8::10/128
+
+[Address]
+Address=0.0.0.0/24
+Label=34
+
+[Address]
+Address=0.0.0.0/16
+Label=35
+
+[Address]
+Address=::/64
'12-dummy.netdev',
'21-macvlan.netdev',
'21-macvtap.netdev',
+ '21-vlan-test1.network',
'21-vlan.netdev',
'21-vlan.network',
'25-6rd-tunnel.netdev',
self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'tlb_dynamic_lb'))
def test_vlan(self):
- self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev', '21-vlan.network')
+ self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
+ '21-vlan.network', '21-vlan-test1.network')
self.start_networkd()
self.assertTrue(self.link_exits('test1'))
self.assertTrue(output, 'MVRP')
self.assertTrue(output, ' id 99 ')
+ output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'test1']).rstrip().decode('utf-8')
+ print(output)
+ self.assertRegex(output, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
+ self.assertRegex(output, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
+
+ output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'vlan99']).rstrip().decode('utf-8')
+ print(output)
+ self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
+
def test_macvtap(self):
self.copy_unit_to_networkd_unit_path('21-macvtap.netdev', '11-dummy.netdev', 'macvtap.network')
self.start_networkd()
self.assertTrue(self.link_exits('dummy98'))
- output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
+ # This also tests address pool
+
+ output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98', 'label', '32']).rstrip().decode('utf-8')
print(output)
self.assertRegex(output, 'inet 10.2.3.4 peer 10.2.3.5/16 scope global 32')
+
+ output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98', 'label', '33']).rstrip().decode('utf-8')
+ print(output)
self.assertRegex(output, 'inet 10.6.7.8/16 brd 10.6.255.255 scope global 33')
+
+ output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98', 'label', '34']).rstrip().decode('utf-8')
+ print(output)
+ self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
+
+ output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98', 'label', '35']).rstrip().decode('utf-8')
+ print(output)
+ self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
+
+ output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
+ print(output)
self.assertRegex(output, 'inet6 2001:db8::20 peer 2001:db8::10/128 scope global')
+ self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
print(output)
info "Starting container $CONT_NAME"
$DOCKER_RUN -v $REPO_ROOT:/build:rw \
-w /build --privileged=true --name $CONT_NAME \
- -dit --net=host debian-with-systemd/latest /usr/bin/systemd
+ -dit --net=host debian-with-systemd/latest /bin/systemd
$DOCKER_EXEC bash -c "echo deb-src http://deb.debian.org/debian $DEBIAN_RELEASE main >>/etc/apt/sources.list"
$DOCKER_EXEC apt-get -y update
$DOCKER_EXEC apt-get -y build-dep systemd
[Unit]
Description=Remove the Offline System Updates symlink
-Documentation=man:systemd.special(5) man:systemd.offline-updates(7)
+Documentation=man:systemd.special(7) man:systemd.offline-updates(7)
After=system-update.target
DefaultDependencies=no
Conflicts=shutdown.target
LockPersonality=yes
MemoryDenyWriteExecute=yes
NoNewPrivileges=yes
-ProtectHostname=yes
Restart=always
RestartSec=0
RestrictAddressFamilies=AF_UNIX AF_NETLINK
[Service]
BusName=org.freedesktop.login1
-CapabilityBoundingSet=CAP_SYS_ADMIN CAP_MAC_ADMIN CAP_AUDIT_CONTROL CAP_CHOWN CAP_KILL CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_FOWNER CAP_SYS_TTY_CONFIG
+CapabilityBoundingSet=CAP_SYS_ADMIN CAP_MAC_ADMIN CAP_AUDIT_CONTROL CAP_CHOWN CAP_KILL CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_FOWNER CAP_SYS_TTY_CONFIG CAP_LINUX_IMMUTABLE
ExecStart=@rootlibexecdir@/systemd-logind
FileDescriptorStoreMax=512
IPAddressDeny=any
NoNewPrivileges=yes
ProtectControlGroups=yes
ProtectHome=yes
-ProtectHostname=yes
ProtectKernelModules=yes
ProtectSystem=strict
Restart=on-failure
PrivateTmp=yes
ProtectControlGroups=yes
ProtectHome=yes
-ProtectHostname=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
ProtectSystem=strict