Skip to content

Commit 9473c44

Browse files
Trond Myklebustchucklever
authored andcommitted
exportfs: fix the fallback implementation of the get_name export operation
The fallback implementation for the get_name export operation uses readdir() to try to match the inode number to a filename. That filename is then used together with lookup_one() to produce a dentry. A problem arises when we match the '.' or '..' entries, since that causes lookup_one() to fail. This has sometimes been seen to occur for filesystems that violate POSIX requirements around uniqueness of inode numbers, something that is common for snapshot directories. This patch just ensures that we skip '.' and '..' rather than allowing a match. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> Acked-by: Amir Goldstein <amir73il@gmail.com> Link: https://lore.kernel.org/linux-nfs/CAOQ4uxiOZobN76OKB-VBNXWeFKVwLW_eK5QtthGyYzWU9mjb7Q@mail.gmail.com/ Acked-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
1 parent 0dd3ee3 commit 9473c44

File tree

1 file changed

+11
-1
lines changed

1 file changed

+11
-1
lines changed

fs/exportfs/expfs.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,16 @@ struct getdents_callback {
244244
int sequence; /* sequence counter */
245245
};
246246

247+
/* Copied from lookup_one_common() */
248+
static inline bool is_dot_dotdot(const char *name, size_t len)
249+
{
250+
if (unlikely(name[0] == '.')) {
251+
if (len < 2 || (len == 2 && name[1] == '.'))
252+
return true;
253+
}
254+
return false;
255+
}
256+
247257
/*
248258
* A rather strange filldir function to capture
249259
* the name matching the specified inode number.
@@ -255,7 +265,7 @@ static bool filldir_one(struct dir_context *ctx, const char *name, int len,
255265
container_of(ctx, struct getdents_callback, ctx);
256266

257267
buf->sequence++;
258-
if (buf->ino == ino && len <= NAME_MAX) {
268+
if (buf->ino == ino && len <= NAME_MAX && !is_dot_dotdot(name, len)) {
259269
memcpy(buf->name, name, len);
260270
buf->name[len] = '\0';
261271
buf->found = 1;

0 commit comments

Comments
 (0)