From: Jeff Layton Date: Mon, 5 Dec 2016 19:11:44 +0000 (-0500) Subject: client: drop setuid/setgid bits on ownership change X-Git-Tag: v11.1.0~27^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=18d2499d6c85a10b4b54f3b8c335cddf86c4588f;p=ceph.git client: drop setuid/setgid bits on ownership change When we hold exclusive auth caps, then the client is responsible for handling changes to the mode. Make sure we remove any setuid/setgid bits on an ownership change. Signed-off-by: Jeff Layton --- diff --git a/src/client/Client.cc b/src/client/Client.cc index a8dd3a2af57b..3638863e81e2 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -6494,15 +6494,8 @@ int Client::_do_setattr(Inode *in, struct ceph_statx *stx, int mask, } if (in->caps_issued_mask(CEPH_CAP_AUTH_EXCL)) { - if (mask & CEPH_SETATTR_MODE) { - in->ctime = ceph_clock_now(cct); - in->cap_dirtier_uid = perms.uid(); - in->cap_dirtier_gid = perms.gid(); - in->mode = (in->mode & ~07777) | (stx->stx_mode & 07777); - mark_caps_dirty(in, CEPH_CAP_AUTH_EXCL); - mask &= ~CEPH_SETATTR_MODE; - ldout(cct,10) << "changing mode to " << stx->stx_mode << dendl; - } + bool kill_sguid = false; + if (mask & CEPH_SETATTR_UID) { in->ctime = ceph_clock_now(cct); in->cap_dirtier_uid = perms.uid(); @@ -6510,6 +6503,7 @@ int Client::_do_setattr(Inode *in, struct ceph_statx *stx, int mask, in->uid = stx->stx_uid; mark_caps_dirty(in, CEPH_CAP_AUTH_EXCL); mask &= ~CEPH_SETATTR_UID; + kill_sguid = true; ldout(cct,10) << "changing uid to " << stx->stx_uid << dendl; } if (mask & CEPH_SETATTR_GID) { @@ -6519,8 +6513,26 @@ int Client::_do_setattr(Inode *in, struct ceph_statx *stx, int mask, in->gid = stx->stx_gid; mark_caps_dirty(in, CEPH_CAP_AUTH_EXCL); mask &= ~CEPH_SETATTR_GID; + kill_sguid = true; ldout(cct,10) << "changing gid to " << stx->stx_gid << dendl; } + + if (mask & CEPH_SETATTR_MODE) { + in->ctime = ceph_clock_now(cct); + in->cap_dirtier_uid = perms.uid(); + in->cap_dirtier_gid = perms.gid(); + in->mode = (in->mode & ~07777) | (stx->stx_mode & 07777); + mark_caps_dirty(in, CEPH_CAP_AUTH_EXCL); + mask &= ~CEPH_SETATTR_MODE; + ldout(cct,10) << "changing mode to " << stx->stx_mode << dendl; + } else if (kill_sguid && S_ISREG(in->mode)) { + /* Must squash the any setuid/setgid bits with an ownership change */ + in->mode &= ~S_ISUID; + if ((in->mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) + in->mode &= ~S_ISGID; + mark_caps_dirty(in, CEPH_CAP_AUTH_EXCL); + } + if (mask & CEPH_SETATTR_BTIME) { in->ctime = ceph_clock_now(cct); in->cap_dirtier_uid = perms.uid();