Merge pull request #12331 from ceph/wip-jlayton-suid

Have ceph clear setuid/setgid bits on chown
This commit is contained in:
jtlayton 2016-12-08 09:35:56 -05:00 committed by GitHub
commit 07fd958b3c
3 changed files with 69 additions and 13 deletions

View File

@ -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();

View File

@ -3793,13 +3793,20 @@ void Server::handle_client_setattr(MDRequestRef& mdr)
pi = cur->project_inode();
if (mask & CEPH_SETATTR_MODE)
pi->mode = (pi->mode & ~07777) | (req->head.args.setattr.mode & 07777);
if (mask & CEPH_SETATTR_UID)
pi->uid = req->head.args.setattr.uid;
if (mask & CEPH_SETATTR_GID)
pi->gid = req->head.args.setattr.gid;
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)) &&
S_ISREG(pi->mode)) {
pi->mode &= ~S_ISUID;
if ((pi->mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP))
pi->mode &= ~S_ISGID;
}
if (mask & CEPH_SETATTR_MTIME)
pi->mtime = req->head.args.setattr.mtime;
if (mask & CEPH_SETATTR_ATIME)

View File

@ -1694,11 +1694,48 @@ TEST(LibCephFS, SetSize) {
struct ceph_statx stx;
uint64_t size = 8388608;
stx.stx_size = (off_t)size;
stx.stx_size = size;
ASSERT_EQ(ceph_fsetattrx(cmount, fd, &stx, CEPH_SETATTR_SIZE), 0);
ASSERT_EQ(ceph_fstatx(cmount, fd, &stx, CEPH_STATX_SIZE, 0), 0);
ASSERT_EQ(stx.stx_size, (off_t)size);
ASSERT_EQ(stx.stx_size, size);
ceph_close(cmount, fd);
ceph_shutdown(cmount);
}
TEST(LibCephFS, ClearSetuid) {
struct ceph_mount_info *cmount;
ASSERT_EQ(ceph_create(&cmount, NULL), 0);
ASSERT_EQ(ceph_conf_read_file(cmount, NULL), 0);
ASSERT_EQ(0, ceph_conf_parse_env(cmount, NULL));
ASSERT_EQ(ceph_mount(cmount, "/"), 0);
Inode *root;
ASSERT_EQ(ceph_ll_lookup_root(cmount, &root), 0);
char filename[32];
sprintf(filename, "clearsetuid%x", getpid());
Fh *fh;
Inode *in;
struct ceph_statx stx;
ceph_ll_unlink(cmount, root, filename, ceph_mount_perms(cmount));
ASSERT_EQ(ceph_ll_create(cmount, root, filename, 06555,
O_RDWR|O_CREAT|O_EXCL, &in, &fh, &stx,
CEPH_STATX_UID|CEPH_STATX_GID|CEPH_STATX_MODE, 0,
ceph_mount_perms(cmount)), 0);
ASSERT_EQ(stx.stx_mode & 07777, 06555);
UserPerm *rootcred = ceph_userperm_new(0, 0, 0, NULL);
ASSERT_TRUE(rootcred);
stx.stx_uid++;
stx.stx_gid++;
ASSERT_EQ(ceph_ll_setattr(cmount, in, &stx, CEPH_SETATTR_UID|CEPH_SETATTR_GID, rootcred), 0);
ASSERT_EQ(ceph_ll_getattr(cmount, in, &stx, CEPH_STATX_MODE, 0, ceph_mount_perms(cmount)), 0);
ASSERT_TRUE(stx.stx_mask & CEPH_STATX_MODE);
ASSERT_FALSE(stx.stx_mode & (S_ISUID|S_ISGID));
ceph_shutdown(cmount);
}