According to [1], the suid/sgid should be cleared if any of the executable bits
are set.
Found this while experimenting for [2].
[1] http://pubs.opengroup.org/onlinepubs/
9699919799/functions/chown.html
[2] https://bugzilla.redhat.com/show_bug.cgi?id=
1480182
Fixes: http://tracker.ceph.com/issues/21004
Signed-off-by: Patrick Donnelly <pdonnell@redhat.com>
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)) {
+ } else if (kill_sguid && S_ISREG(in->mode) && (in->mode & (S_IXUSR|S_IXGRP|S_IXOTH))) {
/* 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;
+ in->mode &= ~(S_ISUID|S_ISGID);
mark_caps_dirty(in, CEPH_CAP_AUTH_EXCL);
}
if (mask & CEPH_SETATTR_MODE)
pi->mode = (pi->mode & ~07777) | (req->head.args.setattr.mode & 07777);
else if ((mask & (CEPH_SETATTR_UID|CEPH_SETATTR_GID|CEPH_SETATTR_KILL_SGUID)) &&
- S_ISREG(pi->mode)) {
- pi->mode &= ~S_ISUID;
- if ((pi->mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP))
- pi->mode &= ~S_ISGID;
+ S_ISREG(pi->mode) &&
+ (pi->mode & (S_IXUSR|S_IXGRP|S_IXOTH))) {
+ pi->mode &= ~(S_ISUID|S_ISGID);
}
if (mask & CEPH_SETATTR_MTIME)