Behaviour is not identical, as shown by the tests in test-strv.
The combination of EXTRACT_UNQUOTE without EXTRACT_RELAX only appears in
the test, so it doesn't seem particularly important. OTOH, the difference
in handling of squished parameters could make a difference. New behaviour
is what both bash and python do, so I think we can ignore this corner case.
This change has the following advantages:
- the duplication of code paths that do a very similar thing is removed
- extract_one_word() / strv_split_extract() return a proper error code.
This tries to address the "bind"/"unbind" uevent kernel API breakage, by
changing the semantics of device tags.
Previously, tags would be applied on uevents (and the database entries
they result in) only depending on the immediate context. This means that
if one uevent causes the tag to be set and the next to be unset, this
would immediately effect what apps would see and the database entries
would contain each time. This is problematic however, as tags are a
filtering concept, and if tags vanish then clients won't hence notice
when a device stops being relevant to them since not only the tags
disappear but immediately also the uevents for it are filtered including
the one necessary for the app to notice that the device lost its tag and
hence relevance.
With this change tags become "sticky". If a tag is applied is once
applied to a device it will stay in place forever, until the device is
removed. Tags can never be removed again. This means that an app
watching a specific set of devices by filtering for a tag is guaranteed
to not only see the events where the tag is set but also all follow-up
events where the tags might be removed again.
This change of behaviour is unfortunate, but is required due to the
kernel introducing new "bind" and "unbind" uevents that generally have
the effect that tags and properties disappear and apps hence don't
notice when a device looses relevance to it. "bind"/"unbind" events were
introduced in kernel 4.12, and are now used in more and more subsystems.
The introduction broke userspace widely, and this commit is an attempt
to provide a way for apps to deal with it.
While tags are now "sticky" a new automatic device property
CURRENT_TAGS is introduced (matching the existing TAGS property) that
always reflects the precise set of tags applied on the most recent
events. Thus, when subscribing to devices through tags, all devices that
ever had the tag put on them will be be seen, and by CURRENT_TAGS it may
be checked whether the device right at the moment matches the tag
requirements.
See: #7587#7018#8221
The parent process may not perform any label operation, so the
database might not get updated on a SELinux policy change on its own.
Reload the label database once on a policy change, instead of n times
in every started child.
Similarly to "setup" vs. "set up", "fallback" is a noun, and "fall back"
is the verb. (This is pretty clear when we construct a sentence in the
present continous: "we are falling back" not "we are fallbacking").
Fixed below systemd codesonar warning.
isprint() is invoked here with an argument of signed
type char, but only has defined behavior for int arguments that are
either representable as unsigned char or equal to the value
of macro EOF(-1).
As per codesonar report, in a number of libc implementations, isprint()
function implemented using lookup tables (arrays): passing in a
negative value can result in a read underrun.
When the kernel does not provide a modalias, we generate our own for usb devices.
For some reason, we generated the expected usb:vXXXXpYYYY string, suffixed by "*".
It was added that way already in 796b06c21b, but I
think that was a mistake, and Kay was thinking about the match pattern instead
of the matched string.
For example, for a qemu device:
old: "usb:v0627p0001*"
new: "usb:v0627p0001:QEMU USB Tablet"
On the match side, all hwdb files in the wild seem to be using match patterns
with "*" at the end. So we can add more stuff to our generated modalias with
impunity.
This will allow more obvious and more certain matches on USB devices. In
principle the vendor+product id should be unique, but it's only 8 digits, and
there's a high chance of people getting this wrong. And matching the wrong
device would be quite problematic. By including the name in the match string we
make a mismatch much less likely.
E.g. udevadm test prints "Invalid inotify descriptor." which is
meaningless without any context. I think it should be OK to call udev_watch_end()
from a cleanup path without any warning (even at debug level).
There is no reason to consider this wrong. In fact one could argue that +=
is more appropriate, because we always add to options, and not replace previous
assignments. If we output a debug message, we implicitly ask people to "fix" this,
and we shouldn't.
Also, all our rules use += right now.
Let's add a catalog entry explaining further details.
Most importantly though: talk to PID 1 directly, via the private D-Bus
socket, so that this actually works correctly during early boot, where
D-Bus is not around.
All devices behind a SPI controller have the same udev ID_PATH property.
This is a problem for predicable network names for CAN controllers.
CAN controllers, in contrast to Ethernet controllers, don't have a MAC
Address, so there's no way to tell two CAN controllers on the same SPI
host controller apart:
$ udevadm info /sys/class/net/can0
P: /devices/platform/soc/fe204000.spi/spi_master/spi0/spi0.1/net/can0
L: 0
E: DEVPATH=/devices/platform/soc/fe204000.spi/spi_master/spi0/spi0.1/net/can0
E: INTERFACE=can0
E: IFINDEX=3
E: SUBSYSTEM=net
E: USEC_INITIALIZED=11187199
E: ID_PATH=platform-fe204000.spi
E: ID_PATH_TAG=platform-fe204000_spi
E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/can0
E: TAGS=:systemd:
$ udevadm info /sys/class/net/can1
P: /devices/platform/soc/fe204000.spi/spi_master/spi0/spi0.0/net/can1
L: 0
E: DEVPATH=/devices/platform/soc/fe204000.spi/spi_master/spi0/spi0.0/net/can1
E: INTERFACE=can1
E: IFINDEX=4
E: SUBSYSTEM=net
E: USEC_INITIALIZED=11192211
E: ID_PATH=platform-fe204000.spi
E: ID_PATH_TAG=platform-fe204000_spi
E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/can1
E: TAGS=:systemd:
With this the chip select number is added to the ID_PATH, to make
predictable network names possible.
$ sudo udevadm info /sys/class/net/can0
P: /devices/platform/soc/fe204000.spi/spi_master/spi0/spi0.1/net/can0
L: 0
E: DEVPATH=/devices/platform/soc/fe204000.spi/spi_master/spi0/spi0.1/net/can0
E: INTERFACE=can0
E: IFINDEX=3
E: SUBSYSTEM=net
E: USEC_INITIALIZED=11187199
E: ID_PATH=platform-fe204000.spi-cs-1
E: ID_PATH_TAG=platform-fe204000_spi-cs-1
E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/can0
E: TAGS=:systemd:
$ sudo udevadm info /sys/class/net/can1
P: /devices/platform/soc/fe204000.spi/spi_master/spi0/spi0.0/net/can1
L: 0
E: DEVPATH=/devices/platform/soc/fe204000.spi/spi_master/spi0/spi0.0/net/can1
E: INTERFACE=can1
E: IFINDEX=4
E: SUBSYSTEM=net
E: USEC_INITIALIZED=11192211
E: ID_PATH=platform-fe204000.spi-cs-0
E: ID_PATH_TAG=platform-fe204000_spi-cs-0
E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/can1
E: TAGS=:systemd:
Prompted by the discussion on #16110, let's migrate more code to
fd_wait_for_event().
This only leaves 7 places where we call into poll()/poll() directly in
our entire codebase. (one of which is fd_wait_for_event() itself)
poll() sets POLLNVAL inside of the poll structures if an invalid fd is
passed. So far we generally didn't check for that, thus not taking
notice of the error. Given that this specific kind of error is generally
indication of a programming error, and given that our code is embedded
into our projects via NSS or because people link against our library,
let's explicitly check for this and convert it to EBADF.
(I ran into a busy loop because of this missing check when some of my
test code accidentally closed an fd it shouldn't close, so this is a
real thing)
On systemd systems we generally don't need to chdir() to root, we don't
need to setup /dev/ ourselves (as PID 1 does that during earliest boot),
and we don't need to set the OOM adjustment values, as that's done via
unit files.
Hence, drop this. if people want to use udev from other init systems
they should do this on their own, I am very sure it's a good thing to do
it from outside of udevd, so that fewer privileges are required by udevd. In
particular the dev_setup() stuff is something that people who build
their own non-systemd distros want to set up themselves anyway, in
particular as they already have to mount devtmpfs themselves anyway.
Note that this only drops stuff that isn't really necessary for testing
stuff, i.e. process properties and settings that don't matter if you
quickly want to invoke udev from a terminal session to test something.
To make Driver= in [Match] section work in containers.
Note that ID_NET_DRIVER= property in udev database is set with the
result of the ethtool. So, this should not change anything for
non-container cases.
Closes#15678.
This is a follow-up for 9f83091e3c.
Instead of reading the mtime off the configuration files after reading,
let's do so before reading, but with the fd we read the data from. This
is not only cleaner (as it allows us to save one stat()), but also has
the benefit that we'll detect changes that happen while we read the
files.
This also reworks unit file drop-ins to use the common code for
determining drop-in mtime, instead of reading system clock for that.
Since the separate binaries contain mostly the same code,
this almost halves the size of the installation.
before:
398K /bin/udevadm
391K /lib/systemd/systemd-udevd
after:
431K /bin/udevadm
0 /lib/systemd/systemd-udevd -> ../../bin/udevadm
Fixes: #14200
if someone implements https://systemd.io/BLOCK_DEVICE_LOCKING/ then we
shouldn't loudly complain about that.
This reverts back to the original behaviour from
3ebdb81ef088afd3b4c72b516beb5610f8c93a0d: when the lock is taken we
silently skip processing the device and sending out the messages for it.
ATA devices should use the ATA ids like port number and (possibly)
master/slave or multiplier id, not the generic SCSI ID.
Currently only port number is included in the link. With this patch
the link would be able to support more cases, which are a) when the
device is behind a port multiplexer b) the distinction between master
and slave (distinguished by target id).
I tried to verify scenario a) with this patch, but I failed to find a
machine with PMP SATA devices attached. But the link below
https://github.com/systemd/systemd/issues/3943
could show what's the difference. Here is my test for scenario b)
Current version:
linux-ql21:~ # ll /sys/class/block/sd[ab]
lrwxrwxrwx 1 root root 0 May 8 20:46 /sys/class/block/sda ->
../../devices/pci0000:00/0000:00:01.1/ata4/host3/target3:0:0/3:0:0:0/block/sda
lrwxrwxrwx 1 root root 0 May 8 20:46 /sys/class/block/sdb ->
../../devices/pci0000:00/0000:00:01.1/ata4/host3/target3:0:1/3:0:1:0/block/sdb
linux-ql21:~ # ll /dev/disk/by-path/pci-0000\:00\:01.1-ata-1
lrwxrwxrwx 1 root root 9 May 8 20:44
/dev/disk/by-path/pci-0000:00:01.1-ata-1 -> ../../sdb
linux-ql21:~ # udevadm info /sys/class/block/sda |grep by-path
S: disk/by-path/pci-0000:00:01.1-ata-1
E: DEVLINKS=/dev/disk/by-id/ata-VBOX_HARDDISK_VB3649e885-3e0cdd64
/dev/disk/by-id/scsi-0ATA_VBOX_HARDDISK_VB3649e885-3e0cdd64
/dev/disk/by-id/scsi-1ATA_VBOX_HARDDISK_VB3649e885-3e0cdd64
/dev/disk/by-path/pci-0000:00:01.1-ata-1
/dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VB3649e885-3e0cdd64
linux-ql21:~ # udevadm info /sys/class/block/sdb |grep by-path
S: disk/by-path/pci-0000:00:01.1-ata-1
E: DEVLINKS=/dev/disk/by-id/ata-VBOX_HARDDISK_VBc53b2498-d84ae8de
/dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VBc53b2498-d84ae8de
/dev/disk/by-id/scsi-1ATA_VBOX_HARDDISK_VBc53b2498-d84ae8de
/dev/disk/by-id/scsi-0ATA_VBOX_HARDDISK_VBc53b2498-d84ae8de
/dev/disk/by-path/pci-0000:00:01.1-ata-1
After patch applied:
linux-ql21:~ # ll /sys/class/block/sd[ab]
lrwxrwxrwx 1 root root 0 May 8 21:07 /sys/class/block/sda ->
../../devices/pci0000:00/0000:00:01.1/ata4/host3/target3:0:0/3:0:0:0/block/sda
lrwxrwxrwx 1 root root 0 May 8 21:07 /sys/class/block/sdb ->
../../devices/pci0000:00/0000:00:01.1/ata4/host3/target3:0:1/3:0:1:0/block/sdb
linux-ql21:~ # ll /dev/disk/by-path/pci-0000\:00\:01.1-ata-*
lrwxrwxrwx 1 root root 9 May 8 21:07
/dev/disk/by-path/pci-0000:00:01.1-ata-1.0 -> ../../sda
lrwxrwxrwx 1 root root 9 May 8 21:07
/dev/disk/by-path/pci-0000:00:01.1-ata-1.1 -> ../../sdb
linux-ql21:~ # udevadm info /sys/class/block/sda |grep by-path
S: disk/by-path/pci-0000:00:01.1-ata-1.0
E: DEVLINKS=/dev/disk/by-id/scsi-1ATA_VBOX_HARDDISK_VB3649e885-3e0cdd64
/dev/disk/by-id/scsi-0ATA_VBOX_HARDDISK_VB3649e885-3e0cdd64
/dev/disk/by-id/ata-VBOX_HARDDISK_VB3649e885-3e0cdd64
/dev/disk/by-path/pci-0000:00:01.1-ata-1.0
/dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VB3649e885-3e0cdd64
linux-ql21:~ # udevadm info /sys/class/block/sdb |grep by-path
S: disk/by-path/pci-0000:00:01.1-ata-1.1
E: DEVLINKS=/dev/disk/by-id/scsi-0ATA_VBOX_HARDDISK_VBc53b2498-d84ae8de
/dev/disk/by-id/ata-VBOX_HARDDISK_VBc53b2498-d84ae8de
/dev/disk/by-id/scsi-1ATA_VBOX_HARDDISK_VBc53b2498-d84ae8de
/dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VBc53b2498-d84ae8de
/dev/disk/by-path/pci-0000:00:01.1-ata-1.1
Changelog:
v5: add another parameter compat_link in handle_scsi()
v4: comment for ID_PATH_ATA_COMPAT
get string length with pointer difference
(suggested by Franck Bui<fbui@suse.com>)
v3: creating compatible link from env
variables type change
v2: remove udev rules modification for compatible link
setup a test scenario of master/slave ATA devices
v1: initial patch
And do not use it in the IMPORT{cmdline} udev code. Wherever we expose
direct interfaces to check the kernel cmdline, let's not consult our
systemd-specific EFI variable, but strictly use the actual kernel
variable, because that's what we claim we do. i.e. it's fine to use the
EFI variable for our own settings, but for the generic APIs to the
kernel cmdline we should not use it.
Specifically, this applies to IMPORT{cmdline} and
ConditionKernelCommandLine=. In the latter case we weren#t checking the
EFI variable anyway, hence let's do the same for the udev case, too.
Fixes: #15739
This is a security feature, and we thus shouldn't derive the random MACs
from a potentially guessable source. MAC addresses are after all facing
to the outside, and can be interacted with from untrusted environments.
Hence, let's generate them the same way as we generate UUIDs: from
getrandom() or /dev/urandom, and optionally with RDRAND if that's
supported.
RDRAND should be fine, since this is not cryptographic key material, but
ultimately public information. We just want to make sure conflicts are
not likely.
Previously we'd generate the MACs via rand(), which means given the
short seed they are a little bit too guessable, making collisions too
likely. See #14355 in particular.
Fixes: #14355
(Note that #14355 was already fixed by
a0f11d1d11, but I think we should do
better even, and not rely on rand() and uninitialized random pools)
When setting flow control attributes of an interface we first acquire
the current settings and then add in the new settings before applying
them again. This only works on interfaces that implement the ethtool
ioctls. on others we'll see an ugly "Could not set flow control of"
message, simply because we issue the SIOCETHTOOL ioctl once, for getting
the data. In particular we'll get it for the "lo" interface all the
time, which sucks hard. Let's get rid of it.
Prompted by the discussions in #15180.
This is a bit more complex than I hoped, since for PID 1 we need to pass
in the synethetic environment block in we generate on demand.
We always need to make them unions with a "struct cmsghdr" in them, so
that things properly aligned. Otherwise we might end up at an unaligned
address and the counting goes all wrong, possibly making the kernel
refuse our buffers.
Also, let's make sure we initialize the control buffers to zero when
sending, but leave them uninitialized when reading.
Both the alignment and the initialization thing is mentioned in the
cmsg(3) man page.
If we're using a set with _put_strdup(), most of the time we want to use
string hash ops on the set, and free the strings when done. This defines
the appropriate a new string_hash_ops_free structure to automatically free
the keys when removing the set, and makes set_put_strdup() and set_put_strdupv()
instantiate the set with those hash ops.
hashmap_put_strdup() was already doing something similar.
(It is OK to instantiate the set earlier, possibly with a different hash ops
structure. set_put_strdup() will then use the existing set. It is also OK
to call set_free_free() instead of set_free() on a set with
string_hash_ops_free, the effect is the same, we're just overriding the
override of the cleanup function.)
No functional change intended.
Let's be extra careful whenever we return from recvmsg() and see
MSG_CTRUNC set. This generally means we ran into a programming error, as
we didn't size the control buffer large enough. It's an error condition
we should at least log about, or propagate up. Hence do that.
This is particularly important when receiving fds, since for those the
control data can be of any size. In particular on stream sockets that's
nasty, because if we miss an fd because of control data truncation we
cannot recover, we might not even realize that we are one off.
(Also, when failing early, if there's any chance the socket might be
AF_UNIX let's close all received fds, all the time. We got this right
most of the time, but there were a few cases missing. God, UNIX is hard
to use)
The function sd_device_get_property_value has some paths where it exits without
touching the n pointer. In those cases, n remained uninitialized until it was
eventually read inside isempty where it caused the segmentation fault.
Fixes#15078
The names with multiple lowercase words run together are hard to read. We
started that way with very short names like rootprefix, but then same pattern
was applied to longer and longer names. Looking at the body of .pc files
available on my machine, many packages use underscores; let's do the same. Old
names are kept for compatiblity, so this is backwards compatible.
Up to now each uevent logs the following things at debug level:
- Device is queued
- Processing device
- Device processed
However when the device is queued it might still have to wait for
earlier devices to be processed before being able to start being
processed itself. When analysing logs this dependency information is
quite cruicial, so add respective debug log calls.
Add SECLABEL{selinux}="some value" cause udevadm crash
systemd-udevd[x]: Worker [x] terminated by signal 11 (SEGV)
It happens since 25de7aa7b9 (Yu Watanabe 2019-04-25 01:21:11 +0200)
when udev rules processing changed to token model. Yu forgot store
attr to SECLABEL token so fix it.
Where we have a device that looks like a mouse and is connected over i2c, tag
it as pointing stick. There is no such thing as a i2c mouse.
Even touchpads that aren't recognized by the kernel will not show up as i2c
mouse - either the touchpad follows the Win8.1 specs in which case the kernel
switches it to multitouch mode and it shows up like a touchpad. The built-in
trackpoint, if any, is then the i2c mouse device.
Where the touchpad doesn't follow the spec, the kernel will not handle it and
the touchpad remains on the PS/2 legacy bus - not i2c. Hence we can assume
that any i2c mouse device is really a pointing stick.
If the peripheral device type is that of a host managed zone block device (0x14),
the device supports the same identification mechanisms as conventional disks (0x00).
Two releases ago we started warning about this, and I think it is now to turn
this into a hard error. People get bitten by this every once in a while, and
there doesn't see to be any legitimate use case where the same .link or
.network files should be applied to _all_ interfaces, since in particular that
configuration would apply both to lo and any other interfaces. And if for
whatever reason that is actually desired, OriginalName=* or Name=* can be
easily added to silence the warning and achieve the effect.
(The case described in #12098 is particularly nasty: 'echo -n >foo.network'
creates a mask file, 'echo >foo.network' creates a "match all" file.)
Fixes#717, #12098 for realz now.