]> git.apps.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, 14 Mar 2023 14:54:05 +0000 (22:54 +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>
src/client/Client.cc

index 365bb8f6ce57b9924088fd38c683909259de7903..f6fb163ca1280e93fe6cb592fcf1e1295033f7ec 100644 (file)
@@ -5819,7 +5819,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;
@@ -5842,7 +5843,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;