When mount points are stacked, bind_remount_recursive_with_mountinfo()
uses the existing mount options of the "lower" level mount (ie: the
first one that was mounted on a mount point). But the actual mount
point in use is the "top" one (ie: the last one that was mounted on a
mount point), so in practice if the mount options are different between
the layers, the bottom options are used by mistake on the top mount,
which is not what we want. This is because libmount returns the "bottom"
one first.
If the hashmap returns EEXIST, which means the same key (path) with different
value (options) is already present, update the hashmap instead of discarding
the result. This way, the last/top mount options are always used when
mounts are stacked on a mount point.
This was found to cause problems as LXC version 4.x stacks two /sys mounts,
the bottom one read-write and the top one read-only. systemd accidentally
remounts the top-one read-write, breaking various expectations since a
read-only /sys is the way we decide whether we are running in a container
or not (in this particular case, networkd tests are broken as networkd
expects to be able to modify network settings with a writable /sys).
Future versions of LXC will no longer do this double-stacking, but we
need to support running inside older versions too.
This was triggered by https://github.com/systemd/systemd/commit/6720e356c137
as that causes a recursive remount of '/', which processes '/sys' as one
of the submounts, from make_nosuid(). But it's likely that other combinations
of options could trigger this as well.
Before:
root@systemd-debug:/# systemd-run -t --wait --property ProtectSystem=yes findmnt
Running as unit: run-u9.service
Press ^] three times within 1s to disconnect TTY.
TARGET SOURCE FSTYPE OPTIONS
/ /dev/sda2[/var/lib/lxc/systemd-debug/rootfs]
│ ext4 ro,nosuid,relatime,errors=remount-ro,stripe=
├─/dev none tmpfs rw,nosuid,relatime,size=492k,mode=755
│ ├─/dev/.lxc/proc proc proc rw,nosuid,relatime
│ ├─/dev/.lxc/sys sys sysfs rw,nosuid,relatime
│ ├─/dev/console devpts[/2] devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptm
│ ├─/dev/pts devpts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptm
│ ├─/dev/ptmx devpts[/ptmx] devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptm
│ ├─/dev/tty1 devpts[/0] devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptm
│ ├─/dev/tty2 devpts[/1] devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptm
│ ├─/dev/tty3 devpts[/2] devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptm
│ ├─/dev/tty4 devpts[/3] devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptm
│ ├─/dev/shm tmpfs tmpfs rw,nosuid,nodev
│ ├─/dev/hugepages hugetlbfs hugetlbfs rw,nosuid,relatime,pagesize=2M
│ └─/dev/mqueue mqueue mqueue rw,nosuid,nodev,noexec,relatime
├─/proc proc proc rw,nosuid,nodev,noexec,relatime
│ ├─/proc/sys proc[/sys] proc ro,nosuid,nodev,noexec,relatime
│ │ ├─/proc/sys/net proc[/sys/net] proc rw,nosuid,nodev,noexec,relatime
│ │ └─/proc/sys/kernel/random/boot_id
│ │ none[/.lxc-boot-id] tmpfs ro,nosuid,nodev,noexec,relatime,size=492k,mo
│ └─/proc/sysrq-trigger proc[/sysrq-trigger] proc ro,nosuid,nodev,noexec,relatime
├─/sys sysfs sysfs rw,nosuid,nodev,noexec,relatime
│ └─/sys sysfs sysfs rw,nosuid,nodev,noexec,relatime
│ ├─/sys/devices/virtual/net sysfs sysfs rw,relatime
│ │ └─/sys/devices/virtual/net
│ │ sysfs[/devices/virtual/net] sysfs rw,nosuid,relatime
│ ├─/sys/fs/fuse/connections fusectl fusectl rw,nosuid,nodev,noexec,relatime
│ └─/sys/fs/cgroup cgroup cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate,m
├─/run tmpfs tmpfs ro,nosuid,nodev,size=4912348k,nr_inodes=8192
│ ├─/run/credentials tmpfs[/systemd/inaccessible/dir] tmpfs ro,nosuid,nodev,noexec,size=4912348k,nr_inod
│ └─/run/systemd/incoming tmpfs[/systemd/propagate/run-u9.service]
│ tmpfs ro,nosuid,nodev,size=4912348k,nr_inodes=8192
├─/tmp tmpfs tmpfs rw,nosuid,nodev,size=12280872k,nr_inodes=409
│ └─/tmp tmpfs[/systemd-private-b730df90da424397a3f246cb15dcdbb1-run-u9.service-K6EUwf/tmp]
│ tmpfs rw,nosuid,nodev,size=12280872k,nr_inodes=409
└─/var/tmp /dev/sda2[/var/lib/lxc/systemd-debug/rootfs/var/tmp/systemd-private-b730df90da424397a3f246cb15dcdbb1-run-u9.service-vEHyRi/tmp]
ext4 rw,nosuid,relatime,errors=remount-ro,stripe=
Finished with result: success
Main processes terminated with: code=exited/status=0
Service runtime: 14.249s
CPU time consumed: 37ms
After:
root@systemd-debug:/# systemd-run -t --wait --property ProtectSystem=yes findmnt
Running as unit: run-u3.service
Press ^] three times within 1s to disconnect TTY.
TARGET SOURCE FSTYPE OPTIONS
/ /dev/sda2[/var/lib/lxc/systemd-debug/rootfs]
│ ext4 rw,relatime,errors=remount-ro,stripe=32699
├─/dev none tmpfs rw,relatime,size=492k,mode=755
│ ├─/dev/.lxc/proc proc proc rw,relatime
│ ├─/dev/.lxc/sys sys sysfs rw,relatime
│ ├─/dev/console devpts[/2] devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode
│ ├─/dev/pts devpts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode
│ ├─/dev/ptmx devpts[/ptmx] devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode
│ ├─/dev/tty1 devpts[/0] devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode
│ ├─/dev/tty2 devpts[/1] devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode
│ ├─/dev/tty3 devpts[/2] devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode
│ ├─/dev/tty4 devpts[/3] devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode
│ ├─/dev/shm tmpfs tmpfs rw,nosuid,nodev
│ ├─/dev/hugepages hugetlbfs hugetlbfs rw,relatime,pagesize=2M
│ └─/dev/mqueue mqueue mqueue rw,nosuid,nodev,noexec,relatime
├─/proc proc proc rw,nosuid,nodev,noexec,relatime
│ ├─/proc/sys proc[/sys] proc ro,nosuid,nodev,noexec,relatime
│ │ ├─/proc/sys/net proc[/sys/net] proc rw,nosuid,nodev,noexec,relatime
│ │ └─/proc/sys/kernel/random/boot_id
│ │ none[/.lxc-boot-id] tmpfs ro,nosuid,nodev,noexec,relatime,size=492k,mode=75
│ └─/proc/sysrq-trigger proc[/sysrq-trigger] proc ro,nosuid,nodev,noexec,relatime
├─/sys sysfs sysfs rw,nosuid,nodev,noexec,relatime
│ └─/sys sysfs sysfs ro,nosuid,nodev,noexec,relatime
│ ├─/sys/devices/virtual/net sysfs sysfs rw,relatime
│ │ └─/sys/devices/virtual/net
│ │ sysfs[/devices/virtual/net] sysfs rw,nosuid,nodev,noexec,relatime
│ ├─/sys/fs/fuse/connections fusectl fusectl rw,nosuid,nodev,noexec,relatime
│ └─/sys/fs/cgroup cgroup cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate,memory
├─/run tmpfs tmpfs rw,nosuid,nodev,size=4912348k,nr_inodes=819200,mo
│ ├─/run/credentials tmpfs[/systemd/inaccessible/dir]
│ │ tmpfs ro,nosuid,nodev,noexec,size=4912348k,nr_inodes=81
│ └─/run/systemd/incoming tmpfs[/systemd/propagate/run-u3.service]
│ tmpfs ro,nosuid,nodev,size=4912348k,nr_inodes=819200,mo
├─/tmp tmpfs tmpfs rw,nosuid,nodev,size=12280872k,nr_inodes=409600
├─/boot /dev/sda2[/var/lib/lxc/systemd-debug/rootfs/boot]
│ ext4 ro,relatime,errors=remount-ro,stripe=32699
└─/usr /dev/sda2[/var/lib/lxc/systemd-debug/rootfs/usr]
ext4 ro,relatime,errors=remount-ro,stripe=32699
Finished with result: success
Main processes terminated with: code=exited/status=0
Service runtime: 14ms
CPU time consumed: 5ms
Host (LXC):
root@systemd-debug:/# findmnt
TARGET SOURCE FSTYPE OPTIONS
/ /dev/sda2[/var/lib/lxc/systemd-debug/rootfs]
│ ext4 rw,relatime,errors=remount-ro,stripe=32699
├─/run tmpfs tmpfs rw,nosuid,nodev,size=4912348k,nr_inodes=819200,mode=755
├─/tmp tmpfs tmpfs rw,nosuid,nodev,size=12280872k,nr_inodes=409600
├─/dev none tmpfs rw,relatime,size=492k,mode=755
│ ├─/dev/pts devpts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666,ma
│ ├─/dev/ptmx devpts[/ptmx] devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666,ma
│ ├─/dev/tty1 devpts[/0] devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666,ma
│ ├─/dev/tty2 devpts[/1] devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666,ma
│ ├─/dev/tty3 devpts[/2] devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666,ma
│ ├─/dev/tty4 devpts[/3] devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666,ma
│ ├─/dev/shm tmpfs tmpfs rw,nosuid,nodev
│ ├─/dev/hugepages hugetlbfs hugetlbfs rw,relatime,pagesize=2M
│ ├─/dev/mqueue mqueue mqueue rw,nosuid,nodev,noexec,relatime
│ ├─/dev/console devpts[/2] devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000
│ ├─/dev/.lxc/proc proc proc rw,relatime
│ └─/dev/.lxc/sys sys sysfs rw,relatime
├─/proc proc proc rw,nosuid,nodev,noexec,relatime
│ ├─/proc/sys proc[/sys] proc ro,nosuid,nodev,noexec,relatime
│ │ ├─/proc/sys/kernel/random/boot_id
│ │ │ none[/.lxc-boot-id] tmpfs ro,nosuid,nodev,noexec,relatime,size=492k,mode=755
│ │ └─/proc/sys/net proc[/sys/net] proc rw,nosuid,nodev,noexec,relatime
│ └─/proc/sysrq-trigger proc[/sysrq-trigger] proc ro,nosuid,nodev,noexec,relatime
└─/sys sysfs sysfs rw,nosuid,nodev,noexec,relatime
└─/sys sysfs sysfs ro,nosuid,nodev,noexec,relatime
├─/sys/devices/virtual/net sysfs sysfs rw,relatime
│ └─/sys/devices/virtual/net
│ sysfs[/devices/virtual/net]
│ sysfs rw,nosuid,nodev,noexec,relatime
├─/sys/fs/fuse/connections fusectl fusectl rw,nosuid,nodev,noexec,relatime
└─/sys/fs/cgroup cgroup cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recurs
Fixes https://github.com/systemd/systemd/issues/20032
This reverts commit cb0e818f7c.
After this was merged, some design and implementation issues were discovered,
see the discussion in #18782 and #19385. They certainly can be fixed, but so
far nobody has stepped up, and we're nearing a release. Hopefully, this feature
can be merged again after a rework.
Fixes#19345.
Parse address family, ip protocol and ports, any of them can be
optional. If neither is specified, a special value 'any' is expected.
Helper is placed in shared to be reused in both fragment and dbus.
Add unit tests with valid and invalid examples.
Thin wrappers of ip_protocol_{from|to}_name targeting IPPROTO_TCP and
IPPROTO_UDP only.
Used to parse IP protocol configuration restricted only to TCP and UDP,
e.g. in SocketBind{Allow|Deny}= unit property.
These helpers are inspired by af_{from|to}_ipv4_ipv6 and potentially
extendable with other IP protocols if there is a use-case to expose
them.
This fixes repart's, systemctl's, sysusers' and tmpfiles' specifier
expansion to honour the root dir specified with --root=. This is
relevant for specifiers such as %m, %o, … which are directly sourced
from files on disk.
This doesn't try to be overly smart: specifiers referring to runtime
concepts (i.e. boot ID, architecture, hostname) rather than files on the
medium are left as is. There's certainly a point to be made that they
should fail in case --root= is specified, but I am not entirely convinced
about that, and it's certainly something we can look into later if
there's reason to.
I wondered for a while how to hook this up best, but given that quite a
large number of specifiers resolve to data from files on disks, and most
of our tools needs this, I ultimately decided to make the root dir a
first class parameter to specifier_printf().
Replaces: #16187Fixes: #16183
The approach with function pointer was neat, but it gets in the way
when we want to resolve the symbol dynamically: static initialization
is not possible. It also makes the code more complicated than necessary.
In this case, a simple boolean is sufficient.
We warn when the operation fails, not when it succeeds. Hence this should be
"<do>_or_<handle failure>", not "<do>_and_<handle failure>". We *could* use
whatever convention we want, but rust and perl are rather consistent in using
the logical convention. We don't care about perl that much, but having a naming
convention inverted wrt. rust would be rather confusing.
Also, pretty much every implementation does similar steps, so add a nice
wrapper which combines opening of the library and loading of the symbols.
Also add missing sentinel attribute in dlopen_or_warn().
The goal is to move everything that requires selinux or smack
away from src/basic/. This means that src/basic/label.[ch] must move,
which implies btrfs-util.[ch], copy.[ch], and a bunch of other files
which form a cluster of internal use.
This is just moving text around, so there should be no functional difference.
test-blockdev-util is new, because path_is_encrypted() is moved to
blockdev-util.c, and so far we didn't have any tests for code there.
This was added in 88d775b734,
with the apparent intent of using in shared/ and the rest of our code.
It doesn't matter much for our code, since libdl is part of glibc anyway,
but moving it removes one linkage from libsystemd. (libshared was already
linking to libdl explicitly).
This is useful for provisioning initially empty secondary A/B root file
systems. We don't want those to ever be considered for automatic
mounting, for example in "systemd-nspawn --image=", hence we should
create them with the No-Auto flag turned on. Once a file system image is
dropped into the partition the flag may be turned off by the updater
tool, so that it is considered from then on.
Thew new option for this is called NoAuto. I dislike negated options
like this, but this is taken from the naming in the spec, which in turn
inherited the name from the same flag for Microsoft Data Partitions. To
minimize confusion, let's stick to the name hence.
Support filtering by ip protocol (L4) in SocketBind{Allow|Deny}=
properties.
The signature of dbus methods must be finalized before new release is
cut, hence reserve a parameter for ip protocol.
Implementation will follow.
Closes https://github.com/systemd/systemd/issues/19891
Creating those string dynamically at runtime is slow and unnecessary.
Let's use static strings with a bit of macro magic and the let the compiler
coalesce as much as possible.
$ size build/src/shared/libsystemd-shared-248.so{.old,}
text data bss dec hex filename
2813453 94572 4584 2912609 2c7161 build/src/shared/libsystemd-shared-248.so.old
2812309 94564 4584 2911457 2c6ce1 build/src/shared/libsystemd-shared-248.so
A nice side-effect is that the same form is used everywhere, so it's easier to
figure out all variables that are used, and where each specific variable is
used.
C.f. 2b0445262a.
Note: 'const char *foo = alloca(…);' seems OK. Our coding style document and
alloca(3) only warn against using alloca() in function invocations. Declaring
both stack variable and alloca at the same time should be fine: no matter in
which order they happen, i.e. if the pointer variable is above the contents,
or the contents are above the pointer, or even if the pointer is elided by the
compiler, everything should be fine.
In the light of https://lwn.net/Articles/859679/ let's drop
quotactl_path() again from the filter set list, as it got backed out
again in 5.13-rc3.
It's likely going to be replaced by quotactl_fd() eventually, but that
hasn't made its way into the tree yet, hence let's not replace the entry
for now.
This partially reverts 34254e599a.
Debugging udev issues especially during the early boot is fairly
difficult. Currently, you need to enable (at least) debug logging and
start monitoring uevents, try to reproduce the issue and then analyze
and correlate two (usually) huge log files. This is not ideal.
This patch aims to provide much more focused debugging tool,
tracepoints. More often then not we tend to have at least the basic idea
about the issue we are trying to debug further, e.g. we know it is
storage related. Hence all of the debug data generated for network
devices is useless, adds clutter to the log files and generally
slows things down.
Using this set of tracepoints you can start asking very specific
questions related to event processing for given device or subsystem.
Tracepoints can be used with various tracing tools but I will provide
examples using bpftrace.
Another important aspect to consider is that using tracepoints you can
debug production systems. There is no need to install test packages with
added logging, no debuginfo packages, etc...
Example usage (you might be asking such questions during the debug session),
Q: How can I list all tracepoints?
A: bpftrace -l 'usdt:/usr/lib/systemd/systemd-udevd:udev:*'
Q: What are the arguments for each tracepoint?
A: Look at the code and search for use of DEVICE_TRACE_POINT macro.
Q: How many times we have executed external binary?
A: bpftrace -e 'usdt:/usr/lib/systemd/systemd-udevd:udev:spawn_exec { @cnt = count(); }'
Q: What binaries where executed while handling events for "dm-0" device?
A bpftrace -e 'usdt:/usr/lib/systemd/systemd-udevd:udev:spawn_exec / str(arg1) == "dm-0"/ { @cmds[str(arg4)] = count(); }'
Thanks to Thomas Weißschuh <thomas@t-8ch.de> for reviewing this patch
and contributions that allowed us to drop the dependency on dtrace tool
and made the resulting code much more concise.
When we have a unit which cannot be enabled:
# foo@.service:
...
[Install]
WantedBy=foo.target # there is no instance, so we don't know what to enable
we should throw an error when invoked directly with 'enable', but
not when doing 'preset' or 'preset-all'.
Fixes#19856.