Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f1f2d871 authored by Andreas Gruenbacher's avatar Andreas Gruenbacher Committed by Linus Torvalds
Browse files

[PATCH] Fix user.* xattr permission check for sticky dirs



The user.* extended attributes are only allowed on regular files and
directories.  Sticky directories further restrict write access to the owner
and privileged users.  (See the attr(5) man page for an explanation.)

The original check in ext2/ext3 when user.* xattrs were merged was more
restrictive than intended, and when the xattr permission checks were moved
into the VFS, read access to user.* attributes on sticky directores ended
up being denied in addition.

Originally-from: Gerard Neil <xyzzy@devferret.org>
Signed-off-by: default avatarAndreas Gruenbacher <agruen@suse.de>
Cc: Dave Kleikamp <shaggy@austin.ibm.com>
Cc: Jan Engelhardt <jengelh@linux01.gwdg.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 8ce08464
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -48,14 +48,21 @@ xattr_permission(struct inode *inode, const char *name, int mask)
		return 0;

	/*
	 * The trusted.* namespace can only accessed by a privilegued user.
	 * The trusted.* namespace can only be accessed by a privileged user.
	 */
	if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
		return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM);

	/* In user.* namespace, only regular files and directories can have
	 * extended attributes. For sticky directories, only the owner and
	 * privileged user can write attributes.
	 */
	if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
		if (!S_ISREG(inode->i_mode) &&
		    (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
		if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
			return -EPERM;
		if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
		    (mask & MAY_WRITE) && (current->fsuid != inode->i_uid) &&
		    !capable(CAP_FOWNER))
			return -EPERM;
	}