]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
client: drop setuid/setgid bits on ownership change 12331/head
authorJeff Layton <jlayton@redhat.com>
Mon, 5 Dec 2016 19:11:44 +0000 (14:11 -0500)
committerJeff Layton <jlayton@redhat.com>
Wed, 7 Dec 2016 17:10:56 +0000 (12:10 -0500)
When we hold exclusive auth caps, then the client is responsible for
handling changes to the mode. Make sure we remove any setuid/setgid
bits on an ownership change.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
src/client/Client.cc

index a8dd3a2af57b81db80a3871026131bcc94d32d74..3638863e81e2408d15995c66d5b7877cd609d47b 100644 (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();