An overlay dentry holds a lower dentry that may belong to an NFS mount. Overlayfs calls ovl_path_open() to get a file descriptor of a lower file for copying up its data and for a lower directory for listing its content. If that lower dentry gets invalidated after ovl_dentry_revalidate() and before ovl_path_open(), the internal error code 518 (EOPENSTALE), which is not a POSIX error code, will be exposed to the user. Check the internal return value -EOPENSTALE in ovl_path_open(), just the same as it is checked in path_openat() and replace it with the POSIX error code ESTALE. Cc: <stable@xxxxxxxxxxxxxxx> Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx> --- fs/overlayfs/util.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) Miklos, Following a similar bug report and a fix I posted for fanotify, I realized that overlayfs can also expose EOPENSTALE to userspace. I did not try to reproduce this with real lower NFS, only tested patch correctness using a debug patch. I guess a reproducer could work with ovl_copy_up_data() that is delayed for a long time without concurrent copy up in kernel <= v4.10 and lower file is pulled underneath while copy up is pending. However, with concurrent copy up in v4.11 that reproducer will be of no use. The only other suspect I found for dentry_open() of an NFS dentry without checking -EOPENSTALE is ecryptfs. David, I think fscache won't be storing it local storage on NFS, right? Added CC stable. Although I am not sure how important this fix is, seems simple enough that breaking POSIX would justify patching stable. Anyway, if you think this calls for a VFS helper I don't mind doing it, I'm just terrible with names so please suggest one. In that case, should we make dentry_open() static? non exportable? Thanks, Amir. diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index 89789bc..931d199 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -328,7 +328,11 @@ bool ovl_is_whiteout(struct dentry *dentry) struct file *ovl_path_open(struct path *path, int flags) { - return dentry_open(path, flags | O_NOATIME, current_cred()); + struct file *f = dentry_open(path, flags | O_NOATIME, current_cred()); + + if (unlikely(IS_ERR(f) && PTR_ERR(f) == -EOPENSTALE)) + return ERR_PTR(-ESTALE); + return f; } int ovl_copy_up_start(struct dentry *dentry) -- 2.7.4