[ ... ]
Thus I have come up with a potential explanation:
* The 'audit' module does not identify the watched file
and
directory by (device,ino) but by a pointer to an inode table
entry, a bit like a filesystem module would.
I had a look at the code and it seems it relies on 'inotify' and
the code does get pointers at the relevant in-memory inode
descriptors.
* During treewalks a lot of inodes get cached in the in-memory
inode table.
* This creates pressure on the inode tables and thus the least
used (in some sense) inodes get evicted, and this includes
those for the "disappearing directories".
* When these least used inodes are evicted the 'audit' module
sees it as if it was a removal of the inode.
To corroborate this I have been running:
while true
do
for D in $(< audit-names.txt)
do (cd "$D" && exec sleep 3001)&
done
sleep 3001
done
Which has the effect of marking the relevant directories as the
active current directories of each 'sleep' process, and none of
those directories were "disappeared" from the 'audit' active
rules list.
The 'inotify' code has a comment that claims:
* inode: Pinned so long as the inode is associated with a watch,
from
* inotify_add_watch() to the final put_inotify_watch().
They use 'igrab'/'iput', and 'audit_tree.c' and
'audit_watch.c'
uses them, so I wonder what is missing.