]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
client: switch to clear_suid_sgid for ftruncate
authorXiubo Li <xiubli@redhat.com>
Mon, 13 Mar 2023 14:22:50 +0000 (22:22 +0800)
committerXiubo Li <xiubli@redhat.com>
Tue, 11 Apr 2023 02:39:48 +0000 (10:39 +0800)
Currently the ftruncate will always clear the suid/sgid even the
privileged users are truncating the file. This isn't consistent with
all the other existing filesystems in Linux.

Fixes: https://tracker.ceph.com/issues/58680
Signed-off-by: Xiubo Li <xiubli@redhat.com>
(cherry picked from commit c5153d77fa2e2a67715c9d78cbbd000ecbea3a17)

src/client/Client.cc
src/client/Client.h

index ee52e9a7b03e192b959d42de9b8a5a9a9d637064..8b95c87c5ba07caf7ce88dd88db538a5ac1bbca5 100644 (file)
@@ -7759,11 +7759,7 @@ int Client::_do_setattr(Inode *in, struct ceph_statx *stx, int mask,
   }
 
   if (in->caps_issued_mask(CEPH_CAP_AUTH_EXCL)) {
-    kill_sguid = mask & (CEPH_SETATTR_SIZE|CEPH_SETATTR_KILL_SGUID);
-  } else if (mask & CEPH_SETATTR_SIZE) {
-    /* If we don't have Ax, then we must ask the server to clear them on truncate */
-    mask |= CEPH_SETATTR_KILL_SGUID;
-    inode_drop |= CEPH_CAP_AUTH_SHARED;
+    kill_sguid = !!(mask & CEPH_SETATTR_KILL_SGUID);
   }
 
   if (mask & CEPH_SETATTR_UID) {
@@ -7991,6 +7987,10 @@ void Client::stat_to_statx(struct stat *st, struct ceph_statx *stx)
 int Client::__setattrx(Inode *in, struct ceph_statx *stx, int mask,
                       const UserPerm& perms, InodeRef *inp)
 {
+  if (mask & CEPH_SETATTR_SIZE) {
+    mask |= clear_suid_sgid(in, perms, true);
+  }
+
   int ret = _do_setattr(in, stx, mask, perms, inp);
   if (ret < 0)
    return ret;
@@ -14809,9 +14809,10 @@ int Client::ll_sync_inode(Inode *in, bool syncdataonly)
   return _fsync(in, syncdataonly);
 }
 
-int Client::clear_suid_sgid(Inode *in, const UserPerm& perms)
+int Client::clear_suid_sgid(Inode *in, const UserPerm& perms, bool defer)
 {
-  ldout(cct, 20) << __func__ << " " << *in << "; " << perms << dendl;
+  ldout(cct, 20) << __func__ << " " << *in << "; " << perms << " defer "
+                 << defer << dendl;
 
   if (!in->is_file()) {
     return 0;
@@ -14825,7 +14826,7 @@ int Client::clear_suid_sgid(Inode *in, const UserPerm& perms)
     return 0;
   }
 
-  int mask;
+  int mask = 0;
 
   // always drop the suid
   if (unlikely(in->mode & S_ISUID)) {
@@ -14840,6 +14841,10 @@ int Client::clear_suid_sgid(Inode *in, const UserPerm& perms)
   }
 
   ldout(cct, 20) << __func__ << " mask " << mask << dendl;
+  if (defer) {
+    return mask;
+  }
+
   struct ceph_statx stx = { 0 };
   return __setattrx(in, &stx, mask, perms);
 }
index bf43dad769114915afd6dfaf6672dec0677ed658..a1b5b9129b3cede13da07d5a302b6ed9ca8b996d 100644 (file)
@@ -1385,7 +1385,7 @@ private:
   int _fsync(Fh *fh, bool syncdataonly);
   int _fsync(Inode *in, bool syncdataonly);
   int _sync_fs();
-  int clear_suid_sgid(Inode *in, const UserPerm& perms);
+  int clear_suid_sgid(Inode *in, const UserPerm& perms, bool defer=false);
   int _fallocate(Fh *fh, int mode, int64_t offset, int64_t length);
   int _getlk(Fh *fh, struct flock *fl, uint64_t owner);
   int _setlk(Fh *fh, struct flock *fl, uint64_t owner, int sleep);