if (in->caps_issued_mask(CEPH_CAP_AUTH_EXCL)) {
kill_sguid = mask & (CEPH_SETATTR_SIZE|CEPH_SETATTR_KILL_SGUID);
-
- mask &= ~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;
} else {
mask &= ~CEPH_SETATTR_MODE;
}
- } else if (in->caps_issued_mask(CEPH_CAP_AUTH_EXCL) &&
- 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|S_ISGID);
+ } else if (in->caps_issued_mask(CEPH_CAP_AUTH_EXCL) && S_ISREG(in->mode)) {
+ if (kill_sguid && (in->mode & (S_IXUSR|S_IXGRP|S_IXOTH))) {
+ in->mode &= ~(S_ISUID|S_ISGID);
+ } else {
+ if (mask & CEPH_SETATTR_KILL_SUID) {
+ in->mode &= ~S_ISUID;
+ }
+ if (mask & CEPH_SETATTR_KILL_SGID) {
+ in->mode &= ~S_ISGID;
+ }
+ }
+ mask &= ~(CEPH_SETATTR_KILL_SGUID|CEPH_SETATTR_KILL_SUID|CEPH_SETATTR_KILL_SGID);
in->mark_caps_dirty(CEPH_CAP_AUTH_EXCL);
}
return _fsync(in, syncdataonly);
}
+int Client::clear_suid_sgid(Inode *in, const UserPerm& perms)
+{
+ ldout(cct, 20) << __func__ << " " << *in << "; " << perms << dendl;
+
+ if (!in->is_file()) {
+ return 0;
+ }
+
+ if (likely(!(in->mode & (S_ISUID|S_ISGID)))) {
+ return 0;
+ }
+
+ if (perms.uid() == 0 || perms.uid() == in->uid) {
+ return 0;
+ }
+
+ int mask;
+
+ // always drop the suid
+ if (unlikely(in->mode & S_ISUID)) {
+ mask = CEPH_SETATTR_KILL_SUID;
+ }
+
+ // remove the sgid if S_IXUGO is set or the inode is
+ // is not in the caller's group list.
+ if ((in->mode & S_ISGID) &&
+ ((in->mode & S_IXUGO) || !perms.gid_in_groups(in->gid))) {
+ mask |= CEPH_SETATTR_KILL_SGID;
+ }
+
+ ldout(cct, 20) << __func__ << " mask " << mask << dendl;
+ struct ceph_statx stx = { 0 };
+ return __setattrx(in, &stx, mask, perms);
+}
+
int Client::_fallocate(Fh *fh, int mode, int64_t offset, int64_t length)
{
ceph_assert(ceph_mutex_is_locked_by_me(client_lock));
if (r < 0)
return r;
+ r = clear_suid_sgid(in, fh->actor_perms);
+ if (r < 0) {
+ put_cap_ref(in, CEPH_CAP_FILE_WR);
+ return r;
+ }
+
std::unique_ptr<C_SaferCond> onuninline = nullptr;
if (mode & FALLOC_FL_PUNCH_HOLE) {
if (in->inline_version < CEPH_INLINE_NONE &&
if (!mref_reader.is_state_satisfied())
return -CEPHFS_ENOTCONN;
- tout(cct) << __func__ << " " << " " << fd << mode << " " << offset << " " << length << std::endl;
+ tout(cct) << __func__ << " " << fd << mode << " " << offset << " " << length << std::endl;
std::scoped_lock lock(client_lock);
Fh *fh = get_filehandle(fd);
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 _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);
}
// xlock inode
- if (mask & (CEPH_SETATTR_MODE|CEPH_SETATTR_UID|CEPH_SETATTR_GID|CEPH_SETATTR_BTIME|CEPH_SETATTR_KILL_SGUID|CEPH_SETATTR_FSCRYPT_AUTH))
+ if (mask & (CEPH_SETATTR_MODE|CEPH_SETATTR_UID|CEPH_SETATTR_GID|CEPH_SETATTR_BTIME|CEPH_SETATTR_KILL_SGUID|CEPH_SETATTR_FSCRYPT_AUTH|CEPH_SETATTR_KILL_SUID|CEPH_SETATTR_KILL_SGID))
lov.add_xlock(&cur->authlock);
if (mask & (CEPH_SETATTR_MTIME|CEPH_SETATTR_ATIME|CEPH_SETATTR_SIZE|CEPH_SETATTR_FSCRYPT_FILE))
lov.add_xlock(&cur->filelock);
if (mask & CEPH_SETATTR_MODE)
pi.inode->mode = (pi.inode->mode & ~07777) | (req->head.args.setattr.mode & 07777);
- else if ((mask & (CEPH_SETATTR_UID|CEPH_SETATTR_GID|CEPH_SETATTR_KILL_SGUID)) &&
- S_ISREG(pi.inode->mode) &&
- (pi.inode->mode & (S_IXUSR|S_IXGRP|S_IXOTH))) {
- pi.inode->mode &= ~(S_ISUID|S_ISGID);
+ else if ((mask & (CEPH_SETATTR_UID|CEPH_SETATTR_GID|CEPH_SETATTR_KILL_SGUID|
+ CEPH_SETATTR_KILL_SUID|CEPH_SETATTR_KILL_SGID)) &&
+ S_ISREG(pi.inode->mode)) {
+ if (mask & (CEPH_SETATTR_UID|CEPH_SETATTR_GID|CEPH_SETATTR_KILL_SGUID) &&
+ (pi.inode->mode & (S_IXUSR|S_IXGRP|S_IXOTH))) {
+ pi.inode->mode &= ~(S_ISUID|S_ISGID);
+ } else {
+ if (mask & CEPH_SETATTR_KILL_SUID) {
+ pi.inode->mode &= ~S_ISUID;
+ }
+ if (mask & CEPH_SETATTR_KILL_SGID) {
+ pi.inode->mode &= ~S_ISGID;
+ }
+ }
}
if (mask & CEPH_SETATTR_MTIME)