summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.packit.yml14
-rw-r--r--docs/PORTABILITY_AND_STABILITY.md2
-rw-r--r--man/org.freedesktop.login1.xml36
-rw-r--r--man/systemctl.xml4
-rw-r--r--man/systemd.preset.xml75
-rw-r--r--meson.build12
-rw-r--r--meson_options.txt2
-rw-r--r--src/basic/login-util.h8
-rw-r--r--src/basic/path-util.c25
-rw-r--r--src/kernel-install/meson.build3
-rw-r--r--src/libudev/libudev-list.c19
-rw-r--r--src/login/logind-dbus.c97
-rw-r--r--src/systemctl/systemctl-logind.c17
-rw-r--r--src/test/test-path-util.c6
-rwxr-xr-xtools/oss-fuzz.sh6
-rwxr-xr-xtools/update-dbus-docs.py2
16 files changed, 243 insertions, 85 deletions
diff --git a/.packit.yml b/.packit.yml
index 0c3c17b9da..e1ace861dd 100644
--- a/.packit.yml
+++ b/.packit.yml
@@ -22,8 +22,18 @@ actions:
# - Patch0000-0499: backported patches from upstream
# - Patch0500-9999: downstream-only patches
- "sed -ri '/^Patch0[0-4][0-9]{2}+\\:.+\\.patch/d' .packit_rpm/systemd.spec"
- # Build the RPMs with -Werror to catch possible compiler warnings
- - "sed -i 's/^%meson /%meson --werror /' .packit_rpm/systemd.spec"
+ # Build the RPMs with -Werror to catch possible compiler warnings. Since
+ # --werror in meson doesn't seem to work with -Db_lto=true [0], let's use
+ # -Dc_args= and -Dcpp_args= instead.
+ #
+ # Exceptions:
+ # - use -Wno-deprecated-declarations to get around mallinfo() use in
+ # basic/selinux-util.c
+ # - don't use -Werror on x86 architectures, otherwise all function checks
+ # will fail (with error: cast from pointer to integer of different size)
+ #
+ # [0] https://github.com/mesonbuild/meson/issues/7360
+ - 'sed -i "/^CONFIGURE_OPTS=(/a%ifnarch i386 i686\n-Dc_args=\"-Werror -Wno-deprecated-declarations\" -Dcpp_args=\"-Werror -Wno-deprecated-declarations\"\n%endif" .packit_rpm/systemd.spec'
jobs:
- job: copr_build
diff --git a/docs/PORTABILITY_AND_STABILITY.md b/docs/PORTABILITY_AND_STABILITY.md
index 0caa5cc048..27562c17d8 100644
--- a/docs/PORTABILITY_AND_STABILITY.md
+++ b/docs/PORTABILITY_AND_STABILITY.md
@@ -120,7 +120,7 @@ And now, here's the list of (hopefully) all APIs that we have introduced with sy
| `/run` | File hierarchy change | yes | yes | numerous | yes | OpenSUSE, Debian, ArchLinux | no |
| [Generators](https://www.freedesktop.org/software/systemd/man/systemd.generator.html) | Subprocess | yes | yes | - | no | - | no |
| [System Updates](https://www.freedesktop.org/software/systemd/man/systemd.offline-updates.html) | System Mode | yes | yes | - | no | - | no |
-| [Presets](https://freedesktop.org/wiki/Software/systemd/Preset) | File format | yes | yes | - | no | - | no |
+| [Presets](https://www.freedesktop.org/software/systemd/man/systemd.preset.html) | File format | yes | yes | - | no | - | no |
| Udev rules | File format | yes | yes | numerous | no | no | partially |
diff --git a/man/org.freedesktop.login1.xml b/man/org.freedesktop.login1.xml
index ad27b226b8..bf7a5fa340 100644
--- a/man/org.freedesktop.login1.xml
+++ b/man/org.freedesktop.login1.xml
@@ -102,12 +102,19 @@ node /org/freedesktop/login1 {
in b interactive);
FlushDevices(in b interactive);
PowerOff(in b interactive);
+ PowerOffWithFlags(in t flags);
Reboot(in b interactive);
+ RebootWithFlags(in t flags);
Halt(in b interactive);
+ HaltWithFlags(in t flags);
Suspend(in b interactive);
+ SuspendWithFlags(in t flags);
Hibernate(in b interactive);
+ HibernateWithFlags(in t flags);
HybridSleep(in b interactive);
+ HybridSleepWithFlags(in t flags);
SuspendThenHibernate(in b interactive);
+ SuspendThenHibernateWithFlags(in t flags);
CanPowerOff(out s result);
CanReboot(out s result);
CanHalt(out s result);
@@ -291,18 +298,32 @@ node /org/freedesktop/login1 {
<variablelist class="dbus-method" generated="True" extra-ref="PowerOff()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="PowerOffWithFlags()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="Reboot()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="RebootWithFlags()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="Halt()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="HaltWithFlags()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="Suspend()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="SuspendWithFlags()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="Hibernate()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="HibernateWithFlags()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="HybridSleep()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="HybridSleepWithFlags()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="SuspendThenHibernate()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="SuspendThenHibernateWithFlags()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="CanPowerOff()"/>
<variablelist class="dbus-method" generated="True" extra-ref="CanReboot()"/>
@@ -525,8 +546,19 @@ node /org/freedesktop/login1 {
using an RTC timer and hibernated. The only argument is the polkit interactivity boolean
<varname>interactive</varname> (see below). The main purpose of these calls is that they enforce
polkit policy and hence allow powering off/rebooting/suspending/hibernating even by unprivileged
- users. They also enforce inhibition locks. UIs should expose these calls as the primary mechanism to
- poweroff/reboot/suspend/hibernate the machine.</para>
+ users. They also enforce inhibition locks for non-privileged users. UIs should expose these calls
+ as the primary mechanism to poweroff/reboot/suspend/hibernate the machine. Methods
+ <function>PowerOffWithFlags()</function>, <function>RebootWithFlags()</function>,
+ <function>HaltWithFlags()</function>, <function>SuspendWithFlags()</function>,
+ <function>HibernateWithFlags()</function>, <function>HybridSleepWithFlags()</function> and
+ <function>SuspendThenHibernateWithFlags()</function> add <varname>flags</varname> to allow for
+ extendability, defined as follows:</para>
+ <programlisting>
+#define SD_LOGIND_ROOT_CHECK_INHIBITORS (UINT64_C(1) &lt;&lt; 0)
+ </programlisting>
+ <para> When the <varname>flags</varname> is 0 then these methods behave just like the versions
+ without flags. When <constant>SD_LOGIND_ROOT_CHECK_INHIBITORS</constant> (0x01) is set, active
+ inhibitors are honoured for privileged users too.</para>
<para><function>SetRebootParameter()</function> sets a parameter for a subsequent reboot operation.
See the description of <command>reboot</command> in
diff --git a/man/systemctl.xml b/man/systemctl.xml
index e49a12a146..db4e2b2c65 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -793,9 +793,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
<para>For more information on the preset policy format, see
<citerefentry><refentrytitle>systemd.preset</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
- For more information on the concept of presets, please consult the
- <ulink url="https://www.freedesktop.org/wiki/Software/systemd/Preset">Preset</ulink>
- document.</para>
+ </para>
</listitem>
</varlistentry>
diff --git a/man/systemd.preset.xml b/man/systemd.preset.xml
index 5697e50be7..cbd89daf16 100644
--- a/man/systemd.preset.xml
+++ b/man/systemd.preset.xml
@@ -32,28 +32,20 @@
<refsect1>
<title>Description</title>
- <para>Preset files may be used to encode policy which units shall
- be enabled by default and which ones shall be disabled. They are
- read by <command>systemctl preset</command> (for more information
- see
- <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>)
- which uses this information to enable or disable a unit according
- to preset policy. <command>systemctl preset</command> is used by
- the post install scriptlets of RPM packages (or other OS package
- formats), to enable/disable specific units by default on package
- installation, enforcing distribution, spin or administrator preset
- policy. This allows choosing a certain set of units to be
- enabled/disabled even before installing the actual package.</para>
-
- <para>For more information on the preset logic please have a look
- at the <ulink
- url="https://www.freedesktop.org/wiki/Software/systemd/Preset">Presets</ulink>
- document.</para>
-
- <para>It is not recommended to ship preset files within the
- respective software packages implementing the units, but rather
- centralize them in a distribution or spin default policy, which
- can be amended by administrator policy.</para>
+ <para>Preset files may be used to encode policy which units shall be enabled by default and which ones
+ shall be disabled. They are read by <command>systemctl preset</command> which uses this information to
+ enable or disable a unit. Depending on that policy, <command>systemctl preset</command> is identical to
+ <command>systemctl enable</command> or <command>systemctl disable</command>.
+
+ <command>systemctl preset</command> is used by the post install scriptlets of rpm packages (or other OS
+ package formats), to enable/disable specific units by default on package installation, enforcing
+ distribution, spin or administrator preset policy. This allows choosing a certain set of units to be
+ enabled/disabled even before installing the actual package. For more information, see
+ <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
+
+ <para>It is not recommended to ship preset files within the respective software packages implementing the
+ units, but rather centralize them in a distribution or spin default policy, which can be amended by
+ administrator policy, see below.</para>
<para>If no preset files exist, <command>systemctl
preset</command> will enable all units that are installed by
@@ -176,12 +168,51 @@ disable *</programlisting>
</refsect1>
<refsect1>
+ <title>Motiviation for the preset logic</title>
+
+ <para>Different distributions have different policies on which services shall be enabled by default when
+ the package they are shipped in is installed. On Fedora all services stay off by default, so that
+ installing a package will not cause a service to be enabled (with some exceptions). On Debian all
+ services are immediately enabled by default, so that installing a package will cause its services to be
+ enabled right-away.</para>
+
+ <para>Even within a single distribution, different spins (flavours, remixes, whatever you might want to
+ call them) of a distribution also have different policies on what services to enable, and what services
+ to leave off. For example, Fedora Workstation will enable <command>gdm</command> as display manager by
+ default, while the Fedora KDE spin will enable <command>sddm</command> instead.</para>
+
+ <para>Different sites might also have different policies what to turn on by default and what to turn
+ off. For example, one administrator would prefer to enforce the policy of "<command>sshd</command> should
+ be always on, but everything else off", while another one might say "<command>snmpd</command> always on,
+ and for everything else use the distribution policy defaults".</para>
+
+ <para>Traditionally, policy about which services shall be enabled were implemented in each package
+ individually. This made it cumbersome to implement different policies per spin or per site, or to create
+ software packages that do the right thing on more than one distribution. The enablement mechanism was
+ also encoding the enablement policy.</para>
+
+ <para>The preset mechanism allows clean separation of the enablement mechanism (inside the package
+ scriptlets, by invoking <command>systemctl preset</command>) and enablement policy (centralized in the
+ preset files), and lifts the configuration out of individual packages. Preset files may be written for
+ specific distributions, for specific spins or for specific sites, in order to enforce different policies
+ as needed. It is recommended to apply the policy encoded in preset files in package installation
+ scriptlets.</para>
+ </refsect1>
+
+ <refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-delta</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
+
+ <para><citerefentry><refentrytitle>daemon</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ has a discussion of packaging scriptlets.</para>
+
+ <para>Fedora page introducing the use of presets:
+ <ulink url="https://fedoraproject.org/wiki/Features/PackagePresets">Features/PackagePresets</ulink>.
+ </para>
</refsect1>
</refentry>
diff --git a/meson.build b/meson.build
index 0af0cce8b8..01eeeb750e 100644
--- a/meson.build
+++ b/meson.build
@@ -1450,14 +1450,6 @@ have = have and conf.get('HAVE_PAM') == 1
conf.set10('ENABLE_PAM_HOME', have)
have = get_option('oomd')
-if have == 'auto'
- have = get_option('mode') == 'developer'
-else
- have = have == 'true'
- if have and get_option('mode') != 'developer'
- warning('oomd is not ready for release mode (yet)')
- endif
-endif
conf.set10('ENABLE_OOMD', have)
substs.set10('ENABLE_OOMD', have)
@@ -3668,8 +3660,8 @@ status = [
conf.get('SYSTEM_ALLOC_UID_MIN')),
'system GIDs: <=@0@ (alloc >=@1@)'.format(conf.get('SYSTEM_GID_MAX'),
conf.get('SYSTEM_ALLOC_GID_MIN')),
- 'dynamic UIDs: @0@–@1@'.format(dynamic_uid_min, dynamic_uid_max),
- 'container UID bases: @0@–@1@'.format(container_uid_base_min, container_uid_base_max),
+ 'dynamic UIDs: @0@…@1@'.format(dynamic_uid_min, dynamic_uid_max),
+ 'container UID bases: @0@…@1@'.format(container_uid_base_min, container_uid_base_max),
'/dev/kvm access mode: @0@'.format(get_option('dev-kvm-mode')),
'render group access mode: @0@'.format(get_option('group-render-mode')),
'certificate root directory: @0@'.format(get_option('certificate-root')),
diff --git a/meson_options.txt b/meson_options.txt
index a421473029..425e958ba2 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -99,7 +99,7 @@ option('coredump', type : 'boolean',
description : 'install the coredump handler')
option('pstore', type : 'boolean',
description : 'install the pstore archival tool')
-option('oomd', type : 'combo', choices : ['auto', 'true', 'false'],
+option('oomd', type : 'boolean',
description : 'install the userspace oom killer')
option('logind', type : 'boolean',
description : 'install the systemd-logind stack')
diff --git a/src/basic/login-util.h b/src/basic/login-util.h
index 00a124dc9f..dff87697a6 100644
--- a/src/basic/login-util.h
+++ b/src/basic/login-util.h
@@ -4,6 +4,14 @@
#include <stdbool.h>
#include <unistd.h>
+#define SD_LOGIND_ROOT_CHECK_INHIBITORS (UINT64_C(1) << 0)
+
+/* For internal use only */
+#define SD_LOGIND_INTERACTIVE (UINT64_C(1) << 63)
+
+#define SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC (SD_LOGIND_ROOT_CHECK_INHIBITORS)
+#define SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_ALL (SD_LOGIND_ROOT_CHECK_INHIBITORS|SD_LOGIND_INTERACTIVE)
+
bool session_id_valid(const char *id);
static inline bool logind_running(void) {
diff --git a/src/basic/path-util.c b/src/basic/path-util.c
index 5bcbc7a794..3dff09b151 100644
--- a/src/basic/path-util.c
+++ b/src/basic/path-util.c
@@ -823,6 +823,8 @@ const char *last_path_component(const char *path) {
* Also, the empty string is mapped to itself.
*
* This is different than basename(), which returns "" when a trailing slash is present.
+ *
+ * This always succeeds (except if you pass NULL in which case it returns NULL, too).
*/
unsigned l, k;
@@ -848,24 +850,24 @@ const char *last_path_component(const char *path) {
int path_extract_filename(const char *p, char **ret) {
_cleanup_free_ char *a = NULL;
- const char *c, *e = NULL, *q;
+ const char *c;
/* Extracts the filename part (i.e. right-most component) from a path, i.e. string that passes
- * filename_is_valid(). A wrapper around last_path_component(), but eats up trailing slashes. */
+ * filename_is_valid(). A wrapper around last_path_component(), but eats up trailing slashes. Returns
+ * -EADDRNOTAVAIL if specified parameter includes no filename (i.e. is "/" or so). Returns -EINVAL if
+ * not a valid path in the first place. */
- if (!p)
+ if (!path_is_valid(p))
return -EINVAL;
- c = last_path_component(p);
-
- for (q = c; *q != 0; q++)
- if (*q != '/')
- e = q + 1;
+ /* Special case the root dir, because in that case we simply have no filename, but
+ * last_path_component() won't complain */
+ if (path_equal(p, "/"))
+ return -EADDRNOTAVAIL;
- if (!e) /* no valid character? */
- return -EINVAL;
+ c = last_path_component(p);
- a = strndup(c, e - c);
+ a = strndup(c, strcspn(c, "/"));
if (!a)
return -ENOMEM;
@@ -873,7 +875,6 @@ int path_extract_filename(const char *p, char **ret) {
return -EINVAL;
*ret = TAKE_PTR(a);
-
return 0;
}
diff --git a/src/kernel-install/meson.build b/src/kernel-install/meson.build
index 4117188f14..92ce23ecf9 100644
--- a/src/kernel-install/meson.build
+++ b/src/kernel-install/meson.build
@@ -4,8 +4,7 @@ want_kernel_install = get_option('kernel-install')
if want_kernel_install
install_data('kernel-install',
- install_mode : 'rwxr-xr-x',
- install_dir : bindir)
+ install_mode : 'rwxr-xr-x')
install_data('00-entry-directory.install',
'50-depmod.install',
diff --git a/src/libudev/libudev-list.c b/src/libudev/libudev-list.c
index 3b2a2cdee4..69efc1013c 100644
--- a/src/libudev/libudev-list.c
+++ b/src/libudev/libudev-list.c
@@ -39,9 +39,10 @@ static struct udev_list_entry *udev_list_entry_free(struct udev_list_entry *entr
return NULL;
if (entry->list) {
- if (entry->list->unique)
+ if (entry->list->unique && entry->name)
hashmap_remove(entry->list->unique_entries, entry->name);
- else
+
+ if (!entry->list->unique || entry->list->uptodate)
LIST_REMOVE(entries, entry->list->entries, entry);
}
@@ -70,9 +71,9 @@ struct udev_list *udev_list_new(bool unique) {
struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char *_name, const char *_value) {
_cleanup_(udev_list_entry_freep) struct udev_list_entry *entry = NULL;
_cleanup_free_ char *name = NULL, *value = NULL;
- int r;
assert(list);
+ assert(_name);
name = strdup(_name);
if (!name)
@@ -89,26 +90,22 @@ struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char *
return NULL;
*entry = (struct udev_list_entry) {
- .list = list,
.name = TAKE_PTR(name),
.value = TAKE_PTR(value),
};
if (list->unique) {
- r = hashmap_ensure_allocated(&list->unique_entries, &string_hash_ops);
- if (r < 0)
- return NULL;
-
udev_list_entry_free(hashmap_get(list->unique_entries, entry->name));
- r = hashmap_put(list->unique_entries, entry->name, entry);
- if (r < 0)
+ if (hashmap_ensure_put(&list->unique_entries, &string_hash_ops, entry->name, entry) < 0)
return NULL;
list->uptodate = false;
} else
LIST_APPEND(entries, list->entries, entry);
+ entry->list = list;
+
return TAKE_PTR(entry);
}
@@ -119,8 +116,8 @@ void udev_list_cleanup(struct udev_list *list) {
return;
if (list->unique) {
- hashmap_clear_with_destructor(list->unique_entries, udev_list_entry_free);
list->uptodate = false;
+ hashmap_clear_with_destructor(list->unique_entries, udev_list_entry_free);
} else
LIST_FOREACH_SAFE(entries, i, n, list->entries)
udev_list_entry_free(i);
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index b95af1a9fd..8f27fe7ee9 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -1793,14 +1793,14 @@ static int verify_shutdown_creds(
Manager *m,
sd_bus_message *message,
InhibitWhat w,
- bool interactive,
const char *action,
const char *action_multiple_sessions,
const char *action_ignore_inhibit,
+ uint64_t flags,
sd_bus_error *error) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- bool multiple_sessions, blocked;
+ bool multiple_sessions, blocked, interactive;
uid_t uid;
int r;
@@ -1823,6 +1823,7 @@ static int verify_shutdown_creds(
multiple_sessions = r > 0;
blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
+ interactive = flags & SD_LOGIND_INTERACTIVE;
if (multiple_sessions && action_multiple_sessions) {
r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
@@ -1832,12 +1833,19 @@ static int verify_shutdown_creds(
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
}
- if (blocked && action_ignore_inhibit) {
- r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, 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 (blocked) {
+ /* We don't check polkit for root here, because you can't be more privileged than root */
+ if (uid == 0 && (flags & SD_LOGIND_ROOT_CHECK_INHIBITORS))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED,
+ "Access denied to root due to active block inhibitor");
+
+ if (action_ignore_inhibit) {
+ r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, 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 (!multiple_sessions && !blocked && action) {
@@ -1860,9 +1868,11 @@ static int method_do_shutdown_or_sleep(
const char *action_multiple_sessions,
const char *action_ignore_inhibit,
const char *sleep_verb,
+ bool with_flags,
sd_bus_error *error) {
- int interactive, r;
+ int interactive = false, r;
+ uint64_t flags = 0;
assert(m);
assert(message);
@@ -1870,10 +1880,20 @@ static int method_do_shutdown_or_sleep(
assert(w >= 0);
assert(w <= _INHIBIT_WHAT_MAX);
- r = sd_bus_message_read(message, "b", &interactive);
+ if (with_flags)
+ r = sd_bus_message_read(message, "t", &flags);
+ else
+ r = sd_bus_message_read(message, "b", &interactive);
+
if (r < 0)
return r;
+ if (with_flags && (flags & ~SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Invalid flags parameter");
+
+ SET_FLAG(flags, SD_LOGIND_INTERACTIVE, interactive);
+
/* Don't allow multiple jobs being executed at the same time */
if (m->action_what > 0)
return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS,
@@ -1891,8 +1911,8 @@ static int method_do_shutdown_or_sleep(
return r;
}
- r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
- action_ignore_inhibit, error);
+ r = verify_shutdown_creds(m, message, w, action, action_multiple_sessions,
+ action_ignore_inhibit, flags, error);
if (r != 0)
return r;
@@ -1914,6 +1934,7 @@ static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error
"org.freedesktop.login1.power-off-multiple-sessions",
"org.freedesktop.login1.power-off-ignore-inhibit",
NULL,
+ sd_bus_message_is_method_call(message, NULL, "PowerOffWithFlags"),
error);
}
@@ -1928,6 +1949,7 @@ static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *
"org.freedesktop.login1.reboot-multiple-sessions",
"org.freedesktop.login1.reboot-ignore-inhibit",
NULL,
+ sd_bus_message_is_method_call(message, NULL, "RebootWithFlags"),
error);
}
@@ -1942,6 +1964,7 @@ static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *er
"org.freedesktop.login1.halt-multiple-sessions",
"org.freedesktop.login1.halt-ignore-inhibit",
NULL,
+ sd_bus_message_is_method_call(message, NULL, "HaltWithFlags"),
error);
}
@@ -1956,6 +1979,7 @@ static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error
"org.freedesktop.login1.suspend-multiple-sessions",
"org.freedesktop.login1.suspend-ignore-inhibit",
"suspend",
+ sd_bus_message_is_method_call(message, NULL, "SuspendWithFlags"),
error);
}
@@ -1970,6 +1994,7 @@ static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_erro
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"hibernate",
+ sd_bus_message_is_method_call(message, NULL, "HibernateWithFlags"),
error);
}
@@ -1984,6 +2009,7 @@ static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_e
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"hybrid-sleep",
+ sd_bus_message_is_method_call(message, NULL, "HybridSleepWithFlags"),
error);
}
@@ -1998,6 +2024,7 @@ static int method_suspend_then_hibernate(sd_bus_message *message, void *userdata
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"hybrid-sleep",
+ sd_bus_message_is_method_call(message, NULL, "SuspendThenHibernateWithFlags"),
error);
}
@@ -2185,8 +2212,8 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_
} else
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
- r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
- action, action_multiple_sessions, action_ignore_inhibit, error);
+ r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, action, action_multiple_sessions,
+ action_ignore_inhibit, 0, error);
if (r != 0)
return r;
@@ -3538,42 +3565,84 @@ static const sd_bus_vtable manager_vtable[] = {
NULL,,
method_poweroff,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("PowerOffWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_poweroff,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("Reboot",
"b",
SD_BUS_PARAM(interactive),
NULL,,
method_reboot,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("RebootWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_reboot,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("Halt",
"b",
SD_BUS_PARAM(interactive),
NULL,,
method_halt,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("HaltWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_halt,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("Suspend",
"b",
SD_BUS_PARAM(interactive),
NULL,,
method_suspend,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("SuspendWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_suspend,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("Hibernate",
"b",
SD_BUS_PARAM(interactive),
NULL,,
method_hibernate,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("HibernateWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_hibernate,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("HybridSleep",
"b",
SD_BUS_PARAM(interactive),
NULL,,
method_hybrid_sleep,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("HybridSleepWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_hybrid_sleep,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("SuspendThenHibernate",
"b",
SD_BUS_PARAM(interactive),
NULL,,
method_suspend_then_hibernate,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("SuspendThenHibernateWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_suspend_then_hibernate,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("CanPowerOff",
NULL,,
"s",
diff --git a/src/systemctl/systemctl-logind.c b/src/systemctl/systemctl-logind.c
index 4070c64257..103f81647d 100644
--- a/src/systemctl/systemctl-logind.c
+++ b/src/systemctl/systemctl-logind.c
@@ -6,6 +6,7 @@
#include "bus-error.h"
#include "bus-locator.h"
+#include "login-util.h"
#include "process-util.h"
#include "systemctl-logind.h"
#include "systemctl-start-unit.h"
@@ -57,6 +58,8 @@ int logind_reboot(enum action a) {
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ const char *method_with_flags;
+ uint64_t flags = 0;
sd_bus *bus;
int r;
@@ -75,6 +78,20 @@ int logind_reboot(enum action a) {
if (arg_dry_run)
return 0;
+ SET_FLAG(flags, SD_LOGIND_ROOT_CHECK_INHIBITORS, arg_check_inhibitors > 0);
+
+ method_with_flags = strjoina(actions[a].method, "WithFlags");
+
+ r = bus_call_method(bus, bus_login_mgr, method_with_flags, &error, NULL, "t", flags);
+ if (r >= 0)
+ return 0;
+ if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
+ return log_error_errno(r, "Failed to %s via logind: %s", actions[a].description, bus_error_message(&error, r));
+
+ /* Fallback to original methods in case there is older version of systemd-logind */
+ log_debug("Method %s not available: %s. Falling back to %s", method_with_flags, bus_error_message(&error, r), actions[a].method);
+ sd_bus_error_free(&error);
+
r = bus_call_method(bus, bus_login_mgr, actions[a].method, &error, NULL, "b", arg_ask_password);
if (r < 0)
return log_error_errno(r, "Failed to %s via logind: %s", actions[a].description, bus_error_message(&error, r));
diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
index fcaffa4539..206f5fd436 100644
--- a/src/test/test-path-util.c
+++ b/src/test/test-path-util.c
@@ -578,9 +578,9 @@ static void test_path_extract_filename(void) {
test_path_extract_filename_one(NULL, NULL, -EINVAL);
test_path_extract_filename_one("a/b/c", "c", 0);
test_path_extract_filename_one("a/b/c/", "c", 0);
- test_path_extract_filename_one("/", NULL, -EINVAL);
- test_path_extract_filename_one("//", NULL, -EINVAL);
- test_path_extract_filename_one("///", NULL, -EINVAL);
+ test_path_extract_filename_one("/", NULL, -EADDRNOTAVAIL);
+ test_path_extract_filename_one("//", NULL, -EADDRNOTAVAIL);
+ test_path_extract_filename_one("///", NULL, -EADDRNOTAVAIL);
test_path_extract_filename_one(".", NULL, -EINVAL);
test_path_extract_filename_one("./.", NULL, -EINVAL);
test_path_extract_filename_one("././", NULL, -EINVAL);
diff --git a/tools/oss-fuzz.sh b/tools/oss-fuzz.sh
index 491246b32b..767da15f7c 100755
--- a/tools/oss-fuzz.sh
+++ b/tools/oss-fuzz.sh
@@ -38,7 +38,11 @@ else
fi
fi
-meson $build -D$fuzzflag -Db_lundef=false
+if ! meson $build -D$fuzzflag -Db_lundef=false; then
+ cat $build/meson-logs/meson-log.txt
+ exit 1
+fi
+
ninja -v -C $build fuzzers
# The seed corpus is a separate flat archive for each fuzzer,
diff --git a/tools/update-dbus-docs.py b/tools/update-dbus-docs.py
index 269b2196a2..b453a0867e 100755
--- a/tools/update-dbus-docs.py
+++ b/tools/update-dbus-docs.py
@@ -197,7 +197,7 @@ def subst_output(document, programlisting, stats):
print(f'COMMAND: {shlex_join(argv)}')
try:
- out = subprocess.check_output(argv, text=True)
+ out = subprocess.check_output(argv, universal_newlines=True)
except FileNotFoundError:
print(f'{executable} not found, ignoring', file=sys.stderr)
return