Spindump manages to bypass kauth protected dylib file, and read it's contents.
site_archiver@lists.apple.com Delivered-To: darwin-kernel@lists.apple.com Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=M6T1WNsMUci5xwYJb1O/sBdlAry7UNgC8rxiuCSWpKk=; b=LRz+2gGtiGiLYJJxLjYew95K+sZn0j/9oJsb8nZazsPjD0AbL9Ey+t0KjCTQdCiUqq 46PzwDgDjpxWZ1r+Od/XaAtexV6adY6+/2YQPFxdQxJ0ONd8Q9CUa9gXOG9AwCPVgk+h 9XO0UQeuWPwsx4yzWtzL0nuTr4IH2PKZvQkYgxUBijqpNod6txQB+HlLV+txGrXC8RDj RoRO6tSDAO52QwEVHSOI3Pyqy5qIbFkUtmx1cSjM4FmJkegmqBFFoOYECKP4C+BQKAC3 A3VUGPn7N+EI8Q9DQtofDzw8nXzSvpObTB9U3RjeG2lDX/nB6vjNbNTqRohc8XOo3Pl4 Amkg== I've got a dylib file which I prevent from accessed using kauth vnode scope. To achieve that, I use driver that listen to kauth vnode scope with callback that prevent any access to this file by other processes but my own. However, I've noticed that spindump coreSymbolication framework can bypass this authorization flow after 4 retries to access the file (using open syscall), and access the file memory directly as it can be shown in the following backtrace : frame #2: 0xffffff7f87ac4784 IOStorageFamily`dkreadwrite(dkr=0xffffff8062fca3e0, dkrtype=<unavailable>) at IOMediaBSDClient.cpp:2975 [opt] frame #3: 0xffffff80072d8734 kernel`spec_strategy(ap=<unavailable>) at spec_vnops.c:2409 [opt] frame #4: 0xffffff8007282212 kernel`buf_strategy(devvp=<unavailable>, ap=<unavailable>) at vfs_bio.c:1379 [opt] frame #5: 0xffffff800728ad42 kernel`cluster_io [inlined] VNOP_STRATEGY(bp=0xffffff8062fca3e0) at kpi_vfs.c:5696 [opt] frame #6: 0xffffff800728ad0b kernel`cluster_io(vp=0xffffff80145a8c18, upl=0xffffff80107f7700, upl_offset=0x0000000000004000, f_offset=40960, non_rounded_size=0, flags=141, real_bp=<unavailable>, iostate=<unavailable>, callback=<unavailable>, callback_arg=<unavailable>) at vfs_cluster.c:1801 [opt] frame #7: 0xffffff800728b8f5 kernel`cluster_pagein_ext(vp=0xffffff80145a8c18, upl=0xffffff80107f7700, upl_offset=<unavailable>, f_offset=24576, size=<unavailable>, filesize=-549414335464, flags=<unavailable>, callback=<unavailable>, callback_arg=<unavailable>) at vfs_cluster.c:2171 [opt] frame #8: 0xffffff800728b7e5 kernel`cluster_pagein(vp=<unavailable>, upl=<unavailable>, upl_offset=<unavailable>, f_offset=<unavailable>, size=<unavailable>, filesize=<unavailable>, flags=0) at vfs_cluster.c:2116 [opt] frame #9: 0xffffff7f893d60be frame #10: 0xffffff80075a811a kernel`vnode_pagein [inlined] VNOP_PAGEIN(size=24576, flags=341478424, ctx=<unavailable>) at kpi_vfs.c:5273 [opt] frame #11: 0xffffff80075a80d3 kernel`vnode_pagein(vp=0xffffff80145a8c18, upl=<unavailable>, upl_offset=<unavailable>, f_offset=24576, size=<unavailable>, flags=341478424, errorp=<unavailable>) at vnode_pager.c:593 [opt] frame #12: 0xffffff80070dc119 kernel`vnode_pager_cluster_read(vnode_object=0xffffff80145a48e8, base_offset=24576, offset=<unavailable>, io_streaming=<unavailable>, cnt=0x0000000000004000) at bsd_vm.c:851 [opt] frame #13: 0xffffff80070dbe93 kernel`vnode_pager_data_request(mem_obj=0xffffff80145a48e8, offset=24576, length=<unavailable>, desired_access=<unavailable>, fault_info=<unavailable>) at bsd_vm.c:639 [opt] frame #14: 0xffffff80070eb011 kernel`vm_fault_page [inlined] memory_object_data_request(memory_object=<unavailable>, offset=<unavailable>, length=4096, desired_access=1, fault_info=<unavailable>) at memory_object.c:2134 [opt] frame #15: 0xffffff80070eaffb kernel`vm_fault_page(first_object=0xffffff8011d64a00, first_offset=4096, fault_type=1, must_be_resident=0, caller_lookup=0, protection=0xffffff806717be90, result_page=<unavailable>, top_page=<unavailable>, type_of_fault=<unavailable>, error_code=<unavailable>, no_zero_fill=<unavailable>, data_supply=0, fault_info=<unavailable>) at vm_fault.c:1770 [opt] frame #16: 0xffffff80070ef82a kernel`vm_fault_internal(map=<unavailable>, vaddr=<unavailable>, caller_prot=1, change_wiring=<unavailable>, wire_tag=0, interruptible=2, caller_pmap=<unavailable>, caller_pmap_addr=<unavailable>, physpage_p=<unavailable>) at vm_fault.c:4610 [opt] frame #17: 0xffffff8007188f92 kernel`user_trap [inlined] vm_fault(map=<unavailable>, fault_type=<unavailable>, change_wiring=0, wire_tag=0, interruptible=2, caller_pmap_addr=0) at vm_fault.c:3416 [opt] frame #18: 0xffffff8007188f6f kernel`user_trap(saved_state=0xffffff800f07b7a0) at trap.c:1083 [opt] I just wonder how it's possible to get memory fault on the file memory without open it first and get the file descriptor (kauth prevent open syscall). what system call can actually initial the kernel thread whose backtrace listed above ? B.S: First I thought it might be mmap, but I eliminate this option after hooking Mac policy function of mpo_file_check_mmap. Then I tried to look at the trace of spindump when it reads my dylib. perhaps any of the syscalls that triggered this memory read exists in there.. *open("/Library/MyDir/MyFile.dylib\0", 0x0, 0x0) = -1 Err#13* *open("/Library/MyDir/MyFile.dylib\0", 0x0, 0x0) = -1 Err#13* *open("/Library/MyDir/MyFile.dylib\0", 0x0, 0x0) = -1 Err#13* *open("/Library/MyDir/MyFile.dylib\0", 0x0, 0x0) = -1 Err#13* proc_info(0x2, 0x22C, 0x3) = 136 0 __mac_syscall(0x7FFF7C5FBAC6, 0x2, 0x70000E7AD6F0) = 0 0 proc_info(0x2, 0x22C, 0x3) = 136 0 proc_info(0x2, 0x22C, 0xB) = 0 0 proc_info(0x2, 0x22C, 0x3) = 136 0 proc_info(0x2, 0x1, 0x3) = 136 0 proc_info(0x2, 0x1, 0xB) = 0 0 bsdthread_create(0x7FFF682EDC18, 0x70000E7AE718, 0x80000) = 244015104 0 thread_selfid(0x0, 0x0, 0x0) = 10973 0 psynch_mutexdrop(0x70000E7AE728, 0x203, 0x100) = 0 0 psynch_mutexwait(0x70000E7AE728, 0x203, 0x0) = 515 0 __disable_threadsignal(0x1, 0x0, 0x0) = 0 0 __semwait_signal(0x1A2F, 0x0, 0x0) = 0 0 getattrlist("/Library/MyDir/MyFile.dylib\0", 0x70000E7ADEA0, 0x70000E7AE2A8) = 0 0 geteuid(0x0, 0x0, 0x0) = 0 0 bsdthread_create(0x7FFF682EDC18, 0x70000E7AE7E0, 0x80000) = 244015104 0 thread_selfid(0x0, 0x0, 0x0) = 10974 0 psynch_mutexdrop(0x70000E7AE7F0, 0x203, 0x100) = 0 0 psynch_mutexwait(0x70000E7AE7F0, 0x203, 0x0) = 515 0 geteuid(0x0, 0x0, 0x0) = 0 0 kevent_qos(0xFFFFFFFFFFFFFFFF, 0x70000E8B56B8, 0x1) = 0 0 workq_kernreturn(0x40, 0x70000E938B80, 0x1) = 0 Err#-2 workq_kernreturn(0x20, 0x0, 0x1) = 0 0 workq_kernreturn(0x4, 0x0, 0x0) = 0 Err#-2 open("/Library/MyDir/MyFile.dylib\0", 0x0, 0x0) = -1 Err#13 open("/Library/MyDir/MyFile.dylib\0", 0x0, 0x0) = -1 Err#13 open("/Library/MyDir/MyFile.dylib\0", 0x0, 0x0) = -1 Err#13 open("/Library/MyDir/MyFile.dylib\0", 0x0, 0x0) = -1 Err#13 write_nocancel(0x2, "Caught EXC_BAD_ACCESS at 0x10bbc4d84, valid page mapping, page query flags (0x80)\n\0", 0x52) = 82 0 __disable_threadsignal(0x1, 0x0, 0x0) = 0 0 __semwait_signal(0x227B, 0x0, 0x0) = 0 0 write_nocancel(0x2, "Missing page in pid 556, create of symbol owner data for [/Library/MyDir/MyFile.dylib] failed, err code 4098\n\0", 0x81) = 129 0 open_nocancel("/Library/MyDir\0", 0x1100004, 0xE7AD20A) = 4 0 fstatfs64(0x4, 0x70000E7AC028, 0x0) = 0 0 getdirentries64(0x4, 0x7FF8BDAF6800, 0x1000) = -1 Err#5 close_nocancel(0x4) = 0 0 stat64("/Library/MyDir\0", 0x70000E7ADAE0, 0x0) = 0 0 open_nocancel("/Library/MyDir\0", 0x1100004, 0xE7AD60A) = 4 0 _______________________________________________ Do not post admin requests to the list. They will be ignored. Darwin-kernel mailing list (Darwin-kernel@lists.apple.com) Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/darwin-kernel/site_archiver%40lists.... This email sent to site_archiver@lists.apple.com
participants (1)
-
Irad K