diff options
Diffstat (limited to 'xlators/system/posix-acl/src/posix-acl.c')
| -rw-r--r-- | xlators/system/posix-acl/src/posix-acl.c | 67 |
1 files changed, 61 insertions, 6 deletions
diff --git a/xlators/system/posix-acl/src/posix-acl.c b/xlators/system/posix-acl/src/posix-acl.c index 3928a56af..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++) { @@ -516,7 +516,7 @@ posix_acl_inherit_mode (struct posix_acl *acl, mode_t modein) if (mask_ce) { mask_ce->perm &= (mode >> 3) | ~S_IRWXO; mode &= (mask_ce->perm << 3) | ~S_IRWXG; - } else { + } else if (group_ce) { group_ce->perm &= (mode >> 3) | ~S_IRWXO; mode &= (group_ce->perm << 3) | ~S_IRWXG; } @@ -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, }; |
