void doit( void ) { volatile char *buf; fptr func; buf = malloc( 1 ); if( buf == NULL ) { fprintf( stderr, "Out of memory\n" ); exit( 1 ); } /* Put a RETN instruction in the buffer */ *buf = '\xc3'; /* Try to make the buffer executable by using mprotect() */ /* Due to a FreeBSD bug PROT_READ is required */ do_mprotect( buf, 1, PROT_READ|PROT_EXEC ); /* Convert the pointer to a function pointer */ func = (fptr)buf; /* Call the code in the buffer */ func(); do_mprotect( buf, 1, PROT_READ|PROT_WRITE ); /* It worked when the function returns */ itworked(); }
void doit( void ) { char *shbss; char *shbss2; fptr func; void *handle1, *handle2; handle1 = dlopen( "shlibtest.so", RTLD_LAZY ); if( handle1 == NULL ) { fprintf( stderr, "dlopen() returned NULL\n" ); exit( 1 ); } dlerror(); /* clear any errors */ shbss = dlsym( handle1, "shbss" ); if( dlerror() != NULL ) { fprintf( stderr, "symbol %s not found in %s\n", "shbss", "shlibtest.so" ); exit( 1 ); } handle2 = dlopen( "shlibtest2.so", RTLD_LAZY ); if( handle2 == NULL ) { fprintf( stderr, "dlopen() returned NULL\n" ); exit( 1 ); } dlerror(); /* clear any errors */ shbss2 = dlsym( handle2, "shbss2" ); if( dlerror() != NULL ) { fprintf( stderr, "symbol %s not found in %s\n", "shbss2", "shlibtest2.so" ); exit( 1 ); } copy_shellcode(shbss, SHELLCODE_RETURN); copy_shellcode(shbss2, SHELLCODE_RETURN); /* Convert the pointer to a function pointer */ func = shbss < shbss2 ? (fptr)shbss : (fptr)shbss2; /* Try to make the memory region executable by using mprotect() */ /* Due to an OpenBSD bug PROT_READ is required */ do_mprotect(func, MAX_SHELLCODE_LEN, PROT_READ|PROT_EXEC ); /* Call the code in the buffer */ func(); do_mprotect(func, MAX_SHELLCODE_LEN, PROT_READ|PROT_WRITE ); /* It worked when the function returns */ itworked(); dlclose( handle1 ); dlclose( handle2 ); }
int main(int argc, char *argv[]) { int ret = 0; int uid; if (argc != 2) { printf("Must run with one argument\n"); exit(EXIT_FAILURE); } uid = atoi(argv[1]); if (!uid) { printf("Need to run this as a non-root user\n"); } ret = setuid(uid); if (ret == -1) { perror("Unable to setuid"); exit(EXIT_FAILURE); } ret = do_mmap(FILENAME); ret += do_mprotect(FILENAME); return ret; }
void doit( void ) { fptr func; /* Convert the pointer to a function pointer */ func = (fptr)&buf; /* Try to make the data executable first by using mprotect */ /* Due to an OpenBSD bug PROT_READ is required */ do_mprotect( &buf, 1, PROT_READ|PROT_EXEC ); /* Call the code in the buffer */ func(); do_mprotect( &buf, 1, PROT_READ|PROT_WRITE ); /* It worked when the function returns */ itworked(); }
//Adding mprotect and munprotect here int mprotect(void *addr, int len) { int ret = -1; uint addrint = (uint)addr; //Checks if page-aligned if (addrint % PGSIZE != 0) { return ret; } //Check if addr is not too large /* int procint = *proc; if ( (*addrint +len) > (procint + proc->sz) ) { return -1; } */ //cprintf("%s%d\n", "lengthoutside = ", len); if(len <= 0) { //cprintf("%s%d\n", "lengthinside = ", len); //cprintf("-1 on 1\n"); return ret; } if(addrint + (len * PGSIZE) > proc->sz) { //cprintf("-1 on 2\n"); return ret; } if(addrint > proc->sz || addrint <= 0) { //cprintf("-1 on 3\n"); return ret; } //NOT SURE IF WE NEED ALL THIS CODE(or what it does) -CONOR //int pid = proc->pid; //int *addrint = addr; //acquire(&ptable.lock); //if (pid < 0 || pid >= NPROC) { // release(&ptable.lock); // return ret; // } ret = 0; do_mprotect(proc, addr); return ret; }
static uint32_t __sys_linux_mprotect(uint32_t arg[]) { void *addr = (void*)arg[0]; size_t len = arg[1]; int prot = arg[2]; //kprintf("mprotect addr=0x%08x len=%08x prot=%08x\n", addr, len, prot); return do_mprotect(addr, len, prot); }
int kern_mprotect(void * addr, int len) { if ((uint)addr % PGSIZE != 0) return -1; // another check needed: addr too large if ((uint)addr <= 0 || (uint)addr > proc->sz) return -1; if (len <= 0 || (len*PGSIZE)+(int)addr > proc->sz) return -1; acquire(&ptable.lock); do_mprotect(proc, (int)addr, len); release(&ptable.lock); return 0; }
int kern_mprotect(void *addr, int len){ if((int)addr % PGSIZE != 0) return -1; if((int)addr >= proc->sz || (int)addr + 4 > proc->sz) return -1; if(len <= 0) return -1; if((int)addr + (len * PGSIZE) > proc->sz) return -1; if(addr == 0) return -1; do_mprotect((void*)addr,len); return 0; }
int kern_mprotect(struct proc* process, void *addr, int len) { unsigned int start = (unsigned int) addr; //bounds checking if (addr == 0) return -1; // fail on null address if (start % PGSIZE != 0) return -1; if (start > process->sz) return -1; if (len <= 0) return -1; if ((start + PGSIZE*len) > process->sz) return -1; int i; for (i = start; i < start + (len * PGSIZE); i+= PGSIZE) { if (do_mprotect(process, (void*) i) == -1) return -1; // propagate -1 to user process } lcr3(v2p(process->pgdir)); return 0; }
uintptr_t sys_mprotect(uintptr_t addr, size_t length, int prot) { return do_mprotect(addr, length, prot); }
static ssize_t write_proc_mm(struct file *file, const char *buffer, size_t count, loff_t *ppos) { struct mm_struct *mm = file->private_data; struct proc_mm_op req; int n, ret; if(count > sizeof(req)) return(-EINVAL); n = copy_from_user(&req, buffer, count); if(n != 0) return(-EFAULT); ret = count; switch(req.op){ case MM_MMAP: { struct mm_mmap *map = &req.u.mmap; ret = do_mmap2(mm, map->addr, map->len, map->prot, map->flags, map->fd, map->offset >> PAGE_SHIFT); if((ret & ~PAGE_MASK) == 0) ret = count; break; } case MM_MUNMAP: { struct mm_munmap *unmap = &req.u.munmap; down_write(&mm->mmap_sem); ret = do_munmap(mm, unmap->addr, unmap->len); up_write(&mm->mmap_sem); if(ret == 0) ret = count; break; } case MM_MPROTECT: { struct mm_mprotect *protect = &req.u.mprotect; ret = do_mprotect(mm, protect->addr, protect->len, protect->prot); if(ret == 0) ret = count; break; } case MM_COPY_SEGMENTS: { struct mm_struct *from = proc_mm_get_mm(req.u.copy_segments); if(IS_ERR(from)){ ret = PTR_ERR(from); break; } mm_copy_segments(from, mm); break; } default: ret = -EINVAL; break; } return(ret); }
void load_elf(const char* fn, elf_info* info) { file_t* file = file_open(fn, O_RDONLY, 0); if (IS_ERR_VALUE(file)) goto fail; Elf_Ehdr eh; ssize_t ehdr_size = file_pread(file, &eh, sizeof(eh), 0); if (ehdr_size < (ssize_t)sizeof(eh) || !(eh.e_ident[0] == '\177' && eh.e_ident[1] == 'E' && eh.e_ident[2] == 'L' && eh.e_ident[3] == 'F')) goto fail; #if __riscv_xlen == 64 assert(IS_ELF64(eh)); #else assert(IS_ELF32(eh)); #endif #ifndef __riscv_compressed assert(!(eh.e_flags & EF_RISCV_RVC)); #endif size_t phdr_size = eh.e_phnum * sizeof(Elf_Phdr); if (phdr_size > info->phdr_size) goto fail; ssize_t ret = file_pread(file, (void*)info->phdr, phdr_size, eh.e_phoff); if (ret < (ssize_t)phdr_size) goto fail; info->phnum = eh.e_phnum; info->phent = sizeof(Elf_Phdr); Elf_Phdr* ph = (typeof(ph))info->phdr; // compute highest VA in ELF uintptr_t max_vaddr = 0; for (int i = 0; i < eh.e_phnum; i++) if (ph[i].p_type == PT_LOAD && ph[i].p_memsz) max_vaddr = MAX(max_vaddr, ph[i].p_vaddr + ph[i].p_memsz); max_vaddr = ROUNDUP(max_vaddr, RISCV_PGSIZE); // don't load dynamic linker at 0, else we can't catch NULL pointer derefs uintptr_t bias = 0; if (eh.e_type == ET_DYN) bias = RISCV_PGSIZE; info->entry = eh.e_entry + bias; int flags = MAP_FIXED | MAP_PRIVATE; for (int i = eh.e_phnum - 1; i >= 0; i--) { if(ph[i].p_type == PT_LOAD && ph[i].p_memsz) { uintptr_t prepad = ph[i].p_vaddr % RISCV_PGSIZE; uintptr_t vaddr = ph[i].p_vaddr + bias; if (vaddr + ph[i].p_memsz > info->brk_min) info->brk_min = vaddr + ph[i].p_memsz; int flags2 = flags | (prepad ? MAP_POPULATE : 0); int prot = get_prot(ph[i].p_flags); if (__do_mmap(vaddr - prepad, ph[i].p_filesz + prepad, prot | PROT_WRITE, flags2, file, ph[i].p_offset - prepad) != vaddr - prepad) goto fail; memset((void*)vaddr - prepad, 0, prepad); if (!(prot & PROT_WRITE)) if (do_mprotect(vaddr - prepad, ph[i].p_filesz + prepad, prot)) goto fail; size_t mapped = ROUNDUP(ph[i].p_filesz + prepad, RISCV_PGSIZE) - prepad; if (ph[i].p_memsz > mapped) if (__do_mmap(vaddr + mapped, ph[i].p_memsz - mapped, prot, flags|MAP_ANONYMOUS, 0, 0) != vaddr + mapped) goto fail; } } file_decref(file); return; fail: panic("couldn't open ELF program: %s!", fn); }