Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

/dev/mem: Add missing memory barriers for devmem_inode

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: 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>
Fixes: 3234ac664a87 ("/dev/mem: Revoke mappings when a driver claims the region")
Signed-off-by: Eric Biggers <ebiggers@google.com>
Cc: stable <stable@vger.kernel.org>
Acked-by: Dan Williams <dan.j.williams@intel.com>
Link: https://lore.kernel.org/r/20200716060553.24618-1-ebiggers@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Eric Biggers and committed by
Greg Kroah-Hartman
b34e7e29 f867c771

+7 -3
+7 -3
drivers/char/mem.c
··· 814 814 #ifdef CONFIG_IO_STRICT_DEVMEM 815 815 void revoke_devmem(struct resource *res) 816 816 { 817 - struct inode *inode = READ_ONCE(devmem_inode); 817 + /* pairs with smp_store_release() in devmem_init_inode() */ 818 + struct inode *inode = smp_load_acquire(&devmem_inode); 818 819 819 820 /* 820 821 * Check that the initialization has completed. Losing the race ··· 1029 1028 return rc; 1030 1029 } 1031 1030 1032 - /* publish /dev/mem initialized */ 1033 - WRITE_ONCE(devmem_inode, inode); 1031 + /* 1032 + * Publish /dev/mem initialized. 1033 + * Pairs with smp_load_acquire() in revoke_devmem(). 1034 + */ 1035 + smp_store_release(&devmem_inode, inode); 1034 1036 1035 1037 return 0; 1036 1038 }