Skip to content

Commit b34e7e2

Browse files
ebiggersgregkh
authored andcommitted
/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 <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Kees Cook <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Russell King <[email protected]> Cc: Andrew Morton <[email protected]> Fixes: 3234ac6 ("/dev/mem: Revoke mappings when a driver claims the region") Signed-off-by: Eric Biggers <[email protected]> Cc: stable <[email protected]> Acked-by: Dan Williams <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent f867c77 commit b34e7e2

File tree

1 file changed

+7
-3
lines changed

1 file changed

+7
-3
lines changed

drivers/char/mem.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,8 @@ static struct inode *devmem_inode;
814814
#ifdef CONFIG_IO_STRICT_DEVMEM
815815
void revoke_devmem(struct resource *res)
816816
{
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);
818819

819820
/*
820821
* Check that the initialization has completed. Losing the race
@@ -1028,8 +1029,11 @@ static int devmem_init_inode(void)
10281029
return rc;
10291030
}
10301031

1031-
/* publish /dev/mem initialized */
1032-
WRITE_ONCE(devmem_inode, inode);
1032+
/*
1033+
* Publish /dev/mem initialized.
1034+
* Pairs with smp_load_acquire() in revoke_devmem().
1035+
*/
1036+
smp_store_release(&devmem_inode, inode);
10331037

10341038
return 0;
10351039
}

0 commit comments

Comments
 (0)