1
0
mirror of https://github.com/systemd/systemd synced 2025-11-18 16:24:44 +01:00

Compare commits

..

8 Commits

Author SHA1 Message Date
Daan De Meyer
308d40626d basic: Use xopenat_full() in mkdir_p_root_full() 2025-10-28 13:01:48 +01:00
Yu Watanabe
16e52afad2
man: handle leading/trailing/repeating whitespaces in anchor links (#39423)
So even if a <term> section contains newlines, we get a reasonable
anchor link to it.

Before:
```
<dt id="
  bind
  UNIT
  PATH
  [PATH]
"><span class="term">
...
<a class="headerlink" title="Permalink to this term" href="#%0A%20%20%20%20%20%20%20%20%20%20%20%20bind%0A%20%20%20%20%20%20%20%20%20%20%20%20UNIT%0A%20%20%20%20%20%20%20%20%20%20%20%20PATH%0A%20%20%20%20%20%20%20%20%20%20%20%20[PATH]%0A%20%20%20%20%20%20%20%20%20%20">¶</a>
```

After:
```
<dt id="bind UNIT PATH [PATH]"><span class="term">
...
<a class="headerlink" title="Permalink to this term" href="#bind%20UNIT%20PATH%20[PATH]">¶</a>
```

Resolves: https://github.com/systemd/systemd/issues/39196

---

The reverts are not strictly necessary here (as already pointed out in
https://github.com/systemd/systemd/pull/39154#issuecomment-3360118164)
but they were helpful in checking if the fix works as expected. I can
drop them if needed.
2025-10-28 15:28:54 +09:00
Yu Watanabe
bdbd902606
logind: support deserializing session leader through pidfdid (#39440)
Fixes #39437
2025-10-28 15:28:09 +09:00
Yu Watanabe
84f3f30e72 udev-watch: allow to log from child process
Otherwise, it is hard to debug issues in reread_partition_table().

This also drop unnecessary FORK_RLIMIT_NOFILE_SAFE flag.
2025-10-28 15:22:21 +09:00
Mike Yuan
ebb730b96d
TEST-35-LOGIN: test coldplug without fdstore on kernels with pidfd id 2025-10-25 19:42:58 +02:00
Mike Yuan
45eea629e3
logind: support deserializing session leader through pidfdid
People make weird assumptions around state preservation and
expect logind to be stoppable. While this is realistically
not OK we can probably improve things a little.

This complements f01d8658a3a57d05a5156aefd32d8137c3ee3996 and
adds support for deserializing the LEADER_PIDFDID= field.
We still prioritize pidfd if got one from fdstore (as with
service_notify_message_parse_new_pid() in pid1), but otherwise
this should make logind restart more robust when fdstore
gets spuriously cleared.

Fixes #39437
2025-10-25 19:42:58 +02:00
Frantisek Sumsal
3b4b3b8a95 Revert "Update systemctl.xml"
This reverts commit b0fe317d14c4e9a02ff661c2ccd37f093cfda396.
This reverts commit 9f4f7f0372688127adc27f82a75db58749eb6d6e.
2025-10-23 15:42:28 +02:00
Frantisek Sumsal
7168535165 man: handle leading/trailing/repeating whitespaces in anchor links
So even if a <term> section contains newlines, we get a reasonable
anchor link to it.

Before:
<dt id="
  bind
  UNIT
  PATH
  [PATH]
"><span class="term">
...
<a class="headerlink" title="Permalink to this term" href="#%0A%20%20%20%20%20%20%20%20%20%20%20%20bind%0A%20%20%20%20%20%20%20%20%20%20%20%20UNIT%0A%20%20%20%20%20%20%20%20%20%20%20%20PATH%0A%20%20%20%20%20%20%20%20%20%20%20%20[PATH]%0A%20%20%20%20%20%20%20%20%20%20">¶</a>

After:
<dt id="bind UNIT PATH [PATH]"><span class="term">
...
<a class="headerlink" title="Permalink to this term" href="#bind%20UNIT%20PATH%20[PATH]">¶</a>

Resolves: #39196
2025-10-23 15:42:28 +02:00
7 changed files with 111 additions and 47 deletions

View File

@ -158,6 +158,8 @@
<xsl:param name="keyNode"/> <xsl:param name="keyNode"/>
<!-- suggested value for generatedID output, a contextually meaningful ID string --> <!-- suggested value for generatedID output, a contextually meaningful ID string -->
<xsl:param name="templateID"/> <xsl:param name="templateID"/>
<!-- Strip leading and trailing whitespaces, and replace repeating whitespaces with a single space -->
<xsl:variable name="normalizedID" select="normalize-space($templateID)"/>
<xsl:variable name="conflictSource" select="preceding::refsect1/title|preceding::refsect1/info/title| <xsl:variable name="conflictSource" select="preceding::refsect1/title|preceding::refsect1/info/title|
preceding::refsect2/title|preceding::refsect2/info/title| preceding::refsect2/title|preceding::refsect2/info/title|
preceding::varlistentry/term[1]"/> preceding::varlistentry/term[1]"/>
@ -165,10 +167,10 @@
<xsl:choose> <xsl:choose>
<!-- special case conflictCount = 0 to preserve compatibility with URLs generated by previous versions of this XSL stylesheet where possible --> <!-- special case conflictCount = 0 to preserve compatibility with URLs generated by previous versions of this XSL stylesheet where possible -->
<xsl:when test="$conflictCount = 0"> <xsl:when test="$conflictCount = 0">
<xsl:value-of select="$templateID"/> <xsl:value-of select="$normalizedID"/>
</xsl:when> </xsl:when>
<xsl:otherwise> <xsl:otherwise>
<xsl:value-of select="concat($templateID, $conflictCount)"/> <xsl:value-of select="concat($normalizedID, $conflictCount)"/>
</xsl:otherwise> </xsl:otherwise>
</xsl:choose> </xsl:choose>
</xsl:template> </xsl:template>

View File

@ -375,7 +375,10 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><command>list-dependencies</command> <optional><replaceable>UNIT</replaceable></optional></term> <term>
<command>list-dependencies</command>
<optional><replaceable>UNIT</replaceable>...</optional>
</term>
<listitem> <listitem>
<para>Shows units required and wanted by the specified <para>Shows units required and wanted by the specified
@ -691,7 +694,12 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><command>bind</command> <replaceable>UNIT</replaceable> <replaceable>PATH</replaceable> [<replaceable>PATH</replaceable>]</term> <term>
<command>bind</command>
<replaceable>UNIT</replaceable>
<replaceable>PATH</replaceable>
[<replaceable>PATH</replaceable>]
</term>
<listitem><para>Bind-mounts a file or directory from the host into the specified unit's mount <listitem><para>Bind-mounts a file or directory from the host into the specified unit's mount
namespace. The first path argument is the source file or directory on the host, the second path namespace. The first path argument is the source file or directory on the host, the second path
@ -718,7 +726,13 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><command>mount-image</command> <replaceable>UNIT</replaceable> <replaceable>IMAGE</replaceable> [<replaceable>PATH</replaceable> [<replaceable>PARTITION_NAME</replaceable>:<replaceable>MOUNT_OPTIONS</replaceable>]]</term> <term>
<command>mount-image</command>
<replaceable>UNIT</replaceable>
<replaceable>IMAGE</replaceable>
[<replaceable>PATH</replaceable>
[<replaceable>PARTITION_NAME</replaceable>:<replaceable>MOUNT_OPTIONS</replaceable>]]
</term>
<listitem><para>Mounts an image from the host into the specified unit's mount namespace. The first <listitem><para>Mounts an image from the host into the specified unit's mount namespace. The first
path argument is the source image on the host, the second path argument is the destination path argument is the source image on the host, the second path argument is the destination
@ -1201,8 +1215,10 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><command>add-wants <replaceable>TARGET</replaceable> <replaceable>UNIT</replaceable></command></term> <term><command>add-wants <replaceable>TARGET</replaceable>
<term><command>add-requires <replaceable>TARGET</replaceable> <replaceable>UNIT</replaceable></command></term> <replaceable>UNIT</replaceable></command></term>
<term><command>add-requires <replaceable>TARGET</replaceable>
<replaceable>UNIT</replaceable></command></term>
<listitem> <listitem>
<para>Adds <literal>Wants=</literal> or <literal>Requires=</literal> <para>Adds <literal>Wants=</literal> or <literal>Requires=</literal>
@ -1428,7 +1444,10 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><command>import-environment</command> <replaceable>VARIABLE…</replaceable></term> <term>
<command>import-environment</command>
<replaceable>VARIABLE…</replaceable>
</term>
<listitem> <listitem>
<para>Import all, one or more environment variables set on the client into the systemd manager <para>Import all, one or more environment variables set on the client into the systemd manager

View File

@ -237,22 +237,19 @@ int mkdir_p_root_full(const char *root, const char *p, uid_t uid, gid_t gid, mod
if (r < 0) if (r < 0)
return r; return r;
if (path_strv_contains(subvolumes, p)) _cleanup_close_ int nfd = xopenat_full(
r = btrfs_subvol_make_fallback(dfd, bn, m); dfd, bn,
else O_DIRECTORY|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC,
r = RET_NERRNO(mkdirat(dfd, bn, m)); path_strv_contains(subvolumes, p) ? XO_SUBVOLUME : 0,
if (r == -EEXIST) m);
if (nfd == -EEXIST)
return 0; return 0;
if (r < 0) if (nfd < 0)
return r; return nfd;
if (ts == USEC_INFINITY && !uid_is_valid(uid) && !gid_is_valid(gid)) if (ts == USEC_INFINITY && !uid_is_valid(uid) && !gid_is_valid(gid))
return 1; return 1;
_cleanup_close_ int nfd = openat(dfd, bn, O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW);
if (nfd < 0)
return -errno;
if (ts != USEC_INFINITY) { if (ts != USEC_INFINITY) {
struct timespec tspec; struct timespec tspec;
timespec_store(&tspec, ts); timespec_store(&tspec, ts);

View File

@ -409,6 +409,46 @@ static int session_load_devices(Session *s, const char *devices) {
return r; return r;
} }
static int session_load_leader(Session *s, uint64_t pidfdid) {
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
int r;
assert(s);
assert(pid_is_valid(s->deserialized_pid));
assert(!pidref_is_set(&s->leader));
if (pidfdid == 0 && s->leader_fd_saved)
/* We have no pidfd id for stable reference, but the pidfd has been submitted to fdstore.
* manager_enumerate_fds() will dispatch the leader fd for us later. */
return 0;
r = pidref_set_pid(&pidref, s->deserialized_pid);
if (r < 0)
return log_error_errno(r, "Failed to deserialize leader PID for session '%s': %m", s->id);
if (pidref.fd < 0)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
"Failed to acquire pidfd for session leader '" PID_FMT "', refusing.",
pidref.pid);
if (pidfdid > 0) {
r = pidref_acquire_pidfd_id(&pidref);
if (r < 0)
return log_error_errno(r, "Failed to acquire pidfd id of deserialized leader '" PID_FMT "': %m",
pidref.pid);
if (pidref.fd_id != pidfdid)
return log_error_errno(SYNTHETIC_ERRNO(ESRCH),
"Deserialized pidfd id for process " PID_FMT " (%" PRIu64 ") doesn't match with the current one (%" PRIu64 "), refusing.",
pidref.pid, pidfdid, pidref.fd_id);
}
r = session_set_leader_consume(s, TAKE_PIDREF(pidref));
if (r < 0)
return log_error_errno(r, "Failed to set leader PID for session '%s': %m", s->id);
return 1;
}
int session_load(Session *s) { int session_load(Session *s) {
_cleanup_free_ char *remote = NULL, _cleanup_free_ char *remote = NULL,
*seat = NULL, *seat = NULL,
@ -418,6 +458,7 @@ int session_load(Session *s) {
*position = NULL, *position = NULL,
*leader_pid = NULL, *leader_pid = NULL,
*leader_fd_saved = NULL, *leader_fd_saved = NULL,
*leader_pidfdid = NULL,
*type = NULL, *type = NULL,
*original_type = NULL, *original_type = NULL,
*class = NULL, *class = NULL,
@ -452,6 +493,7 @@ int session_load(Session *s) {
"POSITION", &position, "POSITION", &position,
"LEADER", &leader_pid, "LEADER", &leader_pid,
"LEADER_FD_SAVED", &leader_fd_saved, "LEADER_FD_SAVED", &leader_fd_saved,
"LEADER_PIDFDID", &leader_pidfdid,
"TYPE", &type, "TYPE", &type,
"ORIGINAL_TYPE", &original_type, "ORIGINAL_TYPE", &original_type,
"CLASS", &class, "CLASS", &class,
@ -594,8 +636,6 @@ int session_load(Session *s) {
} }
if (leader_pid) { if (leader_pid) {
assert(!pidref_is_set(&s->leader));
r = parse_pid(leader_pid, &s->deserialized_pid); r = parse_pid(leader_pid, &s->deserialized_pid);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to parse LEADER=%s: %m", leader_pid); return log_error_errno(r, "Failed to parse LEADER=%s: %m", leader_pid);
@ -605,25 +645,19 @@ int session_load(Session *s) {
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to parse LEADER_FD_SAVED=%s: %m", leader_fd_saved); return log_error_errno(r, "Failed to parse LEADER_FD_SAVED=%s: %m", leader_fd_saved);
s->leader_fd_saved = r > 0; s->leader_fd_saved = r > 0;
if (s->leader_fd_saved)
/* The leader fd will be acquired from fdstore later */
return 0;
} }
_cleanup_(pidref_done) PidRef p = PIDREF_NULL; uint64_t pidfdid;
if (leader_pidfdid) {
r = safe_atou64(leader_pidfdid, &pidfdid);
if (r < 0)
return log_error_errno(r, "Failed to parse LEADER_PIDFDID=%s: %m", leader_pidfdid);
} else
pidfdid = 0;
r = pidref_set_pid(&p, s->deserialized_pid); r = session_load_leader(s, pidfdid);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to deserialize leader PID for session '%s': %m", s->id); return r;
if (p.fd < 0)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
"Failed to acquire pidfd for session leader '" PID_FMT "', refusing.",
p.pid);
r = session_set_leader_consume(s, TAKE_PIDREF(p));
if (r < 0)
return log_error_errno(r, "Failed to set leader PID for session '%s': %m", s->id);
} }
return 0; return 0;

View File

@ -40,6 +40,7 @@
#include "process-util.h" #include "process-util.h"
#include "service-util.h" #include "service-util.h"
#include "signal-util.h" #include "signal-util.h"
#include "stat-util.h"
#include "strv.h" #include "strv.h"
#include "terminal-util.h" #include "terminal-util.h"
#include "udev-util.h" #include "udev-util.h"
@ -448,19 +449,28 @@ static int deliver_session_leader_fd_consume(Session *s, const char *fdname, int
assert(fdname); assert(fdname);
assert(fd >= 0); assert(fd >= 0);
if (!pid_is_valid(s->deserialized_pid)) { /* Already deserialized via pidfd id? */
if (pidref_is_set(&s->leader)) {
assert(s->leader.pid == s->deserialized_pid);
assert(s->leader.fd >= 0);
r = fd_inode_same(fd, s->leader.fd);
if (r < 0)
return log_warning_errno(r, "Failed to compare pidfd with deserialized leader for session '%s': %m",
s->id);
if (r > 0)
return 0;
log_warning("Got leader pidfd for session '%s' which mismatches with the deserialized process, resetting with pidfd.",
s->id);
} else if (!pid_is_valid(s->deserialized_pid)) {
r = log_warning_errno(SYNTHETIC_ERRNO(EOWNERDEAD), r = log_warning_errno(SYNTHETIC_ERRNO(EOWNERDEAD),
"Got leader pidfd for session '%s', but LEADER= is not set, refusing.", "Got leader pidfd for session '%s', but LEADER= is not set, refusing.",
s->id); s->id);
goto fail_close; goto fail_close;
} }
if (!s->leader_fd_saved)
log_warning("Got leader pidfd for session '%s', but not recorded in session state, proceeding anyway.",
s->id);
else
assert(!pidref_is_set(&s->leader));
r = pidref_set_pidfd_take(&leader_fdstore, fd); r = pidref_set_pidfd_take(&leader_fdstore, fd);
if (r < 0) { if (r < 0) {
if (r == -ESRCH) if (r == -ESRCH)

View File

@ -191,7 +191,7 @@ static int synthesize_change(Manager *manager, sd_device *dev) {
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_safe_fork( r = pidref_safe_fork(
"(udev-synth)", "(udev-synth)",
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_REOPEN_LOG,
&pidref); &pidref);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -32,13 +32,15 @@ Environment=SYSTEMD_LOG_LEVEL=debug
EOF EOF
# We test "coldplug" (completely stop and start logind) here. So we need to preserve # We test "coldplug" (completely stop and start logind) here. So we need to preserve
# the fdstore, which might contain session leader pidfds. This is extremely rare use case # the fdstore, which might contain session leader pidfds, but only if pidfd id isn't
# and shall not be considered fully supported. # a thing. This is extremely rare use case and shall not be considered fully supported.
# See also: https://github.com/systemd/systemd/pull/30610#discussion_r1440507850 # See also: https://github.com/systemd/systemd/pull/30610#discussion_r1440507850
systemctl edit --runtime --stdin systemd-logind.service --drop-in=fdstore-preserve.conf <<EOF if systemd-analyze compare-versions "$(uname -r)" lt 6.9; then
systemctl edit --runtime --stdin systemd-logind.service --drop-in=fdstore-preserve.conf <<EOF
[Service] [Service]
FileDescriptorStorePreserve=yes FileDescriptorStorePreserve=yes
EOF EOF
fi
systemctl restart systemd-logind.service systemctl restart systemd-logind.service
} }