Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

umockdev breaks due to systemd changes #69

Closed
gicmo opened this issue Jan 20, 2018 · 0 comments
Closed

umockdev breaks due to systemd changes #69

gicmo opened this issue Jan 20, 2018 · 0 comments

Comments

@gicmo
Copy link
Contributor

gicmo commented Jan 20, 2018

As seen in fwupd/fwupd#370 (and also boltd ci).

$ LD_PRELOAD='libumockdev-preload.so.0' build/plugins/thunderbolt/thunderbolt-self-test -p /thunderbolt/basic

/thunderbolt/basic: 
ERROR: uevent_sender_send: No such device /sys/devices/domain0
ERROR: uevent_sender_send: No such device /sys/devices/domain0/0-0

When stracing you see a change in the syscall pattern:

working (systemd-234-9.fc27):

stat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=1400, ...}) = 0
access("/tmp/umockdev.TU2FDZ", F_OK)    = 0
stat("/tmp/umockdev.TU2FDZ", {st_mode=S_IFDIR|0700, st_size=80, ...}) = 0
access("/tmp/umockdev.TU2FDZ/sys", F_OK) = 0
stat("/tmp/umockdev.TU2FDZ/sys", {st_mode=S_IFDIR|0755, st_size=40, ...}) = 0
access("/tmp/umockdev.TU2FDZ/sys/devices", F_OK) = -1 ENOENT (No such file or directory)
mkdir("/tmp/umockdev.TU2FDZ/sys/devices", 0755) = 0
access("/tmp/umockdev.TU2FDZ/sys/devices/domain0", F_OK) = -1 ENOENT (No such file or directory)
mkdir("/tmp/umockdev.TU2FDZ/sys/devices/domain0", 0755) = 0
access("/tmp", F_OK)                    = 0
stat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=1400, ...}) = 0
access("/tmp/umockdev.TU2FDZ", F_OK)    = 0
stat("/tmp/umockdev.TU2FDZ", {st_mode=S_IFDIR|0700, st_size=80, ...}) = 0
access("/tmp/umockdev.TU2FDZ/sys", F_OK) = 0
stat("/tmp/umockdev.TU2FDZ/sys", {st_mode=S_IFDIR|0755, st_size=60, ...}) = 0
access("/tmp/umockdev.TU2FDZ/sys/class", F_OK) = -1 ENOENT (No such file or directory)
mkdir("/tmp/umockdev.TU2FDZ/sys/class", 0755) = 0
access("/tmp/umockdev.TU2FDZ/sys/class/thunderbolt", F_OK) = -1 ENOENT (No such file or directory)
mkdir("/tmp/umockdev.TU2FDZ/sys/class/thunderbolt", 0755) = 0
symlink("../../class/thunderbolt", "/tmp/umockdev.TU2FDZ/sys/devices/domain0/subsystem") = 0
symlink("../../devices/domain0", "/tmp/umockdev.TU2FDZ/sys/class/thunderbolt/domain0") = 0
openat(AT_FDCWD, "/tmp/umockdev.TU2FDZ/sys/devices/domain0/uevent.LD4FDZ", O_RDWR|O_CREAT|O_EXCL, 0666) = 5
fstat(5, {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
fallocate(5, 0, 0, 27)                  = 0
write(5, "DEVTYPE=thunderbolt_domain\n", 27) = 27
fstatfs(5, {f_type=TMPFS_MAGIC, f_bsize=4096, f_blocks=2038207, f_bfree=2016916, f_bavail=2016916, f_files=2038207, f_ffree=2037878, f_fsid={val=[0, 0]}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID|ST_NOSUID|ST_NODEV}) = 0
lstat("/tmp/umockdev.TU2FDZ/sys/devices/domain0/uevent", 0x7ffd6ab09030) = -1 ENOENT (No such file or directory)
close(5)                                = 0
rename("/tmp/umockdev.TU2FDZ/sys/devices/domain0/uevent.LD4FDZ", "/tmp/umockdev.TU2FDZ/sys/devices/domain0/uevent") = 0
openat(AT_FDCWD, "/tmp/umockdev.TU2FDZ/sys/devices/domain0/security.4Y4FDZ", O_RDWR|O_CREAT|O_EXCL, 0666) = 5
fstat(5, {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
fallocate(5, 0, 0, 6)                   = 0
write(5, "secure", 6)                   = 6
fstatfs(5, {f_type=TMPFS_MAGIC, f_bsize=4096, f_blocks=2038207, f_bfree=2016915, f_bavail=2016915, f_files=2038207, f_ffree=2037877, f_fsid={val=[0, 0]}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID|ST_NOSUID|ST_NODEV}) = 0
lstat("/tmp/umockdev.TU2FDZ/sys/devices/domain0/security", 0x7ffd6ab09030) = -1 ENOENT (No such file or directory)
close(5)                                = 0
rename("/tmp/umockdev.TU2FDZ/sys/devices/domain0/security.4Y4FDZ", "/tmp/umockdev.TU2FDZ/sys/devices/domain0/security") = 0
# [CK] setup done here
access("/tmp/umockdev.TU2FDZ/disabled", F_OK) = -1 ENOENT (No such file or directory)
readlinkat(AT_FDCWD, "/tmp/umockdev.TU2FDZ/sys/devices/domain0", 0x1ccb7d0, 99) = -1 EINVAL (Invalid argument)
access("/tmp/umockdev.TU2FDZ/disabled", F_OK) = -1 ENOENT (No such file or directory)
lstat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=1400, ...}) = 0
lstat("/tmp/umockdev.TU2FDZ", {st_mode=S_IFDIR|0700, st_size=80, ...}) = 0
lstat("/tmp/umockdev.TU2FDZ/sys", {st_mode=S_IFDIR|0755, st_size=80, ...}) = 0
lstat("/tmp/umockdev.TU2FDZ/sys/devices", {st_mode=S_IFDIR|0755, st_size=60, ...}) = 0
lstat("/tmp/umockdev.TU2FDZ/sys/devices/domain0", {st_mode=S_IFDIR|0755, st_size=100, ...}) = 0
access("/tmp/umockdev.TU2FDZ/disabled", F_OK) = -1 ENOENT (No such file or directory)
access("/tmp/umockdev.TU2FDZ/sys/devices/domain0/uevent", F_OK) = 0
access("/tmp/umockdev.TU2FDZ/disabled", F_OK) = -1 ENOENT (No such file or directory)
readlinkat(AT_FDCWD, "/tmp/umockdev.TU2FDZ/sys/devices/domain0/subsystem", "../../class/thunderbolt", 99) = 23
getrandom("\x70\x23\x74\xca\xfe\x46\x99\x38\xea\xdc\x52\x63\x53\x82\x02\x2d", 16, GRND_NONBLOCK) = 16
access("/tmp/umockdev.TU2FDZ/disabled", F_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/umockdev.TU2FDZ/sys/devices/domain0/uevent", O_RDONLY|O_CLOEXEC) = 5
fstat(5, {st_mode=S_IFREG|0664, st_size=27, ...}) = 0
fstat(5, {st_mode=S_IFREG|0664, st_size=27, ...}) = 0
read(5, "DEVTYPE=thunderbolt_domain\n", 4096) = 27
read(5, "", 4096)                       = 0
close(5)                                = 0

not working:

stat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=1140, ...}) = 0
access("/tmp/umockdev.19EKDZ", F_OK)    = 0
stat("/tmp/umockdev.19EKDZ", {st_mode=S_IFDIR|0700, st_size=80, ...}) = 0
access("/tmp/umockdev.19EKDZ/sys", F_OK) = 0
stat("/tmp/umockdev.19EKDZ/sys", {st_mode=S_IFDIR|0755, st_size=40, ...}) = 0
access("/tmp/umockdev.19EKDZ/sys/devices", F_OK) = -1 ENOENT (No such file or directory)
mkdir("/tmp/umockdev.19EKDZ/sys/devices", 0755) = 0
access("/tmp/umockdev.19EKDZ/sys/devices/domain0", F_OK) = -1 ENOENT (No such file or directory)
mkdir("/tmp/umockdev.19EKDZ/sys/devices/domain0", 0755) = 0
access("/tmp", F_OK)                    = 0
stat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=1140, ...}) = 0
access("/tmp/umockdev.19EKDZ", F_OK)    = 0
stat("/tmp/umockdev.19EKDZ", {st_mode=S_IFDIR|0700, st_size=80, ...}) = 0
access("/tmp/umockdev.19EKDZ/sys", F_OK) = 0
stat("/tmp/umockdev.19EKDZ/sys", {st_mode=S_IFDIR|0755, st_size=60, ...}) = 0
access("/tmp/umockdev.19EKDZ/sys/bus", F_OK) = -1 ENOENT (No such file or directory)
mkdir("/tmp/umockdev.19EKDZ/sys/bus", 0755) = 0
access("/tmp/umockdev.19EKDZ/sys/bus/thunderbolt", F_OK) = -1 ENOENT (No such file or directory)
mkdir("/tmp/umockdev.19EKDZ/sys/bus/thunderbolt", 0755) = 0
access("/tmp/umockdev.19EKDZ/sys/bus/thunderbolt/devices", F_OK) = -1 ENOENT (No such file or directory)
mkdir("/tmp/umockdev.19EKDZ/sys/bus/thunderbolt/devices", 0755) = 0
symlink("../../../devices/domain0", "/tmp/umockdev.19EKDZ/sys/bus/thunderbolt/devices/domain0") = 0
symlink("../../bus/thunderbolt", "/tmp/umockdev.19EKDZ/sys/devices/domain0/subsystem") = 0
openat(AT_FDCWD, "/tmp/umockdev.19EKDZ/sys/devices/domain0/uevent.73ILDZ", O_RDWR|O_CREAT|O_EXCL, 0666) = 5
fstat(5, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
fallocate(5, 0, 0, 27)                  = 0
write(5, "DEVTYPE=thunderbolt_domain\n", 27) = 27
fstatfs(5, {f_type=TMPFS_MAGIC, f_bsize=4096, f_blocks=2049628, f_bfree=2045039, f_bavail=2045039, f_files=2049628, f_ffree=2048717, f_fsid={val=[0, 0]}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID|ST_NOSUID|ST_NODEV}) = 0
lstat("/tmp/umockdev.19EKDZ/sys/devices/domain0/uevent", 0x7fff8a9cb810) = -1 ENOENT (No such file or directory)
close(5)                                = 0
rename("/tmp/umockdev.19EKDZ/sys/devices/domain0/uevent.73ILDZ", "/tmp/umockdev.19EKDZ/sys/devices/domain0/uevent") = 0
openat(AT_FDCWD, "/tmp/umockdev.19EKDZ/sys/devices/domain0/security.FEJLDZ", O_RDWR|O_CREAT|O_EXCL, 0666) = 5
fstat(5, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
fallocate(5, 0, 0, 6)                   = 0
write(5, "secure", 6)                   = 6
fstatfs(5, {f_type=TMPFS_MAGIC, f_bsize=4096, f_blocks=2049628, f_bfree=2045038, f_bavail=2045038, f_files=2049628, f_ffree=2048716, f_fsid={val=[0, 0]}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID|ST_NOSUID|ST_NODEV}) = 0
lstat("/tmp/umockdev.19EKDZ/sys/devices/domain0/security", 0x7fff8a9cb810) = -1 ENOENT (No such file or directory)
close(5)                                = 0
rename("/tmp/umockdev.19EKDZ/sys/devices/domain0/security.FEJLDZ", "/tmp/umockdev.19EKDZ/sys/devices/domain0/security") = 0

setup done here is practically identical to working condition

openat(AT_FDCWD, "/", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH) = 5
fstat(5, {st_mode=S_IFDIR|0755, st_size=122, ...}) = 0
openat(5, "sys", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH) = 6
fstat(6, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
close(5)                                = 0
openat(6, "devices", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH) = 5
fstat(5, {st_mode=S_IFDIR|0755, st_size=0, ...}) = 0
close(6)                                = 0
openat(5, "domain0", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH) = -1 ENOENT (No such file or directory)
close(5)                                = 0
write(2, "ERROR: uevent_sender_send: No su"..., 63ERROR: uevent_sender_send: No such device /sys/devices/domain0
) = 63

I suspect the culprit is chase_symlinks which uses openat on each path component and we are not catching those (yet).
I stepped through both processes in the debugger. The critical function is device_set_syspath in src/libsystemd/sd-device/sd-device.c.
In the working condition we get a call r = readlink_and_canonicalize(_syspath, NULL, &syspath); which returns -EINVAL and we get to canonicalize_file_name and all is well.
In the non-working condition (newer systemd) we get r = chase_symlinks(_syspath, NULL, 0, &syspath); returning -ENOENT and thus device_set_syspath returning -ENODEV.
The breaking change I guess is systemd/systemd-stable@d0467ba (as also found by @ArchangeGabriel in the fwup issue).

gicmo added a commit to gicmo/bolt that referenced this issue Jan 25, 2018
gicmo added a commit to gicmo/bolt that referenced this issue Jan 29, 2018
martinpitt added a commit that referenced this issue Feb 9, 2018
Ubuntu 14.04 is becoming too old, and misses changes and breakage from
newer system libraries, like issue #69.

Move to building and testing in Launchpad buildd chroots for a given
Ubuntu release and architecture. Add Travis configuration to use this
for the current LTS, the current stable, and the current devel series.
martinpitt added a commit that referenced this issue Feb 9, 2018
Ubuntu 14.04 is becoming too old, and misses changes and breakage from
newer system libraries, like issue #69.

Move to building and testing in Launchpad buildd chroots for a given
Ubuntu release and architecture. Add Travis configuration to use this
for the current LTS, the current stable, and the current devel series.
martinpitt added a commit that referenced this issue Feb 9, 2018
This reproduces #69. Don't enable it for CI as this is too unreliable in
general.
martinpitt added a commit that referenced this issue Feb 9, 2018
This reproduces #69. Don't enable it for CI as this is too unreliable in
general.
martinpitt added a commit that referenced this issue Feb 9, 2018
This reproduces #69. Don't enable it for CI as this is too unreliable in
general.
martinpitt pushed a commit to gicmo/umockdev that referenced this issue Feb 9, 2018
A recent change in libudev/systemd in device_set_syspath() changed
the pattern of syscalls (by using chase_symlink)
from:
    readlinkat (/sys/devices/XXX)
    canonicalize_file_name(/sys/devices/XXX)
to:
    open64 (/)
    openat64 (sys)
    openat64 (devices)
    openat64 (XXX)

This means it will not trigger trap_path and thus escape our faux
sysfs tree.

Modified by Martin Pitt:
 - More precise test for "sys" or "sys/..."
 - Add unit test for openat() behaviour
 - Turn into a macro and wrap openat() as well

Fixes martinpitt#69
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant