]> 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 01:55:36 +0000 (09:55 +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 473a3c62db2ab1c9602d93631b8526d447eadde5..e84ad8e4416b644c89cee7c2fcd1d164b820e17b 100644 (file)
@@ -5793,7 +5793,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;
@@ -5816,7 +5817,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;