From: Xiubo Li Date: Mon, 13 Mar 2023 14:22:50 +0000 (+0800) Subject: client: switch to clear_suid_sgid for ftruncate X-Git-Tag: v18.1.2~8^2~5 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=d88a2505e8cb05a95659bd2c90717946108c8838;p=ceph.git client: switch to clear_suid_sgid for ftruncate 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 (cherry picked from commit c5153d77fa2e2a67715c9d78cbbd000ecbea3a17) --- diff --git a/src/client/Client.cc b/src/client/Client.cc index 1e5d43f08f38..24c447af2531 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -7796,11 +7796,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) { @@ -8073,6 +8069,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; @@ -14922,9 +14922,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; @@ -14938,7 +14939,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)) { @@ -14953,6 +14954,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); } diff --git a/src/client/Client.h b/src/client/Client.h index f24bb8a37a6b..9dd05517d5cb 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -1389,7 +1389,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);