xattr: Fix error results for non-existent / invisible attributes

Return -ENODATA when trying to read a user.* attribute which cannot
exist: user space otherwise does not have a reasonable way to
distinguish between non-existent and inaccessible attributes.

Likewise, return -ENODATA when an unprivileged process tries to read a
trusted.* attribute: to unprivileged processes, those attributes are
invisible (listxattr() won't include them).

Related to this bug report: https://bugzilla.redhat.com/660613

Signed-off-by: Andreas Gruenbacher <agruen@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Andreas Gruenbacher 2011-05-27 14:50:36 +02:00 committed by Al Viro
parent aa38572954
commit 55b23bde19

View File

@ -46,18 +46,22 @@ xattr_permission(struct inode *inode, const char *name, int mask)
return 0; return 0;
/* /*
* The trusted.* namespace can only be accessed by a privileged user. * The trusted.* namespace can only be accessed by privileged users.
*/ */
if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) {
return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM); if (!capable(CAP_SYS_ADMIN))
return (mask & MAY_WRITE) ? -EPERM : -ENODATA;
return 0;
}
/* In user.* namespace, only regular files and directories can have /*
* In the user.* namespace, only regular files and directories can have
* extended attributes. For sticky directories, only the owner and * extended attributes. For sticky directories, only the owner and
* privileged user can write attributes. * privileged users can write attributes.
*/ */
if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) { if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
return -EPERM; return (mask & MAY_WRITE) ? -EPERM : -ENODATA;
if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) && if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
(mask & MAY_WRITE) && !inode_owner_or_capable(inode)) (mask & MAY_WRITE) && !inode_owner_or_capable(inode))
return -EPERM; return -EPERM;