Skip to content

Commit 3e338d3

Browse files
surenbaghdasaryangregkh
authored andcommitted
staging: android: ashmem: Fix lockdep warning for write operation
syzbot report [1] describes a deadlock when write operation against an ashmem fd executed at the time when ashmem is shrinking its cache results in the following lock sequence: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(fs_reclaim); lock(&sb->s_type->i_mutex_key#13); lock(fs_reclaim); lock(&sb->s_type->i_mutex_key#13); kswapd takes fs_reclaim and then inode_lock while generic_perform_write takes inode_lock and then fs_reclaim. However ashmem does not support writing into backing shmem with a write syscall. The only way to change its content is to mmap it and operate on mapped memory. Therefore the race that lockdep is warning about is not valid. Resolve this by introducing a separate lockdep class for the backing shmem inodes. [1]: https://lkml.kernel.org/lkml/[email protected]/ Reported-by: [email protected] Signed-off-by: Suren Baghdasaryan <[email protected]> Cc: stable <[email protected]> Reviewed-by: Joel Fernandes (Google) <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 97a6f77 commit 3e338d3

File tree

1 file changed

+12
-0
lines changed

1 file changed

+12
-0
lines changed

drivers/staging/android/ashmem.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,15 @@ static DEFINE_MUTEX(ashmem_mutex);
9595
static struct kmem_cache *ashmem_area_cachep __read_mostly;
9696
static struct kmem_cache *ashmem_range_cachep __read_mostly;
9797

98+
/*
99+
* A separate lockdep class for the backing shmem inodes to resolve the lockdep
100+
* warning about the race between kswapd taking fs_reclaim before inode_lock
101+
* and write syscall taking inode_lock and then fs_reclaim.
102+
* Note that such race is impossible because ashmem does not support write
103+
* syscalls operating on the backing shmem.
104+
*/
105+
static struct lock_class_key backing_shmem_inode_class;
106+
98107
static inline unsigned long range_size(struct ashmem_range *range)
99108
{
100109
return range->pgend - range->pgstart + 1;
@@ -396,6 +405,7 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
396405
if (!asma->file) {
397406
char *name = ASHMEM_NAME_DEF;
398407
struct file *vmfile;
408+
struct inode *inode;
399409

400410
if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0')
401411
name = asma->name;
@@ -407,6 +417,8 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
407417
goto out;
408418
}
409419
vmfile->f_mode |= FMODE_LSEEK;
420+
inode = file_inode(vmfile);
421+
lockdep_set_class(&inode->i_rwsem, &backing_shmem_inode_class);
410422
asma->file = vmfile;
411423
/*
412424
* override mmap operation of the vmfile so that it can't be

0 commit comments

Comments
 (0)