]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
client: permission check for harklink
authorYan, Zheng <zyan@redhat.com>
Mon, 12 Oct 2015 09:22:27 +0000 (17:22 +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 7ae066a53a4e13277f9861204b48e2f31bc8017a..0ad9b327f10e52fab984fb4cc61a83d74bf77a0a 100644 (file)
@@ -5026,6 +5026,39 @@ out:
   return r;
 }
 
+int Client::may_hardlink(Inode *in, 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 (uid == 0 || (uid_t)uid == in->uid) {
+    r = 0;
+    goto out;
+  }
+
+  r = -EPERM;
+  if (!S_ISREG(in->mode))
+    goto out;
+
+  if (in->mode & S_ISUID)
+    goto out;
+
+  if ((in->mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))
+    goto out;
+
+  r = inode_permission(in, uid, groups, MAY_READ | MAY_WRITE);
+out:
+  ldout(cct, 3) << __func__ << " " << in << " = " << r <<  dendl;
+  return r;
+}
+
 vinodeno_t Client::_get_vino(Inode *in)
 {
   /* The caller must hold the client lock */
@@ -10596,6 +10629,9 @@ int Client::ll_link(Inode *in, Inode *newparent, const char *newname,
       r = -EPERM;
       goto out;
     }
+    r = may_hardlink(in, uid, gid);
+    if (r < 0)
+      goto out;
     r = may_create(newparent, uid, gid);
     if (r < 0)
       goto out;
index b630b7a165accb5b65f6519296b17ed0eb766a66..7d3a60a363610444ba0186ad9b8a028f37cf50b1 100644 (file)
@@ -789,6 +789,7 @@ private:
   int may_lookup(Inode *dir, 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);
+  int may_hardlink(Inode *in, int uid=-1, int gid=-1);
   int _getgrouplist(gid_t **sgids, int uid=-1, int gid=-1);
 
   int check_data_pool_exist(string name, string value, const OSDMap *osdmap);