summaryrefslogtreecommitdiffstats
path: root/xlators
diff options
context:
space:
mode:
authorGaurav <gaurav@gluster.com>2011-06-02 01:48:40 +0000
committerAnand Avati <avati@gluster.com>2011-06-08 11:18:55 -0700
commit43368cffd23b9dc4b1f98cf595b0d486b9e6dec9 (patch)
tree5f3bec1814a1d95c9653fce70680ddd59777f47d /xlators
parent9e1817126ff625633de9cb13bb9f4174919690a0 (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')
-rw-r--r--xlators/features/access-control/src/access-control.c220
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 92908791b..dc2305116 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;