linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] /dev/mem: Add missing memory barriers for devmem_inode
@ 2020-07-16  6:05 Eric Biggers
  2020-07-16 15:53 ` Dan Williams
  0 siblings, 1 reply; 2+ messages in thread
From: Eric Biggers @ 2020-07-16  6:05 UTC (permalink / raw)
  To: Arnd Bergmann, Greg Kroah-Hartman, linux-kernel
  Cc: linux-mm, Dan Williams, Ingo Molnar, Kees Cook, Matthew Wilcox,
	Russell King, Andrew Morton

From: Eric Biggers <ebiggers@google.com>

WRITE_ONCE() isn't the correct way to publish a pointer to a data
structure, since it doesn't include a write memory barrier.  Therefore
other tasks may see that the pointer has been set but not see that the
pointed-to memory has finished being initialized yet.  Instead a
primitive with "release" semantics is needed.

Use smp_store_release() for this.

The use of READ_ONCE() on the read side is still potentially correct if
there's no control dependency, i.e. if all memory being "published" is
transitively reachable via the pointer itself.  But this pairing is
somewhat confusing and error-prone.  So just upgrade the read side to
smp_load_acquire() so that it clearly pairs with smp_store_release().

Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Fixes: 3234ac664a87 ("/dev/mem: Revoke mappings when a driver claims the region")
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
 drivers/char/mem.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 934c92dcb9ab..687d4af6945d 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -814,7 +814,8 @@ static struct inode *devmem_inode;
 #ifdef CONFIG_IO_STRICT_DEVMEM
 void revoke_devmem(struct resource *res)
 {
-	struct inode *inode = READ_ONCE(devmem_inode);
+	/* pairs with smp_store_release() in devmem_init_inode() */
+	struct inode *inode = smp_load_acquire(&devmem_inode);
 
 	/*
 	 * Check that the initialization has completed. Losing the race
@@ -1028,8 +1029,11 @@ static int devmem_init_inode(void)
 		return rc;
 	}
 
-	/* publish /dev/mem initialized */
-	WRITE_ONCE(devmem_inode, inode);
+	/*
+	 * Publish /dev/mem initialized.
+	 * Pairs with smp_load_acquire() in revoke_devmem().
+	 */
+	smp_store_release(&devmem_inode, inode);
 
 	return 0;
 }

base-commit: f8456690ba8eb18ea4714e68554e242a04f65cff
-- 
2.27.0


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

* Re: [PATCH] /dev/mem: Add missing memory barriers for devmem_inode
  2020-07-16  6:05 [PATCH] /dev/mem: Add missing memory barriers for devmem_inode Eric Biggers
@ 2020-07-16 15:53 ` Dan Williams
  0 siblings, 0 replies; 2+ messages in thread
From: Dan Williams @ 2020-07-16 15:53 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Arnd Bergmann, Greg Kroah-Hartman, Linux Kernel Mailing List,
	Linux MM, Ingo Molnar, Kees Cook, Matthew Wilcox, Russell King,
	Andrew Morton

On Wed, Jul 15, 2020 at 11:07 PM Eric Biggers <ebiggers@kernel.org> wrote:
>
> From: Eric Biggers <ebiggers@google.com>
>
> WRITE_ONCE() isn't the correct way to publish a pointer to a data
> structure, since it doesn't include a write memory barrier.  Therefore
> other tasks may see that the pointer has been set but not see that the
> pointed-to memory has finished being initialized yet.  Instead a
> primitive with "release" semantics is needed.
>
> Use smp_store_release() for this.
>
> The use of READ_ONCE() on the read side is still potentially correct if
> there's no control dependency, i.e. if all memory being "published" is
> transitively reachable via the pointer itself.  But this pairing is
> somewhat confusing and error-prone.  So just upgrade the read side to
> smp_load_acquire() so that it clearly pairs with smp_store_release().
>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Kees Cook <keescook@chromium.org>
> Cc: Matthew Wilcox <willy@infradead.org>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Fixes: 3234ac664a87 ("/dev/mem: Revoke mappings when a driver claims the region")
> Signed-off-by: Eric Biggers <ebiggers@google.com>

Makes sense:

Acked-by: Dan Williams <dan.j.williams@intel.com>

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

end of thread, other threads:[~2020-07-16 15:53 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-16  6:05 [PATCH] /dev/mem: Add missing memory barriers for devmem_inode Eric Biggers
2020-07-16 15:53 ` Dan Williams

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).