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);
extern const char *ceph_mds_op_name(int op);
#ifndef CEPH_SETATTR_MODE
-#define CEPH_SETATTR_MODE (1 << 0)
-#define CEPH_SETATTR_UID (1 << 1)
-#define CEPH_SETATTR_GID (1 << 2)
-#define CEPH_SETATTR_MTIME (1 << 3)
-#define CEPH_SETATTR_ATIME (1 << 4)
-#define CEPH_SETATTR_SIZE (1 << 5)
-#define CEPH_SETATTR_CTIME (1 << 6)
-#define CEPH_SETATTR_MTIME_NOW (1 << 7)
-#define CEPH_SETATTR_ATIME_NOW (1 << 8)
-#define CEPH_SETATTR_BTIME (1 << 9)
+#define CEPH_SETATTR_MODE (1 << 0)
+#define CEPH_SETATTR_UID (1 << 1)
+#define CEPH_SETATTR_GID (1 << 2)
+#define CEPH_SETATTR_MTIME (1 << 3)
+#define CEPH_SETATTR_ATIME (1 << 4)
+#define CEPH_SETATTR_SIZE (1 << 5)
+#define CEPH_SETATTR_CTIME (1 << 6)
+#define CEPH_SETATTR_MTIME_NOW (1 << 7)
+#define CEPH_SETATTR_ATIME_NOW (1 << 8)
+#define CEPH_SETATTR_BTIME (1 << 9)
+#define CEPH_SETATTR_KILL_SGUID (1 << 10)
+#define CEPH_SETATTR_FSCRYPT_AUTH (1 << 11)
+#define CEPH_SETATTR_FSCRYPT_FILE (1 << 12)
+#define CEPH_SETATTR_KILL_SUID (1 << 13)
+#define CEPH_SETATTR_KILL_SGID (1 << 14)
#endif
-#define CEPH_SETATTR_KILL_SGUID (1 << 10)
/*
* open request flags
/* setattr mask bits */
#ifndef CEPH_SETATTR_MODE
-# define CEPH_SETATTR_MODE 1
-# define CEPH_SETATTR_UID 2
-# define CEPH_SETATTR_GID 4
-# define CEPH_SETATTR_MTIME 8
-# define CEPH_SETATTR_ATIME 16
-# define CEPH_SETATTR_SIZE 32
-# define CEPH_SETATTR_CTIME 64
-# define CEPH_SETATTR_MTIME_NOW 128
-# define CEPH_SETATTR_ATIME_NOW 256
-# define CEPH_SETATTR_BTIME 512
+#define CEPH_SETATTR_MODE (1 << 0)
+#define CEPH_SETATTR_UID (1 << 1)
+#define CEPH_SETATTR_GID (1 << 2)
+#define CEPH_SETATTR_MTIME (1 << 3)
+#define CEPH_SETATTR_ATIME (1 << 4)
+#define CEPH_SETATTR_SIZE (1 << 5)
+#define CEPH_SETATTR_CTIME (1 << 6)
+#define CEPH_SETATTR_MTIME_NOW (1 << 7)
+#define CEPH_SETATTR_ATIME_NOW (1 << 8)
+#define CEPH_SETATTR_BTIME (1 << 9)
+#define CEPH_SETATTR_KILL_SGUID (1 << 10)
+#define CEPH_SETATTR_FSCRYPT_AUTH (1 << 11)
+#define CEPH_SETATTR_FSCRYPT_FILE (1 << 12)
+#define CEPH_SETATTR_KILL_SUID (1 << 13)
+#define CEPH_SETATTR_KILL_SGID (1 << 14)
#endif
/* define error codes for the mount function*/
__u32 access_mask = MAY_WRITE;
// xlock inode
- if (mask & (CEPH_SETATTR_MODE|CEPH_SETATTR_UID|CEPH_SETATTR_GID|CEPH_SETATTR_BTIME|CEPH_SETATTR_KILL_SGUID))
+ if (mask & (CEPH_SETATTR_MODE|CEPH_SETATTR_UID|CEPH_SETATTR_GID|CEPH_SETATTR_BTIME|CEPH_SETATTR_KILL_SGUID|CEPH_SETATTR_KILL_SUID|CEPH_SETATTR_KILL_SGID))
lov.add_xlock(&cur->authlock);
if (mask & (CEPH_SETATTR_MTIME|CEPH_SETATTR_ATIME|CEPH_SETATTR_SIZE))
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)