From: Shachar Sharon Date: Tue, 20 Aug 2024 09:45:07 +0000 (+0300) Subject: vfs_ceph_new: handle case of readlinkat with empty name string X-Git-Tag: tdb-1.4.13~1242 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=22182f90e8e7876a9895f77e736d2b96b18b174f;p=thirdparty%2Fsamba.git vfs_ceph_new: handle case of readlinkat with empty name string 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 Reviewed-by: Anoop C S Reviewed-by: Guenther Deschner Autobuild-User(master): Anoop C S Autobuild-Date(master): Fri Aug 30 10:42:27 UTC 2024 on atb-devel-224 --- diff --git a/source3/modules/vfs_ceph_new.c b/source3/modules/vfs_ceph_new.c index cd98cb4e8d6..1e4c3efeb23 100644 --- a/source3/modules/vfs_ceph_new.c +++ b/source3/modules/vfs_ceph_new.c @@ -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);