diff options
| author | Gaurav <gaurav@gluster.com> | 2011-06-02 01:48:40 +0000 | 
|---|---|---|
| committer | Anand Avati <avati@gluster.com> | 2011-06-08 11:18:55 -0700 | 
| commit | 43368cffd23b9dc4b1f98cf595b0d486b9e6dec9 (patch) | |
| tree | 5f3bec1814a1d95c9653fce70680ddd59777f47d /xlators/features | |
| parent | 9e1817126ff625633de9cb13bb9f4174919690a0 (diff) | |
Access-Control : Sticky bit validation for rename, unlink and rmdir.
Signed-off-by: Gaurav <gaurav@gluster.com>
Signed-off-by: Anand Avati <avati@gluster.com>
BUG: 2886 (No sticky bit validation in access control)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2886
Diffstat (limited to 'xlators/features')
| -rw-r--r-- | xlators/features/access-control/src/access-control.c | 220 | 
1 files changed, 197 insertions, 23 deletions
diff --git a/xlators/features/access-control/src/access-control.c b/xlators/features/access-control/src/access-control.c index 92908791bd8..dc2305116ff 100644 --- a/xlators/features/access-control/src/access-control.c +++ b/xlators/features/access-control/src/access-control.c @@ -828,10 +828,8 @@ ac_unlink_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) { +        if (frame->root->uid != buf->ia_uid) { +                op_ret = -1;                  op_errno = EACCES;                  goto out;          } @@ -849,6 +847,48 @@ out:          return 0;  } +int32_t +ac_unlink_parent_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                    int32_t op_ret, int32_t op_errno, struct iatt *buf) +{ +        call_stub_t     *stub = NULL; + +        stub = frame->local; +        if (op_ret == -1) +                goto out; + +        if (buf->ia_prot.sticky == 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) { +                        op_errno = EACCES; +                        goto out; +                } +        } else { +                if ((frame->root->uid == 0) || +                    (frame->root->uid == buf->ia_uid)) +                        goto access; + +                STACK_WIND (frame, ac_unlink_stat_cbk, FIRST_CHILD (this), +                            FIRST_CHILD (this)->fops->stat, &stub->args.unlink.loc); +                goto out; +        } + +access: +        stub = __get_frame_stub (frame); +        call_resume (stub); +out: +        if (op_ret < 0) { +                stub = __get_frame_stub (frame); +                STACK_UNWIND_STRICT (unlink, frame, -1, op_errno, NULL, NULL); +                if (stub) +                        call_stub_destroy (stub); +        } + +        return 0; +} +  int32_t  ac_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc) @@ -872,7 +912,7 @@ ac_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc)          if (ret < 0)                  goto out; -        STACK_WIND (frame, ac_unlink_stat_cbk, FIRST_CHILD (this), +        STACK_WIND (frame, ac_unlink_parent_stat_cbk, FIRST_CHILD (this),                      FIRST_CHILD (this)->fops->stat, &parentloc);          loc_wipe (&parentloc);          ret = 0; @@ -911,10 +951,8 @@ ac_rmdir_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) { +        if (frame->root->uid != buf->ia_uid) { +                op_ret = -1;                  op_errno = EACCES;                  goto out;          } @@ -932,6 +970,48 @@ out:          return 0;  } +int32_t +ac_rmdir_parent_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                   int32_t op_ret, int32_t op_errno, struct iatt *buf) +{ +        call_stub_t     *stub = NULL; + +        stub = frame->local; +        if (op_ret == -1) +                goto out; + +        if (buf->ia_prot.sticky == 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) { +                        op_errno = EACCES; +                        goto out; +                } +        } else { +                if ((frame->root->uid == 0) || +                    (frame->root->uid == buf->ia_uid)) +                        goto access; + +                STACK_WIND (frame, ac_rmdir_stat_cbk, FIRST_CHILD (this), +                            FIRST_CHILD (this)->fops->stat, &stub->args.rmdir.loc); +                goto out; +        } + +access: +        stub = __get_frame_stub (frame); +        call_resume (stub); +out: +        if (op_ret < 0) { +                stub = __get_frame_stub (frame); +                STACK_UNWIND_STRICT (rmdir, frame, -1, op_errno, NULL, NULL); +                if (stub) +                        call_stub_destroy (stub); +        } + +        return 0; +} +  int  ac_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags) @@ -955,7 +1035,7 @@ ac_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags)          if (ret < 0)                  goto out; -        STACK_WIND (frame, ac_rmdir_stat_cbk, FIRST_CHILD (this), +        STACK_WIND (frame, ac_rmdir_parent_stat_cbk, FIRST_CHILD (this),                      FIRST_CHILD (this)->fops->stat, &parentloc);          loc_wipe (&parentloc);          ret = 0; @@ -1080,23 +1160,68 @@ ac_rename_dst_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          call_stub_t     *stub = NULL;          stub = __get_frame_stub (frame); + +        if ((op_ret == -1) && (op_errno == ENOENT)) +                goto access; +          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) { +        if (frame->root->uid == buf->ia_uid) +                goto access; +        else { +                op_ret = -1;                  op_errno = EACCES; -               goto out; +                goto out; +        } +access: +        call_resume (stub); +out: +        if (op_ret < 0) { +                STACK_UNWIND_STRICT (rename, frame, -1, op_errno, NULL, NULL, +                                     NULL, NULL, NULL); +                if (stub) +                        call_stub_destroy (stub);          } +        return 0; +} +int32_t +ac_rename_dst_parent_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                        int32_t op_ret, int32_t op_errno, struct iatt *buf) +{ +        call_stub_t     *stub = NULL; + +        stub = frame->local; +        if (op_ret == -1) +                goto out; + +        if (buf->ia_prot.sticky == 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) { +                        op_errno = EACCES; +                        goto out; +                } +        } else { +                if ((frame->root->uid == 0) || +                    (frame->root->uid == buf->ia_uid)) +                        goto access; +                STACK_WIND (frame, ac_rename_dst_stat_cbk, FIRST_CHILD (this), +                             FIRST_CHILD (this)->fops->stat, &stub->args.rename.new); +                goto out; +        } + +access: +        stub = __get_frame_stub (frame);          call_resume (stub);  out:          if (op_ret < 0) {  		gf_log (this->name, GF_LOG_ERROR, "rename failed with error: %s",                          strerror (op_errno)); +                stub = __get_frame_stub (frame);                  STACK_UNWIND_STRICT (rename, frame, -1, op_errno, NULL, NULL,                                       NULL, NULL, NULL);                  if (stub) @@ -1118,11 +1243,8 @@ ac_rename_src_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) { +        if (buf->ia_uid != frame->root->uid) { +                op_ret = -1;                  op_errno = EACCES;                  goto out;          } @@ -1133,7 +1255,59 @@ ac_rename_src_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  goto out;          } -        STACK_WIND (frame, ac_rename_dst_stat_cbk, FIRST_CHILD (this), +        STACK_WIND (frame, ac_rename_dst_parent_stat_cbk, FIRST_CHILD (this), +                    FIRST_CHILD (this)->fops->stat, &parentloc); +        loc_wipe (&parentloc); + +out: +        if (op_ret < 0) { +                /* Erase the stored stub before unwinding. */ +                stub = __get_frame_stub (frame); +                if (stub) +                        call_stub_destroy (stub); +                STACK_UNWIND_STRICT (rename, frame, -1, op_errno, NULL, NULL, +                                     NULL, NULL, NULL); +        } +        return 0; +} + +int32_t +ac_rename_src_parent_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                        int32_t op_ret, int32_t op_errno, struct iatt *buf) +{ +        call_stub_t     *stub = NULL; +        loc_t           parentloc = {0, }; + +        stub = frame->local; +        if (op_ret == -1) +                goto out; + +        if (buf->ia_prot.sticky == 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) { +                        op_errno = EACCES; +                        goto out; +                } +        } else { +                if ((buf->ia_uid == frame->root->uid) || +                    (frame->root->uid ==0)) +                        goto access; +                STACK_WIND (frame, ac_rename_src_stat_cbk, FIRST_CHILD (this), +                             FIRST_CHILD (this)->fops->stat, &stub->args.rename.old); +                goto out; +        } + +access: +        op_ret = ac_parent_loc_fill (&parentloc, &stub->args.rename.new); +        if (op_ret < 0) { +                op_errno = -EFAULT; +                goto out; +        } + +        STACK_WIND (frame, ac_rename_dst_parent_stat_cbk, FIRST_CHILD (this),                      FIRST_CHILD (this)->fops->stat, &parentloc);          loc_wipe (&parentloc); @@ -1175,7 +1349,7 @@ ac_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc)          if (ret < 0)                  goto out; -        STACK_WIND (frame, ac_rename_src_stat_cbk, FIRST_CHILD (this), +        STACK_WIND (frame, ac_rename_src_parent_stat_cbk, FIRST_CHILD (this),                      FIRST_CHILD (this)->fops->stat, &parentloc);          loc_wipe (&parentloc);          ret = 0;  | 
