Patchwork [BRANCH:release-3.1,BUG:1337] Access-Control : Changes in setattr for posix compliance.

login
register
Submitter Gaurav
Date 2011-05-03 10:16:13
Message ID <1304417773-32054-1-git-send-email-gaurav@gluster.com>
Download mbox | patch
Permalink /patch/7126/
State Accepted
Delegated to: Shehjar Tikoo
Headers show

Comments

Gaurav - 2011-05-03 10:16:13
From: Gaurav <gaurav@gluster.com>


Signed-off-by: Gaurav <gaurav@gluster.com>
---
 .../features/access-control/src/access-control.c   |  141 ++++++++++++++++----
 1 files changed, 116 insertions(+), 25 deletions(-)

Patch

diff --git a/xlators/features/access-control/src/access-control.c b/xlators/features/access-control/src/access-control.c
index 78a0629..a4b4015 100644
--- a/xlators/features/access-control/src/access-control.c
+++ b/xlators/features/access-control/src/access-control.c
@@ -114,6 +114,8 @@  ac_test_group_access (struct iatt *ia, gid_t gid, gid_t *auxgids, int auxcount,
          */
 
         if ((ia->ia_gid != gid) && (auxcount == 0)) {
+                gf_log (ACTRL, GF_LOG_DEBUG, "GID mismatch (orig: %d, user: %d)",
+                        ia->ia_gid, gid);
                 ret = -1;
                 goto out;
         }
@@ -131,6 +133,8 @@  ac_test_group_access (struct iatt *ia, gid_t gid, gid_t *auxgids, int auxcount,
 
         /* None of the gids match with the gid in the stat. */
         if (testgid == -1) {
+                gf_log (ACTRL, GF_LOG_DEBUG, "None of the gids match with gid "
+                        "on the stat");
                 ret = -1;
                 goto out;
         }
@@ -1685,23 +1689,61 @@  ac_setattr_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
         if (op_ret == -1)
                 goto out;
 
-        op_ret = ac_test_access (buf, frame->root->uid, frame->root->gid,
-                                 frame->root->groups, frame->root->ngrps,
-                                 ACCTEST_WRITE, ACCTEST_ANY,
-                                 &op_errno);
-        if (op_ret == -1)
-                goto out;
+        if ((frame->root->uid != buf->ia_uid) && (frame->root->uid != 0)) {
+                op_ret = ac_test_access (buf, frame->root->uid, frame->root->gid,
+                                         frame->root->groups, frame->root->ngrps,
+                                         ACCTEST_WRITE, ACCTEST_ANY,
+                                         &op_errno);
+                if (op_ret == -1) {
+                        gf_log (ACTRL, GF_LOG_DEBUG, "Don't have write permision");
+                        goto out;
+                }
+        }
 
         valid = stub->args.setattr.valid;
         setbuf = &stub->args.setattr.stbuf;
-        if (gf_attr_uid_set (valid) || gf_attr_gid_set (valid)) {
-                /* chown returns EPERM if the operation would change the
-                 * ownership, but the effective user ID is not the
+        if (gf_attr_uid_set (valid) || gf_attr_gid_set (valid)
+            || gf_attr_mode_set(valid)) {
+                /* chown/chmod returns EPERM if the operation would change the
+                 * ownership/permissions, but the effective user ID is not the
                  * super-user and the process is not an owner of the file.
                  * Ref: posix-testsuite/chown/07.t
                  */
-                if ((frame->root->uid != 0) && (gf_attr_uid_set (valid))) {
-                        if (buf->ia_uid != setbuf->ia_uid) {
+                if ((frame->root->uid != 0) && gf_attr_mode_set(valid)) {
+                        if (frame->root->uid != buf->ia_uid) {
+                                gf_log (ACTRL, GF_LOG_DEBUG, "Mismatch effective_uid %d file_uid %d",
+                                        frame->root->uid, buf->ia_uid);
+                                op_ret = -1;
+                                op_errno = EPERM;
+                                goto out;
+                        }
+                        /* POSIX: If the calling process does not have appropriate privileges, and if
+                        the group ID of the file does not match the effective group ID or one of the
+                        supplementary group IDs and if the file is a regular file, bit S_ISGID
+                        (set-group-ID on execution) in the file's mode shall be cleared upon
+                        successful return from chmod().*/
+
+                        if (setbuf->ia_prot.sgid == 1) {
+                                op_ret = ac_test_access (buf, 0, frame->root->gid,
+                                                         frame->root->groups,
+                                                         frame->root->ngrps,
+                                                         ACCTEST_DONTCARE,
+                                                         ACCTEST_GROUP, &op_errno);
+                                if (op_ret == -1) {
+                                        gf_log (ACTRL, GF_LOG_DEBUG, "Reseting set_gid bit");
+                                        setbuf->ia_prot.sgid = 0;
+                                        op_ret = 0;
+                                }
+                        }
+                }
+
+                if ((frame->root->uid != 0) && gf_attr_uid_set (valid)) {
+                        /*Only super user can change the owner,
+                         * for other users changing uid should match
+                         * owner uid*/
+                        if (setbuf->ia_uid != buf->ia_uid) {
+                                gf_log (ACTRL, GF_LOG_DEBUG, "Mismatch set_uid %d file_uid %d",
+                                        setbuf->ia_uid, buf->ia_uid);
                                 op_ret = -1;
                                 op_errno = EPERM;
                                 goto out;
@@ -1714,6 +1756,8 @@  ac_setattr_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
                  */
                 if ((frame->root->uid != 0) && (gf_attr_gid_set (valid))) {
                         if (frame->root->uid != buf->ia_uid) {
+                                gf_log (ACTRL, GF_LOG_DEBUG, "Mismatch effective_uid %d file_uid %d",
+                                        frame->root->uid, buf->ia_uid);
                                 op_ret = -1;
                                 op_errno = EPERM;
                                 goto out;
@@ -1724,8 +1768,11 @@  ac_setattr_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
                                                  frame->root->ngrps,
                                                  ACCTEST_DONTCARE,
                                                  ACCTEST_GROUP, &op_errno);
-                        if (op_ret == -1)
+                        if (op_ret == -1) {
+                                gf_log (ACTRL, GF_LOG_DEBUG, "Set_gid %d is not in aux_gid_list",
+                                        setbuf->ia_gid);
                                 goto out;
+                        }
                 }
         }
 
@@ -1795,23 +1842,62 @@  ac_fsetattr_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
         if (op_ret == -1)
                 goto out;
 
-        op_ret = ac_test_access (buf, frame->root->uid, frame->root->gid,
-                                 frame->root->groups, frame->root->ngrps,
-                                 ACCTEST_WRITE, ACCTEST_ANY,
-                                 &op_errno);
-        if (op_ret == -1)
-                goto out;
+
+        if ((frame->root->uid != buf->ia_uid) && (frame->root->uid != 0)) {
+                op_ret = ac_test_access (buf, frame->root->uid, frame->root->gid,
+                                         frame->root->groups, frame->root->ngrps,
+                                         ACCTEST_WRITE, ACCTEST_ANY,
+                                         &op_errno);
+                if (op_ret == -1) {
+                        gf_log (ACTRL, GF_LOG_DEBUG, "Don't have write permision");
+                        goto out;
+                }
+        }
 
         valid = stub->args.fsetattr.valid;
         setbuf = &stub->args.fsetattr.stbuf;
-        if (gf_attr_uid_set (valid) && gf_attr_gid_set (valid)) {
-                /* chown returns EPERM if the operation would change the
-                 * ownership, but the effective user ID is not the
+        if (gf_attr_uid_set (valid) || gf_attr_gid_set (valid)
+            || gf_attr_mode_set(valid)) {
+                /* chown/chmod returns EPERM if the operation would change the
+                 * ownership/permissions, but the effective user ID is not the
                  * super-user and the process is not an owner of the file.
                  * Ref: posix-testsuite/chown/07.t
                  */
-                if ((frame->root->uid != 0) && (gf_attr_uid_set (valid))) {
-                        if (buf->ia_uid != setbuf->ia_uid) {
+                if ((frame->root->uid != 0) && gf_attr_mode_set(valid)) {
+                        if (frame->root->uid != buf->ia_uid) {
+                                gf_log (ACTRL, GF_LOG_DEBUG, "Mismatch effective_uid %d file_uid %d",
+                                        frame->root->uid, buf->ia_uid);
+                                op_ret = -1;
+                                op_errno = EPERM;
+                                goto out;
+                        }
+                        /* POSIX: If the calling process does not have appropriate privileges, and if
+                        the group ID of the file does not match the effective group ID or one of the
+                        supplementary group IDs and if the file is a regular file, bit S_ISGID
+                        (set-group-ID on execution) in the file's mode shall be cleared upon
+                        successful return from chmod().*/
+
+                        if (setbuf->ia_prot.sgid == 1) {
+                                op_ret = ac_test_access (buf, 0, frame->root->gid,
+                                                         frame->root->groups,
+                                                         frame->root->ngrps,
+                                                         ACCTEST_DONTCARE,
+                                                         ACCTEST_GROUP, &op_errno);
+                                if (op_ret == -1) {
+                                        gf_log (ACTRL, GF_LOG_DEBUG, "Reseting set_gid bit");
+                                        setbuf->ia_prot.sgid = 0;
+                                        op_ret = 0;
+                                }
+                        }
+                }
+
+                if ((frame->root->uid != 0) && gf_attr_uid_set (valid)) {
+                        /*Only super user can change the owner,
+                         * for other users changing uid should match
+                         * owner uid*/
+                        if (setbuf->ia_uid != buf->ia_uid) {
+                                gf_log (ACTRL, GF_LOG_DEBUG, "Mismatch set_uid %d file_uid %d",
+                                        setbuf->ia_uid, buf->ia_uid);
                                 op_ret = -1;
                                 op_errno = EPERM;
                                 goto out;
@@ -1824,18 +1910,23 @@  ac_fsetattr_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
                  */
                 if ((frame->root->uid != 0) && (gf_attr_gid_set (valid))) {
                         if (frame->root->uid != buf->ia_uid) {
+                                gf_log (ACTRL, GF_LOG_DEBUG, "Mismatch effective_uid %d file_uid %d",
+                                        frame->root->uid, buf->ia_uid);
                                 op_ret = -1;
                                 op_errno = EPERM;
                                 goto out;
                         }
 
-                        op_ret = ac_test_access (buf, 0, frame->root->gid,
+                        op_ret = ac_test_access (setbuf, 0, frame->root->gid,
                                                  frame->root->groups,
                                                  frame->root->ngrps,
                                                  ACCTEST_DONTCARE,
                                                  ACCTEST_GROUP, &op_errno);
-                        if (op_ret == -1)
+                        if (op_ret == -1) {
+                                gf_log (ACTRL, GF_LOG_DEBUG, "Set_gid %d is not in aux_gid_list",
+                                        setbuf->ia_gid);
                                 goto out;
+                        }
                 }
         }