Skip to content

Commit 68e73b3

Browse files
committed
Merge PR ceph#59503 into main
* refs/pull/59503/head: client: Resolve symlink from dirfd for empty pathname client: Fix symlink open with O_PATH and O_NOFOLLOW Reviewed-by: Venky Shankar <[email protected]> Reviewed-by: Dhairya Parmar <[email protected]>
2 parents 8981bfc + 24f453d commit 68e73b3

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

src/client/Client.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6125,6 +6125,10 @@ int Client::may_open(Inode *in, int flags, const UserPerm& perms)
61256125
int r = 0;
61266126
switch (in->mode & S_IFMT) {
61276127
case S_IFLNK:
6128+
#if defined(__linux__) && defined(O_PATH)
6129+
if (flags & O_PATH)
6130+
break;
6131+
#endif
61286132
r = -CEPHFS_ELOOP;
61296133
goto out;
61306134
case S_IFDIR:
@@ -7953,6 +7957,12 @@ int Client::readlinkat(int dirfd, const char *relpath, char *buf, loff_t size, c
79537957
return r;
79547958
}
79557959

7960+
if (!strcmp(relpath, "")) {
7961+
if (!dirinode.get()->is_symlink())
7962+
return -CEPHFS_ENOENT;
7963+
return _readlink(dirinode.get(), buf, size);
7964+
}
7965+
79567966
InodeRef in;
79577967
filepath path(relpath);
79587968
r = path_walk(path, &in, perms, false, 0, dirinode);

src/test/libcephfs/test.cc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,13 @@ TEST(LibCephFS, Symlinks) {
976976
fd = ceph_open(cmount, test_symlink, O_NOFOLLOW, 0);
977977
ASSERT_EQ(fd, -CEPHFS_ELOOP);
978978

979+
#if defined(__linux__) && defined(O_PATH)
980+
// test the O_NOFOLLOW with O_PATH case
981+
fd = ceph_open(cmount, test_symlink, O_PATH|O_NOFOLLOW, 0);
982+
ASSERT_GT(fd, 0);
983+
ceph_close(cmount, fd);
984+
#endif /* __linux */
985+
979986
// stat the original file
980987
struct ceph_statx stx_orig;
981988
ASSERT_EQ(ceph_statx(cmount, test_file, &stx_orig, CEPH_STATX_ALL_STATS, 0), 0);
@@ -3012,6 +3019,18 @@ TEST(LibCephFS, Readlinkat) {
30123019
ASSERT_EQ(0, memcmp(target, rel_file_path, target_len));
30133020

30143021
ASSERT_EQ(0, ceph_close(cmount, fd));
3022+
#if defined(__linux__) && defined(O_PATH)
3023+
// test readlinkat with empty pathname relative to O_PATH|O_NOFOLLOW fd
3024+
fd = ceph_open(cmount, link_path, O_PATH | O_NOFOLLOW, 0);
3025+
ASSERT_LE(0, fd);
3026+
size_t link_target_len = strlen(rel_file_path);
3027+
char link_target[link_target_len+1];
3028+
ASSERT_EQ(link_target_len, ceph_readlinkat(cmount, fd, "", link_target, link_target_len));
3029+
link_target[link_target_len] = '\0';
3030+
ASSERT_EQ(0, memcmp(link_target, rel_file_path, link_target_len));
3031+
ASSERT_EQ(0, ceph_close(cmount, fd));
3032+
#endif /* __linux */
3033+
30153034
ASSERT_EQ(0, ceph_unlink(cmount, link_path));
30163035
ASSERT_EQ(0, ceph_unlink(cmount, file_path));
30173036
ASSERT_EQ(0, ceph_rmdir(cmount, dir_path));

0 commit comments

Comments
 (0)