When a plugin process calls fstatat with an empty path, shadow returns 0 instead of -ENOENT.
For example, in an Ubuntu 25.04 container:
$ /usr/bin/sh -c '[ ! -d "" ] && echo true || echo false'
true
$ shadow-exec -- /usr/bin/sh -c '[ ! -d "" ] && echo true || echo false'
false
The reason is that Shadow's fstatat syscall handler, if an fd of AT_FDCWD is given, appends the path to the cwd and calls the native fstatat on that path instead. So for the simulated syscall fstatat(AT_FDCWD, "", ...), shadow will actually call fstatat(-1, "/path/to/cwd", ...). But the man page for fstatat says:
ENOENT
pathname is an empty string and AT_EMPTY_PATH was not specified in flags.
So while the syscall fstatat(AT_FDCWD, "", ...) would normally fail with ENOENT, in Shadow it instead returns 0 since the pathname is not an empty string.
I believe that this is also applicable to the other -at syscall handlers, but I haven't checked this in-depth yet.
This breaks the following common pattern in bash scripts:
if [ ! -d "$DIR" ]; then
DIR="/tmp"
fi
When a plugin process calls
fstatatwith an empty path, shadow returns 0 instead of-ENOENT.For example, in an Ubuntu 25.04 container:
The reason is that Shadow's
fstatatsyscall handler, if an fd ofAT_FDCWDis given, appends the path to the cwd and calls the nativefstataton that path instead. So for the simulated syscallfstatat(AT_FDCWD, "", ...), shadow will actually callfstatat(-1, "/path/to/cwd", ...). But the man page forfstatatsays:So while the syscall
fstatat(AT_FDCWD, "", ...)would normally fail withENOENT, in Shadow it instead returns 0 since thepathnameis not an empty string.I believe that this is also applicable to the other -at syscall handlers, but I haven't checked this in-depth yet.
This breaks the following common pattern in bash scripts: