]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
client: allow unprivileged users to clear suid/sgid
authorXiubo Li <xiubli@redhat.com>
Thu, 9 Feb 2023 11:18:36 +0000 (19:18 +0800)
committerXiubo Li <xiubli@redhat.com>
Tue, 11 Apr 2023 02:34:55 +0000 (10:34 +0800)
The fallocate path will try to clear the suid/sgid if a unprivileged
user changed the file. And the VFS will set the ATTR_MODE and at the
same time by clearing the suid/sgid mode bits.

There is no Posix item requires that we should clear the suid/sgid
in fallocate code path but this is the default behaviour for most of
the filesystems and the VFS layer. And also the same for the write
code path, which have already support it.

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

src/client/Client.cc

index ac41495b72a03a10fc3ee4d83a8d598b8ea35a91..c83f6f4837a8bdec4cf254b7614a79c9c71725ed 100644 (file)
@@ -5764,7 +5764,8 @@ std::ostream& operator<<(std::ostream &out, const UserPerm& perm) {
 int Client::may_setattr(Inode *in, struct ceph_statx *stx, int mask,
                        const UserPerm& perms)
 {
-  ldout(cct, 20) << __func__ << " " << *in << "; " << perms << dendl;
+  ldout(cct, 20) << __func__ << " " << *in << "; " << perms << " stx_mode: "
+      << hex << stx->stx_mode << " mask:" << mask << dec << dendl;
   int r = _getattr_for_perm(in, perms);
   if (r < 0)
     goto out;
@@ -5787,7 +5788,18 @@ int Client::may_setattr(Inode *in, struct ceph_statx *stx, int mask,
   }
 
   if (mask & CEPH_SETATTR_MODE) {
-    if (perms.uid() != 0 && perms.uid() != in->uid)
+    uint32_t m = ~stx->stx_mode & in->mode; // mode bits removed
+    ldout(cct, 20) << __func__ << " " << *in << " = " << hex << m << dec <<  dendl;
+    if (perms.uid() != 0 && perms.uid() != in->uid &&
+       /*
+        * Currently the kernel fuse and libfuse code is buggy and
+        * won't pass the ATTR_KILL_SUID/ATTR_KILL_SGID to ceph-fuse.
+        * But will just set the ATTR_MODE and at the same time by
+        * clearing the suid/sgid bits.
+        *
+        * Only allow unprivileged users to clear S_ISUID and S_ISUID.
+        */
+       (m & ~(S_ISUID | S_ISGID)))
       goto out;
 
     gid_t i_gid = (mask & CEPH_SETATTR_GID) ? stx->stx_gid : in->gid;