runc
runc copied to clipboard
Tests broken in debian due to PR: rootfs: remove --no-mount-fallback and finally fix MS_REMOUNT
Description
After PR #3967 was merged, the tests added there don't work on Debian testing. It doesn't work with or without sshfs installed.
Tests in this file work fine without that PR.
@cyphar @lifubang can you plase take a look? Let me know if you can't repro.
Steps to reproduce the issue
- On debian testing, compile and run: sudo -E PATH=$PWD/../runc/:$PATH bats -t tests/integration/mounts_sshfs.bats
Describe the results you received and expected
This is the output:
ok 1 runc run [mount(8)-like behaviour: --bind with no options]
ok 2 runc run [mount(8)-unlike behaviour: --bind with clearing flag]
ok 3 runc run [implied-rw bind mount of a ro fuse sshfs mount]
ok 4 runc run [explicit-rw bind mount of a ro fuse sshfs mount]
not ok 5 runc run [dev,exec,suid,atime bind mount of a nodev,nosuid,noexec,noatime fuse sshfs mount]
# (from function `setup_sshfs' in file tests/integration/mounts_sshfs.bats, line 46,
# from function `setup_sshfs_bind_flags' in file tests/integration/mounts_sshfs.bats, line 61,
# from function `fail_sshfs_bind_flags' in file tests/integration/mounts_sshfs.bats, line 87,
# in test file tests/integration/mounts_sshfs.bats, line 226)
# `fail_sshfs_bind_flags "nodev,nosuid,nosuid,noatime" "bind,dev,suid,exec,atime"' failed with status 32
# runc spec (status=0):
#
# /home/rodrigo/src/github.com/opencontainers/runc/tests/integration/mounts_sshfs.bats: line 39: sshfs: command not found
# configured /tmp/bats-run-xZAuhy/fuse-sshfs with mount --bind -o remount,nosuid,nodev,noexec,noatime
# tmpfs /tmp/bats-run-xZAuhy/fuse-sshfs tmpfs rw,nosuid,nodev,noexec,noatime,inode64 0 0
# runc run test_busybox (status=0):
# rw,noatime,inode64
# mount: /tmp/bats-run-xZAuhy/fuse-sshfs: mount point not mounted or bad option.
# dmesg(1) may have more information after failed mount system call.
not ok 6 runc run [ro bind mount of a nodev,nosuid,noexec fuse sshfs mount]
# (from function `setup_sshfs' in file tests/integration/mounts_sshfs.bats, line 46,
# from function `setup_sshfs_bind_flags' in file tests/integration/mounts_sshfs.bats, line 61,
# from function `pass_sshfs_bind_flags' in file tests/integration/mounts_sshfs.bats, line 79,
# in test file tests/integration/mounts_sshfs.bats, line 249)
# `pass_sshfs_bind_flags "rw,nodev,nosuid,nodev,noexec,noatime" "bind,ro"' failed with status 32
# runc spec (status=0):
#
# /home/rodrigo/src/github.com/opencontainers/runc/tests/integration/mounts_sshfs.bats: line 39: sshfs: command not found
# configured /tmp/bats-run-xZAuhy/fuse-sshfs with mount --bind -o remount,rw,nodev,nosuid,nodev,noexec,noatime
# tmpfs /tmp/bats-run-xZAuhy/fuse-sshfs tmpfs rw,nosuid,nodev,noexec,noatime,inode64 0 0
# runc run test_busybox (status=0):
# ro,noatime,inode64
# mount: /tmp/bats-run-xZAuhy/fuse-sshfs: mount point not mounted or bad option.
# dmesg(1) may have more information after failed mount system call.
ok 7 runc run [ro,symfollow bind mount of a rw,nodev,nosymfollow fuse sshfs mount]
not ok 8 runc run [ro,noexec bind mount of a nosuid,noatime fuse sshfs mount]
# (from function `setup_sshfs' in file tests/integration/mounts_sshfs.bats, line 46,
# from function `setup_sshfs_bind_flags' in file tests/integration/mounts_sshfs.bats, line 61,
# from function `pass_sshfs_bind_flags' in file tests/integration/mounts_sshfs.bats, line 79,
# in test file tests/integration/mounts_sshfs.bats, line 312)
# `pass_sshfs_bind_flags "nodev,nosuid,noatime" "bind,ro,exec"' failed with status 32
# runc spec (status=0):
#
# /home/rodrigo/src/github.com/opencontainers/runc/tests/integration/mounts_sshfs.bats: line 39: sshfs: command not found
# configured /tmp/bats-run-xZAuhy/fuse-sshfs with mount --bind -o remount,nodev,nosuid,noatime
# tmpfs /tmp/bats-run-xZAuhy/fuse-sshfs tmpfs rw,nosuid,nodev,noatime,inode64 0 0
# runc run test_busybox (status=0):
# ro,noatime,inode64
# mount: /tmp/bats-run-xZAuhy/fuse-sshfs: mount point not mounted or bad option.
# dmesg(1) may have more information after failed mount system call.
not ok 9 runc run [bind mount {no,rel,strict}atime semantics]
# (from function `setup_sshfs' in file tests/integration/mounts_sshfs.bats, line 46,
# from function `setup_sshfs_bind_flags' in file tests/integration/mounts_sshfs.bats, line 61,
# from function `pass_sshfs_bind_flags' in file tests/integration/mounts_sshfs.bats, line 79,
# in test file tests/integration/mounts_sshfs.bats, line 338)
# `pass_sshfs_bind_flags "noatime" "bind,norelatime"' failed with status 32
# runc spec (status=0):
#
# /home/rodrigo/src/github.com/opencontainers/runc/tests/integration/mounts_sshfs.bats: line 39: sshfs: command not found
# configured /tmp/bats-run-xZAuhy/fuse-sshfs with mount --bind -o remount,noatime
# tmpfs /tmp/bats-run-xZAuhy/fuse-sshfs tmpfs rw,noatime,inode64 0 0
# runc run test_busybox (status=0):
# rw,noatime,inode64
# mount: /tmp/bats-run-xZAuhy/fuse-sshfs: mount point not mounted or bad option.
# dmesg(1) may have more information after failed mount system call.
I expect all tests to pass.
There seems to be something fishy with the strictnoatime flag, as removing it from this command: https://github.com/opencontainers/runc/blob/a68529ce5bce15cc8cb2cd8c0d455a9c73e24630/tests/integration/mounts_sshfs.bats#L46
makes all the tests except the last one pass.
Something that adds complexity is that the last test is a collection of lot different of tests and they seems to have side effects, because some things in isolation work, but not when run one after the other in the test.
What version of runc are you using?
runc main as of a68529ce5bce15cc8cb2cd8c0d455a9c73e24630
Host OS information
PRETTY_NAME="Debian GNU/Linux trixie/sid" NAME="Debian GNU/Linux" VERSION_CODENAME=trixie ID=debian HOME_URL="https://www.debian.org/" SUPPORT_URL="https://www.debian.org/support" BUG_REPORT_URL="https://bugs.debian.org/"
Host kernel information
Linux
For some reason, splitting each test before the "and now try with a userns", makes all of them except the last one work fine:
diff --git tests/integration/mounts_sshfs.bats tests/integration/mounts_sshfs.bats
index 0bef0178..0c56988b 100644
--- tests/integration/mounts_sshfs.bats
+++ tests/integration/mounts_sshfs.bats
@@ -4,6 +4,8 @@ load helpers
function setup() {
setup_busybox
+ mkdir -p rootfs/{proc,sys,tmp,mnt}
+
}
function teardown() {
@@ -200,7 +202,7 @@ function fail_sshfs_bind_flags() {
fail_sshfs_bind_flags "ro" "bind,rw,nosuid,nodev,rprivate"
}
-@test "runc run [dev,exec,suid,atime bind mount of a nodev,nosuid,noexec,noatime fuse sshfs mount]" {
+@test "runc run [dev,exec,suid,atime bind mount of a nodev,nosuid,noexec,noatime fuse sshfs mount] rata" {
requires root
# When running without userns, overwriting host flags should work.
@@ -215,7 +217,8 @@ function fail_sshfs_bind_flags() {
# FIXME FIXME: As with mount(8), trying to clear an atime flag the "naive"
# way will be ignored!
run -0 grep -wq noatime <<<"$mnt_flags"
-
+}
+@test "rata 2" {
# Now try with a user namespace.
update_config ' .linux.namespaces += [{"type": "user"}]
| .linux.uidMappings += [{"hostID": 100000, "containerID": 0, "size": 65534}]
@@ -239,7 +242,8 @@ function fail_sshfs_bind_flags() {
run ! grep -wq nosuid <<<"$mnt_flags"
run ! grep -wq nodev <<<"$mnt_flags"
run ! grep -wq noexec <<<"$mnt_flags"
-
+}
+@test "rata 3" {
# Now try with a user namespace.
update_config ' .linux.namespaces += [{"type": "user"}]
| .linux.uidMappings += [{"hostID": 100000, "containerID": 0, "size": 65534}]
@@ -267,6 +271,9 @@ function fail_sshfs_bind_flags() {
# nosymfollow must also be cleared.
run ! grep -wq nosymfollow <<<"$mnt_flags"
+}
+
+@test "rata 4" {
# Now try with a user namespace.
update_config ' .linux.namespaces += [{"type": "user"}]
| .linux.uidMappings += [{"hostID": 100000, "containerID": 0, "size": 65534}]
@@ -303,6 +310,10 @@ function fail_sshfs_bind_flags() {
# FIXME: As with mount(8), runc keeps the old atime setting by default.
run -0 grep -wq noatime <<<"$mnt_flags"
+}
+
+@test "rata 5" {
+
# Now try with a user namespace.
update_config ' .linux.namespaces += [{"type": "user"}]
| .linux.uidMappings += [{"hostID": 100000, "containerID": 0, "size": 65534}]
@@ -376,6 +387,19 @@ function fail_sshfs_bind_flags() {
run -0 grep -wq nodiratime <<<"$mnt_flags"
run -0 grep -wq relatime <<<"$mnt_flags"
+}
+
+@test "rata 6" {
+ requires root
+
+ function is_strictatime() {
+ # There is no "strictatime" in /proc/self/mounts.
+ run ! grep -wq noatime <<<"${1:-$mnt_flags}"
+ run ! grep -wq relatime <<<"${1:-$mnt_flags}"
+ run ! grep -wq nodiratime <<<"${1:-$mnt_flags}"
+ }
+
+
# Now try with a user namespace.
update_config ' .linux.namespaces += [{"type": "user"}]
| .linux.uidMappings += [{"hostID": 100000, "containerID": 0, "size": 65534}]
With this patch, I get this output running the tests:
1..14
ok 1 runc run [mount(8)-like behaviour: --bind with no options]
ok 2 runc run [mount(8)-unlike behaviour: --bind with clearing flag]
ok 3 runc run [implied-rw bind mount of a ro fuse sshfs mount]
ok 4 runc run [explicit-rw bind mount of a ro fuse sshfs mount]
ok 5 runc run [dev,exec,suid,atime bind mount of a nodev,nosuid,noexec,noatime fuse sshfs mount] rata
ok 6 rata 2
ok 7 runc run [ro bind mount of a nodev,nosuid,noexec fuse sshfs mount]
ok 8 rata 3
ok 9 runc run [ro,symfollow bind mount of a rw,nodev,nosymfollow fuse sshfs mount]
ok 10 rata 4
ok 11 runc run [ro,noexec bind mount of a nosuid,noatime fuse sshfs mount]
ok 12 rata 5
not ok 13 runc run [bind mount {no,rel,strict}atime semantics]
# (from function `setup_sshfs' in file tests/integration/mounts_sshfs.bats, line 48,
# from function `setup_sshfs_bind_flags' in file tests/integration/mounts_sshfs.bats, line 63,
# from function `pass_sshfs_bind_flags' in file tests/integration/mounts_sshfs.bats, line 81,
# in test file tests/integration/mounts_sshfs.bats, line 349)
# `pass_sshfs_bind_flags "noatime" "bind,norelatime"' failed with status 32
# runc spec (status=0):
#
# /home/rodrigo/src/github.com/opencontainers/runc/tests/integration/mounts_sshfs.bats: line 41: sshfs: command not found
# configured /tmp/bats-run-0JHcht/fuse-sshfs with mount --bind -o remount,noatime
# tmpfs /tmp/bats-run-0JHcht/fuse-sshfs tmpfs rw,noatime,inode64 0 0
# runc run test_busybox (status=0):
# rw,noatime,inode64
# mount: /tmp/bats-run-0JHcht/fuse-sshfs: mount point not mounted or bad option.
# dmesg(1) may have more information after failed mount system call.
not ok 14 rata 6
# (in test file tests/integration/mounts_sshfs.bats, line 420)
# `run -0 grep -wq relatime <<<"$mnt_flags"' failed, expected exit code 0, got 1
# runc spec (status=0):
#
# /home/rodrigo/src/github.com/opencontainers/runc/tests/integration/mounts_sshfs.bats: line 41: sshfs: command not found
# configured /tmp/bats-run-0JHcht/fuse-sshfs with mount --bind -o remount,strictatime
# tmpfs /tmp/bats-run-0JHcht/fuse-sshfs tmpfs rw,inode64 0 0
# runc run test_busybox (status=0):
# rw,inode64
# configured /tmp/bats-run-0JHcht/fuse-sshfs with mount --bind -o remount,relatime
# tmpfs /tmp/bats-run-0JHcht/fuse-sshfs tmpfs rw,relatime,inode64 0 0
# runc run test_busybox (status=0):
# rw,relatime,inode64
# configured /tmp/bats-run-0JHcht/fuse-sshfs with mount --bind -o remount,nodiratime
# tmpfs /tmp/bats-run-0JHcht/fuse-sshfs tmpfs rw,nodiratime,inode64 0 0
# runc run test_busybox (status=0):
# rw,nodiratime,inode64
@rata Do you have some progress on this? This has been added to #4114.
@lifubang no, I asked you and @cyphar to have a look. Can you have a look, please? :)
Grr, it seems I didn't send this comment earlier when I looked at this...
mount --bind -o remount,diratime,strictatime "$DIR"
resets the mount flags on the mount. strictatime is necessary because of the funky way that atime flags work on Linux (the only way to ensure a mount gets relatime is to set MS_STRICTATIME without setting MS_NOATIME -- MS_RELATIME is ignored by the kernel for historical reasons; the diratime is needed to work around mount(8) copying the existing mount flags -- MS_NODIRATIME is separate to the other atime mount flags and so you need to explicitly clear it otherwise mount(8) will copy it).
Looking at the failures, it seems that there's something weird going on with atime-related mount flags on your system. We could rework the test so that it does a umount instead of re-configuring the mount, but the final test failure appears to be a real failure on your system.
Let me know if you can't repro.
I can't reproduce this on my machine. I can try to test this in Debian VM when I have some time, but given that the tests work on openSUSE (my box) and Ubuntu (CI) it seems strange that it would only fail on Debian...
I tested this on debian 12 (stable), with its 6.1 kernel, and it passes (installed fuse3, with and without sshfs installed).
I don't have a lot of time to look into this now, but it might just be on debian testing or, maybe even better, on my machine only. Debian stable doesn't seem affected.
This blocks https://github.com/docker/for-linux/issues/679 can you estimate how many years to wait
I’m sorry to hear that, I think contributing to open source is a part time job for most of us, we spent most of our free time, which was supposed to be used for rest, to debug bugs in this project, but unfortunately we are still not find a good way to fix it, we need some more useful suggestions to some issues, if there were, it will be appreciated. In some past days, we have made a decision to release it soon, and let these obvious bugs to be fixed in next time.
@evrial there doesn't seem to be there anything related to this there. Version 1.2.0.rc1 is not released due to other reasons, and it is the only thing needed there. Please avoid those comments, then, as it just creates noise here.
I'm literally with a very limited and metered internet connection now.
@rata I test it in a more lower version of debian, it still can't repro:
root@iZrj96eos9qt9eyvkolnezZ:~/go/src/github.com/opencontainers/runc# uname -a
Linux iZrj96eos9qt9eyvkolnezZ 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) x86_64 GNU/Linux
root@iZrj96eos9qt9eyvkolnezZ:~/go/src/github.com/opencontainers/runc# sudo -E PATH=$PWD/../runc/:$PATH bats -t tests/integration/mounts_sshfs.bats
1..9
ok 1 runc run [mount(8)-like behaviour: --bind with no options]
ok 2 runc run [mount(8)-unlike behaviour: --bind with clearing flag]
ok 3 runc run [implied-rw bind mount of a ro fuse sshfs mount]
ok 4 runc run [explicit-rw bind mount of a ro fuse sshfs mount]
ok 5 runc run [dev,exec,suid,atime bind mount of a nodev,nosuid,noexec,noatime fuse sshfs mount]
ok 6 runc run [ro bind mount of a nodev,nosuid,noexec fuse sshfs mount]
ok 7 runc run [ro,symfollow bind mount of a rw,nodev,nosymfollow fuse sshfs mount]
ok 8 runc run [ro,noexec bind mount of a nosuid,noatime fuse sshfs mount]
ok 9 runc run [bind mount {no,rel,strict}atime semantics]
@lifubang cool. So far I've only seen this locally, but I guess a testing/unstable debian version might hit it.
Okay, I've been debugging this for a while. I have a workaround, although I'm not 100% sure why it is needed. Please read this and let me know if you have some ideas.
I've focused on debugging one test first, this one: sudo -E PATH=$PWD/../runc/:$PATH bats -t tests/integration/mounts_sshfs.bats --filter "dev,exec,suid,atime bind mount"
I've added some debug prints and it all comes down to this not working here (see the last mount):
# These mounts run due to this line in the bats file:
# pass_sshfs_bind_flags "nosuid,nodev,noexec,noatime" "bind,dev,suid,exec,atime"
mount -t tmpfs -o rw,suid,dev,exec,diratime,strictatime tmpfs /tmp/fuse-sshfs/
mount --bind -o remount,diratime,strictatime /tmp/fuse-sshfs/
mount --bind -o "remount,nosuid,nodev,noexec,noatime" /tmp/fuse-sshfs/
# Let's see the mount
cat /proc/self/mounts | grep sshfs
tmpfs /tmp/fuse-sshfs tmpfs rw,nosuid,nodev,noexec,noatime,inode64 0 0
# All works fine until the bats file tries to run this other line:
# fail_sshfs_bind_flags "nodev,nosuid,nosuid,noatime" "bind,dev,suid,exec,atime"
# Then it executes this mount that fails
mount --bind -o remount,diratime,strictatime /tmp/fuse-sshfs/
mount: /tmp/fuse-sshfs: mount point not mounted or bad option.
dmesg(1) may have more information after failed mount system call.
If I just execute that sequence of mounts on my laptop, it fails. I've tried the mount package from sid and rc-buggy but the same still happens. I haven't tried to downgrade the mounts dependencies, so I can't discard that yet.
However, if we unmount after each "pass_sshfs_" or "fail_sshfs_", it all works fine.
@cyphar @lifubang do you have any idea why this can be? dmesg doesn't show anything :(
I've opened PR #4242 with the workaround, so it's clear what I refer to.
@rata I suggested doing a umount above:
Looking at the failures, it seems that there's something weird going on with atime-related mount flags on your system. We could rework the test so that it does a umount instead of re-configuring the mount, but the final test failure appears to be a real failure on your system.
Looking into it again, it seems Debian doesn't use util-linux's mount implementation at all, which explains why the behaviour is different. Debian's mount package source appears to be a maintained version of the original mount utility for Linux (from the 90s) while everyone else uses util-linux's implementation using libmount (from 2011).
I don't mind us fixing this issue, but given that this is a weird Debian-ism we should make the smallest possible number of changes because it's clearly not an issue with runc nor our tests.
@cyphar Nice finding, but no, the mount debian package uses util-linux. See the mount version in your link, it's ancient. I didn't know that site, but I don't believe that is providing accurate information.
See the homepage of the mount package: https://packages.debian.org/bookworm/mount, it is util-linux. Also, downloading with apt-source the mount package, downloads util-linux. And the version matches the util-linux version. Furthermore, the manpage says it's part of util-linux and the output of mount --version says that too:
mount from util-linux 2.40 (libmount 2.40.0: selinux, smack, btrfs, verity, namespaces, idmapping, fd-based-mount, statx, assert, debug)
That is definitely not the case here.
Output of strace
root@lindsay:/home/rodrigo/src/github.com/opencontainers/runc# strace -ff -s 512 mount --bind -o remount,diratime,strictatime /tmp/fuse-sshfs/
execve("/usr/bin/mount", ["mount", "--bind", "-o", "remount,diratime,strictatime", "/tmp/fuse-sshfs/"], 0x7ffd919b7ef8 /* 21 vars /) = 0
brk(NULL) = 0x5644761f3000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f269919b000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=105583, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 105583, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f2699181000
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libmount.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0@\0\0\0\0\0\0\0\210#\7\0\0\0\0\0\0\0\0\0@\08\0\n\0@\0\35\0\34\0\1\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0@\274\0\0\0\0\0\0@\274\0\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\5\0\0\0\0\300\0\0\0\0\0\0\0\300\0\0\0\0\0\0\0\300\0\0\0\0\0\0Y\276\4\0\0\0\0\0Y\276\4\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0\200\5\0\0\0\0\0\0\200\5\0\0\0\0\0\0\200\5\0\0\0\0\0dp\1\0\0\0\0\0dp\1\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\6\0\0\0\320\370\6\0\0\0\0\0\320\10\7\0\0\0\0\0\320\10\7\0\0\0\0\0p)\0\0\0\0\0\0\220)\0\0\0\0\0\0\0\20\0\0\0\0\0\0\2\0\0\0\6\0\0\0\310\17\7\0\0\0\0\0\310\37\7\0\0\0\0\0\310\37\7\0\0\0\0\0@\2\0\0\0\0\0\0@\2\0\0\0\0\0\0\10\0\0\0\0\0\0\0\4\0\0\0\4\0\0\0p\2\0\0\0\0\0\0p\2\0\0\0\0\0\0p\2\0\0\0\0\0\0\300\0\0\0\0\0\0\0\300\0\0\0\0\0\0\0\4\0\0\0\0\0\0\0\7\0\0\0\4\0\0\0\320\370\6\0\0\0\0\0\320\10\7\0\0\0\0\0\320\10\7\0\0\0\0\0\0\0\0\0\0\0\0\0\6\0\0\0\0\0\0\0\2\0\0\0\0\0\0\0P\345td\4\0\0\0\354\21\6\0\0\0\0\0\354\21\6\0\0\0\0\0\354\21\6\0\0\0\0\0\\37\0\0\0\0\0\0\\37\0\0\0\0\0\0\4\0\0\0\0\0\0\0"..., 832) = 832
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=469704, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 471648, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f269910d000
mmap(0x7f2699119000, 311296, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xc000) = 0x7f2699119000
mmap(0x7f2699165000, 98304, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x58000) = 0x7f2699165000
mmap(0x7f269917d000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x6f000) = 0x7f269917d000
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0@\0\0\0\0\0\0\0\250\301\2\0\0\0\0\0\0\0\0\0@\08\0\n\0@\0\35\0\34\0\1\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\250f\0\0\0\0\0\0\250f\0\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\5\0\0\0\0p\0\0\0\0\0\0\0p\0\0\0\0\0\0\0p\0\0\0\0\0\0u\261\1\0\0\0\0\0u\261\1\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0000\2\0\0\0\0\0\0000\2\0\0\0\0\0\0000\2\0\0\0\0\0\330u\0\0\0\0\0\0\330u\0\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\6\0\0\0\270\265\2\0\0\0\0\0\270\265\2\0\0\0\0\0\270\265\2\0\0\0\0\0\260\n\0\0\0\0\0\0\0301\0\0\0\0\0\0\0\20\0\0\0\0\0\0\2\0\0\0\6\0\0\0P\266\2\0\0\0\0\0P\266\2\0\0\0\0\0P\266\2\0\0\0\0\0000\2\0\0\0\0\0\0000\2\0\0\0\0\0\0\10\0\0\0\0\0\0\0\4\0\0\0\4\0\0\0p\2\0\0\0\0\0\0p\2\0\0\0\0\0\0p\2\0\0\0\0\0\0$\0\0\0\0\0\0\0$\0\0\0\0\0\0\0\4\0\0\0\0\0\0\0\7\0\0\0\4\0\0\0\270\265\2\0\0\0\0\0\270\265\2\0\0\0\0\0\270\265\2\0\0\0\0\0(\0\0\0\0\0\0\0\350\0\0\0\0\0\0\0\10\0\0\0\0\0\0\0P\345td\4\0\0\0\340P\2\0\0\0\0\0\340P\2\0\0\0\0\0\340P\2\0\0\0\0\0\224\v\0\0\0\0\0\0\224\v\0\0\0\0\0\0\4\0\0\0\0\0\0\0"..., 832) = 832
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=182504, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 190160, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f26990de000
mmap(0x7f26990e5000, 114688, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x7000) = 0x7f26990e5000
mmap(0x7f2699101000, 32768, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x23000) = 0x7f2699101000
mmap(0x7f2699109000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2b000) = 0x7f2699109000
mmap(0x7f269910b000, 5840, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f269910b000
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220x\2\0\0\0\0\0@\0\0\0\0\0\0\0pT\35\0\0\0\0\0\0\0\0\0@\08\0\16\0@\0@\0?\0\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0\20\3\0\0\0\0\0\0\20\3\0\0\0\0\0\0\10\0\0\0\0\0\0\0\3\0\0\0\4\0\0\0\21\32\0\0\0\0\0\21\32\0\0\0\0\0\21\32\0\0\0\0\0\34\0\0\0\0\0\0\0\34\0\0\0\0\0\0\0\20\0\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\230R\2\0\0\0\0\0\230R\2\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\5\0\0\0\0\2\0\0\0\0\0\0\2\0\0\0\0\0\0\2\0\0\0\0\0\C\25\0\0\0\0\0\C\25\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0\260\27\0\0\0\0\0\0\260\27\0\0\0\0\0\0\260\27\0\0\0\0\0\21=\5\0\0\0\0\0\21=\5\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\6\0\0\0\370\373\34\0\0\0\0\0\370\373\34\0\0\0\0\0\370\373\34\0\0\0\0\0\220L\0\0\0\0\0\0X#\1\0\0\0\0\0\0\20\0\0\0\0\0\0\2\0\0\0\6\0\0\0\200+\35\0\0\0\0\0\200+\35\0\0\0\0\0\200+\35\0\0\0\0\0\0\2\0\0\0\0\0\0\0\2\0\0\0\0\0\0\10\0\0\0\0\0\0\0\4\0\0\0\4\0\0\0P\3\0\0\0\0\0\0P\3\0\0\0\0\0\0P\3\0\0\0\0\0\0 \0\0\0\0\0\0\0 \0\0\0\0\0\0\0\10\0\0\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0\20\3\0\0\0\0\0\0\20\3\0\0\0\0\0\0\10\0\0\0\0\0\0\0\3\0\0\0\4\0\0\0\21\32\0\0\0\0\0\21\32\0\0\0\0\0\21\32\0\0\0\0\0\34\0\0\0\0\0\0\0\34\0\0\0\0\0\0\0\20\0\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\230R\2\0\0\0\0\0\230R\2\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\5\0\0\0\0\2\0\0\0\0\0\0\2\0\0\0\0\0\0\2\0\0\0\0\0\C\25\0\0\0\0\0\C\25\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0\260\27\0\0\0\0\0\0\260\27\0\0\0\0\0\0\260\27\0\0\0\0\0\21=\5\0\0\0\0\0\21=\5\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\6\0\0\0\370\373\34\0\0\0\0\0\370\373\34\0\0\0\0\0\370\373\34\0\0\0\0\0\220L\0\0\0\0\0\0X#\1\0\0\0\0\0\0\20\0\0\0\0\0\0\2\0\0\0\6\0\0\0\200+\35\0\0\0\0\0\200+\35\0\0\0\0\0\200+\35\0\0\0\0\0\0\2\0\0\0\0\0\0\0\2\0\0\0\0\0\0\10\0\0\0\0\0\0\0\4\0\0\0\4\0\0\0P\3\0\0\0\0\0\0P\3\0\0\0\0\0\0P\3\0\0\0\0\0\0 \0\0\0\0\0\0\0 \0\0\0\0\0\0\0\10\0\0\0\0\0\0\0\4\0\0\0\4\0\0\0p\3\0\0\0\0\0\0p\3\0\0\0\0\0\0p\3\0\0\0\0\0\0D\0\0\0\0\0\0\0D\0\0\0\0\0\0\0\4\0\0\0\0\0\0\0\7\0\0\0\4\0\0\0"..., 784, 64) = 784
newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=1926256, ...}, AT_EMPTY_PATH) = 0
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0\20\3\0\0\0\0\0\0\20\3\0\0\0\0\0\0\10\0\0\0\0\0\0\0\3\0\0\0\4\0\0\0\21\32\0\0\0\0\0\21\32\0\0\0\0\0\21\32\0\0\0\0\0\34\0\0\0\0\0\0\0\34\0\0\0\0\0\0\0\20\0\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\230R\2\0\0\0\0\0\230R\2\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\5\0\0\0\0\2\0\0\0\0\0\0\2\0\0\0\0\0\0\2\0\0\0\0\0\C\25\0\0\0\0\0\C\25\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0\260\27\0\0\0\0\0\0\260\27\0\0\0\0\0\0\260\27\0\0\0\0\0\21=\5\0\0\0\0\0\21=\5\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\6\0\0\0\370\373\34\0\0\0\0\0\370\373\34\0\0\0\0\0\370\373\34\0\0\0\0\0\220L\0\0\0\0\0\0X#\1\0\0\0\0\0\0\20\0\0\0\0\0\0\2\0\0\0\6\0\0\0\200+\35\0\0\0\0\0\200+\35\0\0\0\0\0\200+\35\0\0\0\0\0\0\2\0\0\0\0\0\0\0\2\0\0\0\0\0\0\10\0\0\0\0\0\0\0\4\0\0\0\4\0\0\0P\3\0\0\0\0\0\0P\3\0\0\0\0\0\0P\3\0\0\0\0\0\0 \0\0\0\0\0\0\0 \0\0\0\0\0\0\0\10\0\0\0\0\0\0\0\4\0\0\0\4\0\0\0p\3\0\0\0\0\0\0p\3\0\0\0\0\0\0p\3\0\0\0\0\0\0D\0\0\0\0\0\0\0D\0\0\0\0\0\0\0\4\0\0\0\0\0\0\0\7\0\0\0\4\0\0\0"..., 784, 64) = 784
mmap(NULL, 1974096, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f2698efc000
mmap(0x7f2698f22000, 1396736, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x26000) = 0x7f2698f22000
mmap(0x7f2699077000, 344064, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x17b000) = 0x7f2699077000
mmap(0x7f26990cb000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1cf000) = 0x7f26990cb000
mmap(0x7f26990d1000, 53072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f26990d1000
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libblkid.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0@\0\0\0\0\0\0\0\340\324\5\0\0\0\0\0\0\0\0\0@\08\0\n\0@\0\35\0\34\0\1\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\230\221\0\0\0\0\0\0\230\221\0\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\5\0\0\0\0\240\0\0\0\0\0\0\0\240\0\0\0\0\0\0\0\240\0\0\0\0\0\0y\250\3\0\0\0\0\0y\250\3\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0P\4\0\0\0\0\0\0P\4\0\0\0\0\0\0P\4\0\0\0\0\0\314 \1\0\0\0\0\0\314 \1\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\6\0\0\0(q\5\0\0\0\0\0(\201\5\0\0\0\0\0(\201\5\0\0\0\0\0pb\0\0\0\0\0\0\230b\0\0\0\0\0\0\0\20\0\0\0\0\0\0\2\0\0\0\6\0\0\0 \306\5\0\0\0\0\0 \326\5\0\0\0\0\0 \326\5\0\0\0\0\0 \2\0\0\0\0\0\0 \2\0\0\0\0\0\0\10\0\0\0\0\0\0\0\4\0\0\0\4\0\0\0p\2\0\0\0\0\0\0p\2\0\0\0\0\0\0p\2\0\0\0\0\0\0\300\0\0\0\0\0\0\0\300\0\0\0\0\0\0\0\4\0\0\0\0\0\0\0\7\0\0\0\4\0\0\0(q\5\0\0\0\0\0(\201\5\0\0\0\0\0(\201\5\0\0\0\0\0\0\0\0\0\0\0\0\0\6\0\0\0\0\0\0\0\2\0\0\0\0\0\0\0P\345td\4\0\0\0L\260\4\0\0\0\0\0L\260\4\0\0\0\0\0L\260\4\0\0\0\0\0\34\32\0\0\0\0\0\0\34\32\0\0\0\0\0\0\4\0\0\0\0\0\0\0"..., 832) = 832
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=384032, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 385984, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f2698e9d000
mmap(0x7f2698ea7000, 241664, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xa000) = 0x7f2698ea7000
mmap(0x7f2698ee2000, 77824, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x45000) = 0x7f2698ee2000
mmap(0x7f2698ef5000, 28672, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x57000) = 0x7f2698ef5000
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpcre2-8.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0@\0\0\0\0\0\0\0\310\243\t\0\0\0\0\0\0\0\0\0@\08\0\t\0@\0\33\0\32\0\1\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0H\37\0\0\0\0\0\0H\37\0\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\5\0\0\0\0 \0\0\0\0\0\0\0 \0\0\0\0\0\0\0 \0\0\0\0\0\0\331\267\6\0\0\0\0\0\331\267\6\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0\340\6\0\0\0\0\0\0\340\6\0\0\0\0\0\0\340\6\0\0\0\0\0\250\256\2\0\0\0\0\0\250\256\2\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\6\0\0\0\360\234\t\0\0\0\0\0\360\234\t\0\0\0\0\0\360\234\t\0\0\0\0\0\260\5\0\0\0\0\0\0\230\6\0\0\0\0\0\0\0\20\0\0\0\0\0\0\2\0\0\0\6\0\0\0\310\235\t\0\0\0\0\0\310\235\t\0\0\0\0\0\310\235\t\0\0\0\0\0\320\1\0\0\0\0\0\0\320\1\0\0\0\0\0\0\10\0\0\0\0\0\0\0\4\0\0\0\4\0\0\08\2\0\0\0\0\0\08\2\0\0\0\0\0\08\2\0\0\0\0\0\0$\0\0\0\0\0\0\0$\0\0\0\0\0\0\0\4\0\0\0\0\0\0\0P\345td\4\0\0\0\300!\t\0\0\0\0\0\300!\t\0\0\0\0\0\300!\t\0\0\0\0\0,\10\0\0\0\0\0\0,\10\0\0\0\0\0\0\4\0\0\0\0\0\0\0Q\345td\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\20\0\0\0\0\0\0\0"..., 832) = 832
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=633480, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 631688, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f2698e02000
mmap(0x7f2698e04000, 442368, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7f2698e04000
mmap(0x7f2698e70000, 176128, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x6e000) = 0x7f2698e70000
mmap(0x7f2698e9b000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x99000) = 0x7f2698e9b000
close(3) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2698e00000
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2698dfd000
arch_prctl(ARCH_SET_FS, 0x7f2698dfd800) = 0
set_tid_address(0x7f2698dfdad0) = 4799
set_robust_list(0x7f2698dfdae0, 24) = 0
rseq(0x7f2698dfe120, 0x20, 0, 0x53053053) = 0
mprotect(0x7f26990cb000, 16384, PROT_READ) = 0
mprotect(0x7f2698e9b000, 4096, PROT_READ) = 0
mprotect(0x7f2698ef5000, 24576, PROT_READ) = 0
mprotect(0x7f2699109000, 4096, PROT_READ) = 0
mprotect(0x7f269917d000, 12288, PROT_READ) = 0
mprotect(0x564474add000, 4096, PROT_READ) = 0
mprotect(0x7f26991cd000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=81921024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0x7f2699181000, 105583) = 0
statfs("/sys/fs/selinux", {f_type=SELINUX_MAGIC, f_bsize=4096, f_blocks=0, f_bfree=0, f_bavail=0, f_files=0, f_ffree=0, f_fsid={val=[0x14, 0]}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID|ST_NOSUID|ST_NOEXEC|ST_RELATIME}) = 0
statfs("/sys/fs/selinux", {f_type=SELINUX_MAGIC, f_bsize=4096, f_blocks=0, f_bfree=0, f_bavail=0, f_files=0, f_ffree=0, f_fsid={val=[0x14, 0]}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID|ST_NOSUID|ST_NOEXEC|ST_RELATIME}) = 0
getrandom("\x44\x38\xa0\x38\x52\x25\xa1\x54", 8, GRND_NONBLOCK) = 8
brk(NULL) = 0x5644761f3000
brk(0x564476214000) = 0x564476214000
access("/etc/selinux/config", F_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=5644192, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 5644192, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f2698800000
close(3) = 0
getuid() = 0
geteuid() = 0
getuid() = 0
geteuid() = 0
getgid() = 0
getegid() = 0
prctl(PR_GET_DUMPABLE) = 1 (SUID_DUMP_USER)
statx(AT_FDCWD, "/etc/fstab", AT_STATX_DONT_SYNC|AT_NO_AUTOMOUNT, STATX_TYPE|STATX_MODE|STATX_INO, {stx_mask=STATX_BASIC_STATS|STATX_MNT_ID, stx_attributes=0, stx_mode=S_IFREG|0644, stx_size=747, ...}) = 0
openat(AT_FDCWD, "/etc/fstab", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=747, ...}, AT_EMPTY_PATH) = 0
read(3, "# /etc/fstab: static file system information.\n#\n# Use 'blkid' to print the universally unique identifier for a\n# device; this may be used with UUID= as a more robust way to name devices\n# that works even if disks are added and removed. See fstab(5).\n#\n#
From the strace output, it seems mount is trying to do run this:
mount_setattr(3, "", AT_EMPTY_PATH, {attr_set=MOUNT_ATTR_NOSUID|MOUNT_ATTR_NODEV|MOUNT_ATTR_NOEXEC|MOUNT_ATTR_NOATIME|MOUNT_ATTR_STRICTATIME, attr_clr=MOUNT_ATTR_RDONLY|MOUNT_ATTR_NOATIME|MOUNT_ATTR_STRICTATIME|MOUNT_ATTR_NODIRATIME|0x40, propagation=0 /* MS_??? */, userns_fd=0}, 32) = -1 EINVAL (Invalid argument)
Note it has MOUNT_ATTR_NOATIME and MOUNT_ATTR_STRICTATIME which probably causes it to return EINVAL.
This led me to realizing that adding atime, the command works just fine here:
# mount --bind -o remount,diratime,atime,strictatime /tmp/fuse-sshfs/
# mount | grep sshfs
tmpfs on /tmp/fuse-sshfs type tmpfs (rw,nosuid,nodev,noexec,inode64)
I think I still prefer to have each mount start from scratch (as the PR is currently doing), but if others prefer to add atime there, that might just do it.
I need to investigate if this happens with a vanialla util-linux or not, and if there is something to fix there that might be triggered only in debian.
And indeed, this diff also fixes the tests in debian (but I still think doing the mount from scratch is better):
diff --git tests/integration/mounts_sshfs.bats tests/integration/mounts_sshfs.bats
index d3719b50..0c712d83 100644
--- tests/integration/mounts_sshfs.bats
+++ tests/integration/mounts_sshfs.bats
@@ -43,7 +43,7 @@ function setup_sshfs() {
fi
# Reset atime flags. "diratime" is quite a strange flag, so we need to make
# sure it's cleared before we apply the requested flags.
- mount --bind -o remount,diratime,strictatime "$DIR"
+ mount --bind -o remount,diratime,atime,strictatime "$DIR"
# We need to set the mount flags separately on the mount because some mount
# flags (such as "ro") are set on the superblock if you do them in the
# initial mount, which means that they cannot be cleared by bind-mounts.
Ah, I got confused by the fact that the util-linux package doesn't contain /usr/bin/mount and then looked for the source of the mount package from sources.debian.org. To be honest, I've always found it unintuitive to get the actual source of debian packages as a non-debian user.
In any case, if the issue is with mount_setattr(2) then that's quite annoying. The way I wrote the tests to pass atime flags was specifically written to work around bugs in both the kernel and util-linux. Unless I'm mistaken it seems they've introduced yet another bug when switching the the new mount API (or maybe they fixed the old bug but only for the new mount API, I'm not sure) meaning that now there's a compatibility difference that is not easy to detect or work around... Grrrrr...
(I'm just confused why I haven't seen this on Tumbleweed, I should have newer packages than Debian...)