]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
client: permission check for setattr
authorYan, Zheng <zyan@redhat.com>
Tue, 29 Sep 2015 08:31:03 +0000 (16:31 +0800)
committerYan, Zheng <zyan@redhat.com>
Tue, 12 Jan 2016 09:21:01 +0000 (17:21 +0800)
Signed-off-by: Yan, Zheng <zyan@redhat.com>
src/client/Client.cc
src/client/Client.h

index 5701c1f786b2ca0e323e498df68c008c4ad1dcc2..7e5ba40ed7434da647a320157cbed93e1d96eb95 100644 (file)
@@ -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) {
index 5bcf760b7733eb97c890324e6522145720a4586d..db3f8d820ca8196f32083bdf2c7ca9a9dfbd2808 100644 (file)
@@ -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);