Repository navigation
procfs: return EINVAL from readlink on non-symlinks - #280
AlbertSanoe wants to merge 2 commits into
Conversation
congwang-mk
left a comment
There was a problem hiding this comment.
Thanks, the diagnosis and fix are correct. A few requests:
-
Rather than translating the errno after
readlinkat(fd, "")fails, check the type first and only callreadlinkatfor links:let mut st: libc::stat = unsafe { std::mem::zeroed() }; if unsafe { libc::fstat(fd.as_raw_fd(), &mut st) } < 0 { return errno_action(); } if !path.is_empty() && st.st_mode & libc::S_IFMT != libc::S_IFLNK { return NotifAction::Errno(libc::EINVAL); }
This states the rule directly (named readlink on a non-link is EINVAL), keeps
errno_action(), and drops the comment. -
Please drop the
allow_degraded(...)calls inrun_readlink_test. No other test in this file needs them and CI runs full Landlock. -
Six sandbox launches is a lot for one errno fix; consider folding them into one or two tests, keeping the libc
realpathone.
Separately, COW has the same bug: readlink_in_root in sys/fs.rs uses the same readlinkat(fd, "") pattern, and handle_cow_readlink maps every failure to ENOENT. Fine to leave for a follow-up.
|
Updated as requested: check the target type before readlinkat, remove allow_degraded, and consolidate the coverage into two tests while keeping the libc realpath case. |
readlink(2) and readlinkat(2) calls with a non-empty pathname returned
ENOENT instead of EINVAL when the target was a regular file or
directory.
The metadata handler pins the target and then calls
readlinkat(fd, "", ...). For a non-symlink, the kernel reports ENOENT
when the pathname is empty but EINVAL for a named lookup. glibc
realpath(3) treats EINVAL as "not a symlink" and continues resolving,
but treats ENOENT as failure, so existing paths such as /etc appeared
to be missing.
Translate ENOENT to EINVAL only when the caller's original pathname is
non-empty and fstat(2) on the same pinned descriptor confirms that the
target is not a symlink. All other cases keep the original errno,
including explicit empty-path requests, errors reported by actual
symlinks (e.g. procfs magic links whose target is gone), and fstat
failures.
Add six regression tests to the existing procfs integration suite,
covering readlink and readlinkat with absolute and relative paths;
regular files, directories, valid and dangling symlinks; ENOENT and
ENOTDIR path errors; empty-path requests and invalid descriptors;
zero-length and truncated buffers; proc links; and libc realpath.
Testing:
while the other four pass, confirming that the tests exercise the
bug.
matching native execution.
Tested on Linux 6.2 x86_64 with Landlock ABI v3, with unsupported
newer protections explicitly allowed to degrade. The full
integration suite was not run because this host does not meet
its strict Landlock ABI v6 requirements.
Fixes #279