]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
vfs_ceph_new: handle case of readlinkat with empty name string
authorShachar Sharon <ssharon@redhat.com>
Tue, 20 Aug 2024 09:45:07 +0000 (12:45 +0300)
committerAnoop C S <anoopcs@samba.org>
Fri, 30 Aug 2024 10:42:27 +0000 (10:42 +0000)
Commit 53c9269b (vfs_ceph_new: use low-level APIs for symlink/readlink)
introduced readlinkat using libcephfs low-level APIs. However, it does
not handle properly the case where readlinkat operates on empty name
string (see man readlinkat(2)), such as:

  fd = openat(dirfd, symname, O_PATH | O_NOFOLLOW, 0);
  readlinkat(fd, "", buf, bufsiz);

Handle this special case of readlinkat with empty name string by using
a reference to the symlink inode itself.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686

Signed-off-by: Shachar Sharon <ssharon@redhat.com>
Reviewed-by: Anoop C S <anoopcs@samba.org>
Reviewed-by: Guenther Deschner <gd@samba.org>
Autobuild-User(master): Anoop C S <anoopcs@samba.org>
Autobuild-Date(master): Fri Aug 30 10:42:27 UTC 2024 on atb-devel-224

source3/modules/vfs_ceph_new.c

index cd98cb4e8d64d85c97666d1d0e83a7b2a939ddf9..1e4c3efeb23b06b92edf194de74e8633514cf0c7 100644 (file)
@@ -2461,7 +2461,6 @@ static int vfs_ceph_readlinkat(struct vfs_handle_struct *handle,
                size_t bufsiz)
 {
        int result = -1;
-       struct vfs_ceph_iref iref = {0};
        struct vfs_ceph_fh *dircfh = NULL;
 
        DBG_DEBUG("[CEPH] readlinkat(%p, %s, %p, %llu)\n",
@@ -2474,17 +2473,29 @@ static int vfs_ceph_readlinkat(struct vfs_handle_struct *handle,
        if (result != 0) {
                goto out;
        }
-       result = vfs_ceph_ll_lookupat(handle,
-                                     dircfh,
-                                     smb_fname->base_name,
-                                     &iref);
-       if (result != 0) {
-               goto out;
-       }
-
-       result = vfs_ceph_ll_readlinkat(handle, dircfh, &iref, buf, bufsiz);
+       if (strcmp(smb_fname->base_name, "") != 0) {
+               struct vfs_ceph_iref iref = {0};
 
-       vfs_ceph_iput(handle, &iref);
+               result = vfs_ceph_ll_lookupat(handle,
+                                             dircfh,
+                                             smb_fname->base_name,
+                                             &iref);
+               if (result != 0) {
+                       goto out;
+               }
+               result = vfs_ceph_ll_readlinkat(handle,
+                                               dircfh,
+                                               &iref,
+                                               buf,
+                                               bufsiz);
+               vfs_ceph_iput(handle, &iref);
+       } else {
+               result = vfs_ceph_ll_readlinkat(handle,
+                                               dircfh,
+                                               &dircfh->iref,
+                                               buf,
+                                               bufsiz);
+       }
 out:
        DBG_DEBUG("[CEPH] readlinkat(...) = %d\n", result);
        return status_code(result);