public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Darius Rad <darius@bluespec.com>
To: linux-arch@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH] include/asm-generic/cmpxchg-local.h: perform comparison in cmpxchg using appropriate size of data
Date: Mon, 25 Aug 2014 11:33:07 -0400	[thread overview]
Message-ID: <53FB5733.4010607@bluespec.com> (raw)

In the generic implementation of cmpxchg, cast the parameters to the size
of the data prior to comparison.  Otherwise, it is possible for the
comparison to be done incorrectly in the case where the data size is
smaller than the architecture register size.

For example, on a 64-bit architecture, a 32-bit value is sign extended
differently if it is typecast from an int to an unsigned long as compared
to being loaded from memory via an unsigned pointer (u32 *).  Given that
the primary, or possibly only, use of cmpxchg is with 4 and 8 byte values,
the incorrect comparison could only occur on 64-bit architectures that make
use of the generic cmpxchg.

Signed-off-by: Darius Rad <darius@bluespec.com>

---
It does not appear that this is relevant to architectures that are in the
kernel tree, since the generic cmpxchg is only ever used by some 32-bit
architectures.  This does impact the RISC-V architecture that is currently
in development.

Patch generated against 3.17-rc1.

 include/asm-generic/cmpxchg-local.h |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

--- linux-3.17-rc1.orig/include/asm-generic/cmpxchg-local.h	2014-08-16 12:40:26.000000000 -0400
+++ linux-3.17-rc1/include/asm-generic/cmpxchg-local.h	2014-08-22 14:26:59.280746090 -0400
@@ -25,19 +25,19 @@ static inline unsigned long __cmpxchg_lo
 	raw_local_irq_save(flags);
 	switch (size) {
 	case 1: prev = *(u8 *)ptr;
-		if (prev == old)
+		if ((u8)prev == (u8)old)
 			*(u8 *)ptr = (u8)new;
 		break;
 	case 2: prev = *(u16 *)ptr;
-		if (prev == old)
+		if ((u16)prev == (u16)old)
 			*(u16 *)ptr = (u16)new;
 		break;
 	case 4: prev = *(u32 *)ptr;
-		if (prev == old)
+		if ((u32)prev == (u32)old)
 			*(u32 *)ptr = (u32)new;
 		break;
 	case 8: prev = *(u64 *)ptr;
-		if (prev == old)
+		if ((u64)prev == (u64)old)
 			*(u64 *)ptr = (u64)new;
 		break;
 	default:

             reply	other threads:[~2014-08-25 15:33 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-25 15:33 Darius Rad [this message]
2014-08-26 12:33 ` [PATCH] include/asm-generic/cmpxchg-local.h: perform comparison in cmpxchg using appropriate size of data Arnd Bergmann
2014-08-26 16:13   ` Darius Rad

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=53FB5733.4010607@bluespec.com \
    --to=darius@bluespec.com \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox