From: Xiubo Li Date: Thu, 9 Feb 2023 11:18:36 +0000 (+0800) Subject: client: allow unprivileged users to clear suid/sgid X-Git-Tag: v18.1.2~8^2~9 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=1d90ea1983f319ef8947bf86772fc5f97a0f6c7a;p=ceph.git client: allow unprivileged users to clear suid/sgid 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 (cherry picked from commit db10cfc8077bc79f59aea5a6fef18900f96edda6) --- diff --git a/src/client/Client.cc b/src/client/Client.cc index 473a3c62db2a..e84ad8e4416b 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -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;