From 5f1efbc32d69097a00b56eec3a2ca2aa26ae084c Mon Sep 17 00:00:00 2001 From: Gaurav Date: Mon, 9 May 2011 23:23:21 +0000 Subject: Access-Control : Sticky bit validation for rename, unlink and rmdir. Signed-off-by: Gaurav Signed-off-by: Anand Avati BUG: 2886 (No sticky bit validation in access control) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2886 --- .../features/access-control/src/access-control.c | 220 ++++++++++++++++++--- 1 file changed, 197 insertions(+), 23 deletions(-) (limited to 'xlators') diff --git a/xlators/features/access-control/src/access-control.c b/xlators/features/access-control/src/access-control.c index a4b40159e1f..dc02b16155d 100644 --- a/xlators/features/access-control/src/access-control.c +++ b/xlators/features/access-control/src/access-control.c @@ -753,10 +753,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; } @@ -772,6 +770,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) @@ -797,7 +837,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; @@ -834,10 +874,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; } @@ -853,6 +891,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) @@ -878,7 +958,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; @@ -999,21 +1079,66 @@ 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) { + stub = __get_frame_stub (frame); STACK_UNWIND_STRICT (rename, frame, -1, op_errno, NULL, NULL, NULL, NULL, NULL); if (stub) @@ -1035,11 +1160,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; } @@ -1050,7 +1172,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); @@ -1092,7 +1266,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; -- cgit