ASA-2019-00083 – Linux: Binder use-after-free do VMA via race condition entre reclaim e munmap


For the English version of this alert, click here.

Allele Security Alert

ASA-2019-00083

Identificador(es)

ASA-2019-00083, A-120025196, CVE-2019-1999

Título

Binder use-after-free do VMA via race condition entre reclaim e munmap

Fabricante(s)

The Linux foundation
Google

Produto(s)

Linux
Android

Versão(ões) afetada(s)

Android Security Patch Level anteriores a February 2019

Versão(ões) corrigida(s)

Android Security Patch Level February 2019

Prova de conceito

Sim

Descrição

Existe um race condition entre o caminho direto de reclaim (entrar no Binder através de binder_shrinker) e a chamada de sistema munmap() (entrar no Binder através do handler ->close de binder_vm_ops).

Detalhes técnicos

Vindo da chamada de sistema munmap():

binder_vma_close() -> binder_alloc_vma_close() -> binder_alloc_set_vma() sets alloc->vma para NULL sem obter nenhum locks extra; binder_vma_close() é chamado de remove_vma() <- remove_vma_list() <- __do_munmap() <- __vm_munmap() <- sys_munmap() com somente o mmap_sem obtido para escrita.

Vindo através do caminho direto de reclaim:

binder_alloc_free_page() não obtém mmap_sem na entrada. Contém o seguinte código:

enum lru_status binder_alloc_free_page(struct list_head *item,
struct list_lru_one *lru,
spinlock_t *lock,
void *cb_arg)
{
[...]
alloc = page->alloc;
if (!mutex_trylock(&alloc->mutex))
goto err_get_alloc_mutex_failed;

if (!page->page_ptr)
goto err_page_already_freed;

index = page - alloc->pages;
page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE;
// Leitura de ponteiro não proetgida! `vma` pode ser liberada imediatamente
vma = binder_alloc_get_vma(alloc);
if (vma) {
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;
// mmap_sem é obtido neste pronto, mas o ponteiro vma foi lido
// antes e pode estar dangling
}

list_lru_isolate(lru, item);
spin_unlock(lock);

if (vma) {
trace_binder_unmap_user_start(alloc, index);

// Ponteiro 'vma' dangling passado para zap_page_range
zap_page_range(vma,
page_addr + alloc->user_buffer_offset,
PAGE_SIZE);

trace_binder_unmap_user_end(alloc, index);

up_write(&mm->mmap_sem);
mmput(mm);
}

Créditos

Jann Horn (Google Project Zero)

Referência(s)

1721 – Android: binder use-after-free of VMA via race between reclaim and munmap –  project-zero – Monorail
https://bugs.chromium.org/p/project-zero/issues/detail?id=1721

Android Security Bulletin — February 2019
https://source.android.com/security/bulletin/2019-02-01.html

CVE-2019-1999
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-1999

CVE-2019-1999
https://nvd.nist.gov/vuln/detail/CVE-2019-1999

Se encontrou algum erro neste alerta ou deseja uma análise compreensiva, entre em contato.

Última modificação: 19 fevereiro 2019

Não somos responsáveis por qualquer perda de dados, corrupção de dispositivos ou qualquer outro tipo de problema devido ao uso de qualquer informação mencionada em nossos alertas de segurança.