All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4.4.y] arm64: ensure extension of smp_store_release value
@ 2017-05-24  9:56 Mark Rutland
  2017-06-12 13:24 ` Greg KH
  0 siblings, 1 reply; 2+ messages in thread
From: Mark Rutland @ 2017-05-24  9:56 UTC (permalink / raw)
  To: stable

commit 994870bead4ab19087a79492400a5478e2906196 upstream.

When an inline assembly operand's type is narrower than the register it
is allocated to, the least significant bits of the register (up to the
operand type's width) are valid, and any other bits are permitted to
contain any arbitrary value. This aligns with the AAPCS64 parameter
passing rules.

Our __smp_store_release() implementation does not account for this, and
implicitly assumes that operands have been zero-extended to the width of
the type being stored to. Thus, we may store unknown values to memory
when the value type is narrower than the pointer type (e.g. when storing
a char to a long).

This patch fixes the issue by casting the value operand to the same
width as the pointer operand in all cases, which ensures that the value
is zero-extended as we expect. We use the same union trickery as
__smp_load_acquire and {READ,WRITE}_ONCE() to avoid GCC complaining that
pointers are potentially cast to narrower width integers in unreachable
paths.

A whitespace issue at the top of __smp_store_release() is also
corrected.

No changes are necessary for __smp_load_acquire(). Load instructions
implicitly clear any upper bits of the register, and the compiler will
only consider the least significant bits of the register as valid
regardless.

Fixes: 47933ad41a86 ("arch: Introduce smp_load_acquire(), smp_store_release()")
Fixes: 878a84d5a8a1 ("arm64: add missing data types in smp_load_acquire/smp_store_release")
Cc: <stable@vger.kernel.org> # 3.14.x-
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Matthias Kaehlcke <mka@chromium.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
 arch/arm64/include/asm/barrier.h | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h
index 9622eb4..f2d2c0b 100644
--- a/arch/arm64/include/asm/barrier.h
+++ b/arch/arm64/include/asm/barrier.h
@@ -41,23 +41,33 @@
 
 #define smp_store_release(p, v)						\
 do {									\
+	union { typeof(*p) __val; char __c[1]; } __u =			\
+		{ .__val = (__force typeof(*p)) (v) }; 			\
 	compiletime_assert_atomic_type(*p);				\
 	switch (sizeof(*p)) {						\
 	case 1:								\
 		asm volatile ("stlrb %w1, %0"				\
-				: "=Q" (*p) : "r" (v) : "memory");	\
+				: "=Q" (*p)				\
+				: "r" (*(__u8 *)__u.__c)		\
+				: "memory");				\
 		break;							\
 	case 2:								\
 		asm volatile ("stlrh %w1, %0"				\
-				: "=Q" (*p) : "r" (v) : "memory");	\
+				: "=Q" (*p)				\
+				: "r" (*(__u16 *)__u.__c)		\
+				: "memory");				\
 		break;							\
 	case 4:								\
 		asm volatile ("stlr %w1, %0"				\
-				: "=Q" (*p) : "r" (v) : "memory");	\
+				: "=Q" (*p)				\
+				: "r" (*(__u32 *)__u.__c)		\
+				: "memory");				\
 		break;							\
 	case 8:								\
 		asm volatile ("stlr %1, %0"				\
-				: "=Q" (*p) : "r" (v) : "memory");	\
+				: "=Q" (*p)				\
+				: "r" (*(__u64 *)__u.__c)		\
+				: "memory");				\
 		break;							\
 	}								\
 } while (0)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v4.4.y] arm64: ensure extension of smp_store_release value
  2017-05-24  9:56 [PATCH v4.4.y] arm64: ensure extension of smp_store_release value Mark Rutland
@ 2017-06-12 13:24 ` Greg KH
  0 siblings, 0 replies; 2+ messages in thread
From: Greg KH @ 2017-06-12 13:24 UTC (permalink / raw)
  To: Mark Rutland; +Cc: stable

On Wed, May 24, 2017 at 10:56:01AM +0100, Mark Rutland wrote:
> commit 994870bead4ab19087a79492400a5478e2906196 upstream.
> 
> When an inline assembly operand's type is narrower than the register it
> is allocated to, the least significant bits of the register (up to the
> operand type's width) are valid, and any other bits are permitted to
> contain any arbitrary value. This aligns with the AAPCS64 parameter
> passing rules.
> 
> Our __smp_store_release() implementation does not account for this, and
> implicitly assumes that operands have been zero-extended to the width of
> the type being stored to. Thus, we may store unknown values to memory
> when the value type is narrower than the pointer type (e.g. when storing
> a char to a long).
> 
> This patch fixes the issue by casting the value operand to the same
> width as the pointer operand in all cases, which ensures that the value
> is zero-extended as we expect. We use the same union trickery as
> __smp_load_acquire and {READ,WRITE}_ONCE() to avoid GCC complaining that
> pointers are potentially cast to narrower width integers in unreachable
> paths.
> 
> A whitespace issue at the top of __smp_store_release() is also
> corrected.
> 
> No changes are necessary for __smp_load_acquire(). Load instructions
> implicitly clear any upper bits of the register, and the compiler will
> only consider the least significant bits of the register as valid
> regardless.
> 
> Fixes: 47933ad41a86 ("arch: Introduce smp_load_acquire(), smp_store_release()")
> Fixes: 878a84d5a8a1 ("arm64: add missing data types in smp_load_acquire/smp_store_release")
> Cc: <stable@vger.kernel.org> # 3.14.x-
> Acked-by: Will Deacon <will.deacon@arm.com>
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> Cc: Matthias Kaehlcke <mka@chromium.org>
> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
> ---
>  arch/arm64/include/asm/barrier.h | 18 ++++++++++++++----
>  1 file changed, 14 insertions(+), 4 deletions(-)

Applied, thanks.

greg k-h

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2017-06-12 13:24 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-24  9:56 [PATCH v4.4.y] arm64: ensure extension of smp_store_release value Mark Rutland
2017-06-12 13:24 ` Greg KH

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.