summaryrefslogtreecommitdiffstats
path: root/xlators/system/posix-acl/src/posix-acl.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/system/posix-acl/src/posix-acl.c')
-rw-r--r--xlators/system/posix-acl/src/posix-acl.c65
1 files changed, 60 insertions, 5 deletions
diff --git a/xlators/system/posix-acl/src/posix-acl.c b/xlators/system/posix-acl/src/posix-acl.c
index a3570c0b2..4658cad49 100644
--- a/xlators/system/posix-acl/src/posix-acl.c
+++ b/xlators/system/posix-acl/src/posix-acl.c
@@ -186,7 +186,7 @@ acl_permits (call_frame_t *frame, inode_t *inode, int want)
ace = acl->entries;
- if (acl->count > 3)
+ if (acl->count > POSIX_ACL_MINIMAL_ACE_COUNT)
acl_present = 1;
for (i = 0; i < acl->count; i++) {
@@ -663,7 +663,12 @@ int
posix_acl_ctx_update (inode_t *inode, xlator_t *this, struct iatt *buf)
{
struct posix_acl_ctx *ctx = NULL;
+ struct posix_acl *acl = NULL;
+ struct posix_ace *ace = NULL;
+ struct posix_ace *mask_ce = NULL;
+ struct posix_ace *group_ce = NULL;
int ret = 0;
+ int i = 0;
ctx = posix_acl_ctx_get (inode, this);
if (!ctx) {
@@ -676,7 +681,46 @@ posix_acl_ctx_update (inode_t *inode, xlator_t *this, struct iatt *buf)
ctx->uid = buf->ia_uid;
ctx->gid = buf->ia_gid;
ctx->perm = st_mode_from_ia (buf->ia_prot, buf->ia_type);
+
+ acl = ctx->acl_access;
+ if (!acl || !(acl->count > POSIX_ACL_MINIMAL_ACE_COUNT))
+ goto unlock;
+
+ /* This is an extended ACL (not minimal acl). In case we
+ are only refreshing from iatt and not ACL xattrs (for
+ e.g. from postattributes of setattr() call, we need to
+ update the corresponding ACEs as well.
+ */
+ ace = acl->entries;
+ for (i = 0; i < acl->count; i++) {
+ switch (ace->tag) {
+ case POSIX_ACL_USER_OBJ:
+ ace->perm = (ctx->perm & S_IRWXU) >> 6;
+ break;
+ case POSIX_ACL_USER:
+ case POSIX_ACL_GROUP:
+ break;
+ case POSIX_ACL_GROUP_OBJ:
+ group_ce = ace;
+ break;
+ case POSIX_ACL_MASK:
+ mask_ce = ace;
+ break;
+ case POSIX_ACL_OTHER:
+ ace->perm = (ctx->perm & S_IRWXO);
+ break;
+ }
+ ace++;
+ }
+
+ if (mask_ce)
+ mask_ce->perm = (ctx->perm & S_IRWXG) >> 3;
+ else if (group_ce)
+ group_ce->perm = (ctx->perm & S_IRWXG) >> 3;
+ else
+ ret = -1;
}
+unlock:
UNLOCK(&inode->lock);
out:
return ret;
@@ -1394,6 +1438,11 @@ posix_acl_link (call_frame_t *frame, xlator_t *this, loc_t *old, loc_t *new, dic
goto red;
}
+ if (!sticky_permits (frame, new->parent, new->inode)) {
+ op_errno = EACCES;
+ goto red;
+ }
+
STACK_WIND (frame, posix_acl_link_cbk,
FIRST_CHILD(this), FIRST_CHILD(this)->fops->link,
old, new, xdata);
@@ -1517,12 +1566,16 @@ posix_acl_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size,
off_t offset, dict_t *dict)
{
int ret = 0;
+ dict_t *alloc_dict = NULL;
if (acl_permits (frame, fd->inode, POSIX_ACL_READ))
goto green;
else
goto red;
green:
+ if (!dict)
+ dict = alloc_dict = dict_new ();
+
if (dict) {
ret = dict_set_int8 (dict, POSIX_ACL_ACCESS_XATTR, 0);
if (ret)
@@ -1541,6 +1594,8 @@ green:
FIRST_CHILD(this), FIRST_CHILD(this)->fops->readdirp,
fd, size, offset, dict);
+ if (alloc_dict)
+ dict_unref (alloc_dict);
return 0;
red:
STACK_UNWIND_STRICT (readdirp, frame, -1, EACCES, NULL, NULL);
@@ -2088,8 +2143,11 @@ struct xlator_fops fops = {
#if FD_MODE_CHECK_IS_IMPLEMENTED
.readv = posix_acl_readv,
.writev = posix_acl_writev,
-#endif
.ftruncate = posix_acl_ftruncate,
+ .fsetattr = posix_acl_fsetattr,
+ .fsetxattr = posix_acl_fsetxattr,
+ .fgetxattr = posix_acl_fgetxattr,
+#endif
.access = posix_acl_access,
.truncate = posix_acl_truncate,
.mkdir = posix_acl_mkdir,
@@ -2104,11 +2162,8 @@ struct xlator_fops fops = {
.readdir = posix_acl_readdir,
.readdirp = posix_acl_readdirp,
.setattr = posix_acl_setattr,
- .fsetattr = posix_acl_fsetattr,
.setxattr = posix_acl_setxattr,
- .fsetxattr = posix_acl_fsetxattr,
.getxattr = posix_acl_getxattr,
- .fgetxattr = posix_acl_fgetxattr,
.removexattr = posix_acl_removexattr,
};