tmpfiles attempts to correct the label of a file during various actions
via the function fd_set_perms(). Currently, said function generally
respects the dry-run mode. However, it attempts to fix the label of a
given file regardless of the state of said dry-run mode.
This causes problems, because a user could attempt to run tmpfiles with
elevated permissions and dry run enabled, expecting the tool to not
modify their system. Instead, tmpfiles would falsely relabel a file,
modifying their system.
This commit explicitly checks for when dry-run is enabled and skips the
file relabelling process. Furthermore, I added logging for both cases.
I found helpful during debugging. That said, I don't think it's
necessary to use the level LOG_INFO on the dry-run path, as it would
always produce an info log.
This reverts commit 490aa05ca1.
As commented https://github.com/systemd/systemd/pull/38569#discussion_r2284978273,
the commit makes autofs check bypassed. Before the commit, when
CHASE_NO_AUTOFS is set, we did not shortcut chasing paths, and refused
any autofs mount points in the path. However, with the commit, the flag
was swapped but even when CHASE_AUTOFS is unset, the autofs check may be
skipped.
To fix the issue, rather than swapping the flag, we should introduce
another flag, say CHASE_TRIGGER_AUTOFS. This revert the commit, and in a
later commit, the new flag will be introduced.
Since c5de7b14ae
file searching implies a new mount api syscall by default,
to trigger automounts.
This is problematic in NSS plugins, as they are dlopen'ed inside
processes by glibc, for two reasons.
First of all, potentially searching on a networked filesystem
automount could lead to nasty surprises, such as the process
responsible for setting up the network filesystem trying to
search on that same filesystem.
More importantly, the new mount api syscall was never part of
the filesystem seccomp filter that we provide by default, and
given mounting/remounting/bind mounting is one of the possible
ways to bypass sandboxing it is very likely not allowed when
custom filters are used in sandboxed processes, if they don't
need to do these operations otherwise.
The filesystem seccomp mask we provide has been updated, however
this only takes effect on the next restart of a service. When
systemd is upgraded via a package upgrade, the new nss plugin is
installed and will be immediately dlopen'ed by glibc when needed,
without waiting for the process to restart, which means the existing
seccomp filter applies, causing the filter to trigger.
Given it's not really possible for any arbitrary program to
predict which NSS modules glibc will load, given programs do not
configure that and instead nsswitch is set up by the sysadmin,
it's impossible to handle at each process level. It's also not
possible to know when it will be triggered, given the plugin
is not linked in each binary tools like need-restart cannot
even pre-emptively restart services that may be affected.
This means in practice, upgrading from systemd << v258 to >= v258
requires a reboot to avoid either subtle or catastrophic system
failures.
By avoiding to trigger automounts in nss-systemd we can avoid
both issues.
userdb drop-ins are searched for in:
/etc/userdb/
/run/userdb/
/run/host/userdb/
/usr/local/lib/userdb/
/usr/lib/userdb/
none of which are supported as automounts anyway.
Note that this happens only when the userdbd service is not running,
as otherwise nss-systemd will go through the varlink IPC, rather than
doing the searches in-process.
So invert CHASE_NO_AUTOFS to CHASE_AUTOFS and set it in the places where
we do want to trigger automounts, like looking for the ESP.
Follow-up for c5de7b14ae
Fixes https://github.com/systemd/systemd/issues/38565
Then, move syscall definitions to the wrapper, and prototypes are moved
to relevant headers.
This also adds checks for add_key() and request_key(), as one day
glibc may be going to add some of them separatedly.
The check for fspick in meson.build is dropped, as it is currently
unused in our code.
This also moves
- basic/missing_bpf.h -> include/override/linux/bpf.h,
- basic/missing_keyctl.h -> include/override/linux/keyctl.h.
The additional definitions provided by the header are
- EXT4_IOC_RESIZE_FS, used in resize-fs.c,
- FILEID_KERNFS, used in cgroup-util.c and pidfd-util.c.
Let's drop the inclusion at other places.
Currently, callers of safe_glob() set an empty glob_t or glob_t with
opendir func, and all other components are always zero.
So, let's introduce safe_glob_full() which optionally takes opendir
function, rather than glob_t, and returns result strv, rather than
storing results in glob_t.
Also, introduce safe_glob() which is a trivial wrapper of
safe_glob_full() without opendir func.
No functional change, just refactoring.
When we remove an existing inode in order to create a symlink we need to
create the symlink via a pinned directory again, instead of using an
absolute path, otherwise this will not work in the --root= case.
Let's fix this, and switch this over to symlinkat_atomic_full().
More porting work to label_ops_pre()/label_ops_post()
This also enables labelling of the /etc/localtime symlink in
systemd-firstboot, which should address one small facet of #37857
git grep -l 'Failed to open /'|xargs sed -r -i 's|"Failed to open (/[^ ]+): %m"|"Failed to open %s: %m", "\1"|g'
git grep -l $'Failed to open \'/'|xargs sed -r -i $'s|"Failed to open \'(/[^ ]+)\': %m"|"Failed to open %s: %m", "\\1"|g'
git grep -l "Failed to open /"|xargs sed -r -i $'s|"Failed to open (/[^ ]+), ignoring: %m"|"Failed to open %s, ignoring: %m", "\\1"|g'
+ some manual fixups.
F2FS returns EINVAL from FS_IOC_SETFLAGS when trying to set
FS_NOCOW_FL. Let's handle this by treating EINVAL as not supported.
While we're at it, make sure we use ERRNO_IS_IOCTL_NOT_SUPPORTED()
across the tree instead of ERRNO_IS_NOT_SUPPORTED() when calling any
of the chattr_xxx() functions.
Fixes#37593
These are built from the same sources as the regular binaries, so we
end up with the same sources multiple times in the compilation database
but with different command line arguments, which trips up tooling that
uses the compilation database. Let's not define the standalone targets if
the option is not enabled to avoid this problem.
Also, let's deflatten the lists of sources in preparation for the
next commit at the same time.
In systemctl, we split out systemctl-main.c to make sure the definition
of main() is in a separate object which allows us to extract the systemctl.c
object and link it in the fuzzer target without getting a multiple definition
error when linking.
This commit cleans up the includes for all the small tools across
the tree.
A few cases of returning EXIT_SUCCESS are replaced with returning
0 to avoid including <stdlib.h>.
Split out of #37344.
Currently, when we want to add unit tests for code that is compiled into
an executable, we either compile the code at least twice (once for the
executable, and once for each test that uses it) or we create a static
library which is then used by both the executable and all the tests.
Both of these options are not ideal, compiling source files more than
once slows down the build for no reason and creating the intermediate
static libraries takes a lot of boilerplate.
Instead, let's use the extract_objects() method that meson exposes on
build targets. This allows us to extract the objects corresponding to
specific source files and use them in other executables. Because we
define all executables upfront into a dictionary, we integrate this into
the dictionary approach by adding two new fields:
- 'extract' takes a list of files for which objects should be extracted.
The extracted objects are stored in a dict keyed by the executable name
from which they were extracted.
- 'objects' takes the name of an executable from which the extracted
objects should be added to the current executable.
One side effect of this approach is that we can't build test executables
anymore without building the main executable, so we stop building test
executables unless we're also building the main executable. This allows
us to switch to using subdir_done() in all of these subdirectories to skip
parsing them if the corresponding component is disabled.
These changes get me down from 2439 => 2403 ninja targets on a full rebuild
from scratch.
Now that the necessary functions from log.h have been moved to macro.h,
we can stop including log.h in macro.h. This requires modifying source
files all over the tree to include log.h instead.
Admittedly, some of our glyphs _are_ special, e.g. "O=" for SPECIAL_GLYPH_TOUCH ;)
But we don't need this in the name. The very long names make some invocations
very wordy, e.g. special_glyph(SPECIAL_GLYPH_SLIGHTLY_UNHAPPY_SMILEY).
Also, I want to add GLYPH_SPACE, which is not special at all.
To resolve conflict with sys/mount.h and linux/mount.h or linux/fs.h.
The conflict between sys/mount.h and linux/mount.h is resolved in
glibc-2.37 (774058d72942249f71d74e7f2b639f77184160a6), but our baseline
is still glibc-2.31. Also, even with the version or newer, still
sys/mount.h conflicts with linux/fs.h, which is included by
linux/btrfs.h.
This introduces our own implementation of sys/mount.h, that can be
simultaneously included with linux/mount.h and linux/fs.h. This also
imports linux/fs.h, linux/mount.h, and several other dependent headers.
The introduced sys/mount.h header itself may not be enough simple, but
by using the header, we can drop most of workarounds in other source files.
When we're building ParticleOS images, we don't want the package
manager (or mkosi) to run systemd-sysusers, systemd-tmpfiles or
systemctl preset so let's add a few more bypass environment
variables that we can set to have execution of these skipped like
we already have $SYSTEMD_HWDB_UPDATE_BYPASS and $KERNEL_INSTALL_BYPASS.
struct statx in glibc header was introduced in glibc-2.28
(fd70af45528d59a00eb3190ef6706cb299488fcd), but at that time,
sys/stat.h conflicts with linux/stat.h. Since glibc-2.30
(5dad6ffbb2b76215cfcd38c3001778536ada8e8a), sys/stat.h includes
linux/stat.h if exists.
Since now our baseline of glibc is 2.31. Hence, we can drop workarounds
for struct statx by importing linux/stat.h from newer kernel (v6.14-rc4).
We printed:
systemd-tmpfiles[705]: /usr/lib/tmpfiles.d/20-systemd-shell-extra.conf:10: Unknown modifiers in command 'L$'.
systemd-tmpfiles[705]: /usr/lib/tmpfiles.d/systemd-network.conf:10: Unknown modifiers in command 'd$'.
systemd-tmpfiles[705]: /usr/lib/tmpfiles.d/systemd-network.conf:11: Unknown modifiers in command 'd$'.
...
There's a lot of additional characters here make the message harder to parse. We know
that the command is a word without any whitespace, so quoting isn't really necessary.
Change this to:
... unknown modifiers in command: L$
This allows a single tmpfiles snippet with lines to symlink directories
from /usr/share/factory to be shared across many different configurations
while making sure symlinks only get created if the source actually exists.
xdg_user_dirs() doesn't seem well-organized currently.
In all other xdg_user_*() funcs we assume /etc/xdg/systemd
to be a symlink to /etc/systemd/, hence it is the odd one out.
Also, when the relevant envvar is unset, it only returns
the global search dirs.
sd_path_lookup() actually covers this nicely with SD_PATH_SEARCH_*,
where the combined search paths (from user home and system) are used.
Therefore, let's introduce a wrapper for that, and deprecate xdg_user_dirs()
(would be removed in later commits).
Our variables for internal libraries are named 'libfoo' for the shared lib
variant, and 'libfoo_static' for the static lib variant. The only exception was
libbasic, because we didn't have a shared variant for it. But let's rename it
for consitency. This makes the build config easier to understand.
This adds %q, %A and %M specifiers to tmpfiles:
- %A and %M were previously added to tmpfiles.d man page, but not to specifier_table
- %q is added via COMMON_SYSTEM_SPECIFIERS