fs/namei.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index d81f73ff1a8b..517bd6a25761 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -294,25 +294,34 @@ static int acl_permission_check(struct inode *inode, int mask) { unsigned int mode = inode->i_mode; - if (likely(uid_eq(current_fsuid(), inode->i_uid))) - mode >>= 6; - else { - if (IS_POSIXACL(inode) && (mode & S_IRWXG)) { - int error = check_acl(inode, mask); - if (error != -EAGAIN) - return error; - } + mask &= MAY_READ | MAY_WRITE | MAY_EXEC; + /* Are we the owner? If so, ACL's don't matter */ + if (likely(uid_eq(current_fsuid(), inode->i_uid))) { + if ((mask << 6) & ~mode) + return -EACCES; + return 0; + } + + /* Do we have ACL's? */ + if (IS_POSIXACL(inode) && (mode & S_IRWXG)) { + int error = check_acl(inode, mask); + if (error != -EAGAIN) + return error; + } + + /* + * Are the group permissions different from + * the other permissions in the bits we care + * about? Need to check group ownership if so. + */ + if (mask & (mode ^ (mode >> 3))) { if (in_group_p(inode->i_gid)) mode >>= 3; } - /* - * If the DACs are ok we don't need any capability check. - */ - if ((mask & ~mode & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) - return 0; - return -EACCES; + /* Bits in 'mode' clear that we require? */ + return (mask & ~mode) ? -EACCES : 0; } /**