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

Commit 9b5e6857 authored by Al Viro's avatar Al Viro Committed by Linus Torvalds
Browse files

regression: cifs endianness bug



access_flags_to_mode() gets on-the-wire data (little-endian) and treats
it as host-endian.

Introduced in commit e01b6400 ("[CIFS]
enable get mode from ACL when cifsacl mount option specified")

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ecaf18c1
Loading
Loading
Loading
Loading
+17 −16
Original line number Diff line number Diff line
@@ -134,9 +134,10 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
   pmode is the existing mode (we only want to overwrite part of this
   bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
*/
static void access_flags_to_mode(__u32 ace_flags, int type, umode_t *pmode,
static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
				 umode_t *pbits_to_set)
{
	__u32 flags = le32_to_cpu(ace_flags);
	/* the order of ACEs is important.  The canonical order is to begin with
	   DENY entries followed by ALLOW, otherwise an allow entry could be
	   encountered first, making the subsequent deny entry like "dead code"
@@ -146,17 +147,17 @@ static void access_flags_to_mode(__u32 ace_flags, int type, umode_t *pmode,
	/* For deny ACEs we change the mask so that subsequent allow access
	   control entries do not turn on the bits we are denying */
	if (type == ACCESS_DENIED) {
		if (ace_flags & GENERIC_ALL) {
		if (flags & GENERIC_ALL) {
			*pbits_to_set &= ~S_IRWXUGO;
		}
		if ((ace_flags & GENERIC_WRITE) ||
			((ace_flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
		if ((flags & GENERIC_WRITE) ||
			((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
			*pbits_to_set &= ~S_IWUGO;
		if ((ace_flags & GENERIC_READ) ||
			((ace_flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
		if ((flags & GENERIC_READ) ||
			((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
			*pbits_to_set &= ~S_IRUGO;
		if ((ace_flags & GENERIC_EXECUTE) ||
			((ace_flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
		if ((flags & GENERIC_EXECUTE) ||
			((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
			*pbits_to_set &= ~S_IXUGO;
		return;
	} else if (type != ACCESS_ALLOWED) {
@@ -165,25 +166,25 @@ static void access_flags_to_mode(__u32 ace_flags, int type, umode_t *pmode,
	}
	/* else ACCESS_ALLOWED type */

	if (ace_flags & GENERIC_ALL) {
	if (flags & GENERIC_ALL) {
		*pmode |= (S_IRWXUGO & (*pbits_to_set));
#ifdef CONFIG_CIFS_DEBUG2
		cFYI(1, ("all perms"));
#endif
		return;
	}
	if ((ace_flags & GENERIC_WRITE) ||
			((ace_flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
	if ((flags & GENERIC_WRITE) ||
			((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
		*pmode |= (S_IWUGO & (*pbits_to_set));
	if ((ace_flags & GENERIC_READ) ||
			((ace_flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
	if ((flags & GENERIC_READ) ||
			((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
		*pmode |= (S_IRUGO & (*pbits_to_set));
	if ((ace_flags & GENERIC_EXECUTE) ||
			((ace_flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
	if ((flags & GENERIC_EXECUTE) ||
			((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
		*pmode |= (S_IXUGO & (*pbits_to_set));

#ifdef CONFIG_CIFS_DEBUG2
	cFYI(1, ("access flags 0x%x mode now 0x%x", ace_flags, *pmode));
	cFYI(1, ("access flags 0x%x mode now 0x%x", flags, *pmode));
#endif
	return;
}