ceph: check the cephx mds auth access for async dirop
authorXiubo Li <xiubli@redhat.com>
Wed, 8 Nov 2023 03:06:05 +0000 (11:06 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Thu, 23 May 2024 08:35:47 +0000 (10:35 +0200)
Before doing the op locally we need to check the cephx access.

Link: https://tracker.ceph.com/issues/61333
Signed-off-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: Milind Changire <mchangir@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/dir.c
fs/ceph/file.c

index 0e9f56eaba1e693d22142487e79b433a0213f759..82a2e2a06a659fd108d1d0a002bfdbefb24a2053 100644 (file)
@@ -1336,8 +1336,12 @@ static int ceph_unlink(struct inode *dir, struct dentry *dentry)
        struct inode *inode = d_inode(dentry);
        struct ceph_mds_request *req;
        bool try_async = ceph_test_mount_opt(fsc, ASYNC_DIROPS);
+       struct dentry *dn;
        int err = -EROFS;
        int op;
+       char *path;
+       int pathlen;
+       u64 pathbase;
 
        if (ceph_snap(dir) == CEPH_SNAPDIR) {
                /* rmdir .snap/foo is RMSNAP */
@@ -1351,6 +1355,30 @@ static int ceph_unlink(struct inode *dir, struct dentry *dentry)
                        CEPH_MDS_OP_RMDIR : CEPH_MDS_OP_UNLINK;
        } else
                goto out;
+
+       dn = d_find_alias(dir);
+       if (!dn) {
+               try_async = false;
+       } else {
+               path = ceph_mdsc_build_path(mdsc, dn, &pathlen, &pathbase, 0);
+               if (IS_ERR(path)) {
+                       try_async = false;
+                       err = 0;
+               } else {
+                       err = ceph_mds_check_access(mdsc, path, MAY_WRITE);
+               }
+               ceph_mdsc_free_path(path, pathlen);
+               dput(dn);
+
+               /* For none EACCES cases will let the MDS do the mds auth check */
+               if (err == -EACCES) {
+                       return err;
+               } else if (err < 0) {
+                       try_async = false;
+                       err = 0;
+               }
+       }
+
 retry:
        req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS);
        if (IS_ERR(req)) {
index 4de4bdd7949e54a0dd59d0116ad2bcfe90ac365c..4b8d59ebda00922bcef14c05561af7559a0e8676 100644 (file)
@@ -790,6 +790,9 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
        bool try_async = ceph_test_mount_opt(fsc, ASYNC_DIROPS);
        int mask;
        int err;
+       char *path;
+       int pathlen;
+       u64 pathbase;
 
        doutc(cl, "%p %llx.%llx dentry %p '%pd' %s flags %d mode 0%o\n",
              dir, ceph_vinop(dir), dentry, dentry,
@@ -807,6 +810,34 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
         */
        flags &= ~O_TRUNC;
 
+       dn = d_find_alias(dir);
+       if (!dn) {
+               try_async = false;
+       } else {
+               path = ceph_mdsc_build_path(mdsc, dn, &pathlen, &pathbase, 0);
+               if (IS_ERR(path)) {
+                       try_async = false;
+                       err = 0;
+               } else {
+                       int fmode = ceph_flags_to_mode(flags);
+
+                       mask = MAY_READ;
+                       if (fmode & CEPH_FILE_MODE_WR)
+                               mask |= MAY_WRITE;
+                       err = ceph_mds_check_access(mdsc, path, mask);
+               }
+               ceph_mdsc_free_path(path, pathlen);
+               dput(dn);
+
+               /* For none EACCES cases will let the MDS do the mds auth check */
+               if (err == -EACCES) {
+                       return err;
+               } else if (err < 0) {
+                       try_async = false;
+                       err = 0;
+               }
+       }
+
 retry:
        if (flags & O_CREAT) {
                if (ceph_quota_is_max_files_exceeded(dir))