android: binder: resolve lru, dentry and task deadlock
cover android: binder: resolve lru, dentry and task deadlock
This patch set removes the unused vma argument in update_page_range and resolves a potential deadlock between lru lock, task lock and dentry lock reported by lockdep.
android: binder: Don't get mm from task
android: binder: Remove unused vma argument
drivers/android/binder_alloc.c | 36 ++++++-------drivers/android/binder_alloc.h | 1 -
2 files changed, 15 insertions(+), 22 deletions(-)
PATCH 1/2 android: binder: Remove unused vma argument
The vma argument in update_page_range is no longer used after 74310e06 ("android: binder: Move buffer out of area shared with user space"), since mmap_handler no longer calls update_page_range with a vma.
--- drivers/android/binder_alloc.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
drivers/android/binder_alloc.c +7 -9
@@ -186,12 +186,12 @@ struct binder_buffer *binder_alloc_prepare_to_free(struct binder_alloc *alloc, }static int binder_update_page_range (struct binder_alloc *alloc,int allocate, -void *start,void *end, -struct vm_area_struct *vma) +void *start,void *end) {void *page_addr;unsigned long user_page_addr;struct binder_lru_page *page; +struct vm_area_struct *vma =NULL ;struct mm_struct *mm =NULL ;bool need_mm = false;
@@ -215,7 +215,7 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, } } -if (!vma && need_mm) +if (need_mm) mm =get_task_mm (alloc->tsk);if (mm) {
@@ -442,7 +442,7 @@ struct binder_buffer *binder_alloc_new_buf_locked(struct binder_alloc *alloc,if (end_page_addr > has_page_addr) end_page_addr = has_page_addr; ret =binder_update_page_range (alloc,1 , - (void *)PAGE_ALIGN ((uintptr_t )buffer->data), end_page_addr,NULL ); + (void *)PAGE_ALIGN ((uintptr_t )buffer->data), end_page_addr);if (ret)return ERR_PTR (ret);
@@ -483,7 +483,7 @@ struct binder_buffer *binder_alloc_new_buf_locked(struct binder_alloc *alloc, err_alloc_buf_struct_failed:binder_update_page_range (alloc,0 , (void *)PAGE_ALIGN ((uintptr_t )buffer->data), - end_page_addr,NULL ); + end_page_addr);return ERR_PTR (-ENOMEM ); }
@@ -567,8 +567,7 @@ static void binder_delete_free_buffer(struct binder_alloc *alloc, alloc->pid, buffer->data, prev->data, next->data);binder_update_page_range (alloc,0 ,buffer_start_page (buffer), -buffer_start_page (buffer) +PAGE_SIZE , -NULL ); +buffer_start_page (buffer) +PAGE_SIZE ); }list_del (&buffer->entry);kfree (buffer);
@@ -605,8 +604,7 @@ static void binder_free_buf_locked(struct binder_alloc *alloc,binder_update_page_range (alloc,0 , (void *)PAGE_ALIGN ((uintptr_t )buffer->data), - (void *)(((uintptr_t )buffer->data + buffer_size) &PAGE_MASK ), -NULL ); + (void *)(((uintptr_t )buffer->data + buffer_size) &PAGE_MASK ));rb_erase (&buffer->rb_node, &alloc->allocated_buffers); buffer->free =1 ;
Signature · 1 line
2.11.0 (Apple Git-81)
PATCH 2/2 android: binder: Don't get mm from task
In reply to Sherry YangUse binder_alloc struct's mm_struct rather than getting a reference to the mm struct through get_task_mm to avoid a potential deadlock between lru lock, task lock and dentry lock, since a thread can be holding the task lock and the dentry lock while trying to acquire the lru lock.
--- drivers/android/binder_alloc.c | 22 +++++++++------------- drivers/android/binder_alloc.h | 1 - 2 files changed, 9 insertions(+), 14 deletions(-)
drivers/android/binder_alloc.c +9 -13
@@ -215,17 +215,12 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, } } -if (need_mm) - mm =get_task_mm (alloc->tsk); +if (need_mm &&mmget_not_zero (alloc->vma_vm_mm)) + mm = alloc->vma_vm_mm;if (mm) {down_write (&mm->mmap_sem); vma = alloc->vma; -if (vma && mm != alloc->vma_vm_mm) { -pr_err ("%d: vma mm and task mm mismatch\n" , - alloc->pid); - vma =NULL ; - } }if (!vma && need_mm) {
@@ -718,6 +713,7 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,barrier (); alloc->vma = vma; alloc->vma_vm_mm = vma->vm_mm; +mmgrab (alloc->vma_vm_mm);return 0 ;
@@ -793,6 +789,8 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc)vfree (alloc->buffer); }mutex_unlock (&alloc->mutex); +if (alloc->vma_vm_mm) +mmdrop (alloc->vma_vm_mm); binder_alloc_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d buffers %d, pages %d\n",
@@ -887,7 +885,6 @@ int binder_alloc_get_allocated_count(struct binder_alloc *alloc)void binder_alloc_vma_close (struct binder_alloc *alloc) {WRITE_ONCE (alloc->vma,NULL ); -WRITE_ONCE (alloc->vma_vm_mm,NULL ); }/**
@@ -924,9 +921,9 @@ enum lru_status binder_alloc_free_page(struct list_head *item, page_addr = (uintptr_t )alloc->buffer + index *PAGE_SIZE ; vma = alloc->vma;if (vma) { - mm =get_task_mm (alloc->tsk); -if (!mm) - goto err_get_task_mm_failed; +if (!mmget_not_zero (alloc->vma_vm_mm)) + goto err_mmget; + mm = alloc->vma_vm_mm;if (!down_write_trylock (&mm->mmap_sem)) goto err_down_write_mmap_sem_failed; }
@@ -961,7 +958,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item, err_down_write_mmap_sem_failed:mmput_async (mm); -err_get_task_mm_failed: +err_mmget: err_page_already_freed:mutex_unlock (&alloc->mutex); err_get_alloc_mutex_failed:
@@ -1000,7 +997,6 @@ struct shrinker binder_shrinker = {*/ void binder_alloc_init (struct binder_alloc *alloc) { - alloc->tsk = current->group_leader; alloc->pid = current->group_leader->pid;mutex_init (&alloc->mutex);INIT_LIST_HEAD (&alloc->buffers);
drivers/android/binder_alloc.h +0 -1
@@ -100,7 +100,6 @@ struct binder_lru_page {*/ struct binder_alloc {struct mutex mutex; -struct task_struct *tsk;struct vm_area_struct *vma;struct mm_struct *vma_vm_mm;void *buffer;
Signature · 1 line
2.11.0 (Apple Git-81)
Make binder shrinker static and fix null dereference
This patch set makes binder shrinker static and fixes the null pointer dereference in kernel debug message in binder_alloc.c. The earlier patches from this email thread ("android: binder:
Remove unused vma argument" and "android: binder: Remove unused vma argument") need to be applied before these two patches can be applied cleanly.
android: binder: Fix null ptr dereference in debug msg
android: binder: Change binder_shrinker to static
drivers/android/binder_alloc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
PATCH 1/2 android: binder: Change binder_shrinker to static
binder_shrinker struct is not used anywhere outside of binder_alloc.c and should be static.
--- drivers/android/binder_alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/android/binder_alloc.c +1 -1
@@ -982,7 +982,7 @@ binder_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)return ret; } -struct shrinker binder_shrinker = { +static struct shrinker binder_shrinker = { .count_objects = binder_shrink_count, .scan_objects = binder_shrink_scan, .seeks =DEFAULT_SEEKS ,
Signature · 1 line
2.11.0 (Apple Git-81)
PATCH 2/2 android: binder: Fix null ptr dereference in debug msg
In reply to Sherry YangDon't access next->data in kernel debug message when the next buffer is null.
--- drivers/android/binder_alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/android/binder_alloc.c +1 -1
@@ -560,7 +560,7 @@ static void binder_delete_free_buffer(struct binder_alloc *alloc,binder_alloc_debug (BINDER_DEBUG_BUFFER_ALLOC ,"%d: merge free, buffer %pK do not share page with %pK or %pK\n" , alloc->pid, buffer->data, - prev->data, next->data); + prev->data, next ? next->data :NULL );binder_update_page_range (alloc,0 ,buffer_start_page (buffer),buffer_start_page (buffer) +PAGE_SIZE ); }
Signature · 1 line
2.11.0 (Apple Git-81)
Greg Kroah-Hartman
maintainerRe: [PATCH 2/2] android: binder: Fix null ptr dereference in debug msg
Quoted 8 lines · Sherry Yang
Don't access
next->datain kernel debug message when the next buffer is null.Acked-by Arve Hjønnevåg <[email protected]>Signed-off-by Sherry Yang <[email protected]>--- drivers/android/binder_alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Same here, can you rebase and resend this one against char-misc-linus and resend?
thanks,
greg k-h
Greg Kroah-Hartman
maintainerRe: [PATCH 2/2] android: binder: Don't get mm from task
In reply to Sherry YangQuoted 6 lines · Sherry Yang
Use
binder_allocstruct'smm_structrather than getting a reference to the mm struct throughget_task_mmto avoid a potential deadlock between lru lock, task lock and dentry lock, since a thread can be holding the task lock and the dentry lock while trying to acquire the lru lock.
Quoted 6 lines
Acked-by Arve Hjønnevåg <[email protected]>Signed-off-by Sherry Yang <[email protected]>--- drivers/android/binder_alloc.c | 22 +++++++++------------- drivers/android/binder_alloc.h | 1 - 2 files changed, 9 insertions(+), 14 deletions(-)
This seems to be needed for 4.14-final, so can you refresh it against my char-misc-linus branch and resend it?
thanks,
greg k-h