diff options
Diffstat (limited to 'fs/posix_acl.c')
| -rw-r--r-- | fs/posix_acl.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 64496020bf1..9607a1df282 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -341,6 +341,35 @@ static int posix_acl_create_masq(struct posix_acl *acl, umode_t *mode_p) return not_equiv; } +/** + * posix_acl_update_mode - update mode in set_acl + * + * Update the file mode when setting an ACL: compute the new file permission + * bits based on the ACL. In addition, if the ACL is equivalent to the new + * file mode, set *acl to NULL to indicate that no ACL should be set. + * + * As with chmod, clear the setgit bit if the caller is not in the owning group + * or capable of CAP_FSETID (see inode_change_ok). + * + * Called from set_acl inode operations. + */ +int posix_acl_update_mode(struct inode *inode, umode_t *mode_p, + struct posix_acl **acl) +{ + umode_t mode = inode->i_mode; + int error; + + error = posix_acl_update_mode(inode, &inode->i_mode, acl); + if (error) + return error; + if (!in_group_p(inode->i_gid) && + !capable(CAP_FSETID)) + mode &= ~S_ISGID; + *mode_p = mode; + return 0; +} +EXPORT_SYMBOL(posix_acl_update_mode); + /* * Modify the ACL for the chmod syscall. */ |
