int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) { struct vm_area_struct * vma; int result = -ENOENT; struct task_struct *task = proc_task(inode); struct mm_struct * mm = get_task_mm(task); if (!mm) goto out; down_read(&mm->mmap_sem); vma = mm->mmap; while (vma) { if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) break; vma = vma->vm_next; } if (vma) { *mnt = mntget(vma->vm_file->f_vfsmnt); *dentry = dget(vma->vm_file->f_dentry); result = 0; } up_read(&mm->mmap_sem); mmput(mm); out: return result; }
static struct proc * mac_task_get_proc(struct task *task) { if (task == current_task()) return proc_self(); /* * Tasks don't really hold a reference on a proc unless the * calling thread belongs to the task in question. */ int pid = task_pid(task); struct proc *p = proc_find(pid); if (p != NULL) { if (proc_task(p) == task) return p; proc_rele(p); } return NULL; }
int mremap_encrypted(__unused struct proc *p, struct mremap_encrypted_args *uap, __unused int32_t *retval) { mach_vm_offset_t user_addr; mach_vm_size_t user_size; kern_return_t result; vm_map_t user_map; uint32_t cryptid; cpu_type_t cputype; cpu_subtype_t cpusubtype; pager_crypt_info_t crypt_info; const char * cryptname = 0; char *vpath; int len, ret; struct proc_regioninfo_internal pinfo; vnode_t vp; uintptr_t vnodeaddr; uint32_t vid; AUDIT_ARG(addr, uap->addr); AUDIT_ARG(len, uap->len); user_map = current_map(); user_addr = (mach_vm_offset_t) uap->addr; user_size = (mach_vm_size_t) uap->len; cryptid = uap->cryptid; cputype = uap->cputype; cpusubtype = uap->cpusubtype; if (user_addr & vm_map_page_mask(user_map)) { /* UNIX SPEC: user address is not page-aligned, return EINVAL */ return EINVAL; } switch(cryptid) { case 0: /* not encrypted, just an empty load command */ return 0; case 1: cryptname="com.apple.unfree"; break; case 0x10: /* some random cryptid that you could manually put into * your binary if you want NULL */ cryptname="com.apple.null"; break; default: return EINVAL; } if (NULL == text_crypter_create) return ENOTSUP; ret = fill_procregioninfo_onlymappedvnodes( proc_task(p), user_addr, &pinfo, &vnodeaddr, &vid); if (ret == 0 || !vnodeaddr) { /* No really, this returns 0 if the memory address is not backed by a file */ return (EINVAL); } vp = (vnode_t)vnodeaddr; if ((vnode_getwithvid(vp, vid)) == 0) { MALLOC_ZONE(vpath, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); if(vpath == NULL) { vnode_put(vp); return (ENOMEM); } len = MAXPATHLEN; ret = vn_getpath(vp, vpath, &len); if(ret) { FREE_ZONE(vpath, MAXPATHLEN, M_NAMEI); vnode_put(vp); return (ret); } vnode_put(vp); } else { return (EINVAL); } #if 0 kprintf("%s vpath %s cryptid 0x%08x cputype 0x%08x cpusubtype 0x%08x range 0x%016llx size 0x%016llx\n", __FUNCTION__, vpath, cryptid, cputype, cpusubtype, (uint64_t)user_addr, (uint64_t)user_size); #endif /* set up decrypter first */ crypt_file_data_t crypt_data = { .filename = vpath, .cputype = cputype, .cpusubtype = cpusubtype }; result = text_crypter_create(&crypt_info, cryptname, (void*)&crypt_data); #if VM_MAP_DEBUG_APPLE_PROTECT if (vm_map_debug_apple_protect) { printf("APPLE_PROTECT: %d[%s] map %p [0x%llx:0x%llx] %s(%s) -> 0x%x\n", p->p_pid, p->p_comm, user_map, (uint64_t) user_addr, (uint64_t) (user_addr + user_size), __FUNCTION__, vpath, result); } #endif /* VM_MAP_DEBUG_APPLE_PROTECT */ FREE_ZONE(vpath, MAXPATHLEN, M_NAMEI); if(result) { printf("%s: unable to create decrypter %s, kr=%d\n", __FUNCTION__, cryptname, result); if (result == kIOReturnNotPrivileged) { /* text encryption returned decryption failure */ return (EPERM); } else { return (ENOMEM); } } /* now remap using the decrypter */ vm_object_offset_t crypto_backing_offset; crypto_backing_offset = -1; /* i.e. use map entry's offset */ result = vm_map_apple_protected(user_map, user_addr, user_addr+user_size, crypto_backing_offset, &crypt_info); if (result) { printf("%s: mapping failed with %d\n", __FUNCTION__, result); } if (result) { return (EPERM); } return 0; }