aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'fs/posix_acl.c')
-rw-r--r--fs/posix_acl.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index a9dafa83678c..0ef1c3722504 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -598,6 +598,37 @@ no_mem:
598} 598}
599EXPORT_SYMBOL_GPL(posix_acl_create); 599EXPORT_SYMBOL_GPL(posix_acl_create);
600 600
601/**
602 * posix_acl_update_mode - update mode in set_acl
603 *
604 * Update the file mode when setting an ACL: compute the new file permission
605 * bits based on the ACL. In addition, if the ACL is equivalent to the new
606 * file mode, set *acl to NULL to indicate that no ACL should be set.
607 *
608 * As with chmod, clear the setgit bit if the caller is not in the owning group
609 * or capable of CAP_FSETID (see inode_change_ok).
610 *
611 * Called from set_acl inode operations.
612 */
613int posix_acl_update_mode(struct inode *inode, umode_t *mode_p,
614 struct posix_acl **acl)
615{
616 umode_t mode = inode->i_mode;
617 int error;
618
619 error = posix_acl_equiv_mode(*acl, &mode);
620 if (error < 0)
621 return error;
622 if (error == 0)
623 *acl = NULL;
624 if (!in_group_p(inode->i_gid) &&
625 !capable_wrt_inode_uidgid(inode, CAP_FSETID))
626 mode &= ~S_ISGID;
627 *mode_p = mode;
628 return 0;
629}
630EXPORT_SYMBOL(posix_acl_update_mode);
631
601/* 632/*
602 * Fix up the uids and gids in posix acl extended attributes in place. 633 * Fix up the uids and gids in posix acl extended attributes in place.
603 */ 634 */