man fchownat(2)[1] says the following:
. . .
AT_EMPTY_PATH (since Linux 2.6.39)
If pathname is an empty string, operate on the file referred to by
dirfd (which may have been obtained using the open(2) O_PATH flag).
In this case, dirfd can refer to any type of file, not just a
directory. If dirfd is AT_FDCWD, the call operates on the current
working directory.
. . .
Look out for an empty pathname and use the relative fd's inode in the
presence of AT_EMPTY_PATH flag before calling internal _setattr().
Fixes: https://tracker.ceph.com/issues/68189
Review with: git show -w
[1] https://www.man7.org/linux/man-pages/man2/fchownat.2.html
Signed-off-by: Anoop C S <anoopcs@cryptolab.net>
(cherry picked from commit
829f38899226fcd1f603ba446b018f53c5b0921d)
tout(cct) << new_gid << std::endl;
tout(cct) << flags << std::endl;
- filepath path(relpath);
InodeRef in;
InodeRef dirinode;
return r;
}
- r = path_walk(path, &in, perms, !(flags & AT_SYMLINK_NOFOLLOW), 0, dirinode);
- if (r < 0) {
- return r;
+ if (!strcmp(relpath, "")) {
+#if defined(__linux__) && defined(AT_EMPTY_PATH)
+ if (flags & AT_EMPTY_PATH) {
+ in = dirinode;
+ goto out;
+ }
+#endif
+ return -CEPHFS_ENOENT;
+ } else {
+ filepath path(relpath);
+ r = path_walk(path, &in, perms, !(flags & AT_SYMLINK_NOFOLLOW), 0, dirinode);
+ if (r < 0) {
+ return r;
+ }
}
+
+out:
+
struct stat attr;
attr.st_uid = new_uid;
attr.st_gid = new_gid;
* @param relpath the relpath of the file/directory to change the ownership of.
* @param uid the user id to set on the file/directory.
* @param gid the group id to set on the file/directory.
- * @param flags bitfield that can be used to set AT_* modifier flags (AT_SYMLINK_NOFOLLOW)
+ * @param flags bitfield that can be used to set AT_* modifier flags (AT_SYMLINK_NOFOLLOW and AT_EMPTY_PATH)
* @returns 0 on success or negative error code on failure.
*/
int ceph_chownat(struct ceph_mount_info *cmount, int dirfd, const char *relpath,
// change ownership to nobody -- we assume nobody exists and id is always 65534
ASSERT_EQ(ceph_conf_set(cmount, "client_permissions", "0"), 0);
ASSERT_EQ(ceph_chownat(cmount, fd, rel_file_path, 65534, 65534, 0), 0);
+ // change relative fd ownership with AT_EMPTY_PATH
+#if defined(__linux__) && defined(AT_EMPTY_PATH)
+ int file_fd = ceph_openat(cmount, fd, rel_file_path, O_RDONLY, 0);
+ ASSERT_LE(0, file_fd);
+ ASSERT_EQ(ceph_chownat(cmount, file_fd, "", 65534, 65534, AT_EMPTY_PATH), 0);
+ ceph_close(cmount, file_fd);
+#endif
ASSERT_EQ(ceph_conf_set(cmount, "client_permissions", "1"), 0);
ceph_close(cmount, fd);