From: Yan, Zheng Date: Tue, 29 Sep 2015 08:31:03 +0000 (+0800) Subject: client: permission check for setattr X-Git-Tag: v10.0.3~48^2~3^2~10 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=96f4af34a4c3d5718210faeebd5c85e3bc5e0ca2;p=ceph.git client: permission check for setattr Signed-off-by: Yan, Zheng --- diff --git a/src/client/Client.cc b/src/client/Client.cc index 5701c1f786b2..7e5ba40ed743 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -4847,6 +4847,54 @@ int Client::inode_permission(Inode *in, uid_t uid, UserGroups& groups, unsigned return 0; } +int Client::may_setattr(Inode *in, struct stat *st, int mask, int uid, int gid) +{ + if (uid < 0) + uid = get_uid(); + if (gid < 0) + gid = get_gid(); + RequestUserGroups groups(this, uid, gid); + + int r = _getattr(in, CEPH_STAT_CAP_MODE, uid, gid); + if (r < 0) + goto out; + + if (mask & CEPH_SETATTR_SIZE) { + r = inode_permission(in, uid, groups, MAY_WRITE); + if (r < 0) + goto out; + } + + r = -EPERM; + if (mask & CEPH_SETATTR_UID) { + if (uid != 0 && ((uid_t)uid != in->uid || st->st_uid != in->uid)) + goto out; + } + if (mask & CEPH_SETATTR_GID) { + if (uid != 0 && ((uid_t)uid != in->uid || + (!groups.is_in(st->st_gid) && st->st_gid != in->gid))) + goto out; + } + + if (mask & CEPH_SETATTR_MODE) { + if (uid != 0 && (uid_t)uid != in->uid) + goto out; + + gid_t i_gid = (mask & CEPH_SETATTR_GID) ? st->st_gid : in->gid; + if (uid != 0 && !groups.is_in(i_gid)) + st->st_mode &= ~S_ISGID; + } + + if (mask & (CEPH_SETATTR_CTIME | CEPH_SETATTR_MTIME | CEPH_SETATTR_ATIME)) { + if (uid != 0 && (uid_t)uid != in->uid) + goto out; + } + r = 0; +out: + ldout(cct, 3) << __func__ << " " << in << " = " << r << dendl; + return r; +} + int Client::may_open(Inode *in, int flags, int uid, int gid) { unsigned want = 0; @@ -9123,6 +9171,12 @@ int Client::ll_setattr(Inode *in, struct stat *attr, int mask, int uid, tout(cct) << attr->st_atime << std::endl; tout(cct) << mask << std::endl; + if (!cct->_conf->fuse_default_permissions) { + int res = may_setattr(in, attr, mask, uid, gid); + if (res < 0) + return res; + } + InodeRef target(in); int res = _setattr(in, attr, mask, uid, gid, &target); if (res == 0) { diff --git a/src/client/Client.h b/src/client/Client.h index 5bcf760b7733..db3f8d820ca8 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -783,6 +783,7 @@ private: }; int inode_permission(Inode *in, uid_t uid, UserGroups& groups, unsigned want); + int may_setattr(Inode *in, struct stat *st, int mask, int uid=-1, int gid=-1); int may_open(Inode *in, int flags, int uid=-1, int gid=-1); int may_create(Inode *dir, int uid=-1, int gid=-1); int may_delete(Inode *dir, const char *name, int uid=-1, int gid=-1);