Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save Wowfunhappy/ae358f8ccf5c9915309800093cd9bf1a to your computer and use it in GitHub Desktop.

Select an option

Save Wowfunhappy/ae358f8ccf5c9915309800093cd9bf1a to your computer and use it in GitHub Desktop.
Codex Analysis of Chromium Legacy #44 (the XNU kernel panic)

Codex conversation

User

Read this Github issue for Chromium Legacy, a fork of the Chromium app which was backported to legacy versions of Mac OS X. You must read the entire conversation without skipping anything. You should probably use the gh command line tool. blueboxd/chromium-legacy#44

The actual root cause of the problem was never found. What do you think was actually happening? Provide a detailed analysis. The Chromium Legacy and XNU source code are included in this directory for reference if needed.

Assistant

I’ll read the full issue conversation, then trace the relevant Chromium and XNU code to assess what could explain the reported behavior.

Activity

$ /bin/bash -lc "pwd && rg --files -g 'AGENTS.md' -g '*44*' -g 'README*' -g '"'!**/third_party/**'"' -g '"'!**/test/**'"' -g '"'!**/tests/**'"' | head -80"
status: Completed · exit 0
  xnu-2422/README
  xnu-2422/tools/lldbmacros/README
  xnu-2422/osfmk/console/panic_ui/README
  xnu-2422/libkern/kmod/README
  xnu-2422/libkern/zlib/README
  xnu-2422/bsd/miscfs/devfs/README
  xnu-2422/config/README.DEBUG-kernel.txt
  chromium-legacy-master/README.md
  chromium-legacy-master/gin/README.md
  chromium-legacy-master/docs/design/README.md
  chromium-legacy-master/extensions/shell/README
  chromium-legacy-master/docs/memory-infra/README.md
  chromium-legacy-master/docs/memory/README.md
  chromium-legacy-master/docs/README.md
  chromium-legacy-master/docs/media/capture/README.md
  chromium-legacy-master/docs/speed_metrics/README.md
  chromium-legacy-master/docs/standards/README.md
  chromium-legacy-master/extensions/common/api/README
  chromium-legacy-master/docs/webapps/README.md
  chromium-legacy-master/docs/security/research/README.md
  chromium-legacy-master/docs/security/research/graphics/README.md
  chromium-legacy-master/docs/security/research/graphics/vulnerabilities/README.md
  chromium-legacy-master/docs/speed/README.md
  chromium-legacy-master/docs/standards/positions/GoogleChrome/README.md
  chromium-legacy-master/docs/security/research/graphics/resources/chromeoffensiv--i5ooq44jbrq.jpg
  chromium-legacy-master/docs/telemetry_extension/README.md
  chromium-legacy-master/docs/testing/chromeos_integration/README.md
  chromium-legacy-master/docs/fuchsia/README.md
  chromium-legacy-master/extensions/shell/app/README
  chromium-legacy-master/extensions/README.md
  chromium-legacy-master/fuchsia_web/shell/README.md
  chromium-legacy-master/docs/speed/metrics_changelog/README.md
  chromium-legacy-master/fuchsia_web/README.md
  chromium-legacy-master/device/vr/README.md
  chromium-legacy-master/extensions/components/README
  chromium-legacy-master/extensions/components/native_app_window/README
  chromium-legacy-master/device/vr/public/mojom/README.md
  chromium-legacy-master/device/vr/openxr/README.md
  chromium-legacy-master/device/bluetooth/README.md
  chromium-legacy-master/device/bluetooth/public/mojom/README.md
  chromium-legacy-master/device/bluetooth/public/mojom/emulation/README.md
  chromium-legacy-master/device/fido/README.md
  chromium-legacy-master/extensions/browser/api/declarative_net_request/README.md
  chromium-legacy-master/extensions/browser/api/declarative_net_request/filter_list_converter/README
  chromium-legacy-master/url/README.md
  chromium-legacy-master/tools/browserbench-webdriver/README.md
  chromium-legacy-master/tools/crbug/README.md
  chromium-legacy-master/tools/get_asan_chrome/README.md
  chromium-legacy-master/tools/get_swarming_logs/README.md
  chromium-legacy-master/tools/gritsettings/README.md
  chromium-legacy-master/tools/infra/README.md
  chromium-legacy-master/tools/valgrind/README
  chromium-legacy-master/tools/visual_debugger/README.md
  chromium-legacy-master/tools/style_variable_generator/README.md
  chromium-legacy-master/tools/vscode/README.md
  chromium-legacy-master/tools/vscode/bazel_lsp/README.md
  chromium-legacy-master/tools/mac/power/README.md
  chromium-legacy-master/tools/tracing/README.md
  chromium-legacy-master/tools/utr/README.md
  chromium-legacy-master/tools/win/chromeexts/README.md
  chromium-legacy-master/tools/win/DebugVisualizers/README.md
  chromium-legacy-master/tools/win/IdleWakeups/README.md
  chromium-legacy-master/tools/win/sizeviewer/README.chromium
  chromium-legacy-master/tools/rust/README.md
  chromium-legacy-master/tools/translation/README.md
  chromium-legacy-master/tools/win/ChromeDebug/README.txt
  chromium-legacy-master/tools/traffic_annotation/README.md
  chromium-legacy-master/tools/translation/testdata/test_grd/README.md
  chromium-legacy-master/tools/traceline/svgui/README
  chromium-legacy-master/tools/traceline/traceline/README
  chromium-legacy-master/tools/symsrc/README.chromium
  chromium-legacy-master/tools/traffic_annotation/summary/README.md
  chromium-legacy-master/tools/traffic_annotation/scripts/README.md
  chromium-legacy-master/tools/python/README.md
  chromium-legacy-master/tools/traffic_annotation/scripts/auditor/README.md
  chromium-legacy-master/tools/mac/icons/additional_tools/README
  chromium-legacy-master/tools/nix/README.md
  chromium-legacy-master/tools/page_cycler/startup_test_common/README
  chromium-legacy-master/tools/traffic_annotation/scripts/test_data/out/README.md
  chromium-legacy-master/tools/mb/README.md

Activity

$ /bin/bash -lc 'gh api repos/blueboxd/chromium-legacy/issues/44'
status: Failed · exit 1
  error connecting to api.github.com
  check your internet connection or https://githubstatus.com

Activity

web search: https://github.com/blueboxd/chromium-legacy/issues/44

Activity

$ /bin/bash -lc "rg --files -g AGENTS.md -g '"'!chromium-legacy-master/third_party/**'"'; ls -la"
status: Completed · exit 0
  total 16
  drwxr-xr-x   5 Jonathan  staff   170 Sep  8 10:20 .
  drwx------@ 15 Jonathan  staff   510 Sep  8 10:06 ..
  -rw-r--r--@  1 Jonathan  staff  6148 Sep  8 10:20 .DS_Store
  drwxr-xr-x@ 91 Jonathan  staff  3094 Sep  8 10:20 chromium-legacy-master
  drwxr-xr-x@ 19 Jonathan  staff   646 Sep  8 10:08 xnu-2422

Activity

$ /bin/bash -lc 'gh api repos/blueboxd/chromium-legacy/issues/44'
status: Completed · exit 0
  {"url":"https://api.github.com/repos/blueboxd/chromium-legacy/issues/44","repository_url":"https://api.github.com/repos/blueboxd/chromium-legacy","labels_url":"https://api.github.com/repos/blueboxd/chromium-legacy/issues/44/labels{/name}","comments_url":"https://api.github.com/repos/blueboxd/chromium-legacy/issues/44/comments","events_url":"https://api.github.com/repos/blueboxd/chromium-legacy/issues/44/events","html_url":"https://github.com/blueboxd/chromium-legacy/issues/44","id":1099728731,"node_id":"I_kwDODnlvEM5BjIdb","number":44,"title":"Chromium Legacy occasionally induces a kernel panic: kqueue_scan_continue: - invalid wait_result","user":{"login":"Wowfunhappy","id":4484096,"node_id":"MDQ6VXNlcjQ0ODQwOTY=","avatar_url":"https://avatars.githubusercontent.com/u/4484096?v=4","gravatar_id":"","url":"https://api.github.com/users/Wowfunhappy","html_url":"https://github.com/Wowfunhappy","followers_url":"https://api.github.com/users/Wowfunhappy/followers","following_url":"https://api.github.com/users/Wowfunhappy/following{/other_user}","gists_url":"https://api.github.com/users/Wowfunhappy/gists{/gist_id}","starred_url":"https://api.github.com/users/Wowfunhappy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Wowfunhappy/subscriptions","organizations_url":"https://api.github.com/users/Wowfunhappy/orgs","repos_url":"https://api.github.com/users/Wowfunhappy/repos","events_url":"https://api.github.com/users/Wowfunhappy/events{/privacy}","received_events_url":"https://api.github.com/users/Wowfunhappy/received_events","type":"User","user_view_type":"public","site_admin":false},"labels":[],"state":"open","locked":false,"assignees":[],"milestone":null,"comments":96,"created_at":"2022-01-11T23:57:16Z","updated_at":"2023-09-30T07:09:06Z","closed_at":null,"assignee":null,"author_association":"NONE","active_lock_reason":null,"sub_issues_summary":{"total":0,"completed":0,"percent_completed":0},"issue_dependencies_summary":{"blocked_by":0,"total_blocked_by":0,"blocking":0,"total_blocking":0},"body":"I've been avoiding reporting this, because I feel like it's going to be impossible to fix. :(\r\n\r\nOccasionally while using Chromium Legacy, OS X kernel panics with a distinctive backtrace. The backtrace implicates Chromium Helper, and I've never seen the panic occur when I'm not using Chromium. I've observed this on my desktop and laptop running 10.9, as have others on MacRumors. I think it _may_ happen more often on Macs with less memory?\r\n\r\nA log is attached. Notably, I have so far never managed to capture a panic while I had `keepsyms` enabled, I'd like to capture one at some point.\r\n\r\n[Kernel_2022-01-11-182654_Jonathans-MacBook-Air.panic.zip](https://github.com/blueboxd/chromium-legacy/files/7850488/Kernel_2022-01-11-182654_Jonathans-MacBook-Air.panic.zip)\r\n\r\n---\r\n\r\nEverything beyond this point is speculation, and probably useless, due to my limited understanding of C. But, I'm going to include it anyway. :)\r\n\r\nI'm technically running XNU version 2422.115.15, which doesn't appear to be open source, but the closest version with source available is 2422.115.4. The file being referenced in the log is here: https://opensource.apple.com/source/xnu/xnu-2422.115.4/bsd/kern/kern_event.c.auto.html\r\n\r\nThe line numbers don't match up, possibly because of the tiny version mismatch, but I assume this is the referenced function:\r\n\r\n```\r\nstatic void\r\nkqueue_scan_continue(void *data, wait_result_t wait_result)\r\n{\r\n\tthread_t self = current_thread();\r\n\tuthread_t ut = (uthread_t)get_bsdthread_info(self);\r\n\tstruct _kqueue_scan * cont_args = &ut->uu_kevent.ss_kqueue_scan;\r\n\tstruct kqueue *kq = (struct kqueue *)data;\r\n\tint error;\r\n\tint count;\r\n\r\n\t/* convert the (previous) wait_result to a proper error */\r\n\tswitch (wait_result) {\r\n\tcase THREAD_AWAKENED:\r\n\t\tkqlock(kq);\r\n\t\terror = kqueue_process(kq, cont_args->call, cont_args, &count,\r\n\t\t    current_proc());\r\n\t\tif (error == 0 && count == 0) {\r\n\t\t\twait_queue_assert_wait((wait_queue_t)kq->kq_wqs,\r\n\t\t\t    KQ_EVENT, THREAD_ABORTSAFE, cont_args->deadline);\r\n\t\t\tkq->kq_state |= KQ_SLEEP;\r\n\t\t\tkqunlock(kq);\r\n\t\t\tthread_block_parameter(kqueue_scan_continue, kq);\r\n\t\t\t/* NOTREACHED */\r\n\t\t}\r\n\t\tkqunlock(kq);\r\n\t\tbreak;\r\n\tcase THREAD_TIMED_OUT:\r\n\t\terror = EWOULDBLOCK;\r\n\t\tbreak;\r\n\tcase THREAD_INTERRUPTED:\r\n\t\terror = EINTR;\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tpanic(\"%s: - invalid wait_result (%d)\", __func__,\r\n\t\t    wait_result);\r\n\t\terror = 0;\r\n\t}\r\n\r\n\t/* call the continuation with the results */\r\n\tassert(cont_args->cont != NULL);\r\n\t(cont_args->cont)(kq, cont_args->data, error);\r\n}\r\n```\r\n\r\nSo, the switch statement expects the `wait_result` parameter to be either `THREAD_AWAKENED`, `THREAD_TIMED_OUT`, or `THREAD_INTERRUPTED`. If it's none of these—as appears to be the case for us—it panics with our error, \"invalid wait result\".\r\n\r\nSo, what _is_ being passed in as `wait_result`? Well, it's printing as the number \"3\", but I don't know enough C to understand how these integers are mapped to their human-readable names. However, note that a fourth option has been added to this switch statement in newer versions of XNU: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/kern/kern_event.c.auto.html\r\n\r\n```\r\n\tcase THREAD_RESTART:\r\n\t\terror = EBADF;\r\n\t\tbreak;\r\n```\r\n\r\nI'm going to hazard a guess that when the kernel panics, `kqueue_scan_continue` is getting called with a value of `THREAD_RESTART` in the `wait_result`parameter, which is understood on new versions of XNU but not the older ones we're using. Is there any way to catch and handle this?","closed_by":null,"reactions":{"url":"https://api.github.com/repos/blueboxd/chromium-legacy/issues/44/reactions","total_count":0,"+1":0,"-1":0,"laugh":0,"hooray":0,"confused":0,"heart":0,"rocket":0,"eyes":0},"timeline_url":"https://api.github.com/repos/blueboxd/chromium-legacy/issues/44/timeline","performed_via_github_app":null,"state_reason":null,"pinned_comment":null}

Activity

$ /bin/bash -lc "mkdir -p investigation && gh api --paginate 'repos/blueboxd/chromium-legacy/issues/44/comments?per_page=100' > investigation/comments.json && gh api repos/blueboxd/chromium-legacy/issues/44 > investigation/issue.json"
status: Completed · exit 0

Activity

$ /bin/bash -lc "rg -n 'THREAD_RESTART|kqueue_scan_continue|kqueue_close|kqueue_drain' xnu-2422/bsd/kern/kern_event.c; rg -n 'THREAD_RESTART' xnu-2422/osfmk/kern/wait_queue.c xnu-2422/osfmk/kern/thread.h xnu-2422/osfmk/mach/thread_status.h; cat xnu-2422/config/MasterVersion"
status: Completed · exit 0
  127:static int kqueue_close(struct fileglob *fg, vfs_context_t ctx);
  130:static int kqueue_drain(struct fileproc *fp, vfs_context_t ctx);
  140:	.fo_close = kqueue_close,
  142:	.fo_drain = kqueue_drain,
  157:static void kqueue_scan_continue(void *contp, wait_result_t wait_result);
  2125:kqueue_scan_continue(void *data, wait_result_t wait_result)
  2145:			thread_block_parameter(kqueue_scan_continue, kq);
  2241:				cont = kqueue_scan_continue;
  2391: * kqueue_close -
  2395:kqueue_close(struct fileglob *fg, __unused vfs_context_t ctx)
  2457: * kqueue_drain - called when kq is closed
  2461:kqueue_drain(struct fileproc *fp, __unused vfs_context_t ctx)
  xnu-2422/osfmk/kern/wait_queue.c:1267:		return (thread->wait_result = THREAD_RESTART);
  xnu-2422/osfmk/kern/wait_queue.c:1308:		return (thread->wait_result = THREAD_RESTART);
  xnu-2422/osfmk/kern/wait_queue.c:1344:		return (thread->wait_result = THREAD_RESTART);
  xnu-2422/osfmk/kern/wait_queue.c:1383:		return (thread->wait_result = THREAD_RESTART);
  13.4.0
  
  # The first line of this file contains the master version number for the kernel.
  # All other instances of the kernel version in xnu are derived from this file.
  #
  # The format of the version number must conform to the version resource format
  # as described in TN1132: http://developer.apple.com/technotes/tn/tn1132.html
  #
  # In particular, the string is formatted as: J[.N[.R[S[L]]]], where:
  #  J represents the kernel major version number (integer)
  #  N represents the kernel minor version number (integer)
  #  R represents the kernel revision number (integer)
  #  S represents the kernel build stage (one of "d", "a", "b", or "r")
  #  L represents the kernel pre-release level (integer)
  #
  # The correct way to make use of the kernel version within kernel code or a
  # kext is to include libkern/verison.h.  version.h contains defines that can
  # be used for build-time version logic and prototypes for variables that can
  # be used for run-time version logic.

Activity

$ /bin/bash -lc "python3 - <<'PY'import jsonc=json.load(open('investigation/comments.json'))print('TOTAL COMMENTS',len(c))for i,x in enumerate(c): if i<24:  print('\\nCOMMENT',i+1,x['user']['login'],x['created_at'],x['html_url'],'\\n'+x['body'])with open('investigation/conversation.txt','w') as f: q=json.load(open('investigation/issue.json')); f.write(q['body']+'\\n') for i,x in enumerate(c):f.write('\\nCOMMENT '+str(i+1)+' '+x['user']['login']+' '+x['created_at']+' '+x['html_url']+'\\n'+x['body']+'\\n')PY"
status: Completed · exit 0
  TOTAL COMMENTS 96
  
  COMMENT 1 pjpreilly 2022-01-12T01:33:55Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1010540986
  When I've triggered this...by chance.. I seem to always be switching windows either through hot corners invoking Mission Control or clicking the Chromium Dock Icon to switch windows..... FWIW.... or maybe switching tabs.... I've noticed sometimes when switching tabs the pointer does not take focus of the new tab until a subsequent click in the tab being switched to...seems to occur after the browser has been running for a good amount of time.
  
  COMMENT 2 krackers 2022-01-17T03:20:42Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1014103146
  @Wowfunhappy Mapping is given in https://opensource.apple.com/source/xnu/xnu-4570.61.1/osfmk/kern/kern_types.h
  
  You're right in that 3 corresponds to THREAD_RESTART.  Not too familiar with kqueue internals but just based on statically analyzing the call hierarchy, seems to be
  
  kevent_internal  -> kqueue_scan -> kqueue_scan_continue
  
  It's really interesting that kevent syscall was only recently updated to return `EBADF` though. Seems like this is returned whenever the fd becomes invalid (e.g. if it's closed), which would definitely explain why it's sporadic and hard to reproduce. I wonder if this bug was just never noticed on older versions of osx because nothing else other than chrome seems to make such heavy use of IPC, and older versions of Chromium probably used some other method for synchronization/ipc [1]?
  
  There are only a few places in chromium source that make the `kevent `syscall (search for
   `"kevent" "#include <sys/event.h>"`).  Might be interesting to add some debugging code around that to see if there's any pattern.
  
  
  [1] https://source.chromium.org/chromium/chromium/src/+/2096391cdcc3bdf963e68977e9015aa8cdbe85c6
  
  https://source.chromium.org/chromium/chromium/src/+/c96c632d5501d5ebba14e1130fdea8b15ac29756
  
  COMMENT 3 Wowfunhappy 2022-01-18T15:42:04Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1015537866
  Thanks! I wonder if [this](https://bugs.chromium.org/p/chromium/issues/detail?id=932175) was the underlying project which introduced the problem. The timing lines up, 9–12 months after 10.9 support was dropped from Chrome.
  
  Aside, I assume it's not possible to just replace `kqueue_scan_continue` with a version that handles `THREAD_RESTART`, right? Because it's an internal kernel function, or something like that?
  
  
  COMMENT 4 krackers 2022-01-19T00:56:37Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1015974367
  @Wowfunhappy Excellent question. It is possible if you are willing to install a kext. Basically since all the kexts will live in the same address space as the kernel code, you can hot-patch the kernel by modifying the instructions in memory.
  
  Now to actually do this patch you'll need to be a bit clever:
  
  * Load the kernel mach-o in ghidra/hopper/ida and find the address of the function that we want to modify (`kqueue_scan_continue`). This will be our magic number that is the offset to patch from base.
  * Then in your kext, you will have to find the base location the kernel is loaded at (due to kaslr this is not fixed), and add that offset from step (1) to find the address of the desired function.
  * Add an extra offset to get to the specific instruction we want to patch. In this case, it's not a trivial modification since we want to insert a block of code, so the best way to do this is to insert a jump to code in your kext that will handle the switch(), then jump back to the original code.
  * Do the patch as described above, and it should all just work.
  
  Conceptually not too difficult, and not that different from code injection in userspace. Only difference is that stakes are higher. If you have a VM and are willing to play around with it, I can give you some code pointers. Of course at this point it might just be easier to recompile the kernel itself since we have the source anyway...
  
  
  COMMENT 5 Wowfunhappy 2022-01-19T01:00:02Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1015976080
  Thanks, makes sense it would need a kext. Probably not ideal if it can be helped.
  
  (Just for my own use, I am a bit tempted to recompile XNU. But _I_ run into this panic so rarely anyway... Some people on MacRumors were saying it happens daily for them.)
  
  COMMENT 6 Wowfunhappy 2022-01-19T23:38:04Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1016969999
  MacBiter over on MacRumors captured a backtrace with `keepsyms` enabled.
  
  ```
  panic(cpu 6 caller 0xffffff80055c7ab4): "kqueue_scan_continue: - invalid wait_result (3)"@/SourceCache/xnu/xnu-2422.115.15/bsd/kern/kern_event.c:2167
  Backtrace (CPU 6), Frame : Return Address
  0xffffff81f05a3ef0 : 0xffffff8005223139 mach_kernel : _panic + 0xc9
  0xffffff81f05a3f70 : 0xffffff80055c7ab4 mach_kernel : _kqueue_scan + 0x8f4
  0xffffff81f05a3fb0 : 0xffffff80052d7c67 mach_kernel : _call_continuation + 0x17
  ```
  
  I assume [this](https://opensource.apple.com/source/xnu/xnu-2422.115.4/osfmk/kern/sched_prim.h.auto.html#:~:text=extern%20void%09%09call_continuation(%0A%09%09%09%09%09thread_continue_t%09continuation%2C%0A%09%09%09%09%09void%09%09%09%09*parameter%2C%0A%09%09%09%09%09wait_result_t%09%09wresult)%3B) is `_call_continuation`? Still an internal kernel function, I naively thought it might give us Chromium's initial syscall.
  
  Edit: And I think [this](https://opensource.apple.com/source/xnu/xnu-2422.115.4/osfmk/x86_64/machine_routines_asm.s.auto.html#:~:text=Entry(call_continuation)%0A%09movq,call%09EXT(thread_terminate)) is the definition... I wasn't expecting to find ASM...
  
  ---
  
  Edit 2: I don't actually understand most of what it's saying, but pages 418 – 420 of Jonathan Levin's _Mac OS X and iOS Internals_ may be relevant here. I think it's saying that `wait_result` is set by the [thread_block_reason()](https://opensource.apple.com/source/xnu/xnu-2422.115.4/osfmk/kern/sched_prim.c.auto.html#:~:text=wait_result_t%0Athread_block_reason) function.
  
  ![Screen Shot 2022-01-19 at 7 10 46 PM](https://user-images.githubusercontent.com/4484096/150240439-c4f04d57-5fe9-4f1f-825e-4971a7d36916.png)
  
  I'm just trying to figure out where that `wait_result` value could be coming from. I find it so weird that XNU is returning a value that didn't exist yet. It would make sense if _Chromium_ was the one setting `wait_result`, since Google is only targeting modern kernels. But this is kernel code calling kernel code. I guess the obvious answer is that it's a bug, but it seems like something that wouldn't have gone unnoticed for years.
  
  COMMENT 7 Wowfunhappy 2022-01-22T14:15:55Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1019278490
  ...well, for what it's worth, I decided to build a custom kernel. As it turns out, [compiling XNU is shockingly easy](https://gist.github.com/Wowfunhappy/2fca7ed5d1b1310de3854b92c65eef7e) and the build itself takes only a few minutes to complete. The only tricky part was that I had to install Xcode 5.0.2; later versions did not appear to work.
  
  The only source change is that I added the `THREAD_RESTART` case to `kqueue_scan_continue`, which sets `error = EBADF` as in newer versions of XNU.
  
  I am (a bit nervously) going to try using this on my main machine. A half hour in, nothing catastrophic has happened so far.
  
  The kernel is attached in case anyone else on Mavericks wants to try it, but I am _not_ necessarily recommending that anyone do so. If you do use it, make sure at minimum to have a secondary partition available to restore your original kernel should the need arise. Remember that you will need to clear the kernel cache on your first boot with the new kernel.
  
  @krackers Do you have any idea why this kernel would be only 8,257,152 bytes, when the original kernel _and_ every custom Hackintosh kernel I've checked is 8,394,688 bytes? It's weirding me out.
  
  [XNU-2422.115.4-THREAD_RESTART add-JA-v2022..01.22.zip](https://github.com/blueboxd/chromium-legacy/files/7918453/XNU-2422.115.4-THREAD_RESTART.add-JA-v2022.01.22.zip)
  
  
  
  COMMENT 8 krackers 2022-01-23T00:50:02Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1019386099
  @Wowfunhappy sorry for the late response.
  
  >I'm just trying to figure out where that wait_result value could be coming from. I find it so weird that XNU is returning a value that didn't exist yet
  
  Note that even in the older xnu version, `THREAD_RESTART` was still a valid defined value for `wait_result_t`. In fact, you can see that it is returned in `wait_queue_assert_wait64` of `osfmk/kern/wait_queue.c` when the queue becomes invalid. The difference is that in this older kernel version, kqueue scan did not properly handle this, and just panicked instead of returning EBADF.
  
  I agree that this seems way too obvious an omission to be a bug. But I can't think of any other explanation at the moment (that said, my knowledge here is very slim). I think the first step might be to see if we can create a scenario that can reliably reproduce this. Based on my current understanding, it seems like the conditions for triggering would look like:
  
  * Have one process call `kqueue` to create a new fd for event queue, and then call `kevent` to wait upon it
  
  * While that happens, another process closes the `fd`
  
  * Based on what's described above, this would generate a `THREAD_RESTART` condition in the wait queue code which would bubble up to `kqueue_scan` and cause the panic.
  
  But this seems way too obvious and easy to trigger, so I'm still skeptical that this is actually what's happening.
  
  >As it turns out, compiling XNU is shockingly easy and the build itself takes only a few minutes to complete
  
  I see you're following the "Kernel Shaman's" [build instructions](http://shantonu.blogspot.com/2013/10/building-xnu-for-os-x-109-mavericks.html)? I'm not quite sure why there would be a difference in size assuming that both are release builds, but it's possible that apple internal builds have some other `ifdefs` set during compile, or the kernel version is different? This wouldn't explain why the hackintosh kernels match in size though...
  
  That's also why I'm personally partial to the "hotpatch via kext" approach. That way you introduce only the minimal difference necessary.
  
  
  
  
  COMMENT 9 Wowfunhappy 2022-01-24T16:38:18Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1020296846
  @krackers I'm not ignoring your suggestions of things to try, they're just mostly outside of my skill level. 🙂 I only barely understand explanations of what a file descriptor is...
  
  Anyway, the plot thickens. I neglected to check something earlier:
  
  https://github.com/apple-oss-distributions/xnu/blame/cc9a63552421e7db025ad771974f3e9f479948ad/bsd/kern/kern_event.c
  
  That `THREAD_RESTART` case was only added to XNU in 3789.1.32, aka macOS 10.12 Sierra.
  
  But, Google Chrome officially supports macOS 10.11. So, why don't Chrome users on El Capitan experience kernel panics?
  
  Could this indicate the problem was introduced by Chromium Legacy? If I'm not missing anything, I think the only Chromium Legacy changes that involve `kevent` come from this commit. https://github.com/blueboxd/chromium-legacy/commit/e0cff58db7f41e2b0b68e058ec49a98f215265c5
  
  Google's [code review comments for this change](https://chromium-review.googlesource.com/c/chromium/src/+/2713848) are interesting...
  
  COMMENT 10 pjpreilly 2022-02-15T12:10:54Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1040198686
  On latest canary..Version 100.0.4889.0 (Official Build) (x86_64)
  two finger scrolling in a facebook messenger chat....
  
  Tue Feb 15 06:40:24 2022
  panic(cpu 0 caller 0x55bb8e): "kevent_scan_cont() - invalid wait_result (3)"@/SourceCache/xnu/xnu-1699.32.7/bsd/kern/kern_event.c:1982
  Backtrace (CPU 0), Frame : Return Address (4 potential args on stack)
  0xe2bf68 : 0x2203de (0x6b08cc 0xe2bf88 0x229fb0 0x0)
  0xe2bf98 : 0x55bb8e (0x7006a4 0x3 0x6 0xa4c39d4)
  0xe2bfc8 : 0x2c7d0c (0x9f03320 0x3 0x10 0xa4e9190)
  
  BSD process name corresponding to current thread: Chromium Helper
  
  Mac OS version:
  11G63
  
  Kernel version:
  Darwin Kernel Version 11.4.2: Thu Aug 23 16:26:45 PDT 2012; root:xnu-1699.32.7~1/RELEASE_I386
  Kernel UUID: 859B45FB-14BB-35ED-B823-08393C63E13B
  System model name: MacBook4,1 (Mac-F22788A9)
  
  System uptime in nanoseconds: 71096824466362
  last loaded kext at 27108605406: com.apple.driver.AudioAUUC	1.59 (addr 0x146b000, size 24576)
  last unloaded kext at 115835844270: com.apple.driver.USBCameraFirmwareLoader	1.1.0 (addr 0xd35000, size 24576)
  loaded kexts:
  com.apple.driver.AudioAUUC	1.59
  com.apple.filesystems.autofs	3.0
  com.apple.driver.AppleHWSensor	1.9.5d0
  com.apple.driver.AppleHDA	2.2.5a5
  com.apple.driver.AppleUpstreamUserClient	3.5.9
  com.apple.driver.AppleBacklight	170.2.2
  com.apple.driver.AppleMCCSControl	1.0.33
  com.apple.driver.AppleIntelGMAX3100	7.0.4
  com.apple.driver.AppleIntelGMAX3100FB	7.0.4
  com.apple.driver.SMCMotionSensor	3.0.2d6
  com.apple.iokit.IOUserEthernet	1.0.0d1
  com.apple.iokit.IOBluetoothSerialManager	4.0.8f17
  com.apple.Dont_Steal_Mac_OS_X	7.0.0
  com.apple.driver.AudioIPCDriver	1.2.3
  com.apple.driver.ApplePolicyControl	3.1.33
  com.apple.driver.ACPI_SMC_PlatformPlugin	5.0.0d8
  com.apple.driver.AppleLPC	1.6.0
  com.apple.driver.AppleSMCPDRC	5.0.0d8
  com.apple.driver.CSRUSBBluetoothHCIController	4.0.8f17
  com.apple.AppleFSCompression.AppleFSCompressionTypeDataless	1.0.0d1
  com.apple.AppleFSCompression.AppleFSCompressionTypeZlib	1.0.0d1
  com.apple.BootCache	33
  com.apple.driver.AppleUSBTrackpad	227.6
  com.apple.driver.AppleUSBTCKeyEventDriver	227.6
  com.apple.driver.AppleUSBTCKeyboard	227.6
  com.apple.driver.AppleIRController	312
  com.apple.iokit.SCSITaskUserClient	3.2.1
  com.apple.driver.XsanFilter	404
  com.apple.iokit.IOAHCIBlockStorage	2.1.0
  com.apple.driver.AirPortBrcm43224	501.36.15
  com.apple.driver.AppleFWOHCI	4.9.0
  com.apple.driver.AppleHPET	1.7
  com.apple.driver.AppleUSBHub	5.1.0
  com.apple.driver.AppleAHCIPort	2.3.1
  com.apple.driver.AppleIntelPIIXATA	2.5.1
  com.apple.driver.AppleUSBEHCI	5.1.0
  com.apple.driver.AppleUSBUHCI	5.1.0
  com.apple.driver.AppleEFINVRAM	1.6.1
  com.apple.driver.AppleRTC	1.5
  com.apple.iokit.AppleYukon2	3.2.2b1
  com.apple.driver.AppleSmartBatteryManager	161.0.0
  com.apple.driver.AppleACPIButtons	1.5
  com.apple.driver.AppleSMBIOS	1.9
  com.apple.driver.AppleACPIEC	1.5
  com.apple.driver.AppleAPIC	1.6
  com.apple.driver.AppleIntelCPUPowerManagementClient	195.0.0
  com.apple.nke.applicationfirewall	3.2.30
  com.apple.security.quarantine	1.4
  com.apple.security.TMSafetyNet	8
  com.apple.driver.AppleIntelCPUPowerManagement	195.0.0
  com.apple.kext.triggers	1.0
  com.apple.driver.DspFuncLib	2.2.5a5
  com.apple.driver.AppleBacklightExpert	1.0.4
  com.apple.driver.AppleSMBusController	1.0.10d0
  com.apple.driver.AppleHDAController	2.2.5a5
  com.apple.iokit.IOHDAFamily	2.2.5a5
  com.apple.iokit.IOSurface	80.0.2
  com.apple.iokit.IOFireWireIP	2.2.5
  com.apple.iokit.IOAudioFamily	1.8.6fc18
  com.apple.kext.OSvKernDSPLib	1.3
  com.apple.driver.AppleGraphicsControl	3.1.33
  com.apple.iokit.IONDRVSupport	2.3.4
  com.apple.iokit.IOGraphicsFamily	2.3.4
  com.apple.iokit.IOSerialFamily	10.0.5
  com.apple.driver.AppleSMC	3.1.3d10
  com.apple.driver.IOPlatformPluginLegacy	5.0.0d8
  com.apple.driver.IOPlatformPluginFamily	5.1.1d6
  com.apple.driver.AppleUSBBluetoothHCIController	4.0.8f17
  com.apple.iokit.IOBluetoothFamily	4.0.8f17
  com.apple.driver.AppleUSBMergeNub	5.1.0
  com.apple.iokit.IOUSBHIDDriver	5.0.0
  com.apple.driver.AppleUSBComposite	5.0.0
  com.apple.iokit.IOSCSIMultimediaCommandsDevice	3.2.1
  com.apple.iokit.IOBDStorageFamily	1.7
  com.apple.iokit.IODVDStorageFamily	1.7.1
  com.apple.iokit.IOCDStorageFamily	1.7.1
  com.apple.iokit.IOATAPIProtocolTransport	3.0.0
  com.apple.iokit.IOSCSIArchitectureModelFamily	3.2.1
  com.apple.iokit.IO80211Family	420.3
  com.apple.iokit.IOFireWireFamily	4.4.8
  com.apple.iokit.IOUSBUserClient	5.0.0
  com.apple.iokit.IOAHCIFamily	2.0.8
  com.apple.iokit.IOATAFamily	2.5.1
  com.apple.iokit.IOUSBFamily	5.1.0
  com.apple.driver.AppleEFIRuntime	1.6.1
  com.apple.iokit.IONetworkingFamily	2.1
  com.apple.iokit.IOHIDFamily	1.7.1
  com.apple.iokit.IOSMBusFamily	1.1
  com.apple.security.sandbox	177.11
  com.apple.kext.AppleMatch	1.0.0d1
  com.apple.driver.DiskImages	331.7
  com.apple.iokit.IOStorageFamily	1.7.2
  com.apple.driver.AppleKeyStore	28.18
  com.apple.driver.AppleACPIPlatform	1.5
  com.apple.iokit.IOPCIFamily	2.7
  com.apple.iokit.IOACPIFamily	1.4
  
  
  COMMENT 11 jgrisham 2022-02-17T00:12:11Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1042431626
  > But, Google Chrome officially supports macOS 10.11. So, why don't Chrome users on El Capitan experience kernel panics?
  
  Do those _(macOS 10.11 Chrome users)_ actually exist?<!--I doubt many people use macOS 10.11. Even fewer with Chrome: -->  ;)
  - [Even last April, macOS 10.10 had a much larger share than 10.11.](https://gs.statcounter.com/os-version-market-share/macos/desktop/worldwide)
  <details><summary>blah...</summary>
  
  - Those still running 10.11 may be using Safari/Firefox/Opera, or blame their kernel panics on running an old OS version.
  - _(I also suspect many are headless or server systems that haven't been updated - these types of systems probably don't see much interactive web browsing.)_
  - Personally, my MacBook Pro still is running Mavericks, but I seem to remember thinking _(for some long-lost rationale)_ that if I were ever to bump it forward, I'd be stopping at 10.10, 10.12, 10.13, or 10.15.
  
  <s>AFAIK, there aren't many (any?) macs where that is the latest installable version. </s>
  
  Systems tend to max out on 10.4, 10.6.8, 10.7.5, 10.11, 10.13.x, etc...
  
  - Having a max supported OS of macOS 10.11 seems mostly limited to `MacMini3,1`s and other similar _late 2008/early 2009_ Penryn/Nehalem models ... the late 2009 models tend to support up to 10.13.x ... I don't remember exactly, but the demarcation point [_may_ ](https://www.imore.com/here-are-macs-work-os-x-el-capitans-metal)have been ['Metal' framework](https://developer.apple.com/documentation/metal/) support by the integrated GPU.
  
  <hr />
  
  </details>
  <details><summary>more blah...</summary>
  
  We recently identified a MS Outlook / Windows MAPI bug that now silently eats emails... but only for IMAP mailboxes, and only for maybe one out of a thousand. It has existed for _at least_ a decade, likely two. _(It was likely dormant for most of that time; surfacing only as mail processors began to support [ARC](https://en.wikipedia.org/wiki/Authenticated_Received_Chain) in late 2019/2020.)_
  - From the public reporting, it wouldn't be _at all surprising_ if Apple had overlooked intermittent kernel bugs for just as long, _especially_ for one that didn't generally cause panics on iOS / TVOS.
  -  The larger the company _(and the older/more stable the codebase)_, the harder it is for even well-meaning and talented engineering teams to find out edge cases exist - there are unintentional gatekeepers at all levels.
  <hr />
  </details>
  
  Tl;dr: it's plausible that it had been broken all along _(i.e. not backported to earlier versions when it was finally discovered / fixed in `XNU 3789.1.32`)_.
  
  COMMENT 12 Wowfunhappy 2022-02-17T14:45:11Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1043024849
  > Do those _(macOS 10.11 Chrome users)_ actually exist? ;)
  
  I mean, anecdotally, I've seen several of them in the wild! I even helped a third grade schoolteacher add the Let's Encrypt certificate to Keychain Access last fall.
  
  This may well be an kernel bug<sup>†</sup>, but I don't think it's happening in official versions of Chrome. A kernel panic is more difficult to overlook than a missing email, and this one appears to happen to _all_ Chromium Legacy users sooner or later, albeit very infrequently. I don't see how Google, with all of their users and analytics, wouldn't know about this problem if it existed.
  
  It seems much more likely to me that https://github.com/blueboxd/chromium-legacy/commit/e0cff58db7f41e2b0b68e058ec49a98f215265c5 is culpable, somehow...
  
  ---
  
  <sup>† Technically, my understanding is that _any_ instance of a userspace application triggering a kernel panic is generally considered a kernel bug, since userspace shouldn't be able to take down the kernel.</sup>
  
  COMMENT 13 jgrisham 2022-02-17T21:52:10Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1043494475
  <details><summary>{discussion clutter}</summary>
  
  > Technically, my understanding is that _any_ instance of a userspace application triggering a kernel panic is generally considered a kernel bug, since userspace shouldn't be able to take down the kernel.
  
  That's what I always thought too... <!--this isn't System 6.0.8! -->
     - anything else seems like users and userspace devs are just being gaslit by kernel devs _(I guess it's technically only gaslighting if it's intentional)_
  
  <hr />
  
  > A kernel panic is more difficult to overlook ...
  
  Indeed.
  
  > this one appears to happen to _all_ Chromium Legacy users sooner or later, albeit very infrequently
  
  Do we actually know that? I mean, [how could we](https://hanadigital.github.io/grev/?user=blueboxd&repo=chromium-legacy) without a major analytics operation? _(I'm honestly curious - not trying to be argumentative!)_
  
  ... yet, someone who recompiles XNU for fun in their spare time also said:
  > I've been avoiding reporting this ...
  
  `Chromium` is one of the most resource-intensive users of a heterogenous variety of OS resources that many users are likely to run these days.
  - _It's also liable to be used in very different ways on each launch; even users visiting the same website day after day will ultimately be running different JS from one month to the next._
  
  <hr  />
  
  > with all of their users and analytics
  
  I _really_ want to believe, but for something that doesn't significantly impact PR or ad revenue, causing occasional and non-reproducible crashes for users of older versions of only one operating system?
   - Simple things break complex systems, and yet only seem simple in retrospect.
   - It would _not be at all surprising_ if they had much more impactful bugs languishing in their backlog, both _then and now_. Knowledge without action and all...
  
  <hr />
  </details>
  
  Consider:
   - Apple fixed this at the kernel level _(after a few years)_
   - You fixed this at the kernel level _(after a few weeks)_
  
  Also:
   - None of that actually matters 😒
  
  Neither one of those fixed kernels will get to the majority of affected users here, so we do have to continue trying to _mitigate_ this kernel bug by rolling back or modifying our userspace code.
  
  <hr />
  
  Tl;dr: Thank you for trying to hunt it down!
  
  
  COMMENT 14 krackers 2022-02-20T03:46:00Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1046153411
  Looking again at the kernel kevent code, it seems there are very few places where `THREAD_RESTART` is actually signaled.  The most likely source for the one received in `kqueue_scan` seems to be
  
  https://github.com/aosm/xnu/blob/os-x-1095/osfmk/kern/wait_queue.c#L1335
  
  ```
  	/* If it is an invalid wait queue, you cant wait on it */
  	if (!wait_queue_is_valid(wq))
  		return (thread->wait_result = THREAD_RESTART);
  
  ```
  
  and in the kevent code `kq->kq_wqs` is the wait queue as part of the kq struct. This again makes me think that somehow the kqueue is being closed by some other process and we're not handling that.
  
  @Wowfunhappy can you add some log statements to each of the sites in `kern_event.c` that call  into `wait_queue_assert`, and then an additional log statement in the place where we would have panicked before? To avoid too much data guard each log statement by `!wait_queue_is_valid(wq)`. (Let me know if you need clarification here). Collecting more data might be useful to try to recreate the exact conditions under which this is triggered.
  
  As for userspace workarounds, assuming that hypothesis is correct then what I can think of is to try to ensure that no thread is waiting on a kqueue that is to be closed. So we'd have to send some sort of interrupt signal to break the wait on kqueue before closing the fd? Not too sure since I'm not too familiar with these parts...
  
  As for the reverted commit you linked, at first glance I don't see anything too suspicious there. Why did that commit need to be reverted for 10.9 compatibility though? I don't see anything that's 10.11+ specific.
  
  COMMENT 15 Wowfunhappy 2022-02-20T16:58:35Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1046278853
  > @Wowfunhappy can you add some log statements to each of the sites in `kern_event.c` that call into `wait_queue_assert`, and then an additional log statement in the place where we would have panicked before? To avoid too much data guard each log statement by `!wait_queue_is_valid(wq)`. (Let me know if you need clarification here). Collecting more data might be useful to try to recreate the exact conditions under which this is triggered.
  
  I'll try next week!
  
  > As for the reverted commit you linked, at first glance I don't see anything too suspicious there.
  
  I don't understand this code, so I'm just looking at the timing of when things were added and the differences between codebases. I'm assuming:
  
  1. The offending code has to make use of the `kevent` system call.
  
  2. There has to be something different in Chromium Legacy's codebase and mainline Chromium's codebase, which is causing Chromium Legacy to kernel panic on 10.11 and below but not mainline Chromium. (This is based on a separate assumption that Chromium Legacy _would_ kernel panic if used on 10.11, since 10.11 contains the offending XNU code.)
  
  The commit I linked contains the only difference I could find between the two codebases which uses `kevent`.
  
  COMMENT 16 krackers 2022-02-20T20:57:30Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1046319380
  @Wowfunhappy Assumption 1 isn't necessarily true. If we use the working hypothesis that the kpanic is caused by attempting to use an invalid (freed) kqueue, then you'd also have to search for references for code which uses MessagePump, since when that instance goes out of scope its destructor will free the kqueue fd.
  
  There's also exactly 1 other place where `THREAD_RESTART` is signalled, and that's in some sephamore related method. If the kpanic is triggered by _that_, then we're really in a pickle since that would mean the root cause might not even be strictly related to kqueue operations.
  
  COMMENT 17 Wowfunhappy 2022-02-21T16:03:41Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1047028911
  @krackers I ran into some stupid trouble guarding the logging statements. `wait_queue_is_valid` doesn't exist in kern_event.c.
  
  I tried to copy the two defines from: https://github.com/aosm/xnu/blob/0a13c7a4dcb9ab989727c2b0e08f7861457ed069/osfmk/kern/wait_queue.h#L161, adding:
  
  ```
  #define _WAIT_QUEUE_inited		0x2
  #define wait_queue_is_valid(wq)	\
  	(((wq)->wq_type & ~1) == _WAIT_QUEUE_inited)
  ```
  
  But the compiler complained:
  `no member named 'wq_type' in 'struct wait_queue'`
  
  The `wait_queue` struct is defined in `kern/wait_queue.h`, and  `wq_type` is ostensibly public, but adding `#include <kern/wait_queue.h>` to `kern_event.c` had no effect. I don't want to copy-paste the struct into `kern_event.c` because I don't know if defining it in a new place will do something weird.
  
  I'm sure I'm doing something dumb. 🙂
  
  For now, I've attached a kernel with _unguarded_ logging statements before each call of `wait_queue_assert` in `kern_event.c`. The source is this revision of: https://gist.github.com/Wowfunhappy/a214411bb52d39bcee9497363a97558d/440e40ec82da87f4240f22981a020e0f169ea915. It works in my VM, but it's noisy enough that I don't want to leave it running on my real system. It seems `wait_queue_assert_wait_with_leeway` is called from `kqueue_scan` many times per second.
  
  Also for reference, the guarded version I can't compile: https://gist.github.com/Wowfunhappy/a214411bb52d39bcee9497363a97558
  [XNU-2422.115.4-THREAD_RESTART add-JA-v2022.02.21.zip](https://github.com/blueboxd/chromium-legacy/files/8110654/XNU-2422.115.4-THREAD_RESTART.add-JA-v2022.02.21.zip)
  d
  
  Edit: Issue was closed by accident, please disregard.
  
  COMMENT 18 krackers 2022-02-21T23:16:46Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1047291155
  @Wowfunhappy
  
  No you're not doing something wrong, the way their includes work is tricky and took me a good 10 minutes to figure out.
  
  Very roughly, when all the headers for  are put together the net result is something like
  
  ```
  
  #include <stdio.h>
  
  
  typedef struct wait_queue		*wait_queue_t;
  #ifndef MACH_KERNEL_PRIVATE
  
  struct wait_queue { unsigned int opaque[2]; int *opaquep[2]; } ; // from kern_types
  
  #else
  
  
  
  typedef struct wait_queue { // from wait_queue.h
  	unsigned long int
  	/* boolean_t */	wq_type:2,		/* only public field */
  					wq_fifo:1,		/* fifo wakeup policy? */
  					wq_prepost:1,	/* waitq supports prepost? set only */
  					wq_eventmask:2;
  	int	wq_interlock;	/* interlock */
  	int	wq_queue;		/* queue of elements */
  } WaitQueue;
  
  #define wait_queue_is_valid(wq)	\
  	(((wq)->wq_type & ~1) == _WAIT_QUEUE_inited)
  
  #endif
  
  
  ```
  
  In particular, note that we actually have two different declarations of the `wait_queue` struct that are selected based on whether `MACH_KERNEL_PRIVATE`. I assume one is intended be used akin to an opaque-type (think "private" in an OO language) to hide internal members, while the other is used only within the `wait_queue.c`. Interestingly for opaque types you normally just leave the declaration without any fields, but here they explicitly initialize with some dummy fields of the proper size, which I assume was done so `sizeof()` would work propery.
  
  This is also why just `#including` didn't work, since the proper `#define` wasn't set, so it effectively never made it past the preprocessor.
  
  Now let's work around this. You're right in that we don't want to just directly copy-paste the struct since we'll run into duplicate definition error. Instead let's do it in a slightly smarter way where we create our own struct with identical layout and then cast to that to access fields.
  
  ```
  
  typedef struct wait_queue		*wait_queue_t;
  
  struct wait_queue { unsigned int opaque[2]; int *opaquep[2]; } ; // from kern_types
  
  
  #define EVENT_MASK_BITS
  
  typedef struct wowfunhappy_wait_queue { // happy little wait queue
  	unsigned long int
  	/* boolean_t */	wq_type:2,		/* only public field */
  					wq_fifo:1,		/* fifo wakeup policy? */
  					wq_prepost:1,	/* waitq supports prepost? set only */
  					wq_eventmask:((sizeof(long) * 8) - 4);
  } WowFunHappyWaitQueue;
  
  #define _WAIT_QUEUE_inited		0x2
  #define wait_queue_is_valid(wq)	\
  	(((wq)->wq_type & ~1) == _WAIT_QUEUE_inited)
  
  void buzz(wait_queue_t wq) {
  	printf("%d", wait_queue_is_valid((WowFunHappyWaitQueue*) wq));
  }
  
  ```
  
  ** Note 2 important things. 1) This is technically undefined behavior I think, although if you were to use a union instead of a cast to do the type-punning then it might be standards compliant? But who cares about standards so long as it works (and casting should indeed work).
  
  2) Note that I only included the initial member of the struct here, and left out the other 2. This should be fine because IIRC type-punning is safe for any prefix of shared fields as well. **
  
  COMMENT 19 Wowfunhappy 2022-02-22T19:53:20Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1048157088
  Unfortunately, I have been forced to revert back to a vanilla XNU kernel on my personal machine.
  
  I woke up this morning and found that my Mac had been logged out of iMessage. When I tried to log back in, the app complained of an unknown error. After a lot of reboots, password changes, network changes, and other dead ends, I finally tried reverting back to stock XNU, and iMessage instantly began working again.
  
  If anyone else is using one of the kernels I attached, and iMessage stops working for you, you know how to fix it. And for what it's worth, I experienced zero panics during my month with the custom kernel.
  
  <details>
  <summary>Stuff related to iMessage and custom kernels</summary>
  
  I'm not entirely sure what happened, since I was using my custom kernel for nearly a month without problems. It may be that because I was already logged into iMessage when I switched kernels, the app kept working up until Apple sent some kind of heartbeat message. The [imessage_debug](https://www.insanelymac.com/forum/files/file/278-imessage_debug/) utility reported failures when retrieving the values of `Gq3489ugfi`, `Fyp98tpgj`, `kbjfrfpoJU`, `oycqAZloTNDm`, and `abKPld1EcMni` on the custom kernel (and success with the stock kernel), but the software's authors neglected to include any documentation as to what these values mean, where they come from, or why they're important. 🤷‍♂️
  
  Regardless, I personally value iMessage compatibility, and the system is enough of a crapshoot that I'd rather not mess with it and potentially get my account flagged. Perhaps I'll see if I can figure out a kext patch instead.
  </details>
  
  COMMENT 20 krackers 2022-02-22T23:01:03Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1048292425
  That's interesting. Based on what I [found online](https://web.archive.org/web/20230000000000*/https://www.insanelymac.com/forum/topic/330149-imessage-on-amd-inject-correct-gq3489ugfi-fyp98tpgj-kbjfrfpoju-oycqazlotndm-abkpld1ecmni/) it seems cause is
  
  >Publicly-available XNU sources lack the necessary functions needed for generating the IOPower data (just look at IORootParent::initialize() in the kernel binary vs. what's in the source).
  
  I assume that the hackintosh community has worked around this by just doing patching instead. There seems to be a robust patching framework they've built up (Lilu). Another alternative might have been to create a kext that _does_ populate these values in the io registry, but I don't know why they didn't go that route. I'm not too familiar with the hackintosh scene so I don't know how they obtain these values in the first place if they don't have an existing mac to copy from (basedo n https://dortania.github.io/OpenCore-Post-Install/universal/iservices.html#fixing-en0 looks like they generate random SNs??)
  
  I personally don't like the idea of using a monolithic framework to do the patching (and Lilu is bloated since it tries to handle both userspace and kernel patching). Looking at ([Onyx the black cat[(https://github.com/gdbinit/onyx-the-black-cat)) is a good reference since it contains some useful functions we might want (especially the write enable on kernel pages). Most of those patches are in-place binary patches though, whereas for a slightly more involved patch like this I'd usually want to insert a trampoline.
  
  I tried to find any existing examples of kexts which have a trampoline insert that we can steal (there are many userspace ones like mach_override that we can port if really needed since the core logic is the same, but I'm lazy and don't want to think too much). I found
  
  https://github.com/lilang-wu/EasyBP/blob/d2d9591417df52b94d21945efb8cea393dc46a9b/makedebugpoint/inline-hook/inline_hook.c
  
  https://github.com/seclab-ucr/SyzGen_setup/blob/5a86c59e3e26ba7c259fbc19de89197dc4edd674/kcov/kcov/hook.c
  
  https://github.com/SilverMoonSecurity/PassiveFuzzFrameworkOSX/blob/be29a4df6e7b2394774a8cc3019bde03d816158c/src/kernel_fuzzer/the_flying_circus/InlineHook/inline_hook.c
  
  (interestingly all same to be the same-ish file, but don't have any attribution...)
  
  
  
  
  
  COMMENT 21 krackers 2022-02-22T23:43:20Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1048316473
  Er actually doing a trampoline is going to be a bit annoying because we need to ensure the return value is actually used. We can either implement the trampoline'd function in assembly so we don't need to worry about C messing things up, try to fuss around with the proper syntax to ensure that `wait_result` gets mapped to the function param and the return value gets mapped to the register that contains `error`, or just forget about doing this properly and patch the `default` section to return `EBADF` directly and hope that this doesn't mask any other bug.
  
  In terms of hacker spirit I still like the trampoline though, and if we set up the framework for that it will be easy to insert the logging I mentioned. After going through the candidates I like the approach taken by
  
  https://github.com/seclab-ucr/SyzGen_setup/blob/5a86c59e3e26ba7c259fbc19de89197dc4edd674/kcov/kcov/hook.c
  
  since it is the easiest for me to understand and flexible enough to coax into doing what we want.
  
  @Wowfunhappy Either way (whether or not we opt to use trampoline) let's start off with creating a simple kext that just reads the contents of `kqueue_scan_continue` function address to make sure we are accessing the correct address. https://github.com/lilang-wu/EasyBP/blob/d2d9591417df52b94d21945efb8cea393dc46a9b/makedebugpoint/solve_kernel_symbols/kernel_info.c has a nifty `solve_kernel_symbol` function but I don't think we can use it because `kqueue_scan_continue` is not exported function. Instead, we need to find that corresponding block in the disassembled binary to get the relative address (relative to kernel base) and then add the kaslr offset to it to get the absolute address in memory.
  
  Once you have the relative address, can you create a basic "hello world" kext (https://craftware.xyz/tips/Building-kernel-extension.html) that uses the `kaslr_slide` function from https://github.com/lilang-wu/EasyBP/blob/d2d9591417df52b94d21945efb8cea393dc46a9b/makedebugpoint/solve_kernel_symbols/kernel_info.c to dump out some bytes from the absolute address to see if they match the assembly we expect? Once we have that then we can take the next steps...
  
  COMMENT 22 Wowfunhappy 2022-02-23T00:21:28Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1048336636
  The Hackintosh community has some good reasons for avoiding custom kernels. Apple releases source code on a delay, and if you're running a non-ancient version of macOS, every update will potentially overwrite your custom kernel with a stock one, and leave you with a non-bootable system if you aren't careful. The more recent OSS releases also leave out _really_ critical things like sleep and power management.
  
  I'd thought that on an EOL OS, there was a certain purity to just fixing an obvious bug in an open-source component and recompiling—after all, what good is code that's never built? But it was never a great solution anyway, and it appears that even Apple's older code releases aren't as complete as I thought.
  
  I am a Hackintosh user (on one of my two machines) and I'm already using Lilu, so it might make sense for me to go that route; it mostly depends on what I can actually manage to do. Downside: AIUI, Lilu _has_ to be injected via a Hackintosh bootloader, because it needs to be loaded before the kexts it's patching. (Although, wait a minute, we're not trying to patch a kext, we're trying to patch the kernel—will this work at all? I know you said it's all the same address space, but then why _does_ the loading order matter...?)
  
  But, I also need to step back for a moment—I'm not sure what we're trying to accomplish here. Even without Lilu, I wouldn't feel comfortable recommending a patch like this to most Chromium Legacy users. The custom kernel had the advantage of being easy, I was done in a couple hours.
  
  How useful do we think this logging data will be? Do we actually have a chance of fixing this properly in userspace?
  
  Edit: I started writing this before your more recent replies/edits @krackers. Okay, if I attempt to keep going with this I'll follow from your starting point, thank you! I would still like to step back for a minute and consider whether this a smart avenue to keep exploring—what are we hoping to find out?
  
  COMMENT 23 krackers 2022-02-23T00:38:39Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1048346247
  @Wowfunhappy
  
  Yes, Lilu will work since it has support for patching kernel functions as well. But I don't like it here because I don't think using Lilu is going to give us any strong benefit that we could not have ourselves by copying a few header files for useful functions. And the Lilu only takes care of boilerplate, but we must still bring core logic. And that too we'd have to learn the Lilu API so the benefits of having boilerplate taking care of is negated. I think it's much simpler and more understandable to just make vanilla kext?
  
  >But, I also need to step back for a moment—I'm not sure what we're trying to accomplish here. Even without Lilu, I wouldn't feel comfortable recommending a patch like this to most Chromium Legacy users.
  
  End result will be to create a kext that users can just place in `/Library/Extensions` or whatever to hotpatch kernel on the fly. Will only work for users with same kernel version that you based offsets on though, other kernel versions people will have to recompile kext with their own offset. It's also fun for learning, but yes it is a bit more work to do than just recompiling xnu. Up to you whether the pain of occasional kernel panic is worth spending a few weekends trying to create a kext though. Happy to provide guidance along the way. I edited previous repose https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1048316473 with some concrete starting steps if you've decided to take this route.
  
  
  >How useful do we think this logging data will be? Do we actually have a chance of fixing this properly in user-space?
  
  To be honest, I don't know. If we can determine for sure that it is caused by a freed kqueue fd, then we need to take next step to figure out why the fd is being freed. This would involve adding some logging code in Chromium (maybe in destructor for messagepump?). If we verify that is indeed the cause, then next step would be to create some work around where we try to only free the kqueue after we ensure no thread is blocked waiting on one. We _could_ try to make that change now itself but to me seems like the effort required to figure out how to implement this (would have to study exactly what type of event to send to interrupt existing kqueue wait) combined with effort to recompile chromium is much more than doing the kext.
  
  Other option is if you can try to find commits involving messagepump we can try to see if one of them might be responsible, but this is more of a shot in the dark compared to the kernel patch which we know will work. If you're optimizing for time spent vs. reward then the kernel patch approach seems to be a surer bet.
  
  
  
  
  
  COMMENT 24 krackers 2022-02-27T04:05:06Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1053079385
  It's also possible that chromium is calling into a system framework/api which then makes use of kqueue in this manner. Can we run chrome under gdb or with dtrace to figure out where the `kevent` syscall is being made?
  
  <details>
  <summary>Tangential thing</summary>
  Completely unrelated, but if you like reading tales about old versions of chrome and patching things, did you know that newer version of chrome actually fixed (well more like worked-around) a coretext bug in 10.9? Under very rare and infrequent conditions (usually when rendering CJK text + emoji, but not deterministically) coretext shaper will get stuck when using AAT font, and just go in an infinite loop.
  
  You can see in
  https://github.com/harfbuzz/harfbuzz/blob/main/src/hb-coretext.cc#L187
  
  that google actually discovered this issue and added a workaround to coretext in v58 or so. But this workaround is not perfect, and there are still conditions which cause this (seems to be a combination of emoji and kanji characters from what I've seen). I actually went a wild chase some time back trying to see if I could fix this myself by hooking and hotpatching that function to determine which parameters caused coretext to crash. I could have recompiled Chromium but figuring out how to build chromium seemed harder than just hotpatching. In fact even figuring out how to parse the crash dump format from non-debug builds (minidump format) was quite an exercise.
  
  As you know, for security chrome divides the main browser process from the helper processes, which are spawned from a different binary. SIMBL works fine to inject into the main chrome process (surprisingly, Chrome is alright with the injection. I would have thought that they do crazy tricks to avoid process injection like in windows, but seems like not.), but since chrome helper does not load any cocoa libraries we cannot simbl inject into that. We can't add dylib to the helper binary because it is codesigned with `CS_RESTRICT` (and removing codesign here seemed like a bad idea) since there are some entitlements it needs I think, but helper binary also loads chrome framework dylib (manually via `dlopen` actually, not via usual dynamic linking), so we _can_ actually modify that chrome framework without tripping any security issues. I tried this and it worked, but changing signature does prevent some keychain related things from working which I didn't like.
  
  I finally realized that what I really want is to use `mach_inject` automatically for every helper process spawned. Newer versions of macforge do this, but for 10.9 mysimbl only does traditional osax injection.
  </details>
  
  (Btw, @wowfunhappy I noticed many of your plugins usually done via `insert_dylib` approach, you should consider packaging as a simbl plugin instead since it's much easier to enable/disable and you don't break signatures).
  
  <details>
  <summary>Continue tangential thing</summary>
  So I thought some more and realized that to do `mach_inject` we only really a way to look for pid of spawned process. Turns out that chrome launches the helper via `posix_spawnp`, and we can hook this call via standard patching techniques. So in my mind I constructed this wacky chain where I'd simble inject into the main chrome process, then hotpatch to interpose `posix_spawnp`, then take the pid result from that call and call `mach_inject` to inject a blob into the helper, and the injected blob would finally hotpatch `harfbuzz_shape`.
  
  _Of course after more thinking I realized this was absolutely insane and I just removed the problematic emoji that was triggering the crash from my webpage. _
  
  EDIT: Fwiw I just realized a way to do this is via DYLD_INSERT_LIBRARIES, it automatically gets propagated to all spawned child processes, and does not break code signing. You can then use mach_override or any other plt hooking library.
  
  Oh so back to how newer version of Chromium fixed it. Turns out that newer versions of harfbuzz don't call into CoreText at all to shape AAT fonts, so we sidestep this problem entirely. Very fortunate, and it probably also avoids a whole class of security vulnerabilities. Anyway, thank you for reading.
  </summary>

Activity

$ /bin/bash -lc "python3 - <<'PY'import jsonc=json.load(open('investigation/comments.json'))for i in range(10,17): x=c[i]; print('\\nCOMMENT',i+1,x['user']['login'],x['created_at'],x['html_url'],'\\n'+x['body'])PY"
status: Completed · exit 0
  
  COMMENT 11 jgrisham 2022-02-17T00:12:11Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1042431626
  > But, Google Chrome officially supports macOS 10.11. So, why don't Chrome users on El Capitan experience kernel panics?
  
  Do those _(macOS 10.11 Chrome users)_ actually exist?<!--I doubt many people use macOS 10.11. Even fewer with Chrome: -->  ;)
  - [Even last April, macOS 10.10 had a much larger share than 10.11.](https://gs.statcounter.com/os-version-market-share/macos/desktop/worldwide)
  <details><summary>blah...</summary>
  
  - Those still running 10.11 may be using Safari/Firefox/Opera, or blame their kernel panics on running an old OS version.
  - _(I also suspect many are headless or server systems that haven't been updated - these types of systems probably don't see much interactive web browsing.)_
  - Personally, my MacBook Pro still is running Mavericks, but I seem to remember thinking _(for some long-lost rationale)_ that if I were ever to bump it forward, I'd be stopping at 10.10, 10.12, 10.13, or 10.15.
  
  <s>AFAIK, there aren't many (any?) macs where that is the latest installable version. </s>
  
  Systems tend to max out on 10.4, 10.6.8, 10.7.5, 10.11, 10.13.x, etc...
  
  - Having a max supported OS of macOS 10.11 seems mostly limited to `MacMini3,1`s and other similar _late 2008/early 2009_ Penryn/Nehalem models ... the late 2009 models tend to support up to 10.13.x ... I don't remember exactly, but the demarcation point [_may_ ](https://www.imore.com/here-are-macs-work-os-x-el-capitans-metal)have been ['Metal' framework](https://developer.apple.com/documentation/metal/) support by the integrated GPU.
  
  <hr />
  
  </details>
  <details><summary>more blah...</summary>
  
  We recently identified a MS Outlook / Windows MAPI bug that now silently eats emails... but only for IMAP mailboxes, and only for maybe one out of a thousand. It has existed for _at least_ a decade, likely two. _(It was likely dormant for most of that time; surfacing only as mail processors began to support [ARC](https://en.wikipedia.org/wiki/Authenticated_Received_Chain) in late 2019/2020.)_
  - From the public reporting, it wouldn't be _at all surprising_ if Apple had overlooked intermittent kernel bugs for just as long, _especially_ for one that didn't generally cause panics on iOS / TVOS.
  -  The larger the company _(and the older/more stable the codebase)_, the harder it is for even well-meaning and talented engineering teams to find out edge cases exist - there are unintentional gatekeepers at all levels.
  <hr />
  </details>
  
  Tl;dr: it's plausible that it had been broken all along _(i.e. not backported to earlier versions when it was finally discovered / fixed in `XNU 3789.1.32`)_.
  
  COMMENT 12 Wowfunhappy 2022-02-17T14:45:11Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1043024849
  > Do those _(macOS 10.11 Chrome users)_ actually exist? ;)
  
  I mean, anecdotally, I've seen several of them in the wild! I even helped a third grade schoolteacher add the Let's Encrypt certificate to Keychain Access last fall.
  
  This may well be an kernel bug<sup>†</sup>, but I don't think it's happening in official versions of Chrome. A kernel panic is more difficult to overlook than a missing email, and this one appears to happen to _all_ Chromium Legacy users sooner or later, albeit very infrequently. I don't see how Google, with all of their users and analytics, wouldn't know about this problem if it existed.
  
  It seems much more likely to me that https://github.com/blueboxd/chromium-legacy/commit/e0cff58db7f41e2b0b68e058ec49a98f215265c5 is culpable, somehow...
  
  ---
  
  <sup>† Technically, my understanding is that _any_ instance of a userspace application triggering a kernel panic is generally considered a kernel bug, since userspace shouldn't be able to take down the kernel.</sup>
  
  COMMENT 13 jgrisham 2022-02-17T21:52:10Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1043494475
  <details><summary>{discussion clutter}</summary>
  
  > Technically, my understanding is that _any_ instance of a userspace application triggering a kernel panic is generally considered a kernel bug, since userspace shouldn't be able to take down the kernel.
  
  That's what I always thought too... <!--this isn't System 6.0.8! -->
     - anything else seems like users and userspace devs are just being gaslit by kernel devs _(I guess it's technically only gaslighting if it's intentional)_
  
  <hr />
  
  > A kernel panic is more difficult to overlook ...
  
  Indeed.
  
  > this one appears to happen to _all_ Chromium Legacy users sooner or later, albeit very infrequently
  
  Do we actually know that? I mean, [how could we](https://hanadigital.github.io/grev/?user=blueboxd&repo=chromium-legacy) without a major analytics operation? _(I'm honestly curious - not trying to be argumentative!)_
  
  ... yet, someone who recompiles XNU for fun in their spare time also said:
  > I've been avoiding reporting this ...
  
  `Chromium` is one of the most resource-intensive users of a heterogenous variety of OS resources that many users are likely to run these days.
  - _It's also liable to be used in very different ways on each launch; even users visiting the same website day after day will ultimately be running different JS from one month to the next._
  
  <hr  />
  
  > with all of their users and analytics
  
  I _really_ want to believe, but for something that doesn't significantly impact PR or ad revenue, causing occasional and non-reproducible crashes for users of older versions of only one operating system?
   - Simple things break complex systems, and yet only seem simple in retrospect.
   - It would _not be at all surprising_ if they had much more impactful bugs languishing in their backlog, both _then and now_. Knowledge without action and all...
  
  <hr />
  </details>
  
  Consider:
   - Apple fixed this at the kernel level _(after a few years)_
   - You fixed this at the kernel level _(after a few weeks)_
  
  Also:
   - None of that actually matters 😒
  
  Neither one of those fixed kernels will get to the majority of affected users here, so we do have to continue trying to _mitigate_ this kernel bug by rolling back or modifying our userspace code.
  
  <hr />
  
  Tl;dr: Thank you for trying to hunt it down!
  
  
  COMMENT 14 krackers 2022-02-20T03:46:00Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1046153411
  Looking again at the kernel kevent code, it seems there are very few places where `THREAD_RESTART` is actually signaled.  The most likely source for the one received in `kqueue_scan` seems to be
  
  https://github.com/aosm/xnu/blob/os-x-1095/osfmk/kern/wait_queue.c#L1335
  
  ```
  	/* If it is an invalid wait queue, you cant wait on it */
  	if (!wait_queue_is_valid(wq))
  		return (thread->wait_result = THREAD_RESTART);
  
  ```
  
  and in the kevent code `kq->kq_wqs` is the wait queue as part of the kq struct. This again makes me think that somehow the kqueue is being closed by some other process and we're not handling that.
  
  @Wowfunhappy can you add some log statements to each of the sites in `kern_event.c` that call  into `wait_queue_assert`, and then an additional log statement in the place where we would have panicked before? To avoid too much data guard each log statement by `!wait_queue_is_valid(wq)`. (Let me know if you need clarification here). Collecting more data might be useful to try to recreate the exact conditions under which this is triggered.
  
  As for userspace workarounds, assuming that hypothesis is correct then what I can think of is to try to ensure that no thread is waiting on a kqueue that is to be closed. So we'd have to send some sort of interrupt signal to break the wait on kqueue before closing the fd? Not too sure since I'm not too familiar with these parts...
  
  As for the reverted commit you linked, at first glance I don't see anything too suspicious there. Why did that commit need to be reverted for 10.9 compatibility though? I don't see anything that's 10.11+ specific.
  
  COMMENT 15 Wowfunhappy 2022-02-20T16:58:35Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1046278853
  > @Wowfunhappy can you add some log statements to each of the sites in `kern_event.c` that call into `wait_queue_assert`, and then an additional log statement in the place where we would have panicked before? To avoid too much data guard each log statement by `!wait_queue_is_valid(wq)`. (Let me know if you need clarification here). Collecting more data might be useful to try to recreate the exact conditions under which this is triggered.
  
  I'll try next week!
  
  > As for the reverted commit you linked, at first glance I don't see anything too suspicious there.
  
  I don't understand this code, so I'm just looking at the timing of when things were added and the differences between codebases. I'm assuming:
  
  1. The offending code has to make use of the `kevent` system call.
  
  2. There has to be something different in Chromium Legacy's codebase and mainline Chromium's codebase, which is causing Chromium Legacy to kernel panic on 10.11 and below but not mainline Chromium. (This is based on a separate assumption that Chromium Legacy _would_ kernel panic if used on 10.11, since 10.11 contains the offending XNU code.)
  
  The commit I linked contains the only difference I could find between the two codebases which uses `kevent`.
  
  COMMENT 16 krackers 2022-02-20T20:57:30Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1046319380
  @Wowfunhappy Assumption 1 isn't necessarily true. If we use the working hypothesis that the kpanic is caused by attempting to use an invalid (freed) kqueue, then you'd also have to search for references for code which uses MessagePump, since when that instance goes out of scope its destructor will free the kqueue fd.
  
  There's also exactly 1 other place where `THREAD_RESTART` is signalled, and that's in some sephamore related method. If the kpanic is triggered by _that_, then we're really in a pickle since that would mean the root cause might not even be strictly related to kqueue operations.
  
  COMMENT 17 Wowfunhappy 2022-02-21T16:03:41Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1047028911
  @krackers I ran into some stupid trouble guarding the logging statements. `wait_queue_is_valid` doesn't exist in kern_event.c.
  
  I tried to copy the two defines from: https://github.com/aosm/xnu/blob/0a13c7a4dcb9ab989727c2b0e08f7861457ed069/osfmk/kern/wait_queue.h#L161, adding:
  
  ```
  #define _WAIT_QUEUE_inited		0x2
  #define wait_queue_is_valid(wq)	\
  	(((wq)->wq_type & ~1) == _WAIT_QUEUE_inited)
  ```
  
  But the compiler complained:
  `no member named 'wq_type' in 'struct wait_queue'`
  
  The `wait_queue` struct is defined in `kern/wait_queue.h`, and  `wq_type` is ostensibly public, but adding `#include <kern/wait_queue.h>` to `kern_event.c` had no effect. I don't want to copy-paste the struct into `kern_event.c` because I don't know if defining it in a new place will do something weird.
  
  I'm sure I'm doing something dumb. 🙂
  
  For now, I've attached a kernel with _unguarded_ logging statements before each call of `wait_queue_assert` in `kern_event.c`. The source is this revision of: https://gist.github.com/Wowfunhappy/a214411bb52d39bcee9497363a97558d/440e40ec82da87f4240f22981a020e0f169ea915. It works in my VM, but it's noisy enough that I don't want to leave it running on my real system. It seems `wait_queue_assert_wait_with_leeway` is called from `kqueue_scan` many times per second.
  
  Also for reference, the guarded version I can't compile: https://gist.github.com/Wowfunhappy/a214411bb52d39bcee9497363a97558
  [XNU-2422.115.4-THREAD_RESTART add-JA-v2022.02.21.zip](https://github.com/blueboxd/chromium-legacy/files/8110654/XNU-2422.115.4-THREAD_RESTART.add-JA-v2022.02.21.zip)
  d
  
  Edit: Issue was closed by accident, please disregard.

Activity

$ /bin/bash -lc "python3 - <<'PY'import jsonc=json.load(open('investigation/comments.json'))for i in range(24,40): x=c[i]; print('\\nCOMMENT',i+1,x['user']['login'],x['created_at'],x['html_url'],'\\n'+x['body'])PY"
status: Completed · exit 0
  
  COMMENT 25 Wowfunhappy 2022-02-27T04:46:15Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1053120862
  @krackers I'm going to continue the tangential discussion a bit [here](https://github.com/blueboxd/chromium-legacy/discussions/51) to try to leave this issue as focused as possible.
  
  COMMENT 26 Wowfunhappy 2022-02-27T15:45:17Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1053594523
  > It's also possible that chromium is calling into a system framework/api which then makes use of kqueue in this manner.
  
  The crash log is pretty explicit though:
  ```
  BSD process name corresponding to current thread: Chromium Helper
  ```
  If it was a system framework, wouldn't that be showing up instead?
  
  I also took a quick look in Instruments, and can confirm that Chromium Helper is certainly making `BSC_kevent64` syscalls. Whether these are _the_ syscalls that sometimes lead to a panic, I have no idea.
  
  Edit: All coming from one place:
  ![Screen Shot 2022-02-27 at 10 46 30 AM](https://user-images.githubusercontent.com/4484096/155889371-28b99fcc-d714-43b5-a202-abcc5a5ad50b.png)
  
  COMMENT 27 krackers 2022-02-28T07:19:34Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1053960032
  >If it was a system framework, wouldn't that be showing up instead
  
  I think even if call into system framework, it's still part of same chrome helper process?
  
  But yes based on your trace seems like it is indeed chromium message pump. Can you try recompiling  chromium add adding some logging in the destructor for `messagepumpkqueue` (assuming that is the class which holds the `kqueue` reference)? I assume that it's one messagepump per chrome helper process, which means it might not be too noisy to run it and see if object destroy is related to kernel panic trigger.
  
  
  
  COMMENT 28 Wowfunhappy 2022-02-28T18:04:45Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1054522041
  I'll try if I can! It may be a while, grad school is picking up so I'm trying (key word) to spend less time screwing around with computers.
  
  Bluebox, if you happen to read this, (I assume you're busy with other life stuff), you may want to add this logging yourself since you have the hardware to compile Chromium easily.
  
  COMMENT 29 Wowfunhappy 2022-03-04T19:54:44Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1059470625
  I'm not sure why (although my best guess is it's something in the latest stable version of Chromium), but I've encountered many, _many_ more kernel panics than usual over the past few days. This is good in some ways, because it means I may be able to capture useful data more easily.
  
  I decided to switch back to the custom kernel for a time, now with the logging messages. @krackers, this is the code I ended up with: https://gist.github.com/Wowfunhappy/a214411bb52d39bcee9497363a97558d#file-kern_event-c-L112. I hope this was enough, including the other defines led to compile errors (which I didn't capture—sorry, I was actually trying to finish this before I have to leave for work).
  
  In the time I've spent writing this comment, I actually may have already captured an averted panic! In the console I have:
  
  > 3/4/22 2:39:26.000 PM kernel[0]: kqueue_scan_continue was called with a wait_result of THREAD_RESTART. A vanilla 2422 XNU kernel would have panicked!
  
  But, bad news: that's the only log I have! So either the `wait_queue_is_valid` check is always returning `true` (either because I coded it wrong or due to something else), _or_ the call order is something completely different!
  
  Anyway, just wanted to share, I'll look into this more later, gotta go teach Scratch programming to a bunch of children... 💨
  
  COMMENT 30 krackers 2022-03-04T22:37:28Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1059582150
  @Wowfunhappy
  
  Your code seems fine to me, so it seems like whatever is causing `THREAD_RESTART` to be signaled is via a different code path. Just to be sure we didn't miss anything, can you add some more logging in all of the
  
  ```
  	if (!wait_queue_is_valid(wq))
  		return (thread->wait_result = THREAD_RESTART);
  ```
  
  lines in
  https://github.com/aosm/xnu/blob/os-x-1095/osfmk/kern/wait_queue.c#L1335?
  
  I.e. like you did before
  
  ```
  	if (!wait_queue_is_valid(wq)) {
                 printf("Func name + error message");
  		return (thread->wait_result = THREAD_RESTART);
          }
  ```
  
  COMMENT 31 Wowfunhappy 2022-03-05T00:01:00Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1059613343
  Thanks for confirming the code looked fine! I've added that additional logging, see the new file in the gist: https://gist.github.com/Wowfunhappy/a214411bb52d39bcee9497363a97558d
  
  Now we just need to wait for a log message to show up again...
  
  COMMENT 32 Wowfunhappy 2022-03-05T00:48:19Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1059629629
  The panic-averted log appeared once again:
  
  > 3/4/22 7:45:05.000 PM kernel[0]: kqueue_scan_continue was called with a wait_result of THREAD_RESTART. A vanilla 2422 XNU kernel would have panicked!
  
  Once again, it was not accompanied by any of the other messages I added.
  
  COMMENT 33 krackers 2022-03-05T01:15:08Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1059637696
  Hm well there goes that theory. Seems like it's not directly caused by a kqueue event then, it just happens when it's in the kqueue wait loop.
  
  The 3 other places `THREAD_ERROR` seems to be signalled are in vm_fault.c, sync_sema.c, and ipc_mqueue.c.
  
  Let's try the last one: can you add a printf before the `wait_queue_wakeup64_all_locked` calls in  `osfmk/ipc/ipc_mqueue.c`? I don't know how noisy this will be though.
  
  We can also try to determine this from the other direction: are there any plausible candidates for commits that would caused these panics to happen more frequently? Anything related to mach ipc or messagepump would be decent candidates.
  
  COMMENT 34 krackers 2022-03-05T01:21:06Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1059639262
  Worst case I guess you could binary search for candidate commits, try 2 builds a day and you'd probably arrive at the change within a week or two.
  
  COMMENT 35 Wowfunhappy 2022-03-05T01:40:41Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1059644132
  > Let's try the last one: can you add a printf before the wait_queue_wakeup64_all_locked calls in osfmk/ipc/ipc_mqueue.c? I don't know how noisy this will be though.
  
  Sure, done, but they're _very_ noisy, running many times per second. I'll give this a try but I'm not sure how much useful information it will give us. And since logs roll off after 4,000 messages I'm not sure I'll be able to catch the critical THREAD_RESTART one...
  
  
  
  COMMENT 36 krackers 2022-03-05T02:02:05Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1059649679
  Yeah that's what I feared. Ok I think we have 2 options going forward then
  
  1) Try to find the commit to Chromium that caused increased rate of kpanic. I tried poking around for changes related to ipc, but didn't find any smoking gun. Bisecting the way to the commit is probably easiest then.
  
  2) Other option is to patch this on kernel side via the kext approach mentioned before. I think we can just take a shortcut here and change the `default` condition to just return `EBADF` instead of panicking (as opposed to the "right" approach of inserting a new jump for a new case condition).
  
  COMMENT 37 Wowfunhappy 2022-03-06T19:12:16Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1060021596
  > Try to find the commit to Chromium that caused increased rate of kpanic. I tried poking around for changes related to ipc, but didn't find any smoking gun. Bisecting the way to the commit is probably easiest then.
  
  Thing is, the frequency is still erratic. Case in point, I haven't received that log message again since Friday. I don't actually know that the change was in Chromium as opposed to something in my usage pattern...
  
  COMMENT 38 Wowfunhappy 2022-03-06T23:10:26Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1060058208
  I found a thing. The more I think about it, the less I'm convinced it's related, but maybe @krackers can take a peek and decide if I may be onto something. :)
  
  Google was running into kernel panics of their own back in 2017. Their kernel backtrace was different than ours, but it touches on same of the same functions: https://bugs.chromium.org/p/chromium/issues/detail?id=756102
  
  Google fixed it here: https://chromium.googlesource.com/chromium/src.git/+/5cd8eef498e28e1aacb9109645c001bbbfe1bc26%5E%21/#F0
  
  ```
     // On macOS 10.11+, using Mach port sets may cause system instability, per
     // https://crbug.com/756102. On macOS 10.12+, a kqueue can be used
     // instead to work around that. On macOS 10.9 and 10.10, kqueue only works
     // for port sets, so port sets are just used directly. On macOS 10.11,
     // libdispatch sources are used. Therefore, there are three different
     // primitives that can be used to implement WaitMany. Which one to use is
     // selected at run-time by OS version checks.
  ```
  
  So, `kPrimitive` is supposed to be set to:
  - 10.12 and newer: `KQUEUE`
  - 10.11 exactly: `DISPATCH`
  - 10.10 and older: `PORT_SET`
  
  This was [set by Chromium via](https://github.com/chromium/chromium/blob/9e784db1c34cf87b56cd1e2d6eda3e592ff5f0bc/base/synchronization/waitable_event_mac.cc#L217):
  `const WaitManyPrimitive kPrimitive = mac::IsAtLeastOS10_12() ? KQUEUE : (mac::IsOS10_11() ? DISPATCH : PORT_SET);`
  
  However, Chromium Legacy [uses](https://github.com/blueboxd/chromium-legacy/blob/f18c5a94f55426830816329d4fca568bb1f00a39/base/synchronization/waitable_event_mac.cc#L228):
  ` const WaitManyPrimitive kPrimitive = mac::IsAtLeastOS10_12() ? KQUEUE : DISPATCH;`
  
  I think this is wrong, isn't it? We're using the 10.11 codepath on 10.7–10.10, whereas Google explicitly built something separate for 10.9–10.10, although it's not clear why. (Since official Chrome doesn't support anything older than 10.11, it seems this code is now only used for iOS?)
  
  Unfortunately, it seems @blueboxd changed this [early on](https://github.com/blueboxd/chromium-legacy/commit/34d9193332569a332e76eb6f05f137c2e04e4a44) to "fix instabilities on loading DevTool and plugins".
  
  Assuming that's still needed... this whole Mac-specific WaitableEvent implementation is a relatively recent addition to Chromium, I wonder if we could just revert [the whole thing](https://github.com/chromium/chromium/commit/d54c0c1eccbddf90ea69bd14ca1290d721eee9b9) and fall back to whatever cross-platform implementation Chromium was using before? Could be more maintainable anyway.
  
  COMMENT 39 krackers 2022-03-07T00:52:56Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1060083986
  Hm it's an interesting find. The bug comments also suggest that watching videos (or doing something with GPU heavy activity) is more likely to trigger the bug.
  
  
  Libdispatch does make use of kevent in its work loop from what I can see, so it's a decent guess. But I'm not really familiar with this part of osx internals so I cannot say for sure.
  
  The comment is a bit hard to parse, but from the surrounding discussion it seems like
  * Mach port sets cause issues with 10.11+
  * KQueue doesn't work for non port-sets on <= 10.11
  * Hence 3 separate implementations for 10.9, 10.11, 10.12+
  
  It's not clear why Google didn't use libdispatch on <= 10.9, but I suppose they wanted the minimal fix possible to avoid introducing any additional instability.
  
  I'm not sure about the "fix instabilities on loading DevTool and plugins" thing. What kind of instability was seen, and how was it narrowed down to the WaitMany implementation?
  
  
  The mac-specific WaitableEvent implementation seems to have been added in v62, and up to v68 officially supported 10.9 so we may not need to revert that entirely (note it's possible that it was never caught, but I never remember running into any kpanics when I was still using that).
  
  COMMENT 40 Wowfunhappy 2022-03-07T01:19:16Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1060095100
  > note it's possible that it was never caught, but I never remember running into any kpanics when I was still using that
  
  Because Chrome v62–68 set `kPrimitive = PORT_SET` on 10.9/10.10, whereas Chromium Legacy does not. That was the basis of my theory, anyway—I'm still confident that if an official version of Chrome _ever_ led to kernel panics on an officially-supported OS, we would know about it. Someone somewhere would have reported it to Google and they would have treated it as a serious issue.
  
  The easiest and most obvious thing would be to match what Chrome does—except, Bluebox may have had a reason for changing it in the first place. Maybe related to Lion support? (Notably, we know the KP exists on Lion because @pjpreilly has seen it and runs Lion.)
  
  I guess the only way to find out at this point is to try... I'll see if I can find some spare cpu time to recompile Chromium this week, since BlueBox seems to still be away (or has wisely chosen to stay out of this quagmire).

Assistant

The conversation contains an important clue: the instrumented kernel received THREAD_RESTART without hitting any of the checks for an invalid wait queue. That weakens the original “closed kqueue” theory. I’m reading the remaining experiments before tracing the other ways that result can reach the waiting thread.

Activity

$ /bin/bash -lc "python3 - <<'PY'import jsonc=json.load(open('investigation/comments.json'))for i in range(40,60): x=c[i]; print('\\nCOMMENT',i+1,x['user']['login'],x['created_at'],x['html_url'],'\\n'+x['body'])PY"
status: Completed · exit 0
  
  COMMENT 41 Wowfunhappy 2022-03-11T03:56:56Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1064747491
  The good news is a re-built Chromium with `kPrimitive = PORT_SET` on 10.7–10.10. The bad news is I triggered the would-be kernel panic in this version of Chromium. Oh well.
  
  But now that I have Chromium building again, maybe I can experiment with some other stuff... I neglected to add the `messagepumpkqueue` logging Krakers suggested, for example.
  
  COMMENT 42 Wowfunhappy 2022-03-11T17:44:46Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1065339969
  The next thing I want to try is wholesale getting rid of https://bugs.chromium.org/p/chromium/issues/detail?id=932175 and going back to the POSIX implementation. This change was made in 2019 after Mavericks support was dropped, and it _clearly_ touches the kernel and kevent.
  
  This is proving a bit challenging, as a lot of files were touched and things have been renamed, etc.
  
  COMMENT 43 Wowfunhappy 2022-03-14T15:35:04Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1066959291
  Okay, actual progress! I just noticed something I should have noticed earlier!
  
  The log message I added to XNU which indicates an averted kernel panic is _always_ immediately followed, within a second, by a crash from a Chromium Helper process! These crashes do not appear to have any user-visible effects, but they do provide a backtrace. See attached!
  
  So, I can now say pretty confidently that the bug is somewhere in `MessagePumpKqueue`.
  
  
  [Chromium Helper_2022-03-14-112231_Jonathans-Mac-Pro.crash.zip](https://github.com/blueboxd/chromium-legacy/files/8246273/Chromium.Helper_2022-03-14-112231_Jonathans-Mac-Pro.crash.zip)
  
  
  
  COMMENT 44 krackers 2022-03-15T06:02:34Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1067595447
  sorry for the late response, that's a very interesting find. It means that the `EBADF` code path is actually not supposed to happen at all, since their code only has checks for EINTR, hence the process crash. I don't know if this means that this is a case where on a 10.11 machine chromium helper process would have crashed as well, or whether it's a more fundamental bug in 10.9 mach ipc and adding the `ebadf` case in the kernel source just works around the issue/shifts the symptom from "stop the world kernel panic" to process crash.
  
  
  Either way as you mentioned it confirms that the kpanic is triggered while one thread is waiting on kevent inside `MessagePumpKqueue`. It's still not clear though what's the other thread/process doing the action that causes the `EBADF` to be signalled though. I didn't see anything immediately obvious in the backtrace for the other threads in your dump, so it could also be one of the other chromium helper processes? Then again none of the log statements you added to the kernel got triggered so that means the EBADF is being signalled from either `vm_fault.c`, `sync_sema.c`, or `ipc_mqueue.c`. But even if we narrow it down to one of those I wouldn't know how to find the corresponding userspace chromium code that results in that call since all of those are pretty broad (I still bet it's in `ipc_mqueue` though).
  
  I haven't looked too much into what it would take to revert the use of `MessagePumpKqueue` but it seems like since all the platform-specific code is abstracted as a subclass of `MessagePumpForIO`, can we change that to the posix-generic messagepumplibevent ? Although I see that some of the other mac-specific parts have been switched to communicate using mach-ports which means we'd need to go back and revert those too...
  
  
  
  COMMENT 45 Wowfunhappy 2022-03-15T16:48:50Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1068215416
  > It's still not clear though what's the other thread/process doing the action that causes the EBADF to be signalled though. I didn't see anything immediately obvious in the backtrace for the other threads in your dump, so it could also be one of the other chromium helper processes?
  
  The other thing I noticed was WaitableEvent (and specifically WaitableEvent::TimedWait) being near the top in several other threads. I still feel like that's implicated somehow, even though switching kPrimitive didn't resolve the issue.
  
  > I haven't looked too much into what it would take to revert the use of MessagePumpKqueue but it seems like since all the platform-specific code is abstracted as a subclass of MessagePumpForIO, can we change that to the posix-generic messagepumplibevent ?
  
  Yes, that's what I was trying to do last week before I noticed the process crash! The original set of changes was documented [here](https://bugs.chromium.org/p/chromium/issues/detail?id=932175). I had a bit of trouble setting it back to the POSIX version, as the changes touched a number of different files which have themselves evolved since 2019, but I'd like to try again at some point.
  
  COMMENT 46 blueboxd 2022-03-31T18:42:30Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1084974435
  Thank you for the deep inspection of panic🙇
  
  I traced this panic with kernel debugger before, but I couldn't find the root cause of panic.
  (there was nothing special about the parameters of kevent64 preceding the panic)
  Maybe it is not due to a single kevent64, but rather a combination of other events in the queue or running threads...?
  
  COMMENT 47 Wowfunhappy 2022-03-31T18:57:38Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1084988188
  @blueboxd Hey there! As a quick catch up, I recompiled XNU so that whenever `kqueue_scan_continue` is called with a `wait_result` value of `THREAD_RESTART`, XNU will log a warning and return `EBADF` instead of panicking.
  
  This resolves the kernel panic, and causes Chromium to merely crash instead. I attached a backtrace [here](https://github.com/blueboxd/chromium-legacy/files/8246273/Chromium.Helper_2022-03-14-112231_Jonathans-Mac-Pro.crash.zip). It points to Chromium's `MessagePumpKqueue` as the culprit.
  
  I suspect that if we can fix that crash, the kernel panics will go away!
  
  COMMENT 48 blueboxd 2022-03-31T19:47:15Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1085030648
  @Wowfunhappy
  Thank you for the catch-up!
  
  Stack trace of kernel debugger also indicates `kevent64` in `MessagePumpKqueue::DoInternalWork` caused panic.
  But, if parameters for `kevent64` are not the root cause, how we can resolve panics/crashes...?
  (simple re-writing of `DoInternalWork` may not resolve the issue:thinking:)
  I'll try to modify the kernel for debugging too.
  
  @aeiouaeiouaeiouaeiouaeiouaeiou
  Chromium crashes are not the topic of this issue.
  (this issue induces kernel panic in normal environment)
  Please open a new issue with the crash log.
  
  COMMENT 49 krackers 2022-03-31T20:05:58Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1085048857
  It might be worth trying to figure out where the EBADF is signaled from in the kernel (since we ruled out the origins in the kevent code,  that leaves only vm_fault.c, sync_sema.c, or ipc_mqueue.c). As you mentioned, it's likely some race condition somewhere between different threads that's causing ebadf to sent to the thread while inside the kernel wait loop.
  
  
  
  
  COMMENT 50 Wowfunhappy 2022-03-31T22:19:44Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1085184099
  > But, if parameters for kevent64 are not the root cause, how we can resolve panics/crashes...?
  
  One thing we could try is using `messagepumplibevent` instead of `MessagePumpKqueue`. I think you'd just need to revert the set of changes described here: https://bugs.chromium.org/p/chromium/issues/detail?id=932175. The changes were a bit too complex for me, but you might have more success.
  
  COMMENT 51 blueboxd 2022-04-02T16:57:56Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1086677461
  @krackers
  A race condition is worst case scenario I had imagined...😔
  OK, I'll embed debug code to the remaining candidates.
  
  @Wowfunhappy
  Ah, got it, there's a predecessor MessagePump mechanism.
  I'll try to revert to the POSIX one and see what happens.
  
  COMMENT 52 blueboxd 2022-04-03T04:55:13Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1086776672
  I tried to revert to `MessagePumpLibevent`, but [`ChannelMac`](https://github.com/blueboxd/chromium-legacy/blob/master.lion/mojo/core/channel_mac.cc), [`CurrentIOThread`](https://github.com/blueboxd/chromium-legacy/blob/master.lion/base/task/current_thread.h) and [`app_shim`](https://github.com/blueboxd/chromium-legacy/tree/master.lion/chrome/browser/apps/app_shim) are too deeply dependent on  `MessagePumpKqueue`...
  [`MessagePumpForIO`](https://github.com/blueboxd/chromium-legacy/blob/3d056a95e025ee808e5f75623f5b3a330e3088f2/base/message_loop/message_pump_for_io.h#L36) cannot be changed to `MessagePumpLibevent` independently, so the current IPC mechanism needs to be nearly overhauled.
  I think this method is a bit harsh at the moment...:pensive:
  
  COMMENT 53 Wowfunhappy 2022-04-03T04:59:54Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1086777048
  Oh well, thanks for trying!
  
  COMMENT 54 Wowfunhappy 2022-04-03T16:46:47Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1086905452
  I have discovered that I can consistently trigger the problem by idling on this awful page: https://gamebanana.com/games/5866. Make sure you are not using an adblocker. There should be an autoplaying video in the lower right of the screen.
  
  The problem usually appears within 90 minutes. I do not know whether the tab needs to be in front, but the crash can occur when the window is entirely minimized.
  
  When Chromium was launched via the Terminal, these messages are always logged at the time of the crash:
  
  ```
  [22670:14595:0403/121124.951621:FATAL:message_pump_kqueue.cc(442)] Check failed: . kevent64: Bad file descriptor (9)
  [1965:1287:0403/121126.049808:ERROR:network_service_instance_impl.cc(978)] Network service crashed, restarting service.
  ```
  
  I assume the first message is printed by [this PCHECK](https://github.com/blueboxd/chromium-legacy/blob/3d056a95e025ee808e5f75623f5b3a330e3088f2/base/message_loop/message_pump_kqueue.cc#L442). I don't think this tells us anything we didn't already know; Chromium got a bad file descriptor in `MessagePumpKqueue::DoInternalWork`.
  
  However, I find the second message somewhat more notable. It looks like `Network service` may be the responsible party?
  
  Note that I have observed instances of the crash in which only the first message is printed, and not the second. However, when the crash occurs on the specific page I linked above, the second message is always present.
  
  COMMENT 55 Wowfunhappy 2022-05-14T19:39:54Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1126800675
  @krackers Does this look notable to you at all? https://github.com/blueboxd/chromium-legacy/commit/6a57f2bc3f617c441be7e8e8891919e983101c28
  
  Annoyingly, bug 640281 is private, but it has something to do with guarding against invalid file descriptors, as well as the use of [kqueue message pump](https://github.com/chromium/chromium/commit/90defe3176bf2448301e5fc82ed3a9bee2804ce7).
  
  I spotted this because Google recently changed the code for modern macOS compatibility, presumably causing https://github.com/blueboxd/chromium-legacy/issues/63. I don't have a complete theory as to why it would only have been failing on Chromium Legacy.
  
  COMMENT 56 krackers 2022-05-14T23:56:32Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1126828700
  That change is from 2016 though? And adding the guards should only help things, not hurt us.
  
  COMMENT 57 Wowfunhappy 2022-05-14T23:58:41Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1126828862
  Well, I was thinking the guards might not be working for some reason. Or, we could potentially add more.
  
  COMMENT 58 krackers 2022-05-15T00:57:37Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1126835208
  You could trace all close syscalls I guess (maybe using dtrace) and see what fd is being used
  
  COMMENT 59 Wowfunhappy 2022-05-27T12:30:53Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1139574286
  Okay @krackers, if you're still willing to help (I would need a lot of hand holding), I'd like to try making a kext patch. The more I look into the crash at the Chromium level, the more unfeasible fixing it there seems to be. I think there are actually a lot of different code paths within Chromium which can trigger the panic, because I keep finding command line switches that will remove the crash on one page, but not somewhere else.
  
  You suggested starting with a kext to find the address of _kqueue_scan_continue and dumping the bytes to confirm the output is correct, using `kaslr_slide` from https://github.com/lilang-wu/EasyBP/blob/d2d9591417df52b94d21945efb8cea393dc46a9b/makedebugpoint/solve_kernel_symbols/kernel_info.c. However, this relies on a kernel function `vm_kernel_unslide_or_perm_external` which AIUI doesn't exist prior to El Capitan. Any idea how to get that address?
  
  I also found https://github.com/leiless/ksymresolver which I think may be better, it's said to be able to resolve non-exported symbols. But it too relies on `vm_kernel_unslide_or_perm_external`.
  
  (Note that I may be away from my computer this weekend, but I'm done with finals so I should have more time in general!)
  
  COMMENT 60 krackers 2022-05-28T07:15:17Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1140192327
  @wowfunhappy
  
  >doesn't exist prior to El Capitan
  
  Interesting, thanks for pointing that out. Based on [1] as well as digging around other kexts, seems like without that function there are only 2 options for discovering the kaslr slide: either "back-read memory to find 0xfeedface" as mentioned in [1] (which I understand to be basically scanning the kernel space for the mach-o header to find the start, which seems to be what Lilu does?), or getting the runtime address of a known exported symbol (e.g. `vnode_close`) and subtracting it from the address of the symbol in the on-disk binary, as done in [2]. Interestingly prior to 10.11 there was a kas_info() syscall to get this info from userspace [3], although I tried searching and couldn't find a way to read `vm_kernel_slide` from kernel-space directly (or maybe it exists and I'm not doing it right).
  
  
  I think the easiest will be to use the approach used in [2] where we basically set
  
  ```
  #define VNODE_CLOSE_BINARY_ADDR 0xf00 // Open up kernel in hopper and put the address of the exported vnode_close symbol here
  kaslr_offset = (mach_vm_address_t) &vnode_close - VNODE_CLOSE_BINARY_ADDR;
  ```
  
  Then once we have the kaslr offset, we can do
  
  ```
  #define KQUEUE_SCAN_CONTINUE_BINARY_ADDR 0x00f // Address of symbol in text segment as found in Hopper
  kqueue_scan_continue = kaslr_offset + KQUEUE_SCAN_CONTINUE_BINARY_ADDR
  
  uint8_t *kqueu_scan_continue_bytes = (uint8_t*) kqueue_scan_continue
  ```
  
  Then hopefully do an `IOLog("Dumping bytes at kqueue_scan_continue %02x %02x %02x", kqueu_scan_continue_bytes[0], kqueu_scan_continue_bytes[1], kqueu_scan_continue_bytes[2])` and check if the hexdump matches what you see in diassembler for the function
  
  [1] https://www.zdziarski.com/blog/?p=6901
  [2] https://github.com/cocoahuke/shrink_trackpad
  [3] https://github.com/gdbinit/kextstat_aslr/

Activity

$ /bin/bash -lc "python3 - <<'PY'import jsonc=json.load(open('investigation/comments.json'))for i in range(60,78): x=c[i]; print('\\nCOMMENT',i+1,x['user']['login'],x['created_at'],x['html_url'],'\\n'+x['body'])PY"
status: Completed · exit 0
  
  COMMENT 61 krackers 2022-05-28T18:40:31Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1140311996
  This blog post also shows a more programmatic way to do approach (2):
  
  http://ho.ax/posts/2012/02/resolving-kernel-symbols/
  
  Basically manually scanning the LC_SYMTAB section of the binary to find the address of the symbol in the binary instead of just hardcoding after finding via Hopper as I suggested. There's an attached github project you can just use. Although I personally think just hardcoding the address of the smybol in binary is cleaner since there's no need to waste cpu cycles scanning through the list when we know which one it's going to be.
  
  COMMENT 62 Wowfunhappy 2022-05-28T18:40:50Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1140312045
  Thank you! I got it working!
  
  https://gist.github.com/Wowfunhappy/8212f5bea4c601ac9a6297789f232321
  
  This outputs `6b` `71` `75`, which matches what is in Hopper.
  
  I initially used your method of getting the slide (which was invaluable, as it gave me a known-good result), but I managed to replace it with code adapted from Lilu, so I could hardcode only one address instead of two. Long term, I'd eventually like to make this work across different builds of XNU. (Long term being the key word, the address of kqueue_scan_continue is still hardcoded...)
  
  What is the next step?
  
  Edit: Eek, we posted at almost the exact same time!
  
  COMMENT 63 krackers 2022-05-28T22:02:43Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1140335295
  Wow that was fast, nice job! Fyi you can also remove the hard-coded `KQUEUE_SCAN_CONTINUE_BINARY_ADDR` and discover it on-the-fly by scanning `LC_SYMTAB` as I mentioned in the previous post.
  
  One thing though, the address of `kqueue_scan_continue` you used seems to be in the strings section, not in the text segment. I loaded it in hopper, and it seems like there's no separate `kqueue_scan_continue` function, I guess it was inlined during compilation.
  
  You should use `ffffff80005c79e0` instead, which is the function that contains the call to `_panic`  we want to avoid. (Since it won't be in `LC_SYMTAB` either, I guess you can't avoid harcoding it after all).
  
  It contains the line we want to avoid:
  
  ```
  _panic("\"%s: - invalid wait_result (%d)\"@/SourceCache/xnu/xnu-2422.115.15/bsd/kern/kern_event.c:2167", "kqueue_scan_continue", LODWORD(r15), rcx, r8, r9, STK-1);
  ```
  
  ---
  
  Now the next step is to find which bytes we need to patch.  Recall the original switch statement was
  
  ```
  	switch (wait_result) {
  	case THREAD_AWAKENED:
  		kqlock(kq);
  		error = kqueue_process(kq, cont_args->call, cont_args, &count,
  		    current_proc());
  		if (error == 0 && count == 0) {
  			wait_queue_assert_wait((wait_queue_t)kq->kq_wqs,
  			    KQ_EVENT, THREAD_ABORTSAFE, cont_args->deadline);
  			kq->kq_state |= KQ_SLEEP;
  			kqunlock(kq);
  			thread_block_parameter(kqueue_scan_continue, kq);
  			/* NOTREACHED */
  		}
  		kqunlock(kq);
  		break;
  	case THREAD_TIMED_OUT:
  		error = EWOULDBLOCK;
  		break;
  	case THREAD_INTERRUPTED:
  		error = EINTR;
  		break;
  	default:
  		panic("%s: - invalid wait_result (%d)", __func__,
  		    wait_result);
  		error = 0;
  	}
  
  ```
  
  and the decompiled-assembly is
  
  ```
      if (LODWORD(r15) != 0x2) {
              LODWORD(r12) = 0x23;
              if (LODWORD(r15) != 0x1) {
                      if (LODWORD(r15) == 0x0) {
                              r15 = r14 + 0x8;
                              _lck_spin_lock(r15);
                              r12 = *(rbx + 0x68);
                              _current_proc();
                              LODWORD(r12) = LODWORD(sub_ffffff80005c7390(r14, r12, rbx + 0x68, var_2C));
                              if (LODWORD(LODWORD(var_2C) | LODWORD(r12)) == 0x0) {
                                      rcx = *(r13 + 0x78);
                                      _wait_queue_assert_wait(*r14, 0x0, 0x2, rcx, r8, r9, STK-1);
                                      *(int8_t *)(r14 + 0x58) = *(int8_t *)(r14 + 0x58) | 0x2;
                                      _lck_spin_unlock(r15);
                                      _thread_block_parameter(sub_ffffff80005c79e0, r14, 0x2, rcx, r8, r9);
                              }
                              _lck_spin_unlock(r15);
                      }
                      else {
                              _panic("\"%s: - invalid wait_result (%d)\"@/SourceCache/xnu/xnu-2422.115.15/bsd/kern/kern_event.c:2167", "kqueue_scan_continue", LODWORD(r15), rcx, r8, r9, STK-1);
                              LODWORD(r12) = 0x0;
                      }
              }
      }
      else {
              LODWORD(r12) = 0x4;
      }
  ```
  
  I was originally thinking we could try inserting a trampoline to our own code in the else of `if (LODWORD(r15) == 0x0) {` in order to add the additional check for EBADF, but we can also do the lazy thing and just assume that any unhandled case must be EBADF, noop the call to `panic`, and set the code to `EBADF` instead of `0x0`. (Basically we'd be betting that there's no way there's _no way_ there's another unhandled `wait_result` type (there are 2 remaining `wait_result_t` types, `THREAD_WAITING, and `THREAD_NOT_WAITING`, but given that even latest xnu source doesn't add anything else I guess it's a safe bet that we won't see those two types here).
  
  If we do the former approach, we use one of the trampolining libraries I think I mentioned in one of the previous posts. Let me know if you want to do this approach, and we can go in more detail.
  
  
  If we do the latter, we basically need to rewrite
  
  ```
  ffffff80005c7a9c         lea        rdi, qword [ds:0xffffff8000766e5e]          ; "\\\"%s: - invalid wait_result (%d)\\\"@/SourceCache/xnu/xnu-2422.115.15/bsd/kern/kern_event.c:2167", argument #1 for method _panic, XREF=sub_ffffff80005c79e0+68
  ffffff80005c7aa3         lea        rsi, qword [ds:0xffffff8000766ebb]          ; "kqueue_scan_continue", argument #2 for method _panic
  ffffff80005c7aaa         mov        edx, r15d                                   ; argument #3 for method _panic
  ffffff80005c7aad         xor        al, al
  ffffff80005c7aaf         call       _panic
  ffffff80005c7ab4         xor        r12d, r12d
  ```
  
  to be `mov r12d, (whatever the numeric value of EBADF is, I think its 0x9 from errno.h but please double check)` followed by a bunch of `nops` to fill out the remaining space.
  
  If we do this approach then it's easier (just a bit tedious though). We can do something like
  
  ```
  uint8_t replacement_bytes = {41, BC, 09, 00, 00, 00 } // assembled mov r12d, 0x9 with padding to match existing
  memcpy(kaslr_base + 0xffffff80005c7a9c, replacement_bytes, 6);
  memset(kaslr_base + 0xffffff80005c7aa3, 0x90 /*noop*/, 0xffffff80005c7ab4 - 0xffffff80005c7aa3);
  ```
  
  And then maybe dump out the bytes after replacing to make sure it's what you want.
  
  I think we also may need to disable interrupts before doing patching. I found this code in lilu
  
  ```
  bool MachInfo::setInterrupts(bool enable) {
  	unsigned long flags;
  
  	if (enable)
  		asm volatile("pushf; pop %0; sti" : "=r"(flags));
  	else
  		asm volatile("pushf; pop %0; cli" : "=r"(flags));
  
  	return static_cast<bool>(flags & EFL_IF) != enable;
  }
  ```
  
  which probably does what we want, but actually seems like apple already provides us `ml_set_interrupts_enabled` which is the exact same code (probably cleaner to use apple's one if it's already there): https://developer.apple.com/documentation/kernel/1593365-ml_set_interrupts_enabled
  
  I also don't know if there is any sort of W^X in kernel land we need to bypass. I guess you can try it and if it doesn't allow us to write there'll be a kernel panic or something when we try to do so.
  
  COMMENT 64 krackers 2022-05-28T22:18:11Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1140336931
  Maybe take a look at Lilu Kernel patching to see if there's any other steps we need:
  
  https://github.com/acidanthera/Lilu/blob/bd48fa7f4d9773bab1f6dfb7890b9a98ab08d829/Lilu/Sources/kern_patcher.cpp#L301
  
  there's a `MachInfo::setKernelWriting` in there, looks like in addition to disabling interrupts we need to unset a write protect bit. So I guess there is indeed W^X in kernel space (makes sense). Still not sure why they decide to flip CR0 instead of using whatever kernel-space equivalent of `vm_protect`there is, but I guess former is easier,
  
  COMMENT 65 Wowfunhappy 2022-05-30T13:51:15Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1141184876
  Thank you! Should be back at my computer tomorrow...
  
  > One thing though, the address of kqueue_scan_continue you used seems to be in the strings section, not in the text segment. I loaded it in hopper, and it seems like there's no separate kqueue_scan_continue function, I guess it was inlined during compilation.
  
  Thanks, I was actually thinking that seemed off...
  
  > Fyi you can also remove the hard-coded KQUEUE_SCAN_CONTINUE_BINARY_ADDR and discover it on-the-fly by scanning LC_SYMTAB as I mentioned in the previous post.
  
  To confirm, this would basically be the same as how I found the slide value, right? Start with a normal exported symbol and then scan forwards until I find what I'm looking for. Since the actual `kqueue_scan_continue` function was inlined and the symbol doesn't exist, I guess I could just look for the hex sequence of the panic message?
  
  > but we can also do the lazy thing and just assume that any unhandled case must be EBADF, noop the call to panic, and set the code to EBADF instead of 0x0. (Basically we'd be betting that there's no way there's no way there's another unhandled wait_result type (there are 2 remaining wait_result_t types, THREAD_WAITING, and THREAD_NOT_WAITING`, but given that even latest xnu source doesn't add anything else I guess it's a safe bet that we won't see those two types here))
  
  Totally on board with this approach!
  
  I suppose it is worth considering... in the scenario where the kernel did send either THREAD_WAITING or THREAD_NOT_WAITING, how inappropriate would it be to send an EBADF (bad file descriptor)? Is there a more generic error we should consider returning instead? We have some options in https://www.freebsd.org/cgi/man.cgi?query=errno&sektion=2&manpath=freebsd-release-ports, assuming of course that XNU is the same.
  
  (I do find it interesting that there are other unhandled types. Maybe that indicates this bug wasn't quite as stupid as it initially appeared? E.g., maybe Apple had a reason to think this shouldn't ever happen, and didn't just blatantly forget to handle a case.)
  
  COMMENT 66 krackers 2022-05-30T21:06:49Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1141476892
  > Start with a normal exported symbol and then scan forwards until I find what I'm looking for.
  
  > I guess I could just look for the hex sequence of the panic message?
  
  The panic message is unfortunately also in the strings segment. So I'm not really sure what's the best way to discover the offset we want to patch at runtime. The best option just seems to be hardcoding the offset (discovered via xref using hopper). Alternatively you could try scanning for the specific instructions we want to replace, but I don't know if that's really any better than hardcoding since there's no guarantee the instructions would be the same between kernel versions (e.g. in another version compiler might have reordered the switch statement differently, or used some other register instead of r12d for return code).
  
  >in the scenario where the kernel did send either THREAD_WAITING or THREAD_NOT_WAITING
  
  I think EBADF should probably be fine there, since the userspace code can handle it as if the syscall failed. But anyway from what I can tell it's not something that should ever happen anyway for 2 reasons:
  
  1) The empirical evidence that we've never seen a kernel panic implicating that type, and Apple also hasn't updated recent kernels to add it as a case
  
  2) Looking at the code flow, it seems like if we enter the kqueue_scan_continue the thread must have been put into a waiting state and now it's not waiting anymore due to some interrupt, context switch, etc., which means that neither `THREAD_WAITING` or `THREAD_NOT_WAITING` would be valid values
  
  >maybe Apple had a reason to think this shouldn't ever happen, and didn't just blatantly forget to handle a case
  
  Yes it's probably that. Maybe the invariant was true at some point but later it became violated. That's why I think usually doing exhaustive switch statement is better since it forces you to confront all posibilities rather than sweeping under the rug with default. And forces you to document all the implicit assumptions for "unrechable" code.
  
  COMMENT 67 Wowfunhappy 2022-06-03T16:21:27Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1146149199
  @krackers So I'm here at the moment:
  
  https://gist.github.com/Wowfunhappy/8212f5bea4c601ac9a6297789f232321
  
  When I comment out lines 55 and 56 (to dump the bytes again and see if they changed), the kext loads fine. However, with those lines—to see if it actually did anything—it KP's.
  
  I haven't done the W^X thing yet because I figured I'd try without it first—but, why would the kernel not panic unless I try to actually print the bytes I modified? If you think write protection is the problem, I'll do that next, as long as the rest of the code so far looks correct to you.
  
  ---
  
  I'm still trying to get rid of hard coded addresses...
  
  - Can we dynamically find the size of the procedure, instead of `memset`'ing `0xffffff80005c7ab4 - 0xffffff80005c7aa3`?
  - This might be stupid, but how difficult would it be to find the function address the same way I can in Hopper? So, presumably it should be possible to scan for the panic message in the strings segment, and then find the code that references that message—right? Any idea what that might look like?
  
  I care about this because I eventually want to integrate the kext into my PrefPane. If I can't find the offset dynamically, my backup plan is to grab them from hopper for a bunch of different kernels (at minimum, the final releases of Lion, Mountain Lion, and Mavericks plus Bronya's Ryzen builds), and select the correct one at runtime by seeing which address has the bytes I expect.
  
  COMMENT 68 krackers 2022-06-04T06:26:57Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1146548659
  You want to do
  
  ```
     memcpy(kqueue_scan_continue_panic_location, replacement_bytes, 6);
     memset(kqueue_scan_continue_panic_location + 7, 0x90 /*noop*/, 0xffffff80005c7ab4 - 0xffffff80005c7aa3);
  ```
  
  Reason is that `kqueue_scan_continue_panic_location` is already a ptr (vm_offset_t is typedef'd to a ptr type).  If you do memcpy to `&kqueue_scan_continue_panic_location` you are actually overwriting the value of `kqueue_scan_continue_panic_location` itself, not writing to the location pointed to by it. Or in other words, you are changing value in the stack instead of actually modifying text segment (possibly smashing your stack as well if the number of bytes written is more than allocated for this frame). That is why you get segfault when you try printing subsequently, because you've now rewritten `kqueue_scan_continue_panic_location` to the value 0x90909090 or something like that, and it's probably pointing to garbage so dereferencing via `*kqueue_scan_continue_panic_location` creates segfault.
  
  You also need to flip the CR0 write protect bit via the previously mentioned function.
  
  Also btw you probably want to print out the entire basic block after modifying, not just the first few values.
  
  ---
  
  >Can we dynamically find the size of the procedure
  
  Yes, in principle. In general what we care about is the size of the basic block, and I suppose if you pulled in some disassembler (there are simple x64 opcode diassemblers) you can scan forward until you find an BB edge (jmp, jne, je, etc.). I think for this specific case it should suffice to scan forward until you see an xor after a call to panic (still need to pull in an x64 disassembler though)
  
  >but how difficult would it be to find the function address the same way I can in Hopper
  
  Simple in principle, but maybe tedious in practice. You basically just do same way Hopper (or any static analysis tool does it), by scanning instructions and finding `lea` with address operand that references the string. But to do this we need to pull in disassembler, and maybe a bit of mach-o header parsing (since x64 is all relative addressing so we need to know the offset between text and data segment.. it's probably fixed, but I don't know for sure). There are some simple library dissassemblers (e.g. Zydis) which you can use for this.
  
  Maybe it's fun to play around with, but I personally am lazy and think it's easier to just have the user disassemble their kernel and recompile the kext with the new constants. Reason is that even if you are able to get away with discovering the basic block size and offset at runtime, it's still not guaranteed that return value will be in `r12d`. So you also need to discover that at runtime, and basically pattern match for something like
  
  ```
  lea _,, <panic string addr>
  ...
  call       _panic
  xor        retVal, retVal
  ```
  
  ---
  
  I suppose technically you could try just pattern matching the assembled opcodes directly, which means you don't need to bring in a disassembler. But then you need to check how the instructions are assembled (e.g. if we want to match `xor r12d, r12d`  or more generically xor-ing some register to zero, figure out which bits in the assembled instruction `45 31 e4` represent the registers and which is the xor opcode. x64 is irregular enough (to me at least) though that this seems even more brittle.
  
  
  
  
  
  
  
  
  COMMENT 69 krackers 2022-06-04T06:34:50Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1146549866
  Oh hah apparently `vm_offset_t` is actually typedef'd to [uintptr_t](https://developer.apple.com/documentation/kernel/uintptr_t) which isn't really a pointer type, just an integer type. So I guess you need to cast it (to void*), since we want to let the compiler you actually want to use it as a pointer.
  
  COMMENT 70 Wowfunhappy 2022-06-04T23:59:21Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1146705932
  Alright, no finding offsets dynamically! :)
  
  Aaaaand... I think I've done it! @krackers can you look over this?
  
  https://gist.github.com/Wowfunhappy/8212f5bea4c601ac9a6297789f232321
  
  Calling out a couple of things in particular:
  -  I added an additional `0x00` to the end of the `replacement_bytes` you gave me, it looked right based on hopper and was needed for the numbers to line up. Does this seem okay?
  - I have two explicit calls to `panic()`, in places where I didn't want to risk leaving the kernel in an unknown state (e.g. without write protection), do these seem reasonable to you? How is the level of defensiveness in general?
  
  This definitely builds and is replacing the memory, so I'm going to give it a try on my own (non-virtual) machine. I've also attached the kext—but use at your own risk!
  
  [kqueue_scan_continue-patch.kext.zip](https://github.com/blueboxd/chromium-legacy/files/8839101/kqueue_scan_continue-patch.kext.zip)
  
  COMMENT 71 krackers 2022-06-05T00:34:41Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1146712682
  > I added an additional 0x00 to the end of the replacement_bytes you gave me
  
  I don't think we should do that? The address for the individual instruction isn't supposed to line up because `lea rdi, qword` is different instruction size than `mov r12d, 0x9`. If you throw `mov r12d, 0x9` in an assembler the instruction should only be 6 bytes. We add the noops afterwards to fill out the rest of the basic block though, so nothing else gets affected (i.e. the address alignment is restored for everything after the basic block we're patching).
  
  If you added the 00, then the instruction stream is now parsed as
  
  ```
  | 0x41, 0xBC, 0x09, 0x00, 0x00 | 0x00 | 0x90 | 0x90 |
  ```
  
  but then the extra 0x00 is left over after decoding, and that doesn't seem to be valid x64 opcode. I'm quite surprised it didn't panic when you did that...
  
  I guess my comment `assembled mov r12d, 0x9 with padding` was misleading, there's no padding in there, that is the actual assembled form of `mov r12d, 0x9`.  (Maybe I had mistakenly thought `r12d` was a 64-bit register since the fact that `dword` is actually only 32-bits always trips me up). The actual version with padding using an imm64 instead of imm32 would be `mov r12, 0x9` which _is_ actually 7 bytes long, so maybe you can use that if you really want instruction-level alignment).
  
  ---
  
  Other than that, nice job! Level of defensiveness seems good, and checking for a match on the expected bytes before replacing is a good idea. Fyi you don't need to define a `uint8_t *kscpb2` for the second print bytes, the `kscpb` pointer from before is still valid and you can just use that.
  
  I don't think your strategy of looking for `search_bytes` will work in other versions though since the `lea` operand references the string in DS relative to RIP, and that's pretty much guaranteed to not be the same between versions.
  
  Also while the replacement logic seems fine to me, probably better to double check by dumping memory from a few bytes before `kqueue_scan_continue_panic_start_location` to a little after `kqueue_scan_continue_panic_end_location`, then throw those bytes in a disassembler. You should expect that the bytes right before `kqueue_scan_continue_panic_start_location` are untouched, the bytes right after `kqueue_scan_continue_panic_end_location` are untouched, and the middle bytes are as expected.
  
  
  COMMENT 72 krackers 2022-06-05T00:38:59Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1146713163
  Ah the reason why it didn't panic when you did that is probably because it hadn't hit it yet. If we did begin executing that codepath, willing to bet that you'd have seen a kpanic.
  
  Once you fix that it should work though, but probably better to do the memory dump mentioned above to make sure there's no off-by-one issues anywhere. You probably have to wait to see if it works or not, checking the chromium crash logs (since you mentioned that with patched kernel returning EBADF, no kpanic but chromium process still crashes).
  
  COMMENT 73 krackers 2022-06-05T00:51:03Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1146714477
  Oh one more crucial defensive check you can do is add the two following asserts:
  
  ```
  kqueue_scan_continue_panic_end_location == kqueue_scan_continue_panic_start_location + sizeof(search_bytes)
  kqueue_scan_continue_panic_start_location + sizeof(replacement_bytes) + extra_space_to_fill ==  kqueue_scan_continue_panic_end_location
  ```
  
  
  COMMENT 74 Wowfunhappy 2022-06-05T01:38:25Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1146720351
  > Ah the reason why it didn't panic when you did that is probably because it hadn't hit it yet. If we did begin executing that codepath, willing to bet that you'd have seen a kpanic.
  
  Yep! I came here to say that I'd gotten a kernel panic. :)
  
  For now as a very quick fix, I've made the last `replace_byte` 0x90 instead of 0x00. The reason I thought that instruction had to be seven bytes was because otherwise I couldn't seem to end up with the right amount for `extra_space_to_fill`, when I tried to calculate it with only the start, end, and replacement instructions as hardcoded. But I don't remember exactly what I was thinking at the time, and I'm too tired now... 😴
  
  Just waiting for the crash log...
  
  COMMENT 75 Wowfunhappy 2022-06-05T23:14:29Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1146901754
  Alright, after another day of futzing with it, I can confirm definitively that this works on 10.9.5 (XNU 2422.115.15). I got the "Bad File Descriptor" crash log from Chromium.
  
  [kqueue_scan_continue-tune-2022.06.05.zip](https://github.com/blueboxd/chromium-legacy/files/8840948/kqueue_scan_continue-tune-2022.06.05.zip)
  
  https://gist.github.com/Wowfunhappy/8212f5bea4c601ac9a6297789f232321
  
  Note that this kext uses the bundle identifier `foo.tun`. This allows it to load from /Library/Extensions despite not being codesigned.
  
  In theory, this should also work on fully-updated copies of Lion (XNU 1699.32.7) and Mountain Lion (XNU 2050.48.19).
  
  COMMENT 76 krackers 2022-06-06T00:25:27Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1146917570
  Nice, looks good! Fyi in terms of style, to make the main code easy to follow you could factor out all the constants and helpers into the `.h` file. Also you can probably take advantage of clang blocks to refactor the flow into something much more readable like:
  
  ```c
  kern_return_t kqueue_scan_continue_tune_start(kmod_info_t * ki, void *d) {
      vm_offset_t kqueue_scan_continue_panic_start_location = 0;
      vm_offset_t kqueue_scan_continue_panic_end_location = 0;
      if (!get_kqueue_scan_continue_locs(&kqueue_scan_continue_panic_start_location, &kqueue_scan_continue_panic_end_location)) {
          return KERN_FAILURE;
      }
  
      unsigned long extra_space_to_fill = kqueue_scan_continue_panic_end_location -
                                          kqueue_scan_continue_panic_start_location - sizeof(replacement_bytes);
  
  
      assert(kqueue_scan_continue_panic_start_location + sizeof(replacement_bytes) + extra_space_to_fill == kqueue_scan_continue_panic_end_location);
  
  
      bool succ = do_with_interrupt_disabled(^bool() {
         return do_with_wp_disabled(^bool() {
              memcpy((void *)kqueue_scan_continue_panic_start_location, replacement_bytes, sizeof(replacement_bytes));
              memset((void *)kqueue_scan_continue_panic_start_location + sizeof(replacement_bytes), 0x90 /*nop*/, extra_space_to_fill);
              printf("kqueue_scan_continue-tune: Memory rewritten\n");
              return true;
          });
      });
  
      if (!succ) {
          return KERN_FAILURE;
      }
  
      printf("Post-patch bytes: ");
      dump_bytes((void*) kqueue_scan_continue_panic_start_location, 40);
  }
  ```
  
  where you have the following helpers defined in the `.h`
  
  ```c
  void dump_bytes(void *start, int num_bytes) {
      for (int i = 0; i < num_bytes; i++) {
          printf("%02x ", ((uint8_t*) start)[i]);
      }
      printf("\n");
  }
  
  bool get_kqueue_scan_continue_locs(vm_offset_t *start_addr_out, vm_offset_t *end_addr_out) {
      vm_offset_t kernel_base = get_kernel_base();
      vm_offset_t kqueue_scan_continue_panic_start_location = 0;
      vm_offset_t kqueue_scan_continue_panic_end_location = 0;
      char search_bytes[sizeof(possible_search_bytes[0])];
      char replacement_bytes[sizeof(possible_replacement_bytes[0])];
      uint8_t *kscpb = NULL;
  
      for (int i = 0; i < LENGTH(possible_kqueue_scan_continue_panic_start_locations); i++) {
          kqueue_scan_continue_panic_start_location = kernel_base + possible_kqueue_scan_continue_panic_start_locations[i];
          kqueue_scan_continue_panic_end_location = kernel_base + possible_kqueue_scan_continue_panic_end_locations[i];
          memcpy(search_bytes, possible_search_bytes[i], sizeof(search_bytes));
          memcpy(replacement_bytes, possible_replacement_bytes[i], sizeof(replacement_bytes));
  
          kscpb = (uint8_t*) kqueue_scan_continue_panic_start_location;
          if (memcmp(kscpb, search_bytes, sizeof(search_bytes)) == 0) {
              break;
          }
          if (i == LENGTH(possible_kqueue_scan_continue_panic_start_locations) - 1) {
              printf("kqueue_scan_continue-tune: Memory region not found. You are probably using an unsupported kernel, or your kernel has already been patched.\n");
              return false;
          }
      }
  
      printf("kqueue_scan_continue-tune: Pre-Patch: Bytes at kqueue_scan_continue panic location" );
      dump_bytes(kscpb, 40);
  
      *start_addr_out = kqueue_scan_continue_panic_start_location;
      *end_addr_out = kqueue_scan_continue_panic_end_location;
      return true;
  }
  
  bool checked_set_interrupt_enabled(bool newVal) {
      printf("kqueue_scan_continue-tune: Set interrupt enabled to %d\n", newVal);
      ml_set_interrupts_enabled(newVal);
      bool succ = ml_get_interrupts_enabled() == newVal;
      if (!succ) {
          printf("kqueue_scan_continue-tune: Failed to set interrupt status to %d\n", newVal);
      }
      return succ;
  }
  
  bool checked_set_wp(bool newVal) {
      printf("kqueue_scan_continue-tune: Set CR0 write protect to %d\n", newVal);
      set_cr0(newVal ? get_cr0() | CR0_WP : get_cr0() & ~CR0_WP);
      bool succ = write_protection_is_enabled() == newVal;
      if (!succ) {
          printf("kqueue_scan_continue-tune: Failed to set write protect status to %d\n", newVal);
      }
      return succ;
  }
  
  bool do_with_interrupt_disabled(bool (^func)(void)) {
      boolean_t interrupts_were_enabled = ml_get_interrupts_enabled();
      if (interrupts_were_enabled && !checked_set_interrupt_enabled(false)) {
          return false;
      }
  
      bool succ = func();
  
      if (interrupts_were_enabled && !ml_get_interrupts_enabled() && !checked_set_interrupt_enabled(true)) {
          panic("kqueue_scan_continue-tune: Failed to re-enable interrupts!\n");
      }
      return succ;
  }
  
  bool do_with_wp_disabled(bool (^func)(void)) {
      boolean_t write_protection_was_enabled = write_protection_is_enabled();
      if (write_protection_was_enable && !checked_set_wp(false)) {
          return false;
      }
  
      bool succ = func();
  
      if (write_protection_was_enabled && !write_protection_is_enabled() && !checked_set_wp(true)) {
          panic("kqueue_scan_continue-tune: Failed to re-enable write protection!\n");
      }
      return succ;
  }
  
  ```
  
  COMMENT 77 krackers 2022-06-06T01:07:57Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1146932060
  Also can you explain more about
  
  >Note that this kext uses the bundle identifier foo.tun. This allows it to load from /Extra/Extensions despite not being codesigned.
  
  I didn't even know /Extra/Extensions was a valid place that osx loaded kexts from, nor that it ignores codesigning for tun/tap driver. Do you have a link where I can read more about this?
  
  Also I was never really sure about 10.9 kext codesign requirements. I can manually kextload an unsigned kext fine, but it gives a warning. I haven't tried installing to `/Library/Extensions` but I assume it would fail to load in that case? But `/System/Library/Extensions` will accept unsigned?  Does ad-hoc signature suffice for /Library/Extensions?
  
  Edit: are you sure /Extra/Extensions works for non-hackintosh? kextd source doesn't seem to show that as a possible location https://opensource.apple.com/source/IOKitUser/IOKitUser-1445.40.1/kext.subproj/OSKextPrivate.h
  
  Btw kext loading is done via `kextd` which is open soruce. As described in https://reverse.put.as/2013/11/23/breaking-os-x-signed-kernel-extensions-with-a-nop/ seems like codesigning is indeed enforced only for /Library/Extensions
  
  ```
  
  
  OSStatus  sigResult = checkKextSignature(theKext, true);
  --
    | if ( sigResult != 0 ) {
    | if ( isInLibraryExtensionsFolder(theKext) \|\|
  
  
  ```
  
  Also looks like ad-hoc won't work since it checks specific chain
  
  ```
  
  
  /* set up correct requirement string.  Apple kexts are signed by B&I while
  --
    | * 3rd party kexts are signed through a special developer kext devid
    | * program
    | */
    | myCFString = OSKextGetIdentifier(aKext);
    | if (CFStringHasPrefix(myCFString, __kOSKextApplePrefix)) {
    | requirementsString = CFSTR("anchor apple");
    | }
    | else {
    | /* DevID for kexts cert
    | */
    | requirementsString =
    | CFSTR("anchor apple generic "
    | "and certificate 1[field.1.2.840.113635.100.6.2.6] "
    | "and certificate leaf[field.1.2.840.113635.100.6.1.13] "
    | "and certificate leaf[field.1.2.840.113635.100.6.1.18]" );
    | }
  
  
  ```
  
  COMMENT 78 Wowfunhappy 2022-06-06T02:19:21Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1146966832
  > I didn't even know /Extra/Extensions was a valid place that osx loaded kexts from, nor that it ignores codesigning for tun/tap driver. Do you have a link where I can read more about this?
  
  Oops! When I said /Extra/Extensions I meant /Library/Extensions, I just wrote the wrong thing. (/Extra/Extensions is indeed a dumb Hackintosh convention.)
  
  As you noted, Mavericks will load unsigned kexts from any location _except_ /Library/Extensions, aka the one place where third party kexts logically _should_ live. It's frustrating!
  
  Not only will ad-hoc codesigning not work, but even a paid developer account is not sufficient, you need to get special approval by Apple.
  
  But, there's a list of bundle identifiers that are allowed to live in /Library/Extensions and be unsigned: System/Library/Extensions/AppleKextExcludeList.kext/Contents/Info.plist
  
  But, now I'm thinking I may let the kext live in /Library/Extensions, but have a launchdaemon that copies it to a temporary location before loading it, instead of usurping an old bundle identifier...

Activity

$ /bin/bash -lc "python3 - <<'PY'import jsonc=json.load(open('investigation/comments.json'))for i in range(78,96): x=c[i]; print('\\nCOMMENT',i+1,x['user']['login'],x['created_at'],x['html_url'],'\\n'+x['body'])PY"
status: Completed · exit 0
  
  COMMENT 79 krackers 2022-06-06T03:31:39Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1146998223
  >But, there's a list of bundle identifiers that are allowed to live in /Library/Extensions and be unsigned
  
  I see,`AppleKextExcludeList.kext` contains both a list of blacklisted kexts which are prevented from loading
  
  https://github.com/st3fan/osx-10.9/blob/master/xnu-2422.1.72/libkern/c++/OSKext.cpp#L4643
  
  as well as as a section on whitelisted kexts that are allowed to skip the codesign check:
  
  https://github.com/st3fan/osx-10.9/blob/master/kext_tools-326.1.12/security.c#L1192
  
  Neat, thanks for teaching me something new.
  
  COMMENT 80 krackers 2022-06-06T09:25:16Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1147245925
  @wowfunhappy actually, here's a good workaround. Invalid signature is only warning for kext in /SLE, so you can inform user to manually update the whitelist plist and then place in /LE. This seems like a clean option, better than installing the kext in /SLE directly I guess.
  
  COMMENT 81 Wowfunhappy 2022-06-06T15:58:43Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1147610909
  @krackers Yeah, so I debated which option was the least hacky:
  
  1. Installing the kext in a non-standard directory.
  2. Installing the kext in `/System/Library/Extensions`.
  3. Installing the kext in `/Library/Extensions` and adding a new bundle identifier to `AppleKextExcludeList.kext`.
  4. Installing the kext in `/Library/Extensions` and usurping a pre-existing bundle identifier inside `AppleKextExcludeList.kext`.
  
  Yesterday, I chose option 4, because I don't think anything with the bundle identifier `foo` is in widespread use. (The list must have been automatically generated somehow, as it also whitelists a bunch of Hackintosh kexts.)
  
  However, I'm actually going with a fifth option that didn't originally occur to me—store the kext in `/Library/Extensions/`, but have [a launchdaemon](https://gist.github.com/Wowfunhappy/8212f5bea4c601ac9a6297789f232321#file-wowfunhappy-kqueuescancontinuepatch-loader-plist) copy it to `/tmp/` before loading. It turns out that non-IOKIt kexts in `/Library/Extensions/` aren't autoloaded anyway, so a launchdaemon is needed regardless.
  
  ---
  
  Thanks for the style notes. I'm think I'm going to leave it be for now, there's not a lot of code and it feels naturally procedural, so I actually prefer having it all in one place.
  
  Anyway, unless I discover a new issue I'm going to try to close the book on this for now (partly because I need to mentally focus on other work).
  
  ---
  
  @blueboxd As a quick recap, we've [created a kext](https://gist.github.com/Wowfunhappy/8212f5bea4c601ac9a6297789f232321) that fixes this problem on 10.7.5 (all security updates applied), 10.8.5 (12F2560), and 10.9.5 (13F1911) by modifying the procedure in kernel memory to return `EBADF` instead of panicking. (Other releases are not currently supported.)
  
  If I don't discover any new issues in the next week or so, I'm going to add this to my Preference Pane, so it gets installed automatically for anyone who uses that. I don't know if it makes sense to incorporate this into the Chromium Legacy app directly, but you are of course welcome to it.
  
  COMMENT 82 blueboxd 2022-06-15T02:16:42Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1155901489
  @Wowfunhappy Wow!! thank you for the great work!!
  I'll try to find a way to integrate this mitigation into Chromium.app.
  
  COMMENT 83 Wowfunhappy 2022-06-18T00:16:09Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1159314810
  Quick note that the kext doesn't work in 32-bit Lion. I briefly looked into adding support today, but from what I can tell, my method of finding the KASLR slide doesn't work, and I don't want to rewrite the entire thing.
  
  COMMENT 84 krackers 2022-06-19T07:36:11Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1159641537
  @Wowfunhappy Wouldn't you have to rewrite (or at least recompile) anyway because in 32-bit mode the mach-o magic is different and header struct layout probably also differs? The approach of scanning memory to look for 0xfeedface should still work though...
  
  Btw I was surprised that 64-bit chromium worked on 32-bit xnu, but then I remember I watched a presentation on how 32-bit xnu had support for running 64-bit userspace processes, so maybe less surprising. I don't remember the presentation though, I'll try to find it since I forget exactly how they supported this.
  
  Edit: Found it, it was a CCC talk: https://www.youtube.com/watch?v=-7GMHB3Plc8
  Also found this article: https://appleinsider.com/articles/08/10/28/road_to_mac_os_x_snow_leopard_64_bit_to_the_kernel
  
  COMMENT 85 Wowfunhappy 2022-06-19T14:34:20Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1159742668
  @krackers ...y'know what, that might be all it is, I forgot I was literally searching for a header called "MH_MAGIC_64" 🤦‍♂️. I'll take another look.
  
  Recompiling isn't a problem, I can just `lipo` together two different binaries that technically have different code. (It does make the built cycle a bit more annoying unless I also take the time to automate that.)
  
  COMMENT 86 Wowfunhappy 2022-07-14T01:21:55Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1183848557
  The kext has been updated with compatibility for 32-bit Lion.
  
  https://gist.github.com/Wowfunhappy/8212f5bea4c601ac9a6297789f232321
  
  (The strategy for finding the kernel base address works fine in 32 bit, but is pointless because Lion lacks KASLR.)
  
  COMMENT 87 fhgwright 2022-09-18T00:27:27Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1250162249
  @Wowfunhappy
  > If I don't discover any new issues in the next week or so, I'm going to add this to my Preference Pane, so it gets installed automatically for anyone who uses that. I don't know if it makes sense to incorporate this into the Chromium Legacy app directly, but you are of course welcome to it.
  
  Please don't.  Kernel patches should never be installed without the user's express permission.  Patching the kernel, either in an application, or in something which represents itself as an application updater, is a really extreme violation of the principle of least surprise.
  
  While it's true that there's a kernel bug at work here, as a practical matter, coming up with a userspace workaround would be much more user-friendly, given that:
  
  1. AFAIK this has never been triggered by any application other than Chromium Legacy.
  2. It was never triggered by any supported release of Chrome.
  3. AIUI, the kernel fix still leads to an application crash, so an application-level fix is _also_ needed, anyway.
  
  Given item 3, the kernel patch _on test systems_ could be useful in identifying the combination of syscalls that provokes the bug.  And assuming that the offending code doesn't provide any new capability, there must be something in Chromium which changed from an "old way" to a "new way" of doing something.  Once that difference can be figured out, the next questions are:
  
  1. How much of an advantage is there in the "new way"?  I.e., how important is it to use the "new way" when it doesn't cause trouble, rather than reverting unconditionally?
  2. How wide is the scope of the difference?  I.e., if there were a patch to revert to the "old way", how maintainable would such a patch be?
  
  
  It would certainly be useful to _also_ have a kernel fix for users who want a more robust kernel and are willing to install a kernel update, but it would be best to avoid making that a requirement for avoiding this bug.  And a "proper" kernel update should involve building from source, rather than applying some kludgy on-the-fly binary patch.  Some work would be needed to identify the correct sources to use as a starting point, though fortunately that needs to be done only once for any given abandoned OS version.
  
  
  COMMENT 88 Wowfunhappy 2022-09-18T00:54:13Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1250165146
  @fhgwright
  
  > Please don't. Kernel patches should never be installed without the user's express permission. Patching the kernel, either in an application, or in something which represents itself as an application updater, is a really extreme violation of the principle of least surprise.
  
  The preference pane does ask for permission!
  
  ![Screen Shot 2022-09-17 at 8 34 57 PM](https://user-images.githubusercontent.com/4484096/190880693-b76a54ee-c443-4dfd-97ea-3134684a044a.png)
  
  The installation is "automatic" in the sense that, if the user says yes, it's done in one click.
  
  Let me know if you think the above message isn't clear enough. I am trying to be respectful of the user. However, I don't think leaving users with kernel panics is particularly respectful either!
  
  > While it's true that there's a kernel bug at work here, as a practical matter, coming up with a userspace workaround would be much more user-friendly
  
  I 100% agree! At the moment, however, I don't think anyone working on Chromium Legacy has the time or expertise to come up with a userspace fix. This is the best that krackers and I can do. If you have the expertise to fix the problem in userspace, please contribute, that would be wonderful!
  
  >  there must be something in Chromium which changed from an "old way" to a "new way" of doing something.
  
  My current best guess (which could definitely still be wrong) is that it's https://bugs.chromium.org/p/chromium/issues/detail?id=932175
  
  > How much of an advantage is there in the "new way"? I.e., how important is it to use the "new way" when it doesn't cause trouble, rather than reverting unconditionally?
  
  It sounds like it's not such a huge advantage. Most users are not exhausting file descriptors. However...
  
  > How wide is the scope of the difference? I.e., if there were a patch to revert to the "old way", how maintainable would such a patch be?
  
  Wide enough that Bluebox wasn't able to do it. https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1086776672
  
  > And a "proper" kernel update should involve building from source, rather than applying some kludgy on-the-fly binary patch.
  
  Already done!
  
  https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1019278490
  
  This kernel is for 10.9.5, but you could easily apply the fix to whichever kernel you'd like. It's literally a three line change.
  
  The problem is that the open source release of XNU is incomplete. Most notably, custom kernels are unable to log into iMessage. This is why we created a kext to patch the memory at runtime instead.
  
  COMMENT 89 fhgwright 2022-09-21T22:20:20Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1254290739
  > @fhgwright
  >
  > > Please don't. Kernel patches should never be installed without the user's express permission. Patching the kernel, either in an application, or in something which represents itself as an application updater, is a really extreme violation of the principle of least surprise.
  >
  > The preference pane does ask for permission!
  >
  > ![Screen Shot 2022-09-17 at 8 34 57 PM](https://user-images.githubusercontent.com/4484096/190880693-b76a54ee-c443-4dfd-97ea-3134684a044a.png)
  >
  > The installation is "automatic" in the sense that, if the user says yes, it's done in one click.
  >
  > Let me know if you think the above message isn't clear enough. I am trying to be respectful of the user. However, I don't think leaving users with kernel panics is particularly respectful either!
  
  I've never seen that dialog box (except here), nor is the kext present here, so I assumed that you hadn't yet implemented the preference-pane hack.  But maybe the preference pane doesn't update itself.
  
  It should let you know whether the patch is already present, and offer an uninstall option as well.  But both goals could be mostly served by giving the full path of the extension in the text.
  
  > > While it's true that there's a kernel bug at work here, as a practical matter, coming up with a userspace workaround would be much more user-friendly
  >
  > I 100% agree! At the moment, however, I don't think anyone working on Chromium Legacy has the time or expertise to come up with a userspace fix. This is the best that krackers and I can do. If you have the expertise to fix the problem in userspace, please contribute, that would be wonderful!
  >
  > > there must be something in Chromium which changed from an "old way" to a "new way" of doing something.
  >
  > My current best guess (which could definitely still be wrong) is that it's https://bugs.chromium.org/p/chromium/issues/detail?id=932175
  >
  > > How much of an advantage is there in the "new way"? I.e., how important is it to use the "new way" when it doesn't cause trouble, rather than reverting unconditionally?
  >
  > It sounds like it's not such a huge advantage. Most users are not exhausting file descriptors. However...
  >
  > > How wide is the scope of the difference? I.e., if there were a patch to revert to the "old way", how maintainable would such a patch be?
  >
  > Wide enough that Bluebox wasn't able to do it. [#44 (comment)](https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1086776672)
  
  But if it's true that the change involved moving away from using FDs for signaling due to FD exhaustion issues, then given that Chrome also runs on Linux, the "old way" must still be present (and fully supported) in the Linux build.
  
  I doubt that I'd have trouble with FD exhaustion here anyway, since I crank up the limit for other reasons, and I'm not the sort to keep hundreds of browser tabs open simultaneously.
  
  > > And a "proper" kernel update should involve building from source, rather than applying some kludgy on-the-fly binary patch.
  >
  > Already done!
  >
  > [#44 (comment)](https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1019278490)
  
  But that didn't match the release kernel, and the discrepancy was never investigated.
  
  > This kernel is for 10.9.5, but you could easily apply the fix to whichever kernel you'd like. It's literally a three line change.
  >
  > The problem is that the open source release of XNU is incomplete. Most notably, custom kernels are unable to log into iMessage. This is why we created a kext to patch the memory at runtime instead.
  
  Until a matching kernel can be built from source, I wouldn't blame the iMessage issue on custom kernels per se.
  
  
  COMMENT 90 Wowfunhappy 2022-09-21T23:06:41Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1254321866
  > I've never seen that dialog box (except here), nor is the kext present here, so I assumed that you hadn't yet implemented the preference-pane hack. But maybe the preference pane doesn't update itself.
  
  Correct, it does not update itself.
  
  > It should let you know whether the patch is already present, and offer an uninstall option as well.
  
  While this does not currently happen, uninstalling the PrefPane (via the provided uninstall script) will also uninstall the kext. In addition, the kext is installed in `/Library/Extensions/`, the standard location for third-party kernel extensions.
  
  > But that didn't match the release kernel, and the discrepancy was never investigated.
  
  We did investigate. It does not match the release kernel because the release kernel is not open source. Which is why we went with a kernel extension instead.
  
  > Until a matching kernel can be built from source, I wouldn't blame the iMessage issue on custom kernels per se.
  
  The open source version of XNU is explicitly missing a function required by iMessage. This was actually documented by the Hackintosh community, I just wasn't aware previously.
  
  > given that Chrome also runs on Linux, the "old way" must still be present (and fully supported) in the Linux build.
  
  Yes, but the Linux build uses Linux-specific code that won't work on XNU, so it's harder than it seems. But again, by all means, please give it a shot. I don't know if it will work, but it might, and I'd love to see this fixed within Chromium Legacy itself. It's just beyond my own ability.
  
  COMMENT 91 onecommon-dev 2023-01-14T19:34:22Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1382896378
  Not sure if this will be valuable for you but I reproduced this on 10.9.4 and here are the logs.
  I was leaving https://piped.mha.fi on, intending to type something but haven't decided, so no interaction with the machine yet. And my Macbook Pro 2012 kernel paniced.
  
  If it's not helpful please let me know and I will remove the comment.
  
  [Kernel_2023-01-14-184339_Hoangs-MacBook-Pro.panic.log](https://github.com/blueboxd/chromium-legacy/files/10418691/Kernel_2023-01-14-184339_Hoangs-MacBook-Pro.panic.log)
  
  ```
  Anonymous UUID:       58645209-3F22-8B42-01B7-0C62519750C7
  
  Sat Jan 14 18:43:39 2023
  panic(cpu 0 caller 0xffffff80071c6bb4): "kqueue_scan_continue: - invalid wait_result (3)"@/SourceCache/xnu/xnu-2422.110.17/bsd/kern/kern_event.c:2167
  Backtrace (CPU 0), Frame : Return Address
  0xffffff81f2053ef0 : 0xffffff8006e22f79
  0xffffff81f2053f70 : 0xffffff80071c6bb4
  0xffffff81f2053fb0 : 0xffffff8006ed7417
  
  BSD process name corresponding to current thread: Chromium Helper
  Boot args: kext-dev-mode=1
  
  Mac OS version:
  13E28
  
  Kernel version:
  Darwin Kernel Version 13.3.0: Tue Jun  3 21:27:35 PDT 2014; root:xnu-2422.110.17~1/RELEASE_X86_64
  Kernel UUID: BBFADD17-672B-35A2-9B7F-E4B12213E4B8
  Kernel slide:     0x0000000006c00000
  Kernel text base: 0xffffff8006e00000
  System model name: MacBookPro9,1 (Mac-4B7AC7E43945597E)
  
  System uptime in nanoseconds: 4066641044880
  last loaded kext at 3901636049533: com.apple.driver.AppleIntelMCEReporter	104 (addr 0xffffff7f8924c000, size 49152)
  last unloaded kext at 3966662167467: com.apple.driver.AppleIntelMCEReporter	104 (addr 0xffffff7f8924c000, size 32768)
  loaded kexts:
  ...
  ```
  
  COMMENT 92 krackers 2023-01-14T20:44:11Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1382912506
  Just to confirm, is this with Wowfunhappy's kext installed? That should  that should hot-patch the kernel to avoid these panics (instead it will "merely" crash just the chromium renderer instead of bringing down your entire system).
  
  Also fyi 10.9.4 is not the latest version of mavericks, you should probably be on 10.9.5.
  
  COMMENT 93 Wowfunhappy 2023-01-14T23:04:01Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1382956474
  > Just to confirm, is this with Wowfunhappy's kext installed? That should hot-patch the kernel to avoid these panics
  
  Not if they're on 10.9.4 it won't! I'd need to add memory addresses for that kernel.
  
  Is there a reason this system is on 10.9.4 instead of 10.9.5? If there's something "special" about 10.9.4 in particular, I could add support for it.
  
  COMMENT 94 onecommon-dev 2023-01-15T00:14:51Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1382976462
  I was on 10.9.4 because I never realised that it wasn't the latest
  Mavericks 😂😂😂
  
  I kind a skimmed through the end of the issue and didn't spot the
  workaround, I'll update to 10.9.5 and try it, will report back after some
  testing.
  
  On Sat, 14 Jan 2023, 11:04 pm Jonathan, ***@***.***> wrote:
  
  > Just to confirm, is this with Wowfunhappy's kext installed? That should
  > hot-patch the kernel to avoid these panics
  >
  > Not if they're on 10.9.4 it won't! I'd need to add offsets for that kernel.
  >
  > Is there a reason this system is on 10.9.4 instead of 10.9.5? If there's
  > something "special" about that version, I could add support for it.
  >
  > —
  > Reply to this email directly, view it on GitHub
  > <https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1382956474>,
  > or unsubscribe
  > <https://github.com/notifications/unsubscribe-auth/AABGIECOLYIBDWF5C6HZBG3WSMWGXANCNFSM5LXTPZ7A>
  > .
  > You are receiving this because you commented.Message ID:
  > ***@***.***>
  >
  
  
  COMMENT 95 Wowfunhappy 2023-01-15T00:18:43Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1382977652
  > I was on 10.9.4 because I never realised that it wasn't the latest Mavericks 😂😂😂 I kind a skimmed through the end of the issue and didn't spot the workaround, I'll update to 10.9.5 and try it, will report back after some testing.
  
  Quick heads up that Apple _also_ released further updates after the base 10.9.5 which don't change the version number, you want 10.9.5 build 13F1911. I'm pretty sure the updater will prompt you, but if not, install: https://support.apple.com/kb/dl1886?locale=en_US
  
  COMMENT 96 onecommon-dev 2023-01-16T11:58:49Z https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1383943770
  Yep, on 13F1911, installed the kext through the preference pane, will see
  how it works over the week.
  
  Thanks!
  
  On Sun, 15 Jan 2023, 12:18 am Jonathan, ***@***.***> wrote:
  
  > I was on 10.9.4 because I never realised that it wasn't the latest
  > Mavericks 😂😂😂 I kind a skimmed through the end of the issue and didn't
  > spot the workaround, I'll update to 10.9.5 and try it, will report back
  > after some testing.
  >
  > Quick heads up that Apple *also* released further updates after the base
  > 10.9.5 which don't change the version number, you want 10.9.5 build
  > 13F1911. I'm pretty sure the updater will prompt you, but if not, install:
  > https://support.apple.com/kb/dl1886?locale=en_US
  >
  > —
  > Reply to this email directly, view it on GitHub
  > <https://github.com/blueboxd/chromium-legacy/issues/44#issuecomment-1382977652>,
  > or unsubscribe
  > <https://github.com/notifications/unsubscribe-auth/AABGIEHJWX4DWYI67R5L5NTWSM665ANCNFSM5LXTPZ7A>
  > .
  > You are receiving this because you commented.Message ID:
  > ***@***.***>
  >

Activity

$ /bin/bash -lc "sed -n '1,260p' chromium-legacy-master/base/message_loop/message_pump_kqueue.cc; sed -n '260,600p' chromium-legacy-master/base/message_loop/message_pump_kqueue.cc"
status: Completed · exit 0
  // Copyright 2019 The Chromium Authors
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #ifdef UNSAFE_BUFFERS_BUILD
  // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
  #pragma allow_unsafe_buffers
  #endif
  
  #include "base/message_loop/message_pump_kqueue.h"
  
  #include <sys/errno.h>
  
  #include <atomic>
  
  #include "base/apple/mach_logging.h"
  #include "base/apple/scoped_nsautorelease_pool.h"
  #include "base/auto_reset.h"
  #include "base/feature_list.h"
  #include "base/logging.h"
  #include "base/mac/mac_util.h"
  #include "base/notreached.h"
  #include "base/posix/eintr_wrapper.h"
  #include "base/task/task_features.h"
  #include "base/time/time_override.h"
  
  namespace base {
  
  namespace {
  
  // Under this feature native work is batched. Remove it once crbug.com/1200141
  // is resolved.
  BASE_FEATURE(kBatchNativeEventsInMessagePumpKqueue,
               "BatchNativeEventsInMessagePumpKqueue",
               base::FEATURE_DISABLED_BY_DEFAULT);
  
  // Caches the state of the "BatchNativeEventsInMessagePumpKqueue".
  std::atomic_bool g_use_batched_version = false;
  
  // Caches the state of the "TimerSlackMac" feature for efficiency.
  std::atomic_bool g_timer_slack = false;
  
  // Prior to macOS 10.14, kqueue timers may spuriously wake up, because earlier
  // wake ups race with timer resets in the kernel. As of macOS 10.14, updating a
  // timer from the thread that reads the kqueue does not cause spurious wakeups.
  // Note that updating a kqueue timer from one thread while another thread is
  // waiting in a kevent64 invocation is still (inherently) racy.
  bool KqueueTimersSpuriouslyWakeUp() {
  #if BUILDFLAG(IS_MAC)
    static const bool kqueue_timers_spuriously_wakeup = mac::IsAtMostOS10_13();
    return kqueue_timers_spuriously_wakeup;
  #else
    return false;
  #endif
  }
  
  int ChangeOneEvent(const ScopedFD& kqueue, kevent64_s* event) {
    return HANDLE_EINTR(kevent64(kqueue.get(), event, 1, nullptr, 0, 0, nullptr));
  }
  
  }  // namespace
  
  MessagePumpKqueue::FdWatchController::FdWatchController(
      const Location& from_here)
      : FdWatchControllerInterface(from_here) {}
  
  MessagePumpKqueue::FdWatchController::~FdWatchController() {
    StopWatchingFileDescriptor();
  }
  
  bool MessagePumpKqueue::FdWatchController::StopWatchingFileDescriptor() {
    if (!pump_)
      return true;
    return pump_->StopWatchingFileDescriptor(this);
  }
  
  void MessagePumpKqueue::FdWatchController::Init(WeakPtr<MessagePumpKqueue> pump,
                                                  int fd,
                                                  int mode,
                                                  FdWatcher* watcher) {
    DCHECK_NE(fd, -1);
    DCHECK(!watcher_);
    DCHECK(watcher);
    DCHECK(pump);
    fd_ = fd;
    mode_ = mode;
    watcher_ = watcher;
    pump_ = pump;
  }
  
  void MessagePumpKqueue::FdWatchController::Reset() {
    fd_ = -1;
    mode_ = 0;
    watcher_ = nullptr;
    pump_ = nullptr;
  }
  
  MessagePumpKqueue::MachPortWatchController::MachPortWatchController(
      const Location& from_here)
      : from_here_(from_here) {}
  
  MessagePumpKqueue::MachPortWatchController::~MachPortWatchController() {
    StopWatchingMachPort();
  }
  
  bool MessagePumpKqueue::MachPortWatchController::StopWatchingMachPort() {
    if (!pump_)
      return true;
    return pump_->StopWatchingMachPort(this);
  }
  
  void MessagePumpKqueue::MachPortWatchController::Init(
      WeakPtr<MessagePumpKqueue> pump,
      mach_port_t port,
      MachPortWatcher* watcher) {
    DCHECK(!watcher_);
    DCHECK(watcher);
    DCHECK(pump);
    port_ = port;
    watcher_ = watcher;
    pump_ = pump;
  }
  
  void MessagePumpKqueue::MachPortWatchController::Reset() {
    port_ = MACH_PORT_NULL;
    watcher_ = nullptr;
    pump_ = nullptr;
  }
  
  MessagePumpKqueue::MessagePumpKqueue()
      : kqueue_(kqueue()), weak_factory_(this) {
    PCHECK(kqueue_.is_valid()) << "kqueue";
  
    // Create a Mach port that will be used to wake up the pump by sending
    // a message in response to ScheduleWork(). This is significantly faster than
    // using an EVFILT_USER event, especially when triggered across threads.
    kern_return_t kr = mach_port_allocate(
        mach_task_self(), MACH_PORT_RIGHT_RECEIVE,
        base::apple::ScopedMachReceiveRight::Receiver(wakeup_).get());
    MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_port_allocate";
  
    kevent64_s event{};
    if (KqueueTimersSpuriouslyWakeUp()) {
      kr =
          mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET,
                             apple::ScopedMachPortSet::Receiver(port_set_).get());
      MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_port_allocate PORT_SET";
  
      kr = mach_port_insert_member(mach_task_self(), wakeup_.get(),
                                   port_set_.get());
      MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_port_insert_member";
  
      event.ident = port_set_.get();
      event.filter = EVFILT_MACHPORT;
      event.flags = EV_ADD;
    } else {
      // When not using a port set, the wakeup port event can be specified to
      // directly receive the Mach message as part of the kevent64() syscall.
      // This is not done when using a port set, since that would potentially
      // receive client MachPortWatchers' messages.
      event.ident = wakeup_.get();
      event.filter = EVFILT_MACHPORT;
      event.flags = EV_ADD;
      event.fflags = MACH_RCV_MSG;
      event.ext[0] = reinterpret_cast<uint64_t>(&wakeup_buffer_);
      event.ext[1] = sizeof(wakeup_buffer_);
    }
  
    int rv = ChangeOneEvent(kqueue_, &event);
    PCHECK(rv == 0) << "kevent64";
  }
  
  MessagePumpKqueue::~MessagePumpKqueue() {}
  
  void MessagePumpKqueue::InitializeFeatures() {
    g_use_batched_version.store(
        base::FeatureList::IsEnabled(kBatchNativeEventsInMessagePumpKqueue),
        std::memory_order_relaxed);
    g_timer_slack.store(FeatureList::IsEnabled(kTimerSlackMac),
                        std::memory_order_relaxed);
  }
  
  void MessagePumpKqueue::Run(Delegate* delegate) {
    AutoReset<bool> reset_keep_running(&keep_running_, true);
  
    if (g_use_batched_version.load(std::memory_order_relaxed)) {
      RunBatched(delegate);
    } else {
      while (keep_running_) {
        apple::ScopedNSAutoreleasePool pool;
  
        bool do_more_work = DoInternalWork(delegate, nullptr);
        if (!keep_running_)
          break;
  
        Delegate::NextWorkInfo next_work_info = delegate->DoWork();
        do_more_work |= next_work_info.is_immediate();
        if (!keep_running_)
          break;
  
        if (do_more_work)
          continue;
  
        delegate->DoIdleWork();
        if (!keep_running_)
          break;
  
        DoInternalWork(delegate, &next_work_info);
      }
    }
  }
  
  void MessagePumpKqueue::RunBatched(Delegate* delegate) {
    // Look for native work once before the loop starts. Without this call the
    // loop would break without checking native work even once in cases where
    // QuitWhenIdle was used. This is sometimes the case in tests.
    DoInternalWork(delegate, nullptr);
  
    while (keep_running_) {
      apple::ScopedNSAutoreleasePool pool;
  
      Delegate::NextWorkInfo next_work_info = delegate->DoWork();
      if (!keep_running_)
        break;
  
      if (!next_work_info.is_immediate()) {
        delegate->DoIdleWork();
      }
      if (!keep_running_)
        break;
  
      int batch_size = 0;
      if (DoInternalWork(delegate, &next_work_info)) {
        // More than one call can be necessary to fully dispatch all available
        // internal work. Making an effort to dispatch more than the minimum
        // before moving on to application tasks reduces the overhead of going
        // through the whole loop. It also more closely mirrors the behavior of
        // application task execution where tasks are batched. A value of 16 was
        // chosen via local experimentation showing that is was sufficient to
        // dispatch all work in roughly 95% of cases.
        constexpr int kMaxAttempts = 16;
        while (DoInternalWork(delegate, nullptr) && batch_size < kMaxAttempts) {
          ++batch_size;
        }
      }
    }
  }
  
  void MessagePumpKqueue::Quit() {
    keep_running_ = false;
    ScheduleWork();
  }
  
  void MessagePumpKqueue::ScheduleWork() {
    mach_msg_empty_send_t message{};
    message.header.msgh_size = sizeof(message);
    message.header.msgh_bits =
        MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MAKE_SEND_ONCE);
    message.header.msgh_remote_port = wakeup_.get();
    kern_return_t kr = mach_msg_send(&message.header);
    kern_return_t kr = mach_msg_send(&message.header);
    if (kr != KERN_SUCCESS) {
      // If ScheduleWork() is being called by other threads faster than the pump
      // can dispatch work, the kernel message queue for the wakeup port can fill
      // up (this happens under base_perftests, for example). The kernel does
      // return a SEND_ONCE right in the case of failure, which must be destroyed
      // to avoid leaking.
      MACH_DLOG_IF(ERROR, (kr & ~MACH_MSG_IPC_SPACE) != MACH_SEND_NO_BUFFER, kr)
          << "mach_msg_send";
      mach_msg_destroy(&message.header);
    }
  }
  
  void MessagePumpKqueue::ScheduleDelayedWork(
      const Delegate::NextWorkInfo& next_work_info) {
    // Nothing to do. This MessagePump uses DoWork().
  }
  
  bool MessagePumpKqueue::WatchMachReceivePort(
      mach_port_t port,
      MachPortWatchController* controller,
      MachPortWatcher* delegate) {
    DCHECK(port != MACH_PORT_NULL);
    DCHECK(controller);
    DCHECK(delegate);
  
    if (controller->port() != MACH_PORT_NULL) {
      DLOG(ERROR)
          << "Cannot use the same MachPortWatchController while it is active";
      return false;
    }
  
    if (KqueueTimersSpuriouslyWakeUp()) {
      kern_return_t kr =
          mach_port_insert_member(mach_task_self(), port, port_set_.get());
      if (kr != KERN_SUCCESS) {
        MACH_LOG(ERROR, kr) << "mach_port_insert_member";
        return false;
      }
    } else {
      kevent64_s event{};
      event.ident = port;
      event.filter = EVFILT_MACHPORT;
      event.flags = EV_ADD;
      int rv = ChangeOneEvent(kqueue_, &event);
      if (rv < 0) {
        DPLOG(ERROR) << "kevent64";
        return false;
      }
      ++event_count_;
    }
  
    controller->Init(weak_factory_.GetWeakPtr(), port, delegate);
    port_controllers_.AddWithID(controller, port);
  
    return true;
  }
  
  TimeTicks MessagePumpKqueue::AdjustDelayedRunTime(TimeTicks earliest_time,
                                                    TimeTicks run_time,
                                                    TimeTicks latest_time) {
    if (GetAlignWakeUpsEnabled() &&
        g_timer_slack.load(std::memory_order_relaxed)) {
      return earliest_time;
    }
    return MessagePump::AdjustDelayedRunTime(earliest_time, run_time,
                                             latest_time);
  }
  
  bool MessagePumpKqueue::WatchFileDescriptor(int fd,
                                              bool persistent,
                                              int mode,
                                              FdWatchController* controller,
                                              FdWatcher* delegate) {
    DCHECK_GE(fd, 0);
    DCHECK(controller);
    DCHECK(delegate);
    DCHECK_NE(mode & Mode::WATCH_READ_WRITE, 0);
  
    if (controller->fd() != -1 && controller->fd() != fd) {
      DLOG(ERROR) << "Cannot use the same FdWatchController on two different FDs";
      return false;
    }
    StopWatchingFileDescriptor(controller);
  
    std::vector<kevent64_s> events;
  
    kevent64_s base_event{};
    base_event.ident = static_cast<uint64_t>(fd);
    base_event.flags = EV_ADD | (!persistent ? EV_ONESHOT : 0);
  
    if (mode & Mode::WATCH_READ) {
      base_event.filter = EVFILT_READ;
      base_event.udata = fd_controllers_.Add(controller);
      events.push_back(base_event);
    }
    if (mode & Mode::WATCH_WRITE) {
      base_event.filter = EVFILT_WRITE;
      base_event.udata = fd_controllers_.Add(controller);
      events.push_back(base_event);
    }
  
    int rv = HANDLE_EINTR(kevent64(kqueue_.get(), events.data(),
                                   checked_cast<int>(events.size()), nullptr, 0,
                                   0, nullptr));
    if (rv < 0) {
      DPLOG(ERROR) << "WatchFileDescriptor kevent64";
      return false;
    }
  
    event_count_ += events.size();
    controller->Init(weak_factory_.GetWeakPtr(), fd, mode, delegate);
  
    return true;
  }
  
  void MessagePumpKqueue::SetWakeupTimerEvent(const base::TimeTicks& wakeup_time,
                                              base::TimeDelta leeway,
                                              kevent64_s* timer_event) {
    // The ident of the wakeup timer. There's only the one timer as the pair
    // (ident, filter) is the identity of the event.
    constexpr uint64_t kWakeupTimerIdent = 0x0;
    timer_event->ident = kWakeupTimerIdent;
    timer_event->filter = EVFILT_TIMER;
    if (wakeup_time == base::TimeTicks::Max()) {
      timer_event->flags = EV_DELETE;
    } else {
      timer_event->filter = EVFILT_TIMER;
      // This updates the timer if it already exists in |kqueue_|.
      timer_event->flags = EV_ADD | EV_ONESHOT;
  
      // Specify the sleep in microseconds to avoid undersleeping due to
      // numeric problems. The sleep is computed from TimeTicks::Now rather than
      // NextWorkInfo::recent_now because recent_now is strictly earlier than
      // current wall-clock. Using an earlier wall clock time  to compute the
      // delta to the next wakeup wall-clock time would guarantee oversleep.
      // If wakeup_time is in the past, the delta below will be negative and the
      // timer is set immediately.
      timer_event->fflags = NOTE_USECONDS;
      timer_event->data = (wakeup_time - base::TimeTicks::Now()).InMicroseconds();
  
      if (!leeway.is_zero() && g_timer_slack.load(std::memory_order_relaxed)) {
        // Specify slack based on |leeway|.
        // See "man kqueue" in recent macOSen for documentation.
        timer_event->fflags |= NOTE_LEEWAY;
        timer_event->ext[1] = static_cast<uint64_t>(leeway.InMicroseconds());
      }
    }
  }
  
  bool MessagePumpKqueue::StopWatchingMachPort(
      MachPortWatchController* controller) {
    mach_port_t port = controller->port();
    controller->Reset();
    port_controllers_.Remove(port);
  
    if (KqueueTimersSpuriouslyWakeUp()) {
      kern_return_t kr =
          mach_port_extract_member(mach_task_self(), port, port_set_.get());
      if (kr != KERN_SUCCESS) {
        MACH_LOG(ERROR, kr) << "mach_port_extract_member";
        return false;
      }
    } else {
      kevent64_s event{};
      event.ident = port;
      event.filter = EVFILT_MACHPORT;
      event.flags = EV_DELETE;
      --event_count_;
      int rv = ChangeOneEvent(kqueue_, &event);
      if (rv < 0) {
        DPLOG(ERROR) << "kevent64";
        return false;
      }
    }
  
    return true;
  }
  
  bool MessagePumpKqueue::StopWatchingFileDescriptor(
      FdWatchController* controller) {
    int fd = controller->fd();
    int mode = controller->mode();
    controller->Reset();
  
    if (fd < 0)
      return true;
  
    std::vector<kevent64_s> events;
  
    kevent64_s base_event{};
    base_event.ident = static_cast<uint64_t>(fd);
    base_event.flags = EV_DELETE;
  
    if (mode & Mode::WATCH_READ) {
      base_event.filter = EVFILT_READ;
      events.push_back(base_event);
    }
    if (mode & Mode::WATCH_WRITE) {
      base_event.filter = EVFILT_WRITE;
      events.push_back(base_event);
    }
  
    int rv = HANDLE_EINTR(kevent64(kqueue_.get(), events.data(),
                                   checked_cast<int>(events.size()), nullptr, 0,
                                   0, nullptr));
    DPLOG_IF(ERROR, rv < 0) << "StopWatchingFileDescriptor kevent64";
  
    // The keys for the IDMap aren't recorded anywhere (they're attached to the
    // kevent object in the kernel), so locate the entries by controller pointer.
    for (IDMap<FdWatchController*, uint64_t>::iterator it(&fd_controllers_);
         !it.IsAtEnd(); it.Advance()) {
      if (it.GetCurrentValue() == controller) {
        fd_controllers_.Remove(it.GetCurrentKey());
      }
    }
  
    event_count_ -= events.size();
  
    return rv >= 0;
  }
  
  bool MessagePumpKqueue::DoInternalWork(Delegate* delegate,
                                         Delegate::NextWorkInfo* next_work_info) {
    if (events_.size() < event_count_) {
      events_.resize(event_count_);
    }
  
    bool poll = next_work_info == nullptr;
    int flags = poll ? KEVENT_FLAG_IMMEDIATE : 0;
    bool indefinite =
        next_work_info != nullptr && next_work_info->delayed_run_time.is_max();
  
    int rv = 0;
    do {
      timespec timeout{};
      if (!indefinite && !poll) {
        if (rv != 0) {
          // The wait was interrupted and made |next_work_info|'s view of
          // TimeTicks::Now() stale. Refresh it before doing another wait.
          next_work_info->recent_now = TimeTicks::Now();
        }
        timeout = next_work_info->remaining_delay().ToTimeSpec();
      }
      // This does not use HANDLE_EINTR, since retrying the syscall requires
      // adjusting the timeout to account for time already waited.
      rv = kevent64(kqueue_.get(), nullptr, 0, events_.data(), events_.size(),
                    flags, indefinite ? nullptr : &timeout);
    } while (rv < 0 && errno == EINTR);
  
    PCHECK(rv >= 0) << "kevent64";
    if (rv == 0) {
      // No events to dispatch so no need to call ProcessEvents().
      return false;
    }
  
    PCHECK(rv > 0) << "kevent64";
    return ProcessEvents(delegate, static_cast<size_t>(rv));
  }
  
  bool MessagePumpKqueue::ProcessEvents(Delegate* delegate, size_t count) {
    bool did_work = false;
  
    delegate->BeginNativeWorkBeforeDoWork();
    for (size_t i = 0; i < count; ++i) {
      auto* event = &events_[i];
      if (event->filter == EVFILT_READ || event->filter == EVFILT_WRITE) {
        did_work = true;
  
        FdWatchController* controller = fd_controllers_.Lookup(event->udata);
        if (!controller) {
          // The controller was removed by some other work callout before
          // this event could be processed.
          continue;
        }
        FdWatcher* fd_watcher = controller->watcher();
  
        if (event->flags & EV_ONESHOT) {
          // If this was a one-shot event, the Controller needs to stop tracking
          // the descriptor, so it is not double-removed when it is told to stop
          // watching.
          controller->Reset();
          fd_controllers_.Remove(event->udata);
          --event_count_;
        }
  
        auto scoped_do_work_item = delegate->BeginWorkItem();
        // WatchFileDescriptor() originally upcasts event->ident from an int.
        if (event->filter == EVFILT_READ) {
          fd_watcher->OnFileCanReadWithoutBlocking(
              static_cast<int>(event->ident));
        } else if (event->filter == EVFILT_WRITE) {
          fd_watcher->OnFileCanWriteWithoutBlocking(
              static_cast<int>(event->ident));
        }
      } else if (event->filter == EVFILT_MACHPORT) {
        mach_port_t port = KqueueTimersSpuriouslyWakeUp()
                               ? static_cast<mach_port_t>(event->data)
                               : static_cast<mach_port_t>(event->ident);
  
        if (port == wakeup_.get()) {
          // The wakeup event has been received, do not treat this as "doing
          // work", this just wakes up the pump.
          if (KqueueTimersSpuriouslyWakeUp()) {
            // When using the kqueue directly, the message can be received
            // straight into a buffer that was created when adding the event.
            // But when using a port set, the message must be drained manually.
            wakeup_buffer_.header.msgh_local_port = port;
            wakeup_buffer_.header.msgh_size = sizeof(wakeup_buffer_);
            kern_return_t kr = mach_msg_receive(&wakeup_buffer_.header);
            MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr)
                << "mach_msg_receive wakeup";
          }
          continue;
        }
  
        did_work = true;
  
        MachPortWatchController* controller = port_controllers_.Lookup(port);
        // The controller could have been removed by some other work callout
        // before this event could be processed.
        if (controller) {
          auto scoped_do_work_item = delegate->BeginWorkItem();
          controller->watcher()->OnMachMessageReceived(port);
        }
      } else {
        NOTREACHED_IN_MIGRATION()
            << "Unexpected event for filter " << event->filter;
      }
    }
  
    return did_work;
  }
  
  void MessagePumpKqueue::MaybeUpdateWakeupTimer(
      const base::TimeTicks& wakeup_time,
      base::TimeDelta leeway) {
    if (wakeup_time == scheduled_wakeup_time_) {
      // No change in the timer setting necessary.
      return;
    }

Activity

$ /bin/bash -lc "rg -n 'THREAD_RESTART|ipc_mqueue_changed|wait_queue_link|wait_queue_unlink|filt_machport|KQ_EVENT' xnu-2422/osfmk/ipc/ipc_mqueue.c xnu-2422/bsd/kern/kern_event.c xnu-2422/osfmk/kern/wait_queue.c; sed -n '2100,2280p' xnu-2422/bsd/kern/kern_event.c; sed -n '2380,2500p' xnu-2422/bsd/kern/kern_event.c"
status: Completed · exit 0
  xnu-2422/osfmk/kern/wait_queue.c:91:static zone_t _wait_queue_link_zone;
  xnu-2422/osfmk/kern/wait_queue.c:208:	_wait_queue_link_zone = zinit(sizeof(struct _wait_queue_link),
  xnu-2422/osfmk/kern/wait_queue.c:209:				      WAIT_QUEUE_LINK_MAX * sizeof(struct _wait_queue_link),
  xnu-2422/osfmk/kern/wait_queue.c:210:				      sizeof(struct _wait_queue_link),
  xnu-2422/osfmk/kern/wait_queue.c:212:	zone_change(_wait_queue_link_zone, Z_NOENCRYPT, TRUE);
  xnu-2422/osfmk/kern/wait_queue.c:330:	wait_queue_link_t wql;
  xnu-2422/osfmk/kern/wait_queue.c:341:		queue_remove_first(q, wql, wait_queue_link_t, wql_preposts);
  xnu-2422/osfmk/kern/wait_queue.c:404: *     Routine:        wait_queue_link_size
  xnu-2422/osfmk/kern/wait_queue.c:409:unsigned int wait_queue_link_size(void) { return sizeof(WaitQueueLink); }
  xnu-2422/osfmk/kern/wait_queue.c:412:static unsigned int _wait_queue_link;
  xnu-2422/osfmk/kern/wait_queue.c:413:static unsigned int _wait_queue_link_noalloc;
  xnu-2422/osfmk/kern/wait_queue.c:414:static unsigned int _wait_queue_unlinked;
  xnu-2422/osfmk/kern/wait_queue.c:416:#define WAIT_QUEUE_LINK ((void *)&_wait_queue_link)
  xnu-2422/osfmk/kern/wait_queue.c:417:#define WAIT_QUEUE_LINK_NOALLOC ((void *)&_wait_queue_link_noalloc)
  xnu-2422/osfmk/kern/wait_queue.c:418:#define WAIT_QUEUE_UNLINKED ((void *)&_wait_queue_unlinked)
  xnu-2422/osfmk/kern/wait_queue.c:426:#define WQSPREV(wqs, wql) ((wait_queue_link_t)queue_prev( \
  xnu-2422/osfmk/kern/wait_queue.c:430:#define WQSNEXT(wqs, wql) ((wait_queue_link_t)queue_next( \
  xnu-2422/osfmk/kern/wait_queue.c:461:	wait_queue_link_t wql2 = (wait_queue_link_t) queue_first(q2); \
  xnu-2422/osfmk/kern/wait_queue.c:464:		wql2 = (wait_queue_link_t) wql2->wql_setlinks.next; \
  xnu-2422/osfmk/kern/wait_queue.c:519:			wait_queue_link_t wql = (wait_queue_link_t)wq_element;
  xnu-2422/osfmk/kern/wait_queue.c:560: *	Routine:	wait_queue_link_internal
  xnu-2422/osfmk/kern/wait_queue.c:563: *		requires us to link the two together using a wait_queue_link
  xnu-2422/osfmk/kern/wait_queue.c:567: *		The wait_queue_link structure must already be properly typed
  xnu-2422/osfmk/kern/wait_queue.c:571:wait_queue_link_internal(
  xnu-2422/osfmk/kern/wait_queue.c:574:	wait_queue_link_t wql)
  xnu-2422/osfmk/kern/wait_queue.c:596:		    ((wait_queue_link_t)wq_element)->wql_setqueue == wq_set) {
  xnu-2422/osfmk/kern/wait_queue.c:617:	queue_enter(&wq->wq_queue, wql, wait_queue_link_t, wql_links);
  xnu-2422/osfmk/kern/wait_queue.c:619:	queue_enter(&wq_set->wqs_setlinks, wql, wait_queue_link_t, wql_setlinks);
  xnu-2422/osfmk/kern/wait_queue.c:629: *	Routine:	wait_queue_link_noalloc
  xnu-2422/osfmk/kern/wait_queue.c:632: *		requires us to link the two together using a wait_queue_link
  xnu-2422/osfmk/kern/wait_queue.c:638:wait_queue_link_noalloc(
  xnu-2422/osfmk/kern/wait_queue.c:641:	wait_queue_link_t wql)
  xnu-2422/osfmk/kern/wait_queue.c:644:	return wait_queue_link_internal(wq, wq_set, wql);
  xnu-2422/osfmk/kern/wait_queue.c:648: *	Routine:	wait_queue_link
  xnu-2422/osfmk/kern/wait_queue.c:651: *		requires us to link the two together using a wait_queue_link
  xnu-2422/osfmk/kern/wait_queue.c:657:wait_queue_link(
  xnu-2422/osfmk/kern/wait_queue.c:661:	wait_queue_link_t wql;
  xnu-2422/osfmk/kern/wait_queue.c:664:	wql = (wait_queue_link_t) zalloc(_wait_queue_link_zone);
  xnu-2422/osfmk/kern/wait_queue.c:669:	ret = wait_queue_link_internal(wq, wq_set, wql);
  xnu-2422/osfmk/kern/wait_queue.c:671:		zfree(_wait_queue_link_zone, wql);
  xnu-2422/osfmk/kern/wait_queue.c:676:wait_queue_link_t
  xnu-2422/osfmk/kern/wait_queue.c:677:wait_queue_link_allocate(void)
  xnu-2422/osfmk/kern/wait_queue.c:679:	wait_queue_link_t wql;
  xnu-2422/osfmk/kern/wait_queue.c:681:	wql = zalloc(_wait_queue_link_zone); /* Can't fail */
  xnu-2422/osfmk/kern/wait_queue.c:689:wait_queue_link_free(wait_queue_link_t wql)
  xnu-2422/osfmk/kern/wait_queue.c:691:	zfree(_wait_queue_link_zone, wql);
  xnu-2422/osfmk/kern/wait_queue.c:697: *	Routine:	wait_queue_unlink_locked
  xnu-2422/osfmk/kern/wait_queue.c:702:wait_queue_unlink_locked(
  xnu-2422/osfmk/kern/wait_queue.c:705:	wait_queue_link_t wql)
  xnu-2422/osfmk/kern/wait_queue.c:711:	queue_remove(&wq->wq_queue, wql, wait_queue_link_t, wql_links);
  xnu-2422/osfmk/kern/wait_queue.c:713:	queue_remove(&wq_set->wqs_setlinks, wql, wait_queue_link_t, wql_setlinks);
  xnu-2422/osfmk/kern/wait_queue.c:716:		queue_remove(ppq, wql, wait_queue_link_t, wql_preposts);
  xnu-2422/osfmk/kern/wait_queue.c:725: *	Routine:	wait_queue_unlink_nofree
  xnu-2422/osfmk/kern/wait_queue.c:734:wait_queue_unlink_nofree(
  xnu-2422/osfmk/kern/wait_queue.c:737:	wait_queue_link_t *wqlp)
  xnu-2422/osfmk/kern/wait_queue.c:740:	wait_queue_link_t wql;
  xnu-2422/osfmk/kern/wait_queue.c:757:		   	wql = (wait_queue_link_t)wq_element;
  xnu-2422/osfmk/kern/wait_queue.c:762:				wait_queue_unlink_locked(wq, wq_set, wql);
  xnu-2422/osfmk/kern/wait_queue.c:779: *	Routine:	wait_queue_unlink
  xnu-2422/osfmk/kern/wait_queue.c:787:wait_queue_unlink(
  xnu-2422/osfmk/kern/wait_queue.c:792:	wait_queue_link_t wql;
  xnu-2422/osfmk/kern/wait_queue.c:809:		   	wql = (wait_queue_link_t)wq_element;
  xnu-2422/osfmk/kern/wait_queue.c:816:				wait_queue_unlink_locked(wq, wq_set, wql);
  xnu-2422/osfmk/kern/wait_queue.c:821:					zfree(_wait_queue_link_zone, wql);
  xnu-2422/osfmk/kern/wait_queue.c:834: *	Routine:	wait_queue_unlink_all_nofree_locked
  xnu-2422/osfmk/kern/wait_queue.c:844:wait_queue_unlink_all_nofree_locked(
  xnu-2422/osfmk/kern/wait_queue.c:851:	wait_queue_link_t wql;
  xnu-2422/osfmk/kern/wait_queue.c:865:			wql = (wait_queue_link_t)wq_element;
  xnu-2422/osfmk/kern/wait_queue.c:868:			wait_queue_unlink_locked(wq, wq_set, wql);
  xnu-2422/osfmk/kern/wait_queue.c:877: *	Routine:	wait_queue_unlink_all_nofree
  xnu-2422/osfmk/kern/wait_queue.c:887:wait_queue_unlink_all_nofree(
  xnu-2422/osfmk/kern/wait_queue.c:899:	wait_queue_unlink_all_nofree_locked(wq, links);
  xnu-2422/osfmk/kern/wait_queue.c:907: *	Routine:	wait_queue_unlink_all_locked
  xnu-2422/osfmk/kern/wait_queue.c:916:wait_queue_unlink_all_locked(
  xnu-2422/osfmk/kern/wait_queue.c:923:	wait_queue_link_t wql;
  xnu-2422/osfmk/kern/wait_queue.c:938:			wql = (wait_queue_link_t)wq_element;
  xnu-2422/osfmk/kern/wait_queue.c:941:			wait_queue_unlink_locked(wq, wq_set, wql);
  xnu-2422/osfmk/kern/wait_queue.c:953: *	Routine:	wait_queue_unlink_all
  xnu-2422/osfmk/kern/wait_queue.c:963:wait_queue_unlink_all(
  xnu-2422/osfmk/kern/wait_queue.c:966:	wait_queue_link_t wql;
  xnu-2422/osfmk/kern/wait_queue.c:979:	wait_queue_unlink_all_locked(wq, links);
  xnu-2422/osfmk/kern/wait_queue.c:984:		wql = (wait_queue_link_t) dequeue(links);
  xnu-2422/osfmk/kern/wait_queue.c:985:		zfree(_wait_queue_link_zone, wql);
  xnu-2422/osfmk/kern/wait_queue.c:1015:	wait_queue_link_t wql;
  xnu-2422/osfmk/kern/wait_queue.c:1031:	wql = (wait_queue_link_t)queue_first(q);
  xnu-2422/osfmk/kern/wait_queue.c:1036:			wait_queue_unlink_locked(wq, wq_set, wql);
  xnu-2422/osfmk/kern/wait_queue.c:1039:			wql = (wait_queue_link_t)queue_first(q);
  xnu-2422/osfmk/kern/wait_queue.c:1049:	wait_queue_unlink_all_nofree_locked(&wq_set->wqs_wait_queue, links);
  xnu-2422/osfmk/kern/wait_queue.c:1071:	wait_queue_link_t wql;
  xnu-2422/osfmk/kern/wait_queue.c:1091:	wql = (wait_queue_link_t)queue_first(q);
  xnu-2422/osfmk/kern/wait_queue.c:1099:			wait_queue_unlink_locked(wq, wq_set, wql);
  xnu-2422/osfmk/kern/wait_queue.c:1103:			wql = (wait_queue_link_t)queue_first(q);
  xnu-2422/osfmk/kern/wait_queue.c:1114:	wait_queue_unlink_all_locked(&wq_set->wqs_wait_queue, links);
  xnu-2422/osfmk/kern/wait_queue.c:1120:		wql = (wait_queue_link_t) dequeue(links);
  xnu-2422/osfmk/kern/wait_queue.c:1121:		zfree(_wait_queue_link_zone, wql);
  xnu-2422/osfmk/kern/wait_queue.c:1129:	wait_queue_link_t wql)
  xnu-2422/osfmk/kern/wait_queue.c:1152:		wait_queue_unlink_locked(wq, wq_set, wql);
  xnu-2422/osfmk/kern/wait_queue.c:1267:		return (thread->wait_result = THREAD_RESTART);
  xnu-2422/osfmk/kern/wait_queue.c:1308:		return (thread->wait_result = THREAD_RESTART);
  xnu-2422/osfmk/kern/wait_queue.c:1344:		return (thread->wait_result = THREAD_RESTART);
  xnu-2422/osfmk/kern/wait_queue.c:1383:		return (thread->wait_result = THREAD_RESTART);
  xnu-2422/osfmk/kern/wait_queue.c:1443:			wait_queue_link_t wql = (wait_queue_link_t)wq_element;
  xnu-2422/osfmk/kern/wait_queue.c:1454:				queue_enter(ppq, wql, wait_queue_link_t, wql_preposts);
  xnu-2422/osfmk/kern/wait_queue.c:1669:			wait_queue_link_t wql = (wait_queue_link_t)wq_element;
  xnu-2422/osfmk/kern/wait_queue.c:1691:				queue_enter(ppq, wql, wait_queue_link_t, wql_preposts);
  xnu-2422/osfmk/kern/wait_queue.c:1834:			wait_queue_link_t wql = (wait_queue_link_t)wq_element;
  xnu-2422/bsd/kern/kern_event.c:108:#define	KQ_EVENT	NULL
  xnu-2422/bsd/kern/kern_event.c:1258:	wait_queue_unlink_all((wait_queue_t)kq->kq_wqs);
  xnu-2422/bsd/kern/kern_event.c:2142:			    KQ_EVENT, THREAD_ABORTSAFE, cont_args->deadline);
  xnu-2422/bsd/kern/kern_event.c:2247:		    KQ_EVENT, THREAD_ABORTSAFE, TIMEOUT_URGENCY_USER_NORMAL,
  xnu-2422/bsd/kern/kern_event.c:2335:		wait_queue_link_noalloc((wait_queue_t)kq->kq_wqs, ut->uu_wqset,
  xnu-2422/bsd/kern/kern_event.c:2336:		    (wait_queue_link_t)wql);
  xnu-2422/bsd/kern/kern_event.c:2509:		wait_queue_wakeup_all((wait_queue_t)kq->kq_wqs, KQ_EVENT,
  xnu-2422/bsd/kern/kern_event.c:2591:knote_link_wait_queue(struct knote *kn, struct wait_queue *wq, wait_queue_link_t wql)
  xnu-2422/bsd/kern/kern_event.c:2596:	kr = wait_queue_link_noalloc(wq, kq->kq_wqs, wql);
  xnu-2422/bsd/kern/kern_event.c:2615:knote_unlink_wait_queue(struct knote *kn, struct wait_queue *wq, wait_queue_link_t *wqlp)
  xnu-2422/bsd/kern/kern_event.c:2620:	kr = wait_queue_unlink_nofree(wq, kq->kq_wqs, wqlp);
  xnu-2422/osfmk/ipc/ipc_mqueue.c:164:	wait_queue_link_t *wqlp)
  xnu-2422/osfmk/ipc/ipc_mqueue.c:169:	return wait_queue_unlink_nofree(mq_waitq, set_waitq, wqlp);
  xnu-2422/osfmk/ipc/ipc_mqueue.c:186:	wait_queue_unlink_all_nofree(mq_waitq, links);
  xnu-2422/osfmk/ipc/ipc_mqueue.c:224:	wait_queue_link_t wql)
  xnu-2422/osfmk/ipc/ipc_mqueue.c:233:	kr = wait_queue_link_noalloc(port_waitq, set_waitq, wql);
  xnu-2422/osfmk/ipc/ipc_mqueue.c:323: *	Routine:	ipc_mqueue_changed
  xnu-2422/osfmk/ipc/ipc_mqueue.c:331:ipc_mqueue_changed(
  xnu-2422/osfmk/ipc/ipc_mqueue.c:337:				THREAD_RESTART,
  xnu-2422/osfmk/ipc/ipc_mqueue.c:438:		case THREAD_RESTART:
  xnu-2422/osfmk/ipc/ipc_mqueue.c:610:	case THREAD_RESTART:
  xnu-2422/osfmk/ipc/ipc_mqueue.c:752:			wait_queue_link_t wql;
  xnu-2422/osfmk/ipc/ipc_mqueue.c:755:			queue_remove_first(q, wql, wait_queue_link_t, wql_preposts);
  xnu-2422/osfmk/ipc/ipc_mqueue.c:768:				queue_enter(q, wql, wait_queue_link_t, wql_preposts);
  xnu-2422/osfmk/ipc/ipc_mqueue.c:792:			queue_enter(q, wql, wait_queue_link_t, wql_preposts);
  xnu-2422/osfmk/ipc/ipc_mqueue.c:1035:	wait_queue_link_t	wql;
  xnu-2422/osfmk/ipc/ipc_mqueue.c:1054:	queue_iterate(q, wql, wait_queue_link_t, wql_preposts) {
  xnu-2422/osfmk/ipc/ipc_mqueue.c:1087:	wait_queue_link_t	wql;
  xnu-2422/osfmk/ipc/ipc_mqueue.c:1102:	queue_iterate(q, wql, wait_queue_link_t, wql_setlinks) {
  xnu-2422/osfmk/ipc/ipc_mqueue.c:1144:				THREAD_RESTART,
  			error = 0;
  		else
  			nevents++;
  	}
  
  	/*
  	 * With the kqueue still locked, move any knotes
  	 * remaining on the inprocess queue back to the
  	 * kq's queue and wake up any waiters.
  	 */
  	while ((kn = TAILQ_FIRST(&inprocess)) != NULL) {
  		assert(kn->kn_tq == &inprocess);
  		TAILQ_REMOVE(&inprocess, kn, kn_tqe);
  		kn->kn_tq = &kq->kq_head;
  		TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe);
  	}
  
  	kqueue_end_processing(kq);
  
  	*countp = nevents;
  	return (error);
  }
  
  
  static void
  kqueue_scan_continue(void *data, wait_result_t wait_result)
  {
  	thread_t self = current_thread();
  	uthread_t ut = (uthread_t)get_bsdthread_info(self);
  	struct _kqueue_scan * cont_args = &ut->uu_kevent.ss_kqueue_scan;
  	struct kqueue *kq = (struct kqueue *)data;
  	int error;
  	int count;
  
  	/* convert the (previous) wait_result to a proper error */
  	switch (wait_result) {
  	case THREAD_AWAKENED:
  		kqlock(kq);
  		error = kqueue_process(kq, cont_args->call, cont_args, &count,
  		    current_proc());
  		if (error == 0 && count == 0) {
  			wait_queue_assert_wait((wait_queue_t)kq->kq_wqs,
  			    KQ_EVENT, THREAD_ABORTSAFE, cont_args->deadline);
  			kq->kq_state |= KQ_SLEEP;
  			kqunlock(kq);
  			thread_block_parameter(kqueue_scan_continue, kq);
  			/* NOTREACHED */
  		}
  		kqunlock(kq);
  		break;
  	case THREAD_TIMED_OUT:
  		error = EWOULDBLOCK;
  		break;
  	case THREAD_INTERRUPTED:
  		error = EINTR;
  		break;
  	default:
  		panic("%s: - invalid wait_result (%d)", __func__,
  		    wait_result);
  		error = 0;
  	}
  
  	/* call the continuation with the results */
  	assert(cont_args->cont != NULL);
  	(cont_args->cont)(kq, cont_args->data, error);
  }
  
  
  /*
   * kqueue_scan - scan and wait for events in a kqueue
   *
   *	Process the triggered events in a kqueue.
   *
   *	If there are no events triggered arrange to
   *	wait for them. If the caller provided a
   *	continuation routine, then kevent_scan will
   *	also.
   *
   *	The callback routine must be valid.
   *	The caller must hold a use-count reference on the kq.
   */
  
  int
  kqueue_scan(struct kqueue *kq,
  	    kevent_callback_t callback,
  	    kqueue_continue_t continuation,
  	    void *data,
  	    struct timeval *atvp,
  	    struct proc *p)
  {
  	thread_continue_t cont = THREAD_CONTINUE_NULL;
  	uint64_t deadline;
  	int error;
  	int first;
  
  	assert(callback != NULL);
  
  	first = 1;
  	for (;;) {
  		wait_result_t wait_result;
  		int count;
  
  		/*
  		 * Make a pass through the kq to find events already
  		 * triggered.
  		 */
  		kqlock(kq);
  		error = kqueue_process(kq, callback, data, &count, p);
  		if (error || count)
  			break; /* lock still held */
  
  		/* looks like we have to consider blocking */
  		if (first) {
  			first = 0;
  			/* convert the timeout to a deadline once */
  			if (atvp->tv_sec || atvp->tv_usec) {
  				uint64_t now;
  
  				clock_get_uptime(&now);
  				nanoseconds_to_absolutetime((uint64_t)atvp->tv_sec * NSEC_PER_SEC +
  							    atvp->tv_usec * (long)NSEC_PER_USEC,
  							    &deadline);
  				if (now >= deadline) {
  					/* non-blocking call */
  					error = EWOULDBLOCK;
  					break; /* lock still held */
  				}
  				deadline -= now;
  				clock_absolutetime_interval_to_deadline(deadline, &deadline);
  			} else {
  				deadline = 0; 	/* block forever */
  			}
  
  			if (continuation) {
  				uthread_t ut = (uthread_t)get_bsdthread_info(current_thread());
  				struct _kqueue_scan *cont_args = &ut->uu_kevent.ss_kqueue_scan;
  
  				cont_args->call = callback;
  				cont_args->cont = continuation;
  				cont_args->deadline = deadline;
  				cont_args->data = data;
  				cont = kqueue_scan_continue;
  			}
  		}
  
  		/* go ahead and wait */
  		wait_queue_assert_wait_with_leeway((wait_queue_t)kq->kq_wqs,
  		    KQ_EVENT, THREAD_ABORTSAFE, TIMEOUT_URGENCY_USER_NORMAL,
  		    deadline, 0);
  		kq->kq_state |= KQ_SLEEP;
  		kqunlock(kq);
  		wait_result = thread_block_parameter(cont, kq);
  		/* NOTREACHED if (continuation != NULL) */
  
  		switch (wait_result) {
  		case THREAD_AWAKENED:
  			continue;
  		case THREAD_TIMED_OUT:
  			return (EWOULDBLOCK);
  		case THREAD_INTERRUPTED:
  			return (EINTR);
  		default:
  			panic("%s: - bad wait_result (%d)", __func__,
  			    wait_result);
  			error = 0;
  		}
  	}
  	kqunlock(kq);
  	return (error);
  }
  
  
  /*
   * XXX
   * This could be expanded to call kqueue_scan, if desired.
   */
  /*ARGSUSED*/
  static int
  kqueue_read(__unused struct fileproc *fp,
      __unused struct uio *uio,
      __unused int flags,
  		TAILQ_REMOVE(&inprocessq, kn, kn_tqe);
  		kn->kn_tq = &kq->kq_head;
  		TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe);
  	}
  
  	kqueue_end_processing(kq);
  	kqunlock(kq);
  	return (retnum);
  }
  
  /*
   * kqueue_close -
   */
  /*ARGSUSED*/
  static int
  kqueue_close(struct fileglob *fg, __unused vfs_context_t ctx)
  {
  	struct kqueue *kq = (struct kqueue *)fg->fg_data;
  
  	kqueue_dealloc(kq);
  	fg->fg_data = NULL;
  	return (0);
  }
  
  /*ARGSUSED*/
  /*
   * The callers has taken a use-count reference on this kqueue and will donate it
   * to the kqueue we are being added to.  This keeps the kqueue from closing until
   * that relationship is torn down.
   */
  static int
  kqueue_kqfilter(__unused struct fileproc *fp, struct knote *kn, __unused vfs_context_t ctx)
  {
  	struct kqueue *kq = (struct kqueue *)kn->kn_fp->f_data;
  	struct kqueue *parentkq = kn->kn_kq;
  
  	if (parentkq == kq ||
  	    kn->kn_filter != EVFILT_READ)
  		return (1);
  
  	/*
  	 * We have to avoid creating a cycle when nesting kqueues
  	 * inside another.  Rather than trying to walk the whole
  	 * potential DAG of nested kqueues, we just use a simple
  	 * ceiling protocol.  When a kqueue is inserted into another,
  	 * we check that the (future) parent is not already nested
  	 * into another kqueue at a lower level than the potenial
  	 * child (because it could indicate a cycle).  If that test
  	 * passes, we just mark the nesting levels accordingly.
  	 */
  
  	kqlock(parentkq);
  	if (parentkq->kq_level > 0 &&
  	    parentkq->kq_level < kq->kq_level)
  	{
  		kqunlock(parentkq);
  		return (1);
  	} else {
  		/* set parent level appropriately */
  		if (parentkq->kq_level == 0)
  			parentkq->kq_level = 2;
  		if (parentkq->kq_level < kq->kq_level + 1)
  			parentkq->kq_level = kq->kq_level + 1;
  		kqunlock(parentkq);
  
  		kn->kn_fop = &kqread_filtops;
  		kqlock(kq);
  		KNOTE_ATTACH(&kq->kq_sel.si_note, kn);
  		/* indicate nesting in child, if needed */
  		if (kq->kq_level == 0)
  			kq->kq_level = 1;
  		kqunlock(kq);
  		return (0);
  	}
  }
  
  /*
   * kqueue_drain - called when kq is closed
   */
  /*ARGSUSED*/
  static int
  kqueue_drain(struct fileproc *fp, __unused vfs_context_t ctx)
  {
  	struct kqueue *kq = (struct kqueue *)fp->f_fglob->fg_data;
  	kqlock(kq);
  	kqueue_wakeup(kq, 1);
  	kqunlock(kq);
  	return (0);
  }
  
  /*ARGSUSED*/
  int
  kqueue_stat(struct fileproc *fp, void *ub, int isstat64,  __unused vfs_context_t ctx)
  {
  
  	struct kqueue *kq = (struct kqueue *)fp->f_data;
  	if (isstat64 != 0) {
  		struct stat64 *sb64 = (struct stat64 *)ub;
  
  		bzero((void *)sb64, sizeof(*sb64));
  		sb64->st_size = kq->kq_count;
  		if (kq->kq_state & KQ_KEV64)
  			sb64->st_blksize = sizeof(struct kevent64_s);
  		else
  			sb64->st_blksize = sizeof(struct kevent);
  		sb64->st_mode = S_IFIFO;
  	} else {
  		struct stat *sb = (struct stat *)ub;
  
  		bzero((void *)sb, sizeof(*sb));
  		sb->st_size = kq->kq_count;
  		if (kq->kq_state & KQ_KEV64)
  			sb->st_blksize = sizeof(struct kevent64_s);
  		else
  			sb->st_blksize = sizeof(struct kevent);
  		sb->st_mode = S_IFIFO;
  	}
  
  	return (0);
  }

Activity

$ /bin/bash -lc "python3 - <<'PY'import json,res=open('investigation/conversation.txt').read()for u in dict.fromkeys(re.findall(r'https://(?:user-images\\.githubusercontent\\.com|github\\.com/blueboxd/chromium-legacy/files)/["'^'"\\s)]+',s)):print(u)PY"
status: Completed · exit 0
  https://github.com/blueboxd/chromium-legacy/files/7850488/Kernel_2022-01-11-182654_Jonathans-MacBook-Air.panic.zip
  https://user-images.githubusercontent.com/4484096/150240439-c4f04d57-5fe9-4f1f-825e-4971a7d36916.png
  https://github.com/blueboxd/chromium-legacy/files/7918453/XNU-2422.115.4-THREAD_RESTART.add-JA-v2022.01.22.zip
  https://github.com/blueboxd/chromium-legacy/files/8110654/XNU-2422.115.4-THREAD_RESTART.add-JA-v2022.02.21.zip
  https://user-images.githubusercontent.com/4484096/155889371-28b99fcc-d714-43b5-a202-abcc5a5ad50b.png
  https://github.com/blueboxd/chromium-legacy/files/8246273/Chromium.Helper_2022-03-14-112231_Jonathans-Mac-Pro.crash.zip
  https://github.com/blueboxd/chromium-legacy/files/8839101/kqueue_scan_continue-patch.kext.zip
  https://github.com/blueboxd/chromium-legacy/files/8840948/kqueue_scan_continue-tune-2022.06.05.zip
  https://user-images.githubusercontent.com/4484096/190880693-b76a54ee-c443-4dfd-97ea-3134684a044a.png
  https://github.com/blueboxd/chromium-legacy/files/10418691/Kernel_2023-01-14-184339_Hoangs-MacBook-Pro.panic.log

Activity

$ /bin/bash -lc "python3 - <<'PY'import urllib.request,concurrent.futuresurls={'continuation.png':'https://user-images.githubusercontent.com/4484096/150240439-c4f04d57-5fe9-4f1f-825e-4971a7d36916.png','instruments.png':'https://user-images.githubusercontent.com/4484096/155889371-28b99fcc-d714-43b5-a202-abcc5a5ad50b.png','permission.png':'https://user-images.githubusercontent.com/4484096/190880693-b76a54ee-c443-4dfd-97ea-3134684a044a.png','helper-crash.zip':'https://github.com/blueboxd/chromium-legacy/files/8246273/Chromium.Helper_2022-03-14-112231_Jonathans-Mac-Pro.crash.zip','original-panic.zip':'https://github.com/blueboxd/chromium-legacy/files/7850488/Kernel_2022-01-11-182654_Jonathans-MacBook-Air.panic.zip','2023-panic.log':'https://github.com/blueboxd/chromium-legacy/files/10418691/Kernel_2023-01-14-184339_Hoangs-MacBook-Pro.panic.log'}def get(kv): n,u=kv try: urllib.request.urlretrieve(u,'investigation/'+n);return n+' OK' except Exception as e:return n+' '+str(e)with concurrent.futures.ThreadPoolExecutor() as e: for r in e.map(get,urls.items()):print(r)PY"
status: Completed · exit 0
  continuation.png <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1007)>
  instruments.png <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1007)>
  permission.png <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1007)>
  helper-crash.zip <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1007)>
  original-panic.zip <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1007)>
  2023-panic.log <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1007)>

Activity

$ /bin/bash -lc "rg -n 'filt_machport|knote_link_wait_queue|ipc_mqueue_changed|ipc_mqueue_destroy' xnu-2422/osfmk/ipc; sed -n '315,350p' xnu-2422/osfmk/ipc/ipc_mqueue.c; sed -n '1120,1165p' xnu-2422/osfmk/ipc/ipc_mqueue.c; sed -n '1400,1535p' xnu-2422/osfmk/kern/wait_queue.c; sed -n '2488,2525p' xnu-2422/bsd/kern/kern_event.c"
status: Completed · exit 0
  xnu-2422/osfmk/ipc/ipc_mqueue.c:323: *	Routine:	ipc_mqueue_changed
  xnu-2422/osfmk/ipc/ipc_mqueue.c:331:ipc_mqueue_changed(
  xnu-2422/osfmk/ipc/ipc_mqueue.c:1117: *	Routine:	ipc_mqueue_destroy
  xnu-2422/osfmk/ipc/ipc_mqueue.c:1127:ipc_mqueue_destroy(
  xnu-2422/osfmk/ipc/ipc_port.c:571:	ipc_mqueue_changed(&port->ip_messages);
  xnu-2422/osfmk/ipc/ipc_port.c:968:	ipc_mqueue_destroy(mqueue);
  xnu-2422/osfmk/ipc/ipc_mqueue.h:145:extern void ipc_mqueue_destroy(
  xnu-2422/osfmk/ipc/ipc_mqueue.h:149:extern void ipc_mqueue_changed(
  xnu-2422/osfmk/ipc/ipc_pset.c:302:	ipc_mqueue_changed(&pset->ips_messages);
  xnu-2422/osfmk/ipc/ipc_pset.c:320:static int      filt_machportattach(struct knote *kn);
  xnu-2422/osfmk/ipc/ipc_pset.c:321:static void	filt_machportdetach(struct knote *kn);
  xnu-2422/osfmk/ipc/ipc_pset.c:322:static int	filt_machport(struct knote *kn, long hint);
  xnu-2422/osfmk/ipc/ipc_pset.c:323:static void     filt_machporttouch(struct knote *kn, struct kevent64_s *kev, long type);
  xnu-2422/osfmk/ipc/ipc_pset.c:324:static unsigned filt_machportpeek(struct knote *kn);
  xnu-2422/osfmk/ipc/ipc_pset.c:326:        .f_attach = filt_machportattach,
  xnu-2422/osfmk/ipc/ipc_pset.c:327:        .f_detach = filt_machportdetach,
  xnu-2422/osfmk/ipc/ipc_pset.c:328:        .f_event = filt_machport,
  xnu-2422/osfmk/ipc/ipc_pset.c:329:        .f_touch = filt_machporttouch,
  xnu-2422/osfmk/ipc/ipc_pset.c:330:	.f_peek = filt_machportpeek,
  xnu-2422/osfmk/ipc/ipc_pset.c:334:filt_machportattach(
  xnu-2422/osfmk/ipc/ipc_pset.c:358:	result = knote_link_wait_queue(kn, &pset->ips_messages.imq_wait_queue, wql);
  xnu-2422/osfmk/ipc/ipc_pset.c:373:filt_machportdetach(
  xnu-2422/osfmk/ipc/ipc_pset.c:393:filt_machport(
  xnu-2422/osfmk/ipc/ipc_pset.c:514:filt_machporttouch(struct knote *kn, struct kevent64_s *kev, long type)
  xnu-2422/osfmk/ipc/ipc_pset.c:531:                panic("filt_machporttouch() - invalid type (%ld)", type);
  xnu-2422/osfmk/ipc/ipc_pset.c:539: * on-queue mechanism (as the knote_link_wait_queue mechanism
  xnu-2422/osfmk/ipc/ipc_pset.c:554:filt_machportpeek(struct knote *kn)
  	}
   leave:
  	imq_unlock(port_mqueue);
  	splx(s);
  	return KERN_SUCCESS;
  }
  
  /*
   *	Routine:	ipc_mqueue_changed
   *	Purpose:
   *		Wake up receivers waiting in a message queue.
   *	Conditions:
   *		The message queue is locked.
   */
  
  void
  ipc_mqueue_changed(
  	ipc_mqueue_t		mqueue)
  {
  	wait_queue_wakeup64_all_locked(
  				&mqueue->imq_wait_queue,
  				IPC_MQUEUE_RECEIVE,
  				THREAD_RESTART,
  				FALSE);		/* unlock waitq? */
  }
  
  
  
  
  /*
   *	Routine:	ipc_mqueue_send
   *	Purpose:
   *		Send a message to a message queue.  The message holds a reference
   *		for the destination port for this message queue in the
   *		msgh_remote_port field.
   *
   *		Set any blocked senders running.
   *	   	Destroy the kmsgs in the queue.
   *	Conditions:
   *		Nothing locked.
   *		Receivers were removed when the receive right was "changed"
   */
  void
  ipc_mqueue_destroy(
  	ipc_mqueue_t	mqueue)
  {
  	ipc_kmsg_queue_t kmqueue;
  	ipc_kmsg_t kmsg;
  	boolean_t reap = FALSE;
  	spl_t s;
  
  	s = splsched();
  	imq_lock(mqueue);
  	/*
  	 *	rouse all blocked senders
  	 */
  	mqueue->imq_fullwaiters = FALSE;
  	wait_queue_wakeup64_all_locked(
  				&mqueue->imq_wait_queue,
  				IPC_MQUEUE_FULL,
  				THREAD_RESTART,
  				FALSE);
  
  	/*
  	 * Move messages from the specified queue to the per-thread
  	 * clean/drain queue while we have the mqueue lock.
  	 */
  	kmqueue = &mqueue->imq_messages;
  	while ((kmsg = ipc_kmsg_dequeue(kmqueue)) != IKM_NULL) {
  		boolean_t first;
  		first = ipc_kmsg_delayed_destroy(kmsg);
  		if (first)
  			reap = first;
  	}
  
  	imq_unlock(mqueue);
  	splx(s);
  
  	/*
  	 * Destroy the messages we enqueued if we aren't nested
  	 * inside some other attempt to drain the same queue.
  	 */
   *		Select all threads off a wait queue that meet the
   *		supplied criteria.
   *	Conditions:
   *		at splsched
   *		wait queue locked
   *		wake_queue initialized and ready for insertion
   *		possibly recursive
   *	Returns:
   *		a queue of locked threads
   */
  static void
  _wait_queue_select64_all(
  	wait_queue_t wq,
  	event64_t event,
  	queue_t wake_queue)
  {
  	wait_queue_element_t wq_element;
  	wait_queue_element_t wqe_next;
  	unsigned long eventmask = 0;
  	boolean_t is_queue_global = FALSE;
  	queue_t q;
  
  	is_queue_global = wait_queue_global(wq);
  	if (is_queue_global) {
  		eventmask = CAST_TO_EVENT_MASK(event);
  		if ((wq->wq_eventmask & eventmask) != eventmask) {
  			return;
  		}
  		eventmask = 0;
  	}
  	q = &wq->wq_queue;
  
  	wq_element = (wait_queue_element_t) queue_first(q);
  	while (!queue_end(q, (queue_entry_t)wq_element)) {
  		WAIT_QUEUE_ELEMENT_CHECK(wq, wq_element);
  		wqe_next = (wait_queue_element_t)
  			   queue_next((queue_t) wq_element);
  
  		/*
  		 * We may have to recurse if this is a compound wait queue.
  		 */
  		if (wq_element->wqe_type == WAIT_QUEUE_LINK ||
  		    wq_element->wqe_type == WAIT_QUEUE_LINK_NOALLOC) {
  			wait_queue_link_t wql = (wait_queue_link_t)wq_element;
  			wait_queue_set_t set_queue = wql->wql_setqueue;
  
  			/*
  			 * We have to check the set wait queue. If it is marked
  			 * as pre-post, and it is the "generic event" then mark
  			 * it pre-posted now (if not already).
  			 */
  			wqs_lock(set_queue);
  			if (event == NO_EVENT64 && set_queue->wqs_prepost && !wql_is_preposted(wql)) {
  				queue_t ppq = &set_queue->wqs_preposts;
  				queue_enter(ppq, wql, wait_queue_link_t, wql_preposts);
  			}
  			if (! wait_queue_empty(&set_queue->wqs_wait_queue))
  				_wait_queue_select64_all(&set_queue->wqs_wait_queue, event, wake_queue);
  			wqs_unlock(set_queue);
  		} else {
  
  			/*
  			 * Otherwise, its a thread.  If it is waiting on
  			 * the event we are posting to this queue, pull
  			 * it off the queue and stick it in out wake_queue.
  			 */
  			thread_t t = (thread_t)(void *)wq_element;
  
  			if (t->wait_event == event) {
  				thread_lock(t);
  				remqueue((queue_entry_t) t);
  				enqueue (wake_queue, (queue_entry_t) t);
  				t->wait_queue = WAIT_QUEUE_NULL;
  				t->wait_event = NO_EVENT64;
  				t->at_safe_point = FALSE;
  				/* returned locked */
  			} else {
  				if (is_queue_global) {
  					eventmask = eventmask |
  						CAST_TO_EVENT_MASK(t->wait_event);
  				}
  			}
  		}
  		wq_element = wqe_next;
  	}
  	/* Update event mask if global wait queue */
  	if (is_queue_global) {
  		wq->wq_eventmask = eventmask;
  	}
  
  }
  
  /*
   *	Routine:        wait_queue_wakeup64_all_locked
   *	Purpose:
   *		Wakeup some number of threads that are in the specified
   *		wait queue and waiting on the specified event.
   *	Conditions:
   *		wait queue already locked (may be released).
   *	Returns:
   *		KERN_SUCCESS - Threads were woken up
   *		KERN_NOT_WAITING - No threads were waiting <wq,event> pair
   */
  __private_extern__ kern_return_t
  wait_queue_wakeup64_all_locked(
  	wait_queue_t wq,
  	event64_t event,
  	wait_result_t result,
  	boolean_t unlock)
  {
  	queue_head_t wake_queue_head;
  	queue_t q = &wake_queue_head;
  	kern_return_t res;
  
  //	assert(wait_queue_held(wq));
  //	if(!wq->wq_interlock.lock_data) {		/* (BRINGUP */
  //		panic("wait_queue_wakeup64_all_locked: lock not held on %p\n", wq);	/* (BRINGUP) */
  //	}
  
  	queue_init(q);
  
  	/*
  	 * Select the threads that we will wake up.	 The threads
  	 * are returned to us locked and cleanly removed from the
  	 * wait queue.
  	 */
  	_wait_queue_select64_all(wq, event, q);
  	if (unlock)
  		wait_queue_unlock(wq);
  
  	/*
  	 * For each thread, set it running.
  	 */
  	res = KERN_NOT_WAITING;
  	while (!queue_empty (q)) {
  		thread_t thread = (thread_t)(void *) dequeue(q);
  
  		bzero((void *)sb, sizeof(*sb));
  		sb->st_size = kq->kq_count;
  		if (kq->kq_state & KQ_KEV64)
  			sb->st_blksize = sizeof(struct kevent64_s);
  		else
  			sb->st_blksize = sizeof(struct kevent);
  		sb->st_mode = S_IFIFO;
  	}
  
  	return (0);
  }
  
  /*
   * Called with the kqueue locked
   */
  static void
  kqueue_wakeup(struct kqueue *kq, int closed)
  {
  	if ((kq->kq_state & (KQ_SLEEP | KQ_SEL)) != 0 || kq->kq_nprocess > 0) {
  		kq->kq_state &= ~(KQ_SLEEP | KQ_SEL);
  		wait_queue_wakeup_all((wait_queue_t)kq->kq_wqs, KQ_EVENT,
  		    (closed) ? THREAD_INTERRUPTED : THREAD_AWAKENED);
  	}
  }
  
  void
  klist_init(struct klist *list)
  {
  	SLIST_INIT(list);
  }
  
  
  /*
   * Query/Post each knote in the object's list
   *
   *	The object lock protects the list. It is assumed
   *	that the filter/event routine for the object can

Activity

$ /bin/bash -lc "sed -n '495,590p' xnu-2422/osfmk/ipc/ipc_port.c; sed -n '255,420p' xnu-2422/osfmk/ipc/ipc_pset.c; sed -n '120,320p' xnu-2422/osfmk/ipc/ipc_mqueue.c; sed -n '1520,1560p' xnu-2422/osfmk/kern/wait_queue.c; rg -n 'IPC_MQUEUE_RECEIVE|IPC_MQUEUE_FULL' xnu-2422/osfmk/ipc/ipc_mqueue.h; rg -n 'ipc_port_clear_receiver' xnu-2422/osfmk/ipc"
status: Completed · exit 0
  
  	*previousp = previous;
  }
  
  /*
   *	Routine:	ipc_port_nsrequest
   *	Purpose:
   *		Make a no-senders request, returning the
   *		previously registered send-once right.
   *		Just cancels the previous request if notify is IP_NULL.
   *	Conditions:
   *		The port is locked and active.  It is unlocked.
   *		Consumes a ref for notify (if non-null), and
   *		returns previous with a ref (if non-null).
   */
  
  void
  ipc_port_nsrequest(
  	ipc_port_t		port,
  	mach_port_mscount_t	sync,
  	ipc_port_t		notify,
  	ipc_port_t		*previousp)
  {
  	ipc_port_t previous;
  	mach_port_mscount_t mscount;
  
  	assert(ip_active(port));
  
  	previous = port->ip_nsrequest;
  	mscount = port->ip_mscount;
  
  	if ((port->ip_srights == 0) && (sync <= mscount) &&
  	    (notify != IP_NULL)) {
  		port->ip_nsrequest = IP_NULL;
  		ip_unlock(port);
  		ipc_notify_no_senders(notify, mscount);
  	} else {
  		port->ip_nsrequest = notify;
  		ip_unlock(port);
  	}
  
  	*previousp = previous;
  }
  
  
  /*
   *	Routine:	ipc_port_clear_receiver
   *	Purpose:
   *		Prepares a receive right for transmission/destruction.
   *	Conditions:
   *		The port is locked and active.
   */
  
  void
  ipc_port_clear_receiver(
  	ipc_port_t	port,
  	queue_t		links)
  {
  	spl_t		s;
  
  	assert(ip_active(port));
  
  	/*
  	 * pull ourselves from any sets.
  	 */
  	if (port->ip_pset_count != 0) {
  		ipc_pset_remove_from_all(port, links);
  		assert(port->ip_pset_count == 0);
  	}
  
  	/*
  	 * Send anyone waiting on the port's queue directly away.
  	 * Also clear the mscount and seqno.
  	 */
  	s = splsched();
  	imq_lock(&port->ip_messages);
  	ipc_mqueue_changed(&port->ip_messages);
  	ipc_port_set_mscount(port, 0);
  	port->ip_messages.imq_seqno = 0;
  	port->ip_context = port->ip_guarded = port->ip_strict_guard = 0;
  	imq_unlock(&port->ip_messages);
  	splx(s);
  }
  
  /*
   *	Routine:	ipc_port_init
   *	Purpose:
   *		Initializes a newly-allocated port.
   *		Doesn't touch the ip_object fields.
   */
  
  void
  ipc_port_init(
  	ipc_port_t		port,
  	ipc_space_t		space,
  	mach_port_name_t	name)
  		return KERN_NOT_IN_SET;
  
  	/*
  	 * Remove the port's mqueue from all sets
  	 */
  	ipc_mqueue_remove_from_all(&port->ip_messages, links);
  	port->ip_pset_count = 0;
  	return KERN_SUCCESS;
  }
  
  
  /*
   *	Routine:	ipc_pset_destroy
   *	Purpose:
   *		Destroys a port_set.
   *	Conditions:
   *		The port_set is locked and alive.
   *		The caller has a reference, which is consumed.
   *		Afterwards, the port_set is unlocked and dead.
   */
  
  void
  ipc_pset_destroy(
  	ipc_pset_t	pset)
  {
  	spl_t		s;
  	queue_head_t link_data;
  	queue_t links = &link_data;
  	wait_queue_link_t wql;
  
  	queue_init(links);
  
  	assert(ips_active(pset));
  
  	pset->ips_object.io_bits &= ~IO_BITS_ACTIVE;
  
  	/*
  	 * remove all the member message queues
  	 */
  	ipc_mqueue_remove_all(&pset->ips_messages, links);
  
  	/*
  	 * Set all waiters on the portset running to
  	 * discover the change.
  	 */
  	s = splsched();
  	imq_lock(&pset->ips_messages);
  	ipc_mqueue_changed(&pset->ips_messages);
  	imq_unlock(&pset->ips_messages);
  	splx(s);
  
  	ips_unlock(pset);
  	ips_release(pset);       /* consume the ref our caller gave us */
  
  	while(!queue_empty(links)) {
  		wql = (wait_queue_link_t) dequeue(links);
  		wait_queue_link_free(wql);
  	}
  
  }
  
  /* Kqueue EVFILT_MACHPORT support */
  
  #include <sys/errno.h>
  
  static int      filt_machportattach(struct knote *kn);
  static void	filt_machportdetach(struct knote *kn);
  static int	filt_machport(struct knote *kn, long hint);
  static void     filt_machporttouch(struct knote *kn, struct kevent64_s *kev, long type);
  static unsigned filt_machportpeek(struct knote *kn);
  struct filterops machport_filtops = {
          .f_attach = filt_machportattach,
          .f_detach = filt_machportdetach,
          .f_event = filt_machport,
          .f_touch = filt_machporttouch,
  	.f_peek = filt_machportpeek,
  };
  
  static int
  filt_machportattach(
          struct knote *kn)
  {
          mach_port_name_t        name = (mach_port_name_t)kn->kn_kevent.ident;
  	wait_queue_link_t	wql = wait_queue_link_allocate();
          ipc_pset_t              pset = IPS_NULL;
          int                     result = ENOSYS;
          kern_return_t           kr;
  
          kr = ipc_object_translate(current_space(), name,
                                    MACH_PORT_RIGHT_PORT_SET,
                                    (ipc_object_t *)&pset);
          if (kr != KERN_SUCCESS) {
  		wait_queue_link_free(wql);
                  return (kr == KERN_INVALID_NAME ? ENOENT : ENOTSUP);
          }
          /* We've got a lock on pset */
  
  	/*
  	 * Bind the portset wait queue directly to knote/kqueue.
  	 * This allows us to just use wait_queue foo to effect a wakeup,
  	 * rather than having to call knote() from the Mach code on each
  	 * message.
  	 */
  	result = knote_link_wait_queue(kn, &pset->ips_messages.imq_wait_queue, wql);
  	if (result == 0) {
  		/* keep a reference for the knote */
  		kn->kn_ptr.p_pset = pset;
  		ips_reference(pset);
  		ips_unlock(pset);
  		return 0;
  	}
  
  	ips_unlock(pset);
  	wait_queue_link_free(wql);
  	return result;
  }
  
  static void
  filt_machportdetach(
          struct knote *kn)
  {
          ipc_pset_t              pset = kn->kn_ptr.p_pset;
  	wait_queue_link_t	wql = WAIT_QUEUE_LINK_NULL;
  
  	/*
  	 * Unlink the portset wait queue from knote/kqueue,
  	 * and release our reference on the portset.
  	 */
  	ips_lock(pset);
  	(void)knote_unlink_wait_queue(kn, &pset->ips_messages.imq_wait_queue, &wql);
  	kn->kn_ptr.p_pset = IPS_NULL;
  	ips_unlock(pset);
  	ips_release(pset);
  	if (wql != WAIT_QUEUE_LINK_NULL)
  		wait_queue_link_free(wql);
  }
  
  static int
  filt_machport(
          struct knote *kn,
          __unused long hint)
  {
          mach_port_name_t        name = (mach_port_name_t)kn->kn_kevent.ident;
          ipc_pset_t              pset = IPS_NULL;
  	wait_result_t		wresult;
  	thread_t		self = current_thread();
          kern_return_t           kr;
  	mach_msg_option_t	option;
  	mach_msg_size_t		size;
  
  	/* never called from below */
  	assert(hint == 0);
  
  	/*
  	 * called from user context. Have to validate the
  	 * name.  If it changed, we have an EOF situation.
  	 */
  	kr = ipc_object_translate(current_space(), name,
  				  MACH_PORT_RIGHT_PORT_SET,
  				  (ipc_object_t *)&pset);
  	if (kr != KERN_SUCCESS || pset != kn->kn_ptr.p_pset || !ips_active(pset)) {
  		kn->kn_data = 0;
  		kn->kn_flags |= (EV_EOF | EV_ONESHOT);
  		if (pset != IPS_NULL) {
  			ips_unlock(pset);
  		}
  		wait_queue_init(&mqueue->imq_wait_queue, SYNC_POLICY_FIFO);
  		ipc_kmsg_queue_init(&mqueue->imq_messages);
  		mqueue->imq_seqno = 0;
  		mqueue->imq_msgcount = 0;
  		mqueue->imq_qlimit = MACH_PORT_QLIMIT_DEFAULT;
  		mqueue->imq_fullwaiters = FALSE;
  	}
  }
  
  /*
   *	Routine:	ipc_mqueue_member
   *	Purpose:
   *		Indicate whether the (port) mqueue is a member of
   *		this portset's mqueue.  We do this by checking
   *		whether the portset mqueue's waitq is an member of
   *		the port's mqueue waitq.
   *	Conditions:
   *		the portset's mqueue is not already a member
   *		this may block while allocating linkage structures.
   */
  
  boolean_t
  ipc_mqueue_member(
  	ipc_mqueue_t		port_mqueue,
  	ipc_mqueue_t		set_mqueue)
  {
  	wait_queue_t	port_waitq = &port_mqueue->imq_wait_queue;
  	wait_queue_set_t set_waitq = &set_mqueue->imq_set_queue;
  
  	return (wait_queue_member(port_waitq, set_waitq));
  
  }
  
  /*
   *	Routine:	ipc_mqueue_remove
   *	Purpose:
   *		Remove the association between the queue and the specified
   *		set message queue.
   */
  
  kern_return_t
  ipc_mqueue_remove(
  	ipc_mqueue_t	  mqueue,
  	ipc_mqueue_t	  set_mqueue,
  	wait_queue_link_t *wqlp)
  {
  	wait_queue_t	 mq_waitq = &mqueue->imq_wait_queue;
  	wait_queue_set_t set_waitq = &set_mqueue->imq_set_queue;
  
  	return wait_queue_unlink_nofree(mq_waitq, set_waitq, wqlp);
  }
  
  /*
   *	Routine:	ipc_mqueue_remove_from_all
   *	Purpose:
   *		Remove the mqueue from all the sets it is a member of
   *	Conditions:
   *		Nothing locked.
   */
  void
  ipc_mqueue_remove_from_all(
  	ipc_mqueue_t	mqueue,
  	queue_t 	links)
  {
  	wait_queue_t	mq_waitq = &mqueue->imq_wait_queue;
  
  	wait_queue_unlink_all_nofree(mq_waitq, links);
  	return;
  }
  
  /*
   *	Routine:	ipc_mqueue_remove_all
   *	Purpose:
   *		Remove all the member queues from the specified set.
   *	Conditions:
   *		Nothing locked.
   */
  void
  ipc_mqueue_remove_all(
  	ipc_mqueue_t	mqueue,
  	queue_t		links)
  {
  	wait_queue_set_t	mq_setq = &mqueue->imq_set_queue;
  
  	wait_queue_set_unlink_all_nofree(mq_setq, links);
  	return;
  }
  
  
  /*
   *	Routine:	ipc_mqueue_add
   *	Purpose:
   *		Associate the portset's mqueue with the port's mqueue.
   *		This has to be done so that posting the port will wakeup
   *		a portset waiter.  If there are waiters on the portset
   *		mqueue and messages on the port mqueue, try to match them
   *		up now.
   *	Conditions:
   *		May block.
   */
  kern_return_t
  ipc_mqueue_add(
  	ipc_mqueue_t	 port_mqueue,
  	ipc_mqueue_t	 set_mqueue,
  	wait_queue_link_t wql)
  {
  	wait_queue_t	 port_waitq = &port_mqueue->imq_wait_queue;
  	wait_queue_set_t set_waitq = &set_mqueue->imq_set_queue;
  	ipc_kmsg_queue_t kmsgq;
  	ipc_kmsg_t       kmsg, next;
  	kern_return_t	 kr;
  	spl_t		 s;
  
  	kr = wait_queue_link_noalloc(port_waitq, set_waitq, wql);
  	if (kr != KERN_SUCCESS)
  		return kr;
  
  	/*
  	 * Now that the set has been added to the port, there may be
  	 * messages queued on the port and threads waiting on the set
  	 * waitq.  Lets get them together.
  	 */
  	s = splsched();
  	imq_lock(port_mqueue);
  	kmsgq = &port_mqueue->imq_messages;
  	for (kmsg = ipc_kmsg_queue_first(kmsgq);
  	     kmsg != IKM_NULL;
  	     kmsg = next) {
  		next = ipc_kmsg_queue_next(kmsgq, kmsg);
  
  		for (;;) {
  			thread_t th;
  			mach_msg_size_t msize;
  
  			th = wait_queue_wakeup64_identity_locked(
  						port_waitq,
  						IPC_MQUEUE_RECEIVE,
  						THREAD_AWAKENED,
  						FALSE);
  			/* waitq/mqueue still locked, thread locked */
  
  			if (th == THREAD_NULL)
  				goto leave;
  
  			/*
  			 * If the receiver waited with a facility not directly
  			 * related to Mach messaging, then it isn't prepared to get
  			 * handed the message directly.  Just set it running, and
  			 * go look for another thread that can.
  			 */
  			if (th->ith_state != MACH_RCV_IN_PROGRESS) {
  				  thread_unlock(th);
  				  continue;
  			}
  
  			/*
  			 * Found a receiver. see if they can handle the message
  			 * correctly (the message is not too large for them, or
  			 * they didn't care to be informed that the message was
  			 * too large).  If they can't handle it, take them off
  			 * the list and let them go back and figure it out and
  			 * just move onto the next.
  			 */
  			msize = ipc_kmsg_copyout_size(kmsg, th->map);
  			if (th->ith_msize <
  					(msize + REQUESTED_TRAILER_SIZE(thread_is_64bit(th), th->ith_option))) {
  				th->ith_state = MACH_RCV_TOO_LARGE;
  				th->ith_msize = msize;
  				if (th->ith_option & MACH_RCV_LARGE) {
  					/*
  					 * let him go without message
  					 */
  					th->ith_receiver_name = port_mqueue->imq_receiver_name;
  					th->ith_kmsg = IKM_NULL;
  					th->ith_seqno = 0;
  					thread_unlock(th);
  					continue; /* find another thread */
  				}
  			} else {
  				th->ith_state = MACH_MSG_SUCCESS;
  			}
  
  			/*
  			 * This thread is going to take this message,
  			 * so give it to him.
  			 */
  			ipc_kmsg_rmqueue(kmsgq, kmsg);
  			ipc_mqueue_release_msgcount(port_mqueue);
  
  			th->ith_kmsg = kmsg;
  			th->ith_seqno = port_mqueue->imq_seqno++;
  			thread_unlock(th);
  			break;  /* go to next message */
  		}
  
  	}
   leave:
  	imq_unlock(port_mqueue);
  	splx(s);
  	return KERN_SUCCESS;
  }
  
  	/*
  	 * Select the threads that we will wake up.	 The threads
  	 * are returned to us locked and cleanly removed from the
  	 * wait queue.
  	 */
  	_wait_queue_select64_all(wq, event, q);
  	if (unlock)
  		wait_queue_unlock(wq);
  
  	/*
  	 * For each thread, set it running.
  	 */
  	res = KERN_NOT_WAITING;
  	while (!queue_empty (q)) {
  		thread_t thread = (thread_t)(void *) dequeue(q);
  		res = thread_go(thread, result);
  		assert(res == KERN_SUCCESS);
  		thread_unlock(thread);
  	}
  	return res;
  }
  
  
  /*
   *	Routine:		wait_queue_wakeup_all
   *	Purpose:
   *		Wakeup some number of threads that are in the specified
   *		wait queue and waiting on the specified event.
   *	Conditions:
   *		Nothing locked
   *	Returns:
   *		KERN_SUCCESS - Threads were woken up
   *		KERN_NOT_WAITING - No threads were waiting <wq,event> pair
   */
  kern_return_t
  wait_queue_wakeup_all(
  	wait_queue_t wq,
  	event_t event,
  	wait_result_t result)
  {
  132:#define IPC_MQUEUE_FULL		CAST_EVENT64_T(&ipc_mqueue_full)
  133:#define IPC_MQUEUE_RECEIVE	NO_EVENT64
  xnu-2422/osfmk/ipc/ipc_right.c:669:			ipc_port_clear_receiver(port, links);
  xnu-2422/osfmk/ipc/ipc_right.c:824:			ipc_port_clear_receiver(port, links);
  xnu-2422/osfmk/ipc/ipc_right.c:1214:		ipc_port_clear_receiver(port, links);
  xnu-2422/osfmk/ipc/ipc_right.c:1588:	ipc_port_clear_receiver(port, links);
  xnu-2422/osfmk/ipc/ipc_right.c:1978:		ipc_port_clear_receiver(port, links);
  xnu-2422/osfmk/ipc/ipc_port.h:413:extern void ipc_port_clear_receiver(
  xnu-2422/osfmk/ipc/ipc_port.c:541: *	Routine:	ipc_port_clear_receiver
  xnu-2422/osfmk/ipc/ipc_port.c:549:ipc_port_clear_receiver(
  xnu-2422/osfmk/ipc/ipc_port.c:1734:	/* relevant part of ipc_port_clear_receiver */
  xnu-2422/osfmk/ipc/ipc_object.c:605:			/* relevant part of ipc_port_clear_receiver */

Activity

$ /bin/bash -lc "curl -L --fail 'https://github.com/blueboxd/chromium-legacy/files/8246273/Chromium.Helper_2022-03-14-112231_Jonathans-Mac-Pro.crash.zip' -o investigation/helper-crash.zip"
status: Completed · exit 0
    0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0  0     0    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0
  100 14982  100 14982    0     0  11519      0  0:00:01  0:00:01 --:--:-- 11519

Assistant

I’ve now read the issue body and all 96 comments, including the later patching discussion and follow-up reports. The source confirms that closing a kqueue normally wakes its waiter with THREAD_INTERRUPTED, not THREAD_RESTART. I’m checking the Mach-port paths, where a linked wait queue can pass a wakeup result into the kqueue.

Activity

$ /bin/bash -lc "sed -n '985,1065p' xnu-2422/osfmk/kern/wait_queue.c; sed -n '395,515p' xnu-2422/osfmk/ipc/ipc_pset.c; rg -n 'THREAD_RESTART' xnu-2422/osfmk | head -90; rg -n 'mach_port_(mod_refs|destroy|extract_member|move_member)|MACH_MSG_TYPE_MOVE_RECEIVE|StopWatchingMachPort|WatchMachReceivePort' chromium-legacy-master/mojo/core/channel_mac.cc"
status: Completed · exit 0
  		zfree(_wait_queue_link_zone, wql);
  	}
  
  	return(KERN_SUCCESS);
  }
  
  /* legacy interface naming */
  kern_return_t
  wait_subqueue_unlink_all(
  	wait_queue_set_t	wq_set)
  {
  	return wait_queue_set_unlink_all(wq_set);
  }
  
  
  /*
   *	Routine:	wait_queue_set_unlink_all_nofree
   *	Purpose:
   *		Remove the linkage between a set wait queue and all its
   *		member wait queues and all the sets it may be a member of.
   *		The links structures are returned for later freeing by the
   *		caller.
   *	Conditions:
   *		The wait queue must be a set
   */
  kern_return_t
  wait_queue_set_unlink_all_nofree(
  	wait_queue_set_t wq_set,
  	queue_t		links)
  {
  	wait_queue_link_t wql;
  	wait_queue_t wq;
  	queue_t q;
  	spl_t s;
  
  	if (!wait_queue_is_set(wq_set)) {
  		return KERN_INVALID_ARGUMENT;
  	}
  
  retry:
  	s = splsched();
  	wqs_lock(wq_set);
  
  	/* remove the wait queues that are members of our set */
  	q = &wq_set->wqs_setlinks;
  
  	wql = (wait_queue_link_t)queue_first(q);
  	while (!queue_end(q, (queue_entry_t)wql)) {
  		WAIT_QUEUE_SET_LINK_CHECK(wq_set, wql);
  		wq = wql->wql_queue;
  		if (wait_queue_lock_try(wq)) {
  			wait_queue_unlink_locked(wq, wq_set, wql);
  			wait_queue_unlock(wq);
  			enqueue(links, &wql->wql_links);
  			wql = (wait_queue_link_t)queue_first(q);
  		} else {
  			wqs_unlock(wq_set);
  			splx(s);
  			delay(1);
  			goto retry;
  		}
  	}
  
  	/* remove this set from sets it belongs to */
  	wait_queue_unlink_all_nofree_locked(&wq_set->wqs_wait_queue, links);
  
  	wqs_unlock(wq_set);
  	splx(s);
  
  	return(KERN_SUCCESS);
  }
  
  /*
   *	Routine:	wait_queue_set_unlink_all
   *	Purpose:
   *		Remove the linkage between a set wait queue and all its
   *		member wait queues and all the sets it may be members of.
   *		The link structures are freed for those	links which were
   *		dynamically allocated.
   *	Conditions:
   *		The wait queue must be a set
          __unused long hint)
  {
          mach_port_name_t        name = (mach_port_name_t)kn->kn_kevent.ident;
          ipc_pset_t              pset = IPS_NULL;
  	wait_result_t		wresult;
  	thread_t		self = current_thread();
          kern_return_t           kr;
  	mach_msg_option_t	option;
  	mach_msg_size_t		size;
  
  	/* never called from below */
  	assert(hint == 0);
  
  	/*
  	 * called from user context. Have to validate the
  	 * name.  If it changed, we have an EOF situation.
  	 */
  	kr = ipc_object_translate(current_space(), name,
  				  MACH_PORT_RIGHT_PORT_SET,
  				  (ipc_object_t *)&pset);
  	if (kr != KERN_SUCCESS || pset != kn->kn_ptr.p_pset || !ips_active(pset)) {
  		kn->kn_data = 0;
  		kn->kn_flags |= (EV_EOF | EV_ONESHOT);
  		if (pset != IPS_NULL) {
  			ips_unlock(pset);
  		}
  		return(1);
          }
  
  	/* just use the reference from here on out */
  	ips_reference(pset);
  	ips_unlock(pset);
  
  	/*
  	 * Only honor supported receive options. If no options are
  	 * provided, just force a MACH_RCV_TOO_LARGE to detect the
  	 * name of the port and sizeof the waiting message.
  	 */
  	option = kn->kn_sfflags & (MACH_RCV_MSG|MACH_RCV_LARGE|MACH_RCV_LARGE_IDENTITY|MACH_RCV_TRAILER_MASK);
  	if (option & MACH_RCV_MSG) {
  		self->ith_msg_addr = (mach_vm_address_t) kn->kn_ext[0];
  		size = (mach_msg_size_t)kn->kn_ext[1];
  	} else {
  		option = MACH_RCV_LARGE;
  		self->ith_msg_addr = 0;
  		size = 0;
  	}
  
  	/*
  	 * Set up to receive a message or the notification of a
  	 * too large message.  But never allow this call to wait.
  	 * If the user provided aditional options, like trailer
  	 * options, pass those through here.  But we don't support
  	 * scatter lists through this interface.
  	 */
  	self->ith_object = (ipc_object_t)pset;
  	self->ith_msize = size;
  	self->ith_option = option;
  	self->ith_scatter_list_size = 0;
  	self->ith_receiver_name = MACH_PORT_NULL;
  	self->ith_continuation = NULL;
  	option |= MACH_RCV_TIMEOUT; // never wait
  	self->ith_state = MACH_RCV_IN_PROGRESS;
  
  	wresult = ipc_mqueue_receive_on_thread(
  			&pset->ips_messages,
  			option,
  			size, /* max_size */
  			0, /* immediate timeout */
  			THREAD_INTERRUPTIBLE,
  			self);
  	assert(wresult == THREAD_NOT_WAITING);
  	assert(self->ith_state != MACH_RCV_IN_PROGRESS);
  
  	/*
  	 * If we timed out, just release the reference on the
  	 * portset and return zero.
  	 */
  	if (self->ith_state == MACH_RCV_TIMED_OUT) {
  		ips_release(pset);
  		return 0;
  	}
  
  	/*
  	 * If we weren't attempting to receive a message
  	 * directly, we need to return the port name in
  	 * the kevent structure.
  	 */
  	if ((option & MACH_RCV_MSG) != MACH_RCV_MSG) {
  		assert(self->ith_state == MACH_RCV_TOO_LARGE);
  		assert(self->ith_kmsg == IKM_NULL);
  		kn->kn_data = self->ith_receiver_name;
  		ips_release(pset);
  		return 1;
  	}
  
  	/*
  	 * Attempt to receive the message directly, returning
  	 * the results in the fflags field.
  	 */
  	assert(option & MACH_RCV_MSG);
  	kn->kn_ext[1] = self->ith_msize;
  	kn->kn_data = MACH_PORT_NULL;
  	kn->kn_fflags = mach_msg_receive_results();
  	/* kmsg and pset reference consumed */
  
  	/*
  	 * if the user asked for the identity of ports containing a
  	 * a too-large message, return it in the data field (as we
  	 * do for messages we didn't try to receive).
  	 */
          if ((kn->kn_fflags == MACH_RCV_TOO_LARGE) &&
  	    (option & MACH_RCV_LARGE_IDENTITY))
  	    kn->kn_data = self->ith_receiver_name;
  
  	return 1;
  }
  
  static void
  filt_machporttouch(struct knote *kn, struct kevent64_s *kev, long type)
  {
  xnu-2422/osfmk/vm/vm_fault.c:1043:					if (wait_result == THREAD_RESTART)
  xnu-2422/osfmk/vm/vm_fault.c:2348:			 * PAGE_WAKEUP that uses the THREAD_RESTART
  xnu-2422/osfmk/vm/vm_fault.c:2354:				thread_wakeup_with_result((event_t) m, THREAD_RESTART);
  xnu-2422/osfmk/vm/vm_fault.c:3400:				if (result == THREAD_AWAKENED || result == THREAD_RESTART)
  xnu-2422/osfmk/kern/wait_queue.c:1267:		return (thread->wait_result = THREAD_RESTART);
  xnu-2422/osfmk/kern/wait_queue.c:1308:		return (thread->wait_result = THREAD_RESTART);
  xnu-2422/osfmk/kern/wait_queue.c:1344:		return (thread->wait_result = THREAD_RESTART);
  xnu-2422/osfmk/kern/wait_queue.c:1383:		return (thread->wait_result = THREAD_RESTART);
  xnu-2422/osfmk/kern/sync_sema.c:274:					     THREAD_RESTART,
  xnu-2422/osfmk/kern/sync_sema.c:568:	case THREAD_RESTART:
  xnu-2422/osfmk/kern/kern_types.h:80:#define THREAD_RESTART		3		/* restart operation entirely */
  xnu-2422/osfmk/ipc/ipc_mqueue.c:337:				THREAD_RESTART,
  xnu-2422/osfmk/ipc/ipc_mqueue.c:438:		case THREAD_RESTART:
  xnu-2422/osfmk/ipc/ipc_mqueue.c:610:	case THREAD_RESTART:
  xnu-2422/osfmk/ipc/ipc_mqueue.c:1144:				THREAD_RESTART,
  225:    base::CurrentIOThread::Get()->WatchMachReceivePort(
  232:    watch_controller_.StopWatchingMachPort();
  420:          descriptor->disposition = MACH_MSG_TYPE_MOVE_RECEIVE;
  652:        case MACH_MSG_TYPE_MOVE_RECEIVE:

Activity

$ /bin/bash -lc "python3 - <<'PY'import zipfilefor n in ['helper-crash']: z=zipfile.ZipFile('investigation/'+n+'.zip') for f in z.namelist():  if not f.startswith('__MACOSX') and not f.endswith('/'):   b=z.read(f);open('investigation/'+n+'.txt','wb').write(b);print(b.decode(errors='replace'))PY"
status: Completed · exit 0
  Process:         Chromium Helper [24783]
  Path:            /Applications/Chromium.app/Contents/Frameworks/Chromium Framework.framework/Versions/99.0.4844.51/Helpers/Chromium Helper.app/Contents/MacOS/Chromium Helper
  Identifier:      Chromium Helper
  Version:         99.0.4844.51 (4844.51)
  Code Type:       X86-64 (Native)
  Parent Process:  _Chromium [8138]
  Responsible:     _Chromium [8138]
  User ID:         501
  
  Date/Time:       2022-03-14 11:22:30.813 -0400
  OS Version:      Mac OS X 10.9.5 (13F1911)
  Report Version:  11
  Anonymous UUID:  552BC867-8AAA-03C1-82A7-8F2945B54FF3
  
  
  Crashed Thread:  4  Chrome_ChildIOThread
  
  Exception Type:  EXC_BREAKPOINT (SIGTRAP)
  Exception Codes: 0x0000000000000002, 0x0000000000000000
  
  Thread 0:: CrUtilityMain  Dispatch queue: com.apple.main-thread
  0   libsystem_kernel.dylib        	0x0000000103dbba1a mach_msg_trap + 10
  1   libsystem_kernel.dylib        	0x0000000103dbad18 mach_msg + 64
  2   org.chromium.Chromium.framework	0x00000001080811b8 base::WaitableEvent::TimedWait(base::TimeDelta const&) + 344
  3   org.chromium.Chromium.framework	0x000000010808104e base::WaitableEvent::Wait() + 30
  4   org.chromium.Chromium.framework	0x0000000107fd0fcc base::MessagePumpDefault::Run(base::MessagePump::Delegate*) + 284
  5   org.chromium.Chromium.framework	0x0000000108033c5a base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run(bool, base::TimeDelta) + 122
  6   org.chromium.Chromium.framework	0x0000000107ffb4dd base::RunLoop::Run(base::Location const&) + 173
  7   org.chromium.Chromium.framework	0x0000000107a3061c content::UtilityMain(content::MainFunctionParams) + 876
  8   org.chromium.Chromium.framework	0x0000000107a776cd content::RunOtherNamedProcessTypeMain(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, content::MainFunctionParams, content::ContentMainDelegate*) + 573
  9   org.chromium.Chromium.framework	0x0000000107a78025 content::ContentMainRunnerImpl::Run() + 469
  10  org.chromium.Chromium.framework	0x0000000107a767cb content::RunContentProcess(content::ContentMainParams, content::ContentMainRunner*) + 635
  11  org.chromium.Chromium.framework	0x0000000107a76ed6 content::ContentMain(content::ContentMainParams) + 86
  12  org.chromium.Chromium.framework	0x000000010451e8f1 ChromeMain + 353
  13  org.chromium.Chromium.helper  	0x00000001035e6896 main + 246
  14  org.chromium.Chromium.helper  	0x00000001035e6794 start + 52
  
  Thread 1:: Dispatch queue: com.apple.libdispatch-manager
  0   libsystem_kernel.dylib        	0x0000000103dc0662 kevent64 + 10
  1   libdispatch.dylib             	0x0000000103be0421 _dispatch_mgr_invoke + 239
  2   libdispatch.dylib             	0x0000000103be0136 _dispatch_mgr_thread + 52
  
  Thread 2:: ThreadPoolServiceThread
  0   libsystem_kernel.dylib        	0x0000000103dc0662 kevent64 + 10
  1   org.chromium.Chromium.framework	0x000000010809fe2b base::MessagePumpKqueue::DoInternalWork(base::MessagePump::Delegate*, base::MessagePump::Delegate::NextWorkInfo*) + 267
  2   org.chromium.Chromium.framework	0x000000010809fcc0 base::MessagePumpKqueue::Run(base::MessagePump::Delegate*) + 192
  3   org.chromium.Chromium.framework	0x0000000108033c5a base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run(bool, base::TimeDelta) + 122
  4   org.chromium.Chromium.framework	0x0000000107ffb4dd base::RunLoop::Run(base::Location const&) + 173
  5   org.chromium.Chromium.framework	0x00000001080539b8 base::Thread::Run(base::RunLoop*) + 56
  6   org.chromium.Chromium.framework	0x000000010803f28d base::internal::ServiceThread::Run(base::RunLoop*) + 13
  7   org.chromium.Chromium.framework	0x0000000108053b41 base::Thread::ThreadMain() + 369
  8   org.chromium.Chromium.framework	0x00000001080705e8 base::(anonymous namespace)::ThreadFunc(void*) + 104
  9   libsystem_pthread.dylib       	0x0000000103ecc899 _pthread_body + 138
  10  libsystem_pthread.dylib       	0x0000000103ecc72a _pthread_start + 137
  11  libsystem_pthread.dylib       	0x0000000103ed0fc9 thread_start + 13
  
  Thread 3:: ThreadPoolBackgroundWorker
  0   libsystem_kernel.dylib        	0x0000000103dbba1a mach_msg_trap + 10
  1   libsystem_kernel.dylib        	0x0000000103dbad18 mach_msg + 64
  2   org.chromium.Chromium.framework	0x00000001080811b8 base::WaitableEvent::TimedWait(base::TimeDelta const&) + 344
  3   org.chromium.Chromium.framework	0x000000010804a5b2 base::internal::WorkerThread::RunWorker() + 1666
  4   org.chromium.Chromium.framework	0x0000000108049e1d base::internal::WorkerThread::RunBackgroundPooledWorker() + 13
  5   org.chromium.Chromium.framework	0x00000001080705e8 base::(anonymous namespace)::ThreadFunc(void*) + 104
  6   libsystem_pthread.dylib       	0x0000000103ecc899 _pthread_body + 138
  7   libsystem_pthread.dylib       	0x0000000103ecc72a _pthread_start + 137
  8   libsystem_pthread.dylib       	0x0000000103ed0fc9 thread_start + 13
  
  Thread 4 Crashed:: Chrome_ChildIOThread
  0   org.chromium.Chromium.framework	0x0000000107fca03b logging::LogMessage::~LogMessage() + 2075
  1   org.chromium.Chromium.framework	0x0000000107fca599 logging::ErrnoLogMessage::~ErrnoLogMessage() + 137
  2   org.chromium.Chromium.framework	0x0000000107fca5ce logging::ErrnoLogMessage::~ErrnoLogMessage() + 14
  3   org.chromium.Chromium.framework	0x000000010809fe7e base::MessagePumpKqueue::DoInternalWork(base::MessagePump::Delegate*, base::MessagePump::Delegate::NextWorkInfo*) + 350
  4   org.chromium.Chromium.framework	0x000000010809fcc0 base::MessagePumpKqueue::Run(base::MessagePump::Delegate*) + 192
  5   org.chromium.Chromium.framework	0x0000000108033c5a base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run(bool, base::TimeDelta) + 122
  6   org.chromium.Chromium.framework	0x0000000107ffb4dd base::RunLoop::Run(base::Location const&) + 173
  7   org.chromium.Chromium.framework	0x00000001080539b8 base::Thread::Run(base::RunLoop*) + 56
  8   org.chromium.Chromium.framework	0x0000000108053b41 base::Thread::ThreadMain() + 369
  9   org.chromium.Chromium.framework	0x00000001080705e8 base::(anonymous namespace)::ThreadFunc(void*) + 104
  10  libsystem_pthread.dylib       	0x0000000103ecc899 _pthread_body + 138
  11  libsystem_pthread.dylib       	0x0000000103ecc72a _pthread_start + 137
  12  libsystem_pthread.dylib       	0x0000000103ed0fc9 thread_start + 13
  
  Thread 5:: ThreadPoolForegroundWorker
  0   libsystem_kernel.dylib        	0x0000000103dbba1a mach_msg_trap + 10
  1   libsystem_kernel.dylib        	0x0000000103dbad18 mach_msg + 64
  2   org.chromium.Chromium.framework	0x00000001080811b8 base::WaitableEvent::TimedWait(base::TimeDelta const&) + 344
  3   org.chromium.Chromium.framework	0x000000010804a5b2 base::internal::WorkerThread::RunWorker() + 1666
  4   org.chromium.Chromium.framework	0x0000000108049ead base::internal::WorkerThread::RunPooledWorker() + 13
  5   org.chromium.Chromium.framework	0x00000001080705e8 base::(anonymous namespace)::ThreadFunc(void*) + 104
  6   libsystem_pthread.dylib       	0x0000000103ecc899 _pthread_body + 138
  7   libsystem_pthread.dylib       	0x0000000103ecc72a _pthread_start + 137
  8   libsystem_pthread.dylib       	0x0000000103ed0fc9 thread_start + 13
  
  Thread 6:: NetworkConfigWatcher
  0   libsystem_kernel.dylib        	0x0000000103dbba1a mach_msg_trap + 10
  1   libsystem_kernel.dylib        	0x0000000103dbad18 mach_msg + 64
  2   com.apple.CoreFoundation      	0x000000010371bf15 __CFRunLoopServiceMachPort + 181
  3   com.apple.CoreFoundation      	0x000000010371b539 __CFRunLoopRun + 1161
  4   com.apple.CoreFoundation      	0x000000010371ae75 CFRunLoopRunSpecific + 309
  5   com.apple.Foundation          	0x0000000120b150fc -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 253
  6   org.chromium.Chromium.framework	0x000000010807a9b9 base::MessagePumpNSRunLoop::DoRun(base::MessagePump::Delegate*) + 121
  7   org.chromium.Chromium.framework	0x00000001080795a2 base::MessagePumpCFRunLoopBase::Run(base::MessagePump::Delegate*) + 98
  8   org.chromium.Chromium.framework	0x0000000108033c5a base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run(bool, base::TimeDelta) + 122
  9   org.chromium.Chromium.framework	0x0000000107ffb4dd base::RunLoop::Run(base::Location const&) + 173
  10  org.chromium.Chromium.framework	0x00000001080539b8 base::Thread::Run(base::RunLoop*) + 56
  11  org.chromium.Chromium.framework	0x0000000108053b41 base::Thread::ThreadMain() + 369
  12  org.chromium.Chromium.framework	0x00000001080705e8 base::(anonymous namespace)::ThreadFunc(void*) + 104
  13  libsystem_pthread.dylib       	0x0000000103ecc899 _pthread_body + 138
  14  libsystem_pthread.dylib       	0x0000000103ecc72a _pthread_start + 137
  15  libsystem_pthread.dylib       	0x0000000103ed0fc9 thread_start + 13
  
  Thread 7:: ThreadPoolForegroundWorker
  0   libsystem_kernel.dylib        	0x0000000103dbba1a mach_msg_trap + 10
  1   libsystem_kernel.dylib        	0x0000000103dbad18 mach_msg + 64
  2   org.chromium.Chromium.framework	0x00000001080811b8 base::WaitableEvent::TimedWait(base::TimeDelta const&) + 344
  3   org.chromium.Chromium.framework	0x000000010804a5b2 base::internal::WorkerThread::RunWorker() + 1666
  4   org.chromium.Chromium.framework	0x0000000108049ead base::internal::WorkerThread::RunPooledWorker() + 13
  5   org.chromium.Chromium.framework	0x00000001080705e8 base::(anonymous namespace)::ThreadFunc(void*) + 104
  6   libsystem_pthread.dylib       	0x0000000103ecc899 _pthread_body + 138
  7   libsystem_pthread.dylib       	0x0000000103ecc72a _pthread_start + 137
  8   libsystem_pthread.dylib       	0x0000000103ed0fc9 thread_start + 13
  
  Thread 8:
  0   libsystem_kernel.dylib        	0x0000000103dbfe6a __workq_kernreturn + 10
  1   libsystem_pthread.dylib       	0x0000000103ecdf08 _pthread_wqthread + 330
  2   libsystem_pthread.dylib       	0x0000000103ed0fb9 start_wqthread + 13
  
  Thread 9:
  0   libsystem_kernel.dylib        	0x0000000103dbfe6a __workq_kernreturn + 10
  1   libsystem_pthread.dylib       	0x0000000103ecdf08 _pthread_wqthread + 330
  2   libsystem_pthread.dylib       	0x0000000103ed0fb9 start_wqthread + 13
  
  Thread 4 crashed with X86 Thread State (64-bit):
    rax: 0x000000011085b580  rbx: 0x000000012f2e8720  rcx: 0x0000000000000000  rdx: 0x00000001107aea78
    rdi: 0x00013b0000013c03  rsi: 0x00013c0000013c00  rbp: 0x000000012f2e8be0  rsp: 0x000000012f2e86c0
     r8: 0x0000000000000040   r9: 0x000000012f2e8600  r10: 0x00007fa4133b6e45  r11: 0x0000000000000202
    r12: 0x00007fa4133b6dd0  r13: 0x00007fa413376fb0  r14: 0x00007fa413376fc0  r15: 0x0000000000000075
    rip: 0x0000000107fca03b  rfl: 0x0000000000000246  cr2: 0x0000000103d17bd0
  
  Logical CPU:     4
  Error Code:      0x00000000
  Trap Number:     3
  
  
  Binary Images:
         0x1035e5000 -        0x10361eff7 +org.chromium.Chromium.helper (99.0.4844.51 - 4844.51) <19404BEA-B2DC-37EA-BF21-30593D1E15F1> /Applications/Chromium.app/Contents/Frameworks/Chromium Framework.framework/Versions/99.0.4844.51/Helpers/Chromium Helper.app/Contents/MacOS/Chromium Helper
         0x103665000 -        0x10368fff7  libsandbox.1.dylib (278.11.2) <5C750008-A22B-35E8-8B11-D84F82E08680> /usr/lib/libsandbox.1.dylib
         0x10369c000 -        0x10369dff7  libSystem.B.dylib (1197.1.1) <72A98ACC-7606-3AD5-82AF-02D4EBBD4F02> /usr/lib/libSystem.B.dylib
         0x1036a4000 -        0x1036a4fff  com.apple.Accelerate (1.9 - Accelerate 1.9) <509BB27A-AE62-366D-86D8-0B06D217CF56> /System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate
         0x1036a7000 -        0x1036a7fff  com.apple.ApplicationServices (48 - 48) <3E3F01A8-314D-378F-835E-9CC4F8820031> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices
         0x1036ab000 -        0x103890fff  com.apple.CoreFoundation (6.9 - 855.17) <729BD6DA-1F63-3E72-A148-26F21EBF52BB> /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
         0x103a02000 -        0x103a02ffd  com.apple.audio.units.AudioUnit (1.10 - 1.10) <68B21135-55A6-3563-A3D6-3E692A7DEB7F> /System/Library/Frameworks/AudioUnit.framework/Versions/A/AudioUnit
         0x103a09000 -        0x103af3fff  libsqlite3.dylib (158) <00269BF9-43BE-39E0-9C85-24585B9923C8> /usr/lib/libsqlite3.dylib
         0x103b0a000 -        0x103b0afff  com.apple.Carbon (154 - 157) <EFC1A1C0-CB07-395A-B038-CFA2E71D3E69> /System/Library/Frameworks/Carbon.framework/Versions/A/Carbon
         0x103b0f000 -        0x103b17fff  libMatch.1.dylib (19) <021293AB-407D-309A-87F5-8E782F46753E> /usr/lib/libMatch.1.dylib
         0x103b1c000 -        0x103b1cfff  com.apple.CoreServices (59 - 59) <7A697B5E-F179-30DF-93F2-8B503CEEEFD5> /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices
         0x103b20000 -        0x103b24ff7  libcache.dylib (62) <BDC1E65B-72A1-3DA3-A57C-B23159CAAD0B> /usr/lib/system/libcache.dylib
         0x103b29000 -        0x103b29fff  com.apple.quartzframework (1.5 - 1.5) <3B2A72DB-39FC-3C5B-98BE-605F37777F37> /System/Library/Frameworks/Quartz.framework/Versions/A/Quartz
         0x103b2c000 -        0x103b2cfff  com.apple.Cocoa (6.8 - 20) <E90E99D7-A425-3301-A025-D9E0CD11918E> /System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa
         0x103b2f000 -        0x103b39fff  libcommonCrypto.dylib (60049) <8C4F0CA0-389C-3EDC-B155-E62DD2187E1D> /usr/lib/system/libcommonCrypto.dylib
         0x103b47000 -        0x103b47ffd  libOpenScriptingUtil.dylib (157.1) <D3B6E577-3CDB-3139-9B94-19496DFA7318> /usr/lib/libOpenScriptingUtil.dylib
         0x103b4b000 -        0x103b52fff  libcompiler_rt.dylib (35) <4CD916B2-1B17-362A-B403-EF24A1DAC141> /usr/lib/system/libcompiler_rt.dylib
         0x103b5e000 -        0x103b60fff  com.apple.ForceFeedback (1.0.6 - 1.0.6) <D21AD43F-147B-3B50-89AB-26695EB89998> /System/Library/Frameworks/ForceFeedback.framework/Versions/A/ForceFeedback
         0x103b65000 -        0x103b6cffb  libcopyfile.dylib (103.92.1) <CF29DFF6-0589-3590-834C-82E2316612E8> /usr/lib/system/libcopyfile.dylib
         0x103b73000 -        0x103b74fff  liblangid.dylib (117) <9546E641-F730-3AB0-B3CD-E0E2FDD173D9> /usr/lib/liblangid.dylib
         0x103b79000 -        0x103bc7fff  libcorecrypto.dylib (161.1) <F3973C28-14B6-3006-BB2B-00DD7F09ABC7> /usr/lib/system/libcorecrypto.dylib
         0x103bd8000 -        0x103bd8fff  com.apple.Accelerate.vecLib (3.9 - vecLib 3.9) <F8D0CC77-98AC-3B58-9FE6-0C25421827B6> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/vecLib
         0x103bdd000 -        0x103bf7fff  libdispatch.dylib (339.92.1) <C4E4A18D-3C3B-3C9C-8709-A4270D998DE7> /usr/lib/system/libdispatch.dylib
         0x103c12000 -        0x103c15ff7  libdyld.dylib (239.5) <CAE7A50D-F156-3D47-81C0-DC41EB975D38> /usr/lib/system/libdyld.dylib
         0x103c1e000 -        0x103c1eff7  libkeymgr.dylib (28) <3AA8D85D-CF00-3BD3-A5A0-E28E1A32A6D8> /usr/lib/system/libkeymgr.dylib
         0x103c23000 -        0x103c2aff8  liblaunch.dylib (842.92.1) <A40A0C7B-3216-39B4-8AE0-B5D3BAF1DA8A> /usr/lib/system/liblaunch.dylib
         0x103c32000 -        0x103c34fff  libRadiance.dylib (1052) <82A880BE-DEFD-3445-9809-71043BC55AFC> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libRadiance.dylib
         0x103c38000 -        0x103c3dfff  libmacho.dylib (845) <1D2910DF-C036-3A82-A3FD-44FF73B5FF9B> /usr/lib/system/libmacho.dylib
         0x103c43000 -        0x103c44fff  com.apple.TrustEvaluationAgent (2.0 - 25) <334A82F4-4AE4-3719-A511-86D0B0723E2B> /System/Library/PrivateFrameworks/TrustEvaluationAgent.framework/Versions/A/TrustEvaluationAgent
         0x103c4a000 -        0x103c4cff7  libquarantine.dylib (71) <7A1A2BCB-C03D-3A25-BFA4-3E569B2D2C38> /usr/lib/system/libquarantine.dylib
         0x103c52000 -        0x103c54fff  libCVMSPluginSupport.dylib (9.6.5) <9DE29AD9-5F59-3B9B-899C-4DED190CB817> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCVMSPluginSupport.dylib
         0x103c59000 -        0x103c5affb  libremovefile.dylib (33) <3543F917-928E-3DB2-A2F4-7AB73B4970EF> /usr/lib/system/libremovefile.dylib
         0x103c60000 -        0x103c61ff7  com.apple.print.framework.Print (9.0 - 260) <EE00FAE1-DA03-3EC2-8571-562518C46994> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Print.framework/Versions/A/Print
         0x103c67000 -        0x103c78ff7  libsystem_asl.dylib (217.1.4) <655FB343-52CF-3E2F-B14D-BEBF5AAEF94D> /usr/lib/system/libsystem_asl.dylib
         0x103c85000 -        0x103c86ff7  libsystem_blocks.dylib (63) <FB856CD1-2AEA-3907-8E9B-1E54B6827F82> /usr/lib/system/libsystem_blocks.dylib
         0x103c92000 -        0x103d1bfef  libsystem_c.dylib (997.90.5) <889AA3F9-121C-3985-8B1D-5E908C5693BC> /usr/lib/system/libsystem_c.dylib
         0x103d4a000 -        0x103d4cff3  libsystem_configuration.dylib (596.15) <4998CB6A-9D54-390A-9F57-5D1AC53C135C> /usr/lib/system/libsystem_configuration.dylib
         0x103d58000 -        0x103d60fff  libsystem_dnssd.dylib (522.92.3) <1418DF66-01BE-3A87-8553-09EAA945F4FE> /usr/lib/system/libsystem_dnssd.dylib
         0x103d69000 -        0x103d90ffb  libsystem_info.dylib (449.1.4) <12CD9E42-8CEE-3A8D-B006-F8A6EB98804D> /usr/lib/system/libsystem_info.dylib
         0x103daa000 -        0x103dc6ff7  libsystem_kernel.dylib (2422.115.15) <34ABAF79-E147-3C34-B05D-46A566E689CC> /usr/lib/system/libsystem_kernel.dylib
         0x103ded000 -        0x103e1cfd2  libsystem_m.dylib (3047.16) <B7F0E2E4-2777-33FC-A787-D6430B630D54> /usr/lib/system/libsystem_m.dylib
         0x103e28000 -        0x103e43ff7  libsystem_malloc.dylib (23.10.1) <A695B4E4-38E9-332E-A772-29D31E3F1385> /usr/lib/system/libsystem_malloc.dylib
         0x103e4f000 -        0x103e76ff7  libsystem_network.dylib (241.4) <0D630D53-C772-3EC5-8257-EFB0ACCE3153> /usr/lib/system/libsystem_network.dylib
         0x103e99000 -        0x103ea2ffb  libsystem_notify.dylib (121.20.1) <9B34B4FE-F5AD-3F09-A5F0-46AFF3571323> /usr/lib/system/libsystem_notify.dylib
         0x103eb2000 -        0x103eb8ff7  libsystem_platform.dylib (24.90.1) <3C3D3DA8-32B9-3243-98EC-D89B9A1670B3> /usr/lib/system/libsystem_platform.dylib
         0x103ecb000 -        0x103ed2ff7  libsystem_pthread.dylib (53.1.4) <AB498556-B555-310E-9041-F67EC9E00E2C> /usr/lib/system/libsystem_pthread.dylib
         0x103ee2000 -        0x103ee3fff  libsystem_sandbox.dylib (278.11.2) <0C93EB23-7364-3670-B511-212A7A524695> /usr/lib/system/libsystem_sandbox.dylib
         0x103ee9000 -        0x103eedff7  libsystem_stats.dylib (93.90.3) <2304C7C2-BE45-35DE-BCC6-707D61B7AE7E> /usr/lib/system/libsystem_stats.dylib
         0x103ef4000 -        0x103ef5fff  libunc.dylib (28) <62682455-1862-36FE-8A04-7A6B91256438> /usr/lib/system/libunc.dylib
         0x103efb000 -        0x103f00ff7  libunwind.dylib (35.3) <78DCC358-2FC1-302E-B395-0155B47CB547> /usr/lib/system/libunwind.dylib
         0x103f07000 -        0x103f2bfff  libxpc.dylib (300.90.2) <AB40CD57-F454-3FD4-B415-63B3C0D5C624> /usr/lib/system/libxpc.dylib
         0x103f4a000 -        0x1040f7f27  libobjc.A.dylib (551.1) <AD7FD984-271E-30F4-A361-6B20319EC73B> /usr/lib/libobjc.A.dylib
         0x10411f000 -        0x104161ff7  libauto.dylib (185.5) <F45C36E8-B606-3886-B5B1-B6745E757CA8> /usr/lib/libauto.dylib
         0x10417d000 -        0x1041a6ff7  libc++abi.dylib (49.1) <21A807D3-6732-3455-B77F-743E9F916DF0> /usr/lib/libc++abi.dylib
         0x1041ba000 -        0x10420cfff  libc++.1.dylib (120) <4F68DFC5-2077-39A8-A449-CAC5FDEE7BDE> /usr/lib/libc++.1.dylib
         0x10426b000 -        0x10426cff7  libDiagnosticMessagesClient.dylib (100) <4CDB0F7B-C0AF-3424-BC39-495696F0DB1E> /usr/lib/libDiagnosticMessagesClient.dylib
         0x104276000 -        0x10442effb  libicucore.A.dylib (511.36) <9AAC5980-2C1F-3B86-8A16-DB533F5E7C84> /usr/lib/libicucore.A.dylib
         0x1044d6000 -        0x1044e7ff7  libz.1.dylib (53) <42E0C8C6-CA38-3CA4-8619-D24ED5DD492E> /usr/lib/libz.1.dylib
         0x10451b000 -        0x10ff76f97 +org.chromium.Chromium.framework (99.0.4844.51 - 4844.51) <D1160355-AA4E-3838-B297-705E1F1E0E31> /Applications/Chromium.app/Contents/Frameworks/Chromium Framework.framework/Versions/99.0.4844.51/Chromium Framework
         0x11e8ca000 -        0x11ed18fef  com.apple.VideoToolbox (1.0 - 1273.57) <AA4D613A-1066-3E85-8BE0-7806566652B4> /System/Library/Frameworks/VideoToolbox.framework/Versions/A/VideoToolbox
         0x11ed73000 -        0x11ee95fff  com.apple.avfoundation (2.0 - 651.12.1) <FDCF1F41-E0BD-3F8C-974A-3F48A0A85B00> /System/Library/Frameworks/AVFoundation.framework/Versions/A/AVFoundation
         0x11efad000 -        0x11efb2fff  com.apple.DiskArbitration (2.6 - 2.6) <A4165553-770E-3D27-B217-01FC1F852B87> /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration
         0x11efbc000 -        0x11f028fff  com.apple.framework.IOKit (2.0.1 - 907.100.14) <10932113-9F7E-38A0-A158-A019A555CAC3> /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit
         0x11f05d000 -        0x11f0a8fff  com.apple.ImageCaptureCore (5.0 - 5.0) <F529EDDC-E2F5-30CA-9938-AF23296B5C5B> /System/Library/Frameworks/ImageCaptureCore.framework/Versions/A/ImageCaptureCore
         0x11f0ea000 -        0x11f0f8fff  com.apple.opengl (9.6.5 - 9.6.5) <4FAEADD8-EEB3-3FD9-ADC6-BA65806228CC> /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL
         0x11f100000 -        0x11f29cff3  com.apple.QuartzCore (1.8 - 332.4) <CFB972D1-FA37-380C-9A47-2A67A84B7442> /System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore
         0x11f373000 -        0x11f3a1ff7  com.apple.securityinterface (9.0 - 55047) <0346D8A9-2CAA-38F3-A741-5FBA5E9F1E7C> /System/Library/Frameworks/SecurityInterface.framework/Versions/A/SecurityInterface
         0x11f3cf000 -        0x11ff45ff7  com.apple.AppKit (6.9 - 1265.21) <9DC13B27-841D-3839-93B2-3EDE66157BDE> /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit
         0x1206cc000 -        0x1206d8ff7  com.apple.OpenDirectory (10.9 - 173.90.1) <383F96FF-1DF3-37E8-8540-03A697C873F6> /System/Library/Frameworks/OpenDirectory.framework/Versions/A/OpenDirectory
         0x1206ed000 -        0x12095dffd  com.apple.security (7.0 - 55471.14.40) <58F50B4A-FC1E-3AE0-A5DB-DD737E50AC17> /System/Library/Frameworks/Security.framework/Versions/A/Security
         0x120aac000 -        0x120dacff7  com.apple.Foundation (6.9 - 1056.17) <E0B0FAF6-5CA8-3EEB-8BF2-104C0AEEF925> /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation
         0x120fea000 -        0x120ff4ff7  com.apple.bsd.ServiceManagement (2.0 - 2.0) <2D27B498-BB9C-3D88-B05A-76908A8A26F3> /System/Library/Frameworks/ServiceManagement.framework/Versions/A/ServiceManagement
         0x120fff000 -        0x121024ff7  com.apple.CoreVideo (1.8 - 117.2) <4674339E-26D0-35FA-9958-422832B39B12> /System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo
         0x121040000 -        0x1210a3ffb  com.apple.SystemConfiguration (1.13.1 - 1.13.1) <339A2A90-DA25-33AF-88E5-2FB38A758FEE> /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration
         0x1210de000 -        0x1210e1ffc  com.apple.IOSurface (91.3 - 91.3) <E93485CC-12B1-318E-BAE3-AB532B264935> /System/Library/Frameworks/IOSurface.framework/Versions/A/IOSurface
         0x1210ea000 -        0x121133fff  com.apple.CoreMedia (1.0 - 1273.57) <74FA3D80-A6DB-331A-B32A-683C8E0CC0A6> /System/Library/Frameworks/CoreMedia.framework/Versions/A/CoreMedia
         0x121161000 -        0x1212b5ff3  com.apple.audio.toolbox.AudioToolbox (1.10 - 1.10) <69B273E8-5A8E-3FC7-B807-C16B657662FE> /System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox
         0x12134b000 -        0x12139cff7  com.apple.audio.CoreAudio (4.2.1 - 4.2.1) <07F2B103-AE29-3118-BBC4-9A72E13B013B> /System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio
         0x1213c2000 -        0x121456ff7  com.apple.Bluetooth (4.2.7 - 4.2.7f5) <A7F0360A-DBDA-32EA-AA37-6937B94E6A72> /System/Library/Frameworks/IOBluetooth.framework/Versions/A/IOBluetooth
         0x1214c7000 -        0x121502ff2  com.apple.audio.midi.CoreMIDI (1.10 - 88) <D9D7F8A1-B30F-324D-AAFD-5DB9EECDAA48> /System/Library/Frameworks/CoreMIDI.framework/Versions/A/CoreMIDI
         0x12152a000 -        0x121538fff  com.apple.GameController (1.0 - 1) <0082D276-BE12-317C-852D-D9309E47CD12> /System/Library/Frameworks/GameController.framework/Versions/A/GameController
         0x12154d000 -        0x1215acfff  com.apple.framework.CoreWLAN (4.3.3 - 433.48) <1F17FA12-6E84-309D-9808-C536D445FA6E> /System/Library/Frameworks/CoreWLAN.framework/Versions/A/CoreWLAN
         0x1215ea000 -        0x121648ff7  com.apple.corelocation (1486.17 - 1486.24.1) <69C6AD7D-BA34-3F40-B73F-D66DB9C2BBE9> /System/Library/Frameworks/CoreLocation.framework/Versions/A/CoreLocation
         0x121685000 -        0x1216ccff7  libcups.2.dylib (372.6) <CBD2F0CF-FA10-36E1-A1D5-1B946B45B3B3> /usr/lib/libcups.2.dylib
         0x1216e1000 -        0x1216f1fff  libbsm.0.dylib (33) <2CAC00A2-1352-302A-88FA-C567D4D69179> /usr/lib/libbsm.0.dylib
         0x1216fa000 -        0x121716fff  libresolv.9.dylib (54) <11C2C826-F1C6-39C6-B4E8-6E0C41D4FA95> /usr/lib/libresolv.9.dylib
         0x121721000 -        0x12172eff0  libbz2.1.0.dylib (29) <0B98AC35-B138-349C-8063-2B987A75D24C> /usr/lib/libbz2.1.0.dylib
         0x121734000 -        0x12173aff7 +libChromiumModifier.dylib (1) <F90CC783-94FD-37EC-88B4-A93DB29CDBB1> /Applications/Chromium.app/Contents/Frameworks/Chromium Framework.framework/Versions/99.0.4844.51/Libraries/libChromiumModifier.dylib
         0x121744000 -        0x121791fff  com.apple.AppleVAFramework (5.0.27 - 5.0.27) <B28D0F5C-EEDD-3586-8986-33BC79E8DE56> /System/Library/PrivateFrameworks/AppleVA.framework/Versions/A/AppleVA
         0x12179c000 -        0x1220c55ab  com.apple.CoreGraphics (1.600.0 - 599.35.15) <ED5E3C37-7E2F-3885-8091-DFC9B44B38E8> /System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics
         0x1221f3000 -        0x1222b5ffd  com.apple.CoreText (367.23 - 367.23) <C799261E-2E19-3D69-8A8D-098B7DD8D31D> /System/Library/Frameworks/CoreText.framework/Versions/A/CoreText
         0x122324000 -        0x12242bff7  com.apple.ImageIO.framework (3.3.0 - 1052) <6BFA69B9-A607-39BC-B302-E2E92E5BC7F3> /System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO
         0x122493000 -        0x122500ff1  com.apple.ApplicationServices.ATS (360 - 363.6) <828C2711-4577-3F75-B436-3BDF328DFB11> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/ATS
         0x12252c000 -        0x1225b5fff  com.apple.ColorSync (4.9.0 - 4.9.0) <B756B908-9AD1-3F5D-83F9-7A0B068387D2> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ColorSync.framework/Versions/A/ColorSync
         0x1225fc000 -        0x122641ff6  com.apple.HIServices (1.23 - 468) <FD17FE8C-A355-3B6B-B8B7-E56E5C595EDE> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/HIServices
         0x122674000 -        0x122683ff8  com.apple.LangAnalysis (1.7.0 - 1.7.0) <8FE131B6-1180-3892-98F5-C9C9B79072D4> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LangAnalysis.framework/Versions/A/LangAnalysis
         0x122691000 -        0x1226deff2  com.apple.print.framework.PrintCore (9.0 - 428) <8D8253E3-302F-3DB2-9C5C-572CB974E8B3> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/PrintCore
         0x12270b000 -        0x122744ff7  com.apple.QD (3.50 - 298) <C1F20764-DEF0-34CF-B3AB-AB5480D64E66> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/QD
         0x122760000 -        0x122769fff  com.apple.speech.synthesis.framework (4.7.1 - 4.7.1) <383FB557-E88E-3239-82B8-15F9F885B702> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/SpeechSynthesis.framework/Versions/A/SpeechSynthesis
         0x12277c000 -        0x122787fff  libkxld.dylib (2422.115.15) <8850BC2B-EB64-3B0F-8047-DCC113021292> /usr/lib/system/libkxld.dylib
         0x12278c000 -        0x122927ff8  com.apple.CFNetwork (673.6 - 673.6) <CAA196FE-BF5A-384F-975E-E0F81359805B> /System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork
         0x122a2e000 -        0x122d18fff  com.apple.CoreServices.CarbonCore (1077.17 - 1077.17) <3A2E92FD-DEE2-3D45-9619-11500801A61C> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore
         0x122d95000 -        0x122e25ff7  com.apple.Metadata (10.7.0 - 800.30) <E107CE36-FBC3-35A5-84E0-864B4178FC5D> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Metadata
         0x122e8c000 -        0x122f03fff  com.apple.CoreServices.OSServices (600.4 - 600.4) <6BC86B46-AFD3-3F06-8659-2C954CBEBD43> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/OSServices.framework/Versions/A/OSServices
         0x122fa6000 -        0x123013fff  com.apple.SearchKit (1.4.0 - 1.4.0) <B9B8D510-A27E-36B0-93E9-17146D9E9045> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SearchKit.framework/Versions/A/SearchKit
         0x123057000 -        0x1230b2ffb  com.apple.AE (665.5 - 665.6) <9B17E7B7-D493-346A-827E-6DF1474E4977> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/AE
         0x1230e1000 -        0x1231abff7  com.apple.LaunchServices (572.32 - 572.32) <A4699DED-5101-3068-94F8-8D0B7A84BC79> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/LaunchServices
         0x123220000 -        0x123249fff  com.apple.DictionaryServices (1.2 - 208) <A539A058-BA57-35EE-AA08-D0B0E835127D> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/DictionaryServices.framework/Versions/A/DictionaryServices
         0x12326c000 -        0x123354fff  libxml2.2.dylib (26.11) <282EF071-71D7-3C56-9FFD-543F2A083F18> /usr/lib/libxml2.2.dylib
         0x12338a000 -        0x123397ff7  libxar.1.dylib (202) <5572AA71-E98D-3FE1-9402-BB4A84E0E71E> /usr/lib/libxar.1.dylib
         0x12339f000 -        0x1233a3fff  libpam.2.dylib (20) <B93CE8F5-DAA8-30A1-B1F6-F890509513CB> /usr/lib/libpam.2.dylib
         0x1233a8000 -        0x1233affff  com.apple.NetFS (6.0 - 4.0) <8E26C099-CE9D-3819-91A2-64EA929C6137> /System/Library/Frameworks/NetFS.framework/Versions/A/NetFS
         0x1233b7000 -        0x1233c2ff7  com.apple.NetAuth (5.0 - 5.0) <C811E662-9EC3-3B74-808A-A75D624F326B> /System/Library/PrivateFrameworks/NetAuth.framework/Versions/A/NetAuth
         0x1233ce000 -        0x1233e9ff7  libCRFSuite.dylib (34) <FFAE75FA-C54E-398B-AA97-18164CD9789D> /usr/lib/libCRFSuite.dylib
         0x1233f3000 -        0x123457fff  com.apple.datadetectorscore (5.0 - 354.5) <D4DBCCF4-9622-3AB9-9076-32579FCC2E39> /System/Library/PrivateFrameworks/DataDetectorsCore.framework/Versions/A/DataDetectorsCore
         0x123496000 -        0x123499fff  com.apple.TCC (1.0 - 1) <32A075D9-47FD-3E71-95BC-BFB0D583F41C> /System/Library/PrivateFrameworks/TCC.framework/Versions/A/TCC
         0x1234a0000 -        0x1234b7ff7  com.apple.CFOpenDirectory (10.9 - 173.90.1) <D7F2E159-CF6B-3EB1-9806-3BC59E63D24F> /System/Library/Frameworks/OpenDirectory.framework/Versions/A/Frameworks/CFOpenDirectory.framework/Versions/A/CFOpenDirectory
         0x1234d5000 -        0x1234fdff3  libxslt.1.dylib (13.12) <38FD3D1E-5335-398F-A663-47298EDDA231> /usr/lib/libxslt.1.dylib
         0x12350a000 -        0x1237defc7  com.apple.vImage (7.0 - 7.0) <D241DBFA-AC49-31E2-893D-EAAC31890C90> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vImage.framework/Versions/A/vImage
         0x123821000 -        0x1238ecfff  libvDSP.dylib (423.32) <3BF732BE-DDE0-38EB-8C54-E4E3C64F77A7> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvDSP.dylib
         0x1238f7000 -        0x1239a7ff7  libvMisc.dylib (423.32) <049C0735-1808-39B9-943F-76CB8021744F> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvMisc.dylib
         0x1239b3000 -        0x123d94ffe  libLAPACK.dylib (1094.5) <7E7A9B8D-1638-3914-BAE0-663B69865986> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib
         0x123df7000 -        0x123f65ff7  libBLAS.dylib (1094.5) <DE93A590-5FA5-32A2-A16C-5D7D7361769F> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
         0x123f8e000 -        0x124088fff  libFontParser.dylib (111.1.6) <77253632-B3F6-3151-ABA0-C1EF458668A8> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontParser.dylib
         0x12410a000 -        0x124151ffb  libFontRegistry.dylib (127.0.1) <F267F500-6E4A-3BE3-97C1-08AAA649E02E> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontRegistry.dylib
         0x124177000 -        0x12419bff7  libJPEG.dylib (1052) <6836134F-8701-3A6B-82F3-19A0A72CE21C> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJPEG.dylib
         0x1241a3000 -        0x1241fcff7  libTIFF.dylib (1052) <909BF5F6-6FC5-3126-9028-593130CAEBE6> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib
         0x12420b000 -        0x124226ff7  libPng.dylib (1052) <6A2D3E6E-AA2E-3B6F-9E3B-8D08A5A3B9C1> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib
         0x12422f000 -        0x124233ff7  libGIF.dylib (1052) <E51B4EFE-F99B-35F4-BE33-0456635EC7B3> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libGIF.dylib
         0x124238000 -        0x124326fff  libJP2.dylib (1052) <CB242C3E-F10C-38C5-A090-B757F9269143> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJP2.dylib
         0x124350000 -        0x124369ff7  com.apple.Kerberos (3.0 - 1) <F108AFEB-198A-3BAF-BCA5-9DFCE55EFF92> /System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos
         0x124382000 -        0x1243b1ff9  com.apple.GSS (4.0 - 2.0) <27FCA2B4-0767-3002-8755-862B19B5CF92> /System/Library/Frameworks/GSS.framework/Versions/A/GSS
         0x1243d0000 -        0x1244c1ff9  libiconv.2.dylib (41) <BB44B115-AC32-3877-A0ED-AEC6232A4563> /usr/lib/libiconv.2.dylib
         0x1244d1000 -        0x124536ffb  com.apple.Heimdal (4.0 - 2.0) <C28DBCAE-01AC-363A-9046-3BD33F225526> /System/Library/PrivateFrameworks/Heimdal.framework/Versions/A/Heimdal
         0x124562000 -        0x124566ff7  libheimdal-asn1.dylib (323.92.2) <979AEAA0-59B3-3E99-94B1-9BB9C6C45273> /usr/lib/libheimdal-asn1.dylib
         0x12456c000 -        0x124575ffd  com.apple.CommonAuth (4.0 - 2.0) <BD720379-757B-305C-A7BE-E00E680F8218> /System/Library/PrivateFrameworks/CommonAuth.framework/Versions/A/CommonAuth
         0x12457c000 -        0x1245effff  com.apple.securityfoundation (6.0 - 55122.3) <0AFCF575-97C3-3458-A72E-39DA07804EB9> /System/Library/Frameworks/SecurityFoundation.framework/Versions/A/SecurityFoundation
         0x12462f000 -        0x12466efff  libGLU.dylib (9.6.5) <7463B411-2DB0-3338-BC8D-403293E2CA34> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib
         0x12467d000 -        0x124685ffc  libGFXShared.dylib (9.6.5) <FCCD0CD3-02FD-3A79-B048-A14745D76CC8> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGFXShared.dylib
         0x12468c000 -        0x124697fff  libGL.dylib (9.6.5) <A5F36623-33E8-379D-A423-8F873018CD79> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib
         0x1246ab000 -        0x1246e9ff7  libGLImage.dylib (9.6.5) <C242B319-6F4B-3FB3-8FCE-0B77424F0BED> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLImage.dylib
         0x1246f1000 -        0x1246f4fff  libCoreVMClient.dylib (58.1) <EBC36C69-C896-3C3D-8589-3E9023E7E56F> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCoreVMClient.dylib
         0x1246fa000 -        0x124711ffa  libAVFAudio.dylib (32.2) <DAE7465E-DE8E-3900-84E7-F5DE72560E76> /System/Library/Frameworks/AVFoundation.framework/Versions/A/Resources/libAVFAudio.dylib
         0x124723000 -        0x124a59fff  com.apple.MediaToolbox (1.0 - 1273.57) <26FB55D1-11B8-3CEF-A8E1-40BC215B610F> /System/Library/Frameworks/MediaToolbox.framework/Versions/A/MediaToolbox
         0x124b07000 -        0x124b53ffe  com.apple.CoreMediaIO (408.0 - 4570) <292C2C20-E3D6-39EA-AEF8-CB2AC4934136> /System/Library/Frameworks/CoreMediaIO.framework/Versions/A/CoreMediaIO
         0x124b7b000 -        0x124b91fff  com.apple.CoreMediaAuthoring (2.2 - 947) <6317ACCD-98DB-3ACB-B662-98DEBF38F5BF> /System/Library/PrivateFrameworks/CoreMediaAuthoring.framework/Versions/A/CoreMediaAuthoring
         0x124ba9000 -        0x124cd8fef  com.apple.MediaControlSender (2.0 - 200.34.4) <FC24EC8D-2E46-3F76-AF63-749F30857B96> /System/Library/PrivateFrameworks/MediaControlSender.framework/Versions/A/MediaControlSender
         0x124d10000 -        0x124d3fff7  com.apple.CoreAVCHD (5.7.0 - 5700.4.3) <404369C0-ED9F-3010-8D2F-BC55285F7808> /System/Library/PrivateFrameworks/CoreAVCHD.framework/Versions/A/CoreAVCHD
         0x124d4a000 -        0x124d4fff7  com.apple.MediaAccessibility (1.0 - 43) <D309D83D-5FAE-37A4-85ED-FFBDA8B66B82> /System/Library/Frameworks/MediaAccessibility.framework/Versions/A/MediaAccessibility
         0x124d5a000 -        0x124d5cfff  com.apple.Mangrove (1.0 - 1) <72F5CBC7-4E78-374E-98EA-C3700136904E> /System/Library/PrivateFrameworks/Mangrove.framework/Versions/A/Mangrove
         0x124d62000 -        0x125139fef  CoreAUC (197.5) <2D7DC96C-BA83-3220-A03F-C790D50A23D8> /System/Library/PrivateFrameworks/CoreAUC.framework/Versions/A/CoreAUC
         0x125146000 -        0x125163ff7  com.apple.framework.Apple80211 (9.4 - 940.60) <043C7CFD-B57B-3F9D-B0FE-CA4B97C43968> /System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Apple80211
         0x12516f000 -        0x125177ff7  com.apple.AppleSRP (5.0 - 1) <ABC7F088-1FD5-3768-B9F3-847F355E90B3> /System/Library/PrivateFrameworks/AppleSRP.framework/Versions/A/AppleSRP
         0x12517e000 -        0x1251e5ff7  com.apple.CoreUtils (2.0 - 200.34.4) <E53B97FE-E067-33F6-A9C1-D4EC2A20FB9F> /System/Library/PrivateFrameworks/CoreUtils.framework/Versions/A/CoreUtils
         0x125211000 -        0x12523bff7  libpcap.A.dylib (42) <91D3FF51-D6FE-3C05-98C9-1182E0EC3D58> /usr/lib/libpcap.A.dylib
         0x125249000 -        0x1252affff  com.apple.framework.CoreWiFi (2.0 - 200.21.1) <5491896D-78C5-30B6-96E9-D8DDECF3BE73> /System/Library/Frameworks/CoreWiFi.framework/Versions/A/CoreWiFi
         0x12530e000 -        0x125556ff7  com.apple.CoreData (107 - 481.3) <E78734AA-E3D0-33CB-A014-620BBCAB2E96> /System/Library/Frameworks/CoreData.framework/Versions/A/CoreData
         0x12567e000 -        0x1256b6ff7  com.apple.RemoteViewServices (2.0 - 94) <3F34D630-3DDB-3411-BC28-A56A9B55EBDA> /System/Library/PrivateFrameworks/RemoteViewServices.framework/Versions/A/RemoteViewServices
         0x1256ef000 -        0x12581fff7  com.apple.desktopservices (1.8.3 - 1.8.3) <225BEC20-F8E0-3F22-9560-890A1A5B9050> /System/Library/PrivateFrameworks/DesktopServicesPriv.framework/Versions/A/DesktopServicesPriv
         0x12589f000 -        0x125b49ff5  com.apple.HIToolbox (2.1.1 - 698) <26FF0E2C-1CD7-311F-ACF0-84F3D5273AD6> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox
         0x125ca1000 -        0x125ca9ff7  com.apple.speech.recognition.framework (4.2.4 - 4.2.4) <98BBB3E4-6239-3EF1-90B2-84EA0D3B8D61> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SpeechRecognition.framework/Versions/A/SpeechRecognition
         0x125cb3000 -        0x125d97ff7  com.apple.coreui (2.2 - 231.1) <187DF89C-8A64-366D-8782-F90315FA3CD7> /System/Library/PrivateFrameworks/CoreUI.framework/Versions/A/CoreUI
         0x125e59000 -        0x125e6bff7  com.apple.MultitouchSupport.framework (245.13.1 - 245.13.1) <38262B92-C63F-35A0-997D-AD2EBF2F8338> /System/Library/PrivateFrameworks/MultitouchSupport.framework/Versions/A/MultitouchSupport
         0x125e7a000 -        0x125ebbfff  com.apple.PerformanceAnalysis (1.47 - 47) <95435F84-C251-3C48-B6CD-9EE7A63D6E26> /System/Library/PrivateFrameworks/PerformanceAnalysis.framework/Versions/A/PerformanceAnalysis
         0x12670c000 -        0x126724ff7  com.apple.GenerationalStorage (2.0 - 160.3) <64749B08-0212-3AC8-9B49-73D662B09304> /System/Library/PrivateFrameworks/GenerationalStorage.framework/Versions/A/GenerationalStorage
         0x126734000 -        0x126741fff  com.apple.Sharing (132.2 - 132.2) <F983394A-226D-3244-B511-FA51FDB6ADDA> /System/Library/PrivateFrameworks/Sharing.framework/Versions/A/Sharing
         0x126752000 -        0x126816ff7  com.apple.backup.framework (1.5.5 - 1.5.5) <CA77A4FC-7B76-30C7-94BE-FF4B8140D05A> /System/Library/PrivateFrameworks/Backup.framework/Versions/A/Backup
         0x12689e000 -        0x12692aff7  com.apple.ink.framework (10.9 - 207) <8A50B893-AD03-3826-8555-A54FEAF08F47> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Ink.framework/Versions/A/Ink
         0x12695d000 -        0x126998fff  com.apple.bom (14.0 - 193.1) <EF24A562-6D3C-379E-8B9B-FAE0E4A0EF7C> /System/Library/PrivateFrameworks/Bom.framework/Versions/A/Bom
         0x1269ab000 -        0x126c7cffc  com.apple.CoreImage (9.4.1) <7B28C3F3-8EB3-3150-A55D-EBCDBDCA4977> /System/Library/Frameworks/QuartzCore.framework/Versions/A/Frameworks/CoreImage.framework/Versions/A/CoreImage
         0x126d71000 -        0x126dc4fff  com.apple.ScalableUserInterface (1.0 - 1) <CF745298-7373-38D2-B3B1-727D5A569E48> /System/Library/Frameworks/QuartzCore.framework/Versions/A/Frameworks/ScalableUserInterface.framework/Versions/A/ScalableUserInterface
         0x126de9000 -        0x12721cffb  com.apple.vision.FaceCore (3.0.0 - 3.0.0) <F42BFC9C-0B16-35EF-9A07-91B7FDAB7FC5> /System/Library/PrivateFrameworks/FaceCore.framework/Versions/A/FaceCore
         0x127434000 -        0x12743eff7  com.apple.CrashReporterSupport (10.9 - 539) <B25A09EC-A021-32EC-86F8-05B4837E0EDE> /System/Library/PrivateFrameworks/CrashReporterSupport.framework/Versions/A/CrashReporterSupport
         0x12744c000 -        0x12749aff7  com.apple.opencl (2.3.59 - 2.3.59) <E37E2219-6EA7-3666-8DB5-8FC60EFB0BC9> /System/Library/Frameworks/OpenCL.framework/Versions/A/OpenCL
         0x1274b2000 -        0x1274beffb  com.apple.AppleFSCompression (56.92.2 - 1.0) <16542F97-9D21-317D-8A50-4C34AAD35F41> /System/Library/PrivateFrameworks/AppleFSCompression.framework/Versions/A/AppleFSCompression
         0x1274c6000 -        0x1274dfff7  com.apple.Ubiquity (1.3 - 289) <C7F1B734-CE81-334D-BE41-8B20D95A1F9B> /System/Library/PrivateFrameworks/Ubiquity.framework/Versions/A/Ubiquity
         0x1274f2000 -        0x127522fff  com.apple.IconServices (25 - 25.17) <4751127E-FBD5-3ED5-8510-08D4E4166EFE> /System/Library/PrivateFrameworks/IconServices.framework/Versions/A/IconServices
         0x12754b000 -        0x127570ff7  com.apple.ChunkingLibrary (2.0 - 155.1) <B845DC7A-D1EA-31E2-967C-D1FE0C628036> /System/Library/PrivateFrameworks/ChunkingLibrary.framework/Versions/A/ChunkingLibrary
         0x12757c000 -        0x1275fdfff  com.apple.CoreSymbolication (3.0.1 - 141.0.6) <D46DE002-1FEB-38B7-8583-3DF3496274F5> /System/Library/PrivateFrameworks/CoreSymbolication.framework/Versions/A/CoreSymbolication
         0x12764e000 -        0x1276a6ff7  com.apple.Symbolication (1.4 - 129.0.2) <3DCCAB8A-6FA1-3BB9-B4D3-A3CBDB3BDF04> /System/Library/PrivateFrameworks/Symbolication.framework/Versions/A/Symbolication
         0x1276ed000 -        0x12771cfff  com.apple.DebugSymbols (106 - 106) <E1BDED08-523A-36F4-B2DA-9D5C712F0AC7> /System/Library/PrivateFrameworks/DebugSymbols.framework/Versions/A/DebugSymbols
         0x127737000 -        0x12773dff7  com.apple.XPCService (2.0 - 1) <2CE632D7-FE57-36CF-91D4-C57D0F2E0BFE> /System/Library/PrivateFrameworks/XPCService.framework/Versions/A/XPCService
         0x127747000 -        0x127751ff7  com.apple.AppSandbox (3.0 - 1) <9F27DC25-C566-3AEF-92D3-DCFE7836916D> /System/Library/PrivateFrameworks/AppSandbox.framework/Versions/A/AppSandbox
         0x12775c000 -        0x12776fff7  com.apple.AppContainer (3.0 - 1) <BD342039-430E-39FE-BC2D-8F97B557548E> /System/Library/PrivateFrameworks/AppContainer.framework/Versions/A/AppContainer
         0x127784000 -        0x127786fff  com.apple.SecCodeWrapper (3.0 - 1) <DE7CA981-2B8B-34AC-845D-06D5C8F10441> /System/Library/PrivateFrameworks/SecCodeWrapper.framework/Versions/A/SecCodeWrapper
         0x12778c000 -        0x127790fff  com.apple.CommonPanels (1.2.6 - 96) <6B434AFD-50F8-37C7-9A56-162C17E375B3> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/CommonPanels.framework/Versions/A/CommonPanels
         0x127797000 -        0x12779afff  com.apple.help (1.3.3 - 46) <AE763646-D07A-3F9A-ACD4-F5CBD734EE36> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Help.framework/Versions/A/Help
         0x1277a0000 -        0x1277b2fff  com.apple.ImageCapture (9.0 - 9.0) <BE0B65DA-3031-359B-8BBA-B9803D4ADBF4> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/ImageCapture.framework/Versions/A/ImageCapture
         0x1277cd000 -        0x1277e5fff  com.apple.openscripting (1.4.1 - 157.1) <2C6C6498-D88E-3D9B-B933-9873890F382E> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/OpenScripting.framework/Versions/A/OpenScripting
         0x1277f7000 -        0x1277f9ff7  com.apple.securityhi (9.0 - 55005) <0CB82072-BA4B-357B-BE46-A96D317C1D91> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SecurityHI.framework/Versions/A/SecurityHI
         0x1277ff000 -        0x127d22fff  com.apple.QuartzComposer (5.1 - 319.2) <E8D9D10C-D5E7-3C7A-9923-D5305578E6BF> /System/Library/Frameworks/Quartz.framework/Versions/A/Frameworks/QuartzComposer.framework/Versions/A/QuartzComposer
         0x128044000 -        0x1280dfff7  com.apple.PDFKit (2.9.2 - 2.9.2) <DF2CE219-6256-3A8A-BDB1-51EF556F5BC8> /System/Library/Frameworks/Quartz.framework/Versions/A/Frameworks/PDFKit.framework/Versions/A/PDFKit
         0x128152000 -        0x128176fff  com.apple.quartzfilters (1.8.0 - 1.7.0) <39C08086-9866-372F-9420-81F5689149DF> /System/Library/Frameworks/Quartz.framework/Versions/A/Frameworks/QuartzFilters.framework/Versions/A/QuartzFilters
         0x1281a5000 -        0x128406fff  com.apple.imageKit (2.5 - 774) <AACDE16E-ED9F-3B3F-A792-69BA1942753B> /System/Library/Frameworks/Quartz.framework/Versions/A/Frameworks/ImageKit.framework/Versions/A/ImageKit
         0x128651000 -        0x128722fff  com.apple.QuickLookUIFramework (5.0 - 622.7) <13841701-34C2-353D-868D-3E08D020C90F> /System/Library/Frameworks/Quartz.framework/Versions/A/Frameworks/QuickLookUI.framework/Versions/A/QuickLookUI
         0x1287d4000 -        0x128b4bff6  com.apple.JavaScriptCore (9537 - 9537.78.1) <8623A109-9E9D-3E3B-A8E1-6EE447C0110C> /System/Library/Frameworks/JavaScriptCore.framework/Versions/A/JavaScriptCore
         0x128c44000 -        0x128d85fff  com.apple.QTKit (7.7.3 - 2826.34) <3BB88D64-71FA-3824-A52A-D51C761E6EE0> /System/Library/Frameworks/QTKit.framework/Versions/A/QTKit
         0x128e9a000 -        0x128e9dfff  com.apple.AppleSystemInfo (3.0 - 3.0) <61FE171D-3D88-313F-A832-280AEC8F4AB7> /System/Library/PrivateFrameworks/AppleSystemInfo.framework/Versions/A/AppleSystemInfo
         0x128ea4000 -        0x128f2dff7  com.apple.CorePDF (4.0 - 4) <ADCCD075-2572-3C64-9C40-67A30C9CB07D> /System/Library/PrivateFrameworks/CorePDF.framework/Versions/A/CorePDF
         0x128f82000 -        0x128fd3fff  com.apple.QuickLookFramework (5.0 - 622.7) <17685CEC-C94B-3F83-ADE1-B24840B35E44> /System/Library/Frameworks/QuickLook.framework/Versions/A/QuickLook
         0x12900f000 -        0x129018fff  com.apple.DisplayServicesFW (2.8 - 360.8.14) <816A9CED-1BC0-3C76-8103-1B9BE0F723BB> /System/Library/PrivateFrameworks/DisplayServices.framework/Versions/A/DisplayServices
         0x129023000 -        0x129027ff7  com.apple.ServerInformation (2.1.1 - 1) <7FAF2B82-FE90-3398-98D8-0F84C6FE6A4A> /System/Library/PrivateFrameworks/ServerInformation.framework/Versions/A/ServerInformation
         0x12902e000 -        0x129040ff7  com.apple.CoreBluetooth (1.0 - 1) <67A00F44-563E-3C55-9187-34D502D84DDE> /System/Library/Frameworks/IOBluetooth.framework/Versions/A/Frameworks/CoreBluetooth.framework/Versions/A/CoreBluetooth
         0x129055000 -        0x12906dfff  libexpat.1.dylib (12) <97F4A9A7-CB3E-3BBF-9314-4997FC770E52> /usr/lib/libexpat.1.dylib
         0x129077000 -        0x129235fff  com.apple.GeoServices (1.0 - 702.15.12) <850DC458-20CC-3E16-BB50-7C9FDBA308D3> /System/Library/PrivateFrameworks/GeoServices.framework/Versions/A/GeoServices
         0x12938d000 -        0x129397ff7  com.apple.ProtocolBuffer (1 - 182.1.3) <82E68598-A8AA-3AF1-843E-2A64F19472D4> /System/Library/PrivateFrameworks/ProtocolBuffer.framework/Versions/A/ProtocolBuffer
         0x12dce2000 -        0x12dd0efff  com.apple.CoreServicesInternal (184.9 - 184.9) <4DEA54F9-81D6-3EDB-AA3C-1F9C497B3379> /System/Library/PrivateFrameworks/CoreServicesInternal.framework/CoreServicesInternal
      0x7fff6e82c000 -     0x7fff6e85f887  dyld (239.5) <1D3130FE-FE7E-3C4C-8E74-EB51895B6BA5> /usr/lib/dyld
  
  External Modification Summary:
    Calls made by other processes targeting this process:
      task_for_pid: 0
      thread_create: 0
      thread_set_state: 0
    Calls made by this process:
      task_for_pid: 0
      thread_create: 0
      thread_set_state: 0
    Calls made by all processes on this machine:
      task_for_pid: 2664943
      thread_create: 0
      thread_set_state: 0
  
  VM Region Summary:
  ReadOnly portion of Libraries: Total=569.3M resident=317.3M(56%) swapped_out_or_unallocated=252.0M(44%)
  Writable regions: Total=186.0M written=19.0M(10%) resident=24.0M(13%) swapped_out=0K(0%) unallocated=161.9M(87%)
  
  REGION TYPE                      VIRTUAL
  ===========                      =======
  Dispatch continuations             16.0M
  Kernel Alloc Once                     4K
  MALLOC                             93.1M
  MALLOC (admin)                       32K
  Mach message                         24K
  Memory Tag 241                      296K
  STACK GUARD                        56.0M
  Stack                              57.1M
  VM_ALLOCATE                        2712K
  __DATA                             35.6M
  __IMAGE                             528K
  __LINKEDIT                        259.8M
  __TEXT                            309.6M
  __UNICODE                           544K
  mapped file                        43.0M
  shared memory                         4K
  ===========                      =======
  TOTAL                             874.4M

Activity

$ /bin/bash -lc "curl -L --fail -sS 'https://user-images.githubusercontent.com/4484096/150240439-c4f04d57-5fe9-4f1f-825e-4971a7d36916.png' -o investigation/continuation.png && curl -L --fail -sS 'https://user-images.githubusercontent.com/4484096/155889371-28b99fcc-d714-43b5-a202-abcc5a5ad50b.png' -o investigation/instruments.png && curl -L --fail -sS 'https://user-images.githubusercontent.com/4484096/190880693-b76a54ee-c443-4dfd-97ea-3134684a044a.png' -o investigation/permission.png && curl -L --fail -sS 'https://github.com/blueboxd/chromium-legacy/files/7850488/Kernel_2022-01-11-182654_Jonathans-MacBook-Air.panic.zip' -o investigation/original-panic.zip && curl -L --fail -sS 'https://github.com/blueboxd/chromium-legacy/files/10418691/Kernel_2023-01-14-184339_Hoangs-MacBook-Pro.panic.log' -o investigation/2023-panic.log"
status: Completed · exit 0

Activity

$ /bin/bash -lc "sed -n '1160,1400p' xnu-2422/osfmk/kern/wait_queue.c; sed -n '700,830p' xnu-2422/osfmk/ipc/ipc_mqueue.c; sed -n '850,990p' xnu-2422/osfmk/ipc/ipc_port.c; sed -n '235,290p' xnu-2422/osfmk/kern/sync_sema.c; sed -n '1700,1765p' xnu-2422/osfmk/ipc/ipc_port.c"
status: Completed · exit 0
  
  out:
  	wqs_unlock(wq_set);
  	splx(s);
  
  	return KERN_SUCCESS;
  }
  
  /*
   *	Routine:	wait_queue_assert_wait64_locked
   *	Purpose:
   *		Insert the current thread into the supplied wait queue
   *		waiting for a particular event to be posted to that queue.
   *
   *	Conditions:
   *		The wait queue is assumed locked.
   *		The waiting thread is assumed locked.
   *
   */
  __private_extern__ wait_result_t
  wait_queue_assert_wait64_locked(
  	wait_queue_t wq,
  	event64_t event,
  	wait_interrupt_t interruptible,
  	wait_timeout_urgency_t urgency,
  	uint64_t deadline,
  	uint64_t leeway,
  	thread_t thread)
  {
  	wait_result_t wait_result;
  	boolean_t realtime;
  
  	if (!wait_queue_assert_possible(thread))
  		panic("wait_queue_assert_wait64_locked");
  
  	if (wq->wq_type == _WAIT_QUEUE_SET_inited) {
  		wait_queue_set_t wqs = (wait_queue_set_t)wq;
  
  		if (event == NO_EVENT64 && wqs_is_preposted(wqs))
  			return(THREAD_AWAKENED);
  	}
  
  	/*
  	 * Realtime threads get priority for wait queue placements.
  	 * This allows wait_queue_wakeup_one to prefer a waiting
  	 * realtime thread, similar in principle to performing
  	 * a wait_queue_wakeup_all and allowing scheduler prioritization
  	 * to run the realtime thread, but without causing the
  	 * lock contention of that scenario.
  	 */
  	realtime = (thread->sched_pri >= BASEPRI_REALTIME);
  
  	/*
  	 * This is the extent to which we currently take scheduling attributes
  	 * into account.  If the thread is vm priviledged, we stick it at
  	 * the front of the queue.  Later, these queues will honor the policy
  	 * value set at wait_queue_init time.
  	 */
  	wait_result = thread_mark_wait_locked(thread, interruptible);
  	if (wait_result == THREAD_WAITING) {
  		if (!wq->wq_fifo
  			|| (thread->options & TH_OPT_VMPRIV)
  			|| realtime)
  			enqueue_head(&wq->wq_queue, (queue_entry_t) thread);
  		else
  			enqueue_tail(&wq->wq_queue, (queue_entry_t) thread);
  
  		thread->wait_event = event;
  		thread->wait_queue = wq;
  
  		if (deadline != 0) {
  
  			if (!timer_call_enter_with_leeway(&thread->wait_timer, NULL,
  				deadline, leeway, urgency, FALSE))
  				thread->wait_timer_active++;
  			thread->wait_timer_is_set = TRUE;
  		}
  		if (wait_queue_global(wq)) {
  			wq->wq_eventmask = wq->wq_eventmask | CAST_TO_EVENT_MASK(event);
  		}
  
  	}
  	return(wait_result);
  }
  
  /*
   *	Routine:	wait_queue_assert_wait
   *	Purpose:
   *		Insert the current thread into the supplied wait queue
   *		waiting for a particular event to be posted to that queue.
   *
   *	Conditions:
   *		nothing of interest locked.
   */
  wait_result_t
  wait_queue_assert_wait(
  	wait_queue_t wq,
  	event_t event,
  	wait_interrupt_t interruptible,
  	uint64_t deadline)
  {
  	spl_t s;
  	wait_result_t ret;
  	thread_t thread = current_thread();
  
  	/* If it is an invalid wait queue, you can't wait on it */
  	if (!wait_queue_is_valid(wq))
  		return (thread->wait_result = THREAD_RESTART);
  
  	s = splsched();
  	wait_queue_lock(wq);
  	thread_lock(thread);
  	ret = wait_queue_assert_wait64_locked(wq, CAST_DOWN(event64_t,event),
  					      interruptible,
  					      TIMEOUT_URGENCY_SYS_NORMAL,
  					      deadline, 0,
  					      thread);
  	thread_unlock(thread);
  	wait_queue_unlock(wq);
  	splx(s);
  	return(ret);
  }
  
  /*
   *	Routine:	wait_queue_assert_wait_with_leeway
   *	Purpose:
   *		Insert the current thread into the supplied wait queue
   *		waiting for a particular event to be posted to that queue.
   *		Deadline values are specified with urgency and leeway.
   *
   *	Conditions:
   *		nothing of interest locked.
   */
  wait_result_t
  wait_queue_assert_wait_with_leeway(
  	wait_queue_t wq,
  	event_t event,
  	wait_interrupt_t interruptible,
  	wait_timeout_urgency_t urgency,
  	uint64_t deadline,
  	uint64_t leeway)
  {
  	spl_t s;
  	wait_result_t ret;
  	thread_t thread = current_thread();
  
  	/* If it is an invalid wait queue, you can't wait on it */
  	if (!wait_queue_is_valid(wq))
  		return (thread->wait_result = THREAD_RESTART);
  
  	s = splsched();
  	wait_queue_lock(wq);
  	thread_lock(thread);
  	ret = wait_queue_assert_wait64_locked(wq, CAST_DOWN(event64_t,event),
  					      interruptible,
  					      urgency, deadline, leeway,
  					      thread);
  	thread_unlock(thread);
  	wait_queue_unlock(wq);
  	splx(s);
  	return(ret);
  }
  
  /*
   *	Routine:	wait_queue_assert_wait64
   *	Purpose:
   *		Insert the current thread into the supplied wait queue
   *		waiting for a particular event to be posted to that queue.
   *	Conditions:
   *		nothing of interest locked.
   */
  wait_result_t
  wait_queue_assert_wait64(
  	wait_queue_t wq,
  	event64_t event,
  	wait_interrupt_t interruptible,
  	uint64_t deadline)
  {
  	spl_t s;
  	wait_result_t ret;
  	thread_t thread = current_thread();
  
  	/* If it is an invalid wait queue, you cant wait on it */
  	if (!wait_queue_is_valid(wq))
  		return (thread->wait_result = THREAD_RESTART);
  
  	s = splsched();
  	wait_queue_lock(wq);
  	thread_lock(thread);
  	ret = wait_queue_assert_wait64_locked(wq, event, interruptible,
  					      TIMEOUT_URGENCY_SYS_NORMAL,
  					      deadline, 0,
  					      thread);
  	thread_unlock(thread);
  	wait_queue_unlock(wq);
  	splx(s);
  	return(ret);
  }
  
  /*
   *	Routine:	wait_queue_assert_wait64_with_leeway
   *	Purpose:
   *		Insert the current thread into the supplied wait queue
   *		waiting for a particular event to be posted to that queue.
   *		Deadline values are specified with urgency and leeway.
   *	Conditions:
   *		nothing of interest locked.
   */
  wait_result_t
  wait_queue_assert_wait64_with_leeway(
  	wait_queue_t wq,
  	event64_t event,
  	wait_interrupt_t interruptible,
  	wait_timeout_urgency_t urgency,
  	uint64_t deadline,
  	uint64_t leeway)
  {
  	spl_t s;
  	wait_result_t ret;
  	thread_t thread = current_thread();
  
  	/* If it is an invalid wait queue, you cant wait on it */
  	if (!wait_queue_is_valid(wq))
  		return (thread->wait_result = THREAD_RESTART);
  
  	s = splsched();
  	wait_queue_lock(wq);
  	thread_lock(thread);
  	ret = wait_queue_assert_wait64_locked(wq, event, interruptible,
  					      urgency, deadline, leeway,
  					      thread);
  	thread_unlock(thread);
  	wait_queue_unlock(wq);
  	splx(s);
  	return(ret);
  }
  
  /*
   *	Routine:	_wait_queue_select64_all
   *	Purpose:
   *		Select all threads off a wait queue that meet the
  	if (wresult == THREAD_WAITING) {
  		counter((interruptible == THREAD_ABORTSAFE) ?
  			c_ipc_mqueue_receive_block_user++ :
  			c_ipc_mqueue_receive_block_kernel++);
  
  		if (self->ith_continuation)
  			thread_block(ipc_mqueue_receive_continue);
  			/* NOTREACHED */
  
  		wresult = thread_block(THREAD_CONTINUE_NULL);
  	}
  	ipc_mqueue_receive_results(wresult);
  }
  
  wait_result_t
  ipc_mqueue_receive_on_thread(
          ipc_mqueue_t            mqueue,
  	mach_msg_option_t       option,
  	mach_msg_size_t         max_size,
  	mach_msg_timeout_t      rcv_timeout,
  	int                     interruptible,
  	thread_t                thread)
  {
  	ipc_kmsg_queue_t        kmsgs;
  	wait_result_t           wresult;
  	uint64_t		deadline;
  	spl_t                   s;
  #if CONFIG_MACF_MACH
  	ipc_labelh_t lh;
  	task_t task;
  	int rc;
  #endif
  
  	s = splsched();
  	imq_lock(mqueue);
  
  	if (imq_is_set(mqueue)) {
  		queue_t q;
  
  		q = &mqueue->imq_preposts;
  
  		/*
  		 * If we are waiting on a portset mqueue, we need to see if
  		 * any of the member ports have work for us.  Ports that
  		 * have (or recently had) messages will be linked in the
  		 * prepost queue for the portset. By holding the portset's
  		 * mqueue lock during the search, we tie up any attempts by
  		 * mqueue_deliver or portset membership changes that may
  		 * cross our path.
  		 */
  	search_set:
  		while(!queue_empty(q)) {
  			wait_queue_link_t wql;
  			ipc_mqueue_t port_mq;
  
  			queue_remove_first(q, wql, wait_queue_link_t, wql_preposts);
  			assert(!wql_is_preposted(wql));
  
  			/*
  			 * This is a lock order violation, so we have to do it
  			 * "softly," putting the link back on the prepost list
  			 * if it fails (at the tail is fine since the order of
  			 * handling messages from different sources in a set is
  			 * not guaranteed and we'd like to skip to the next source
  			 * if one is available).
  			 */
  			port_mq = (ipc_mqueue_t)wql->wql_queue;
  			if (!imq_lock_try(port_mq)) {
  				queue_enter(q, wql, wait_queue_link_t, wql_preposts);
  				imq_unlock(mqueue);
  				splx(s);
  				mutex_pause(0);
  				s = splsched();
  				imq_lock(mqueue);
  				goto search_set; /* start again at beginning - SMP */
  			}
  
  			/*
  			 * If there are no messages on this queue, just skip it
  			 * (we already removed the link from the set's prepost queue).
  			 */
  			kmsgs = &port_mq->imq_messages;
  			if (ipc_kmsg_queue_first(kmsgs) == IKM_NULL) {
  				imq_unlock(port_mq);
  				continue;
  			}
  
  			/*
  			 * There are messages, so reinsert the link back
  			 * at the tail of the preposted queue (for fairness)
  			 * while we still have the portset mqueue locked.
  			 */
  			queue_enter(q, wql, wait_queue_link_t, wql_preposts);
  			imq_unlock(mqueue);
  
  			/*
  			 * Continue on to handling the message with just
  			 * the port mqueue locked.
  			 */
  			ipc_mqueue_select_on_thread(port_mq, option, max_size, thread);
  			imq_unlock(port_mq);
  #if CONFIG_MACF_MACH
  			if (thread->task != TASK_NULL &&
  			    thread->ith_kmsg != NULL &&
  			    thread->ith_kmsg->ikm_sender != NULL) {
  				lh = thread->ith_kmsg->ikm_sender->label;
  				tasklabel_lock(thread->task);
  				ip_lock(lh->lh_port);
  				rc = mac_port_check_receive(&thread->task->maclabel,
                                                              &lh->lh_label);
  				ip_unlock(lh->lh_port);
  				tasklabel_unlock(thread->task);
  				if (rc)
  					thread->ith_state = MACH_RCV_INVALID_DATA;
  			}
  #endif
  			splx(s);
  			return THREAD_NOT_WAITING;
  
  		}
  
  	} else {
  
  		/*
  		 * Receive on a single port. Just try to get the messages.
  		 */
  	  	kmsgs = &mqueue->imq_messages;
  		if (ipc_kmsg_queue_first(kmsgs) != IKM_NULL) {
  			ipc_mqueue_select_on_thread(mqueue, option, max_size, thread);
  			imq_unlock(mqueue);
  #if CONFIG_MACF_MACH
  			if (MACH_PORT_VALID(name) && IP_VALID(soright)) {
  				ipc_notify_dead_name(soright, name);
  			}
  		}
  	}
  }
  
  
  /*
   *	Routine:	ipc_port_destroy
   *	Purpose:
   *		Destroys a port.  Cleans up queued messages.
   *
   *		If the port has a backup, it doesn't get destroyed,
   *		but is sent in a port-destroyed notification to the backup.
   *	Conditions:
   *		The port is locked and alive; nothing else locked.
   *		The caller has a reference, which is consumed.
   *		Afterwards, the port is unlocked and dead.
   */
  
  void
  ipc_port_destroy(
  	ipc_port_t	port)
  {
  	ipc_port_t pdrequest, nsrequest;
  	ipc_mqueue_t mqueue;
  	ipc_kmsg_t kmsg;
  
  #if IMPORTANCE_INHERITANCE
  	task_t release_imp_task = TASK_NULL;
  	thread_t self = current_thread();
  	boolean_t top = (self->ith_assertions == 0);
  	natural_t assertcnt = 0;
  #endif /* IMPORTANCE_INHERITANCE */
  
  	assert(ip_active(port));
  	/* port->ip_receiver_name is garbage */
  	/* port->ip_receiver/port->ip_destination is garbage */
  	assert(port->ip_pset_count == 0);
  	assert(port->ip_mscount == 0);
  
  	/* check for a backup port */
  	pdrequest = port->ip_pdrequest;
  
  #if IMPORTANCE_INHERITANCE
  	/* determine how may assertions to drop and from whom */
  	if (port->ip_tempowner != 0) {
  		assert(top);
  		if (port->ip_taskptr != 0) {
  			release_imp_task = port->ip_imp_task;
  			port->ip_imp_task = TASK_NULL;
  			port->ip_taskptr = 0;
  			assertcnt = port->ip_impcount;
  		}
  		/* Otherwise, nothing to drop */
  	} else {
  		assert(port->ip_taskptr == 0);
  		assertcnt = port->ip_impcount;
  		if (pdrequest != IP_NULL)
  			/* mark in limbo for the journey */
  			port->ip_tempowner = 1;
  	}
  
  	if (top)
  		self->ith_assertions = assertcnt;
  #endif /* IMPORTANCE_INHERITANCE */
  
  	if (pdrequest != IP_NULL) {
  		/* we assume the ref for pdrequest */
  		port->ip_pdrequest = IP_NULL;
  
  		/* make port be in limbo */
  		port->ip_receiver_name = MACH_PORT_NULL;
  		port->ip_destination = IP_NULL;
  		ip_unlock(port);
  
  		/* consumes our refs for port and pdrequest */
  		ipc_notify_port_destroyed(pdrequest, port);
  
  		goto drop_assertions;
  	}
  
  	/* once port is dead, we don't need to keep it locked */
  
  	port->ip_object.io_bits &= ~IO_BITS_ACTIVE;
  	port->ip_timestamp = ipc_port_timestamp();
  
  	/*
  	 * If the port has a preallocated message buffer and that buffer
  	 * is not inuse, free it.  If it has an inuse one, then the kmsg
  	 * free will detect that we freed the association and it can free it
  	 * like a normal buffer.
  	 */
  	if (IP_PREALLOC(port)) {
  		ipc_port_t inuse_port;
  
  		kmsg = port->ip_premsg;
  		assert(kmsg != IKM_NULL);
  		inuse_port = ikm_prealloc_inuse_port(kmsg);
  		IP_CLEAR_PREALLOC(port, kmsg);
  		ip_unlock(port);
  		if (inuse_port != IP_NULL) {
  			assert(inuse_port == port);
  		} else {
  			ipc_kmsg_free(kmsg);
  		}
  	} else {
  		ip_unlock(port);
  	}
  
  	/* throw away no-senders request */
  	nsrequest = port->ip_nsrequest;
  	if (nsrequest != IP_NULL)
  		ipc_notify_send_once(nsrequest); /* consumes ref */
  
  	/* destroy any queued messages */
  	mqueue = &port->ip_messages;
  	ipc_mqueue_destroy(mqueue);
  
  	/* generate dead-name notifications */
  	ipc_port_dnnotify(port);
  
  	ipc_kobject_destroy(port);
  
  	ip_release(port); /* consume caller's ref */
  
   drop_assertions:
  #if IMPORTANCE_INHERITANCE
  	if (release_imp_task != TASK_NULL) {
  		if (assertcnt > 0) {
  			assert(top);
  			self->ith_assertions = 0;
  			assert(release_imp_task->imp_receiver != 0);
  			task_importance_drop_internal_assertion(release_imp_task, assertcnt);
  		}
  		task_deallocate(release_imp_task);
  
  	} else if (assertcnt > 0) {
  		if (top) {
  			self->ith_assertions = 0;
  {
  	int				old_count;
  	spl_t			spl_level;
  
  
  	if (task == TASK_NULL || semaphore == SEMAPHORE_NULL)
  		return KERN_INVALID_ARGUMENT;
  
  	/*
  	 *  Disown semaphore
  	 */
  	task_lock(task);
  	if (semaphore->owner != task) {
  		task_unlock(task);
  		return KERN_INVALID_ARGUMENT;
  	}
  	remqueue((queue_entry_t) semaphore);
  	semaphore->owner = TASK_NULL;
  	task->semaphores_owned--;
  	task_unlock(task);
  
  	spl_level = splsched();
  	semaphore_lock(semaphore);
  
  	/*
  	 *  Deactivate semaphore
  	 */
  	assert(semaphore->active);
  	semaphore->active = FALSE;
  
  	/*
  	 *  Wakeup blocked threads
  	 */
  	old_count = semaphore->count;
  	semaphore->count = 0;
  
  	if (old_count < 0) {
  		wait_queue_wakeup64_all_locked(&semaphore->wait_queue,
  					     SEMAPHORE_EVENT,
  					     THREAD_RESTART,
  					     TRUE);		/* unlock? */
  	} else {
  		semaphore_unlock(semaphore);
  	}
  	splx(spl_level);
  
  	/*
  	 *  Deallocate
  	 *
  	 *  Drop the task's semaphore reference, which in turn deallocates
  	 *  the semaphore structure if the reference count goes to zero.
  	 */
  	semaphore_dereference(semaphore);
  	return KERN_SUCCESS;
  }
  
  	mac_port_label_init(&port->ip_label);
  	mac_port_label_associate_kernel(&port->ip_label, space == ipc_space_reply);
  #endif
  
  	return port;
  }
  
  /*
   *	Routine:	ipc_port_dealloc_special
   *	Purpose:
   *		Deallocate a port in a special space.
   *		Consumes one ref for the port.
   *	Conditions:
   *		Nothing locked.
   */
  
  void
  ipc_port_dealloc_special(
  	ipc_port_t			port,
  	__assert_only ipc_space_t	space)
  {
  	ip_lock(port);
  	assert(ip_active(port));
  //	assert(port->ip_receiver_name != MACH_PORT_NULL);
  	assert(port->ip_receiver == space);
  
  	/*
  	 *	We clear ip_receiver_name and ip_receiver to simplify
  	 *	the ipc_space_kernel check in ipc_mqueue_send.
  	 */
  
  	port->ip_receiver_name = MACH_PORT_NULL;
  	port->ip_receiver = IS_NULL;
  
  	/* relevant part of ipc_port_clear_receiver */
  	ipc_port_set_mscount(port, 0);
  	port->ip_messages.imq_seqno = 0;
  
  	ipc_port_destroy(port);
  }
  
  /*
   *	Routine:	ipc_port_finalize
   *	Purpose:
   *		Called on last reference deallocate to
   *		free any remaining data associated with the
   *		port.
   *	Conditions:
   *		Nothing locked.
   */
  void
  ipc_port_finalize(
  	ipc_port_t		port)
  {
  	ipc_port_request_t requests = port->ip_requests;
  
  	assert(!ip_active(port));
  	if (requests != IPR_NULL) {
  		ipc_table_size_t its = requests->ipr_size;
  		it_requests_free(its, requests);
  		port->ip_requests = IPR_NULL;
  	}
  
  #if	MACH_ASSERT
  	ipc_port_track_dealloc(port);
  #endif	/* MACH_ASSERT */

Activity

image: /Users/Jonathan/Desktop/Question/investigation/continuation.png

Activity

image: /Users/Jonathan/Desktop/Question/investigation/instruments.png

Activity

image: /Users/Jonathan/Desktop/Question/investigation/permission.png

Activity

$ /bin/bash -lc "rg -n 'thread_block_reason|thread_invoke\\(|wait_result =|call_continuation\\(' xnu-2422/osfmk/kern/sched_prim.c; sed -n '2300,2390p' xnu-2422/osfmk/vm/vm_fault.c; sed -n '990,1070p' xnu-2422/osfmk/vm/vm_fault.c; rg -n 'wqs_prepost|wait_queue_set_allocate|wait_queue_set_init' xnu-2422/bsd/kern/kern_event.c xnu-2422/osfmk/ipc/ipc_mqueue.c xnu-2422/osfmk/kern/wait_queue.h; sed -n '1240,1265p' xnu-2422/bsd/kern/kern_event.c"
status: Completed · exit 0
  xnu-2422/osfmk/kern/wait_queue.h:98:	queue_head_t	wqs_preposts;	/* preposted links */
  xnu-2422/osfmk/kern/wait_queue.h:103:#define wqs_prepost	wqs_wait_queue.wq_prepost
  xnu-2422/osfmk/kern/wait_queue.h:211:#define wqs_is_preposted(wqs)	((wqs)->wqs_prepost && !queue_empty(&(wqs)->wqs_preposts))
  xnu-2422/osfmk/kern/wait_queue.h:312:extern kern_return_t wait_queue_set_init(
  xnu-2422/osfmk/ipc/ipc_mqueue.c:118:		wait_queue_set_init(&mqueue->imq_set_queue, SYNC_POLICY_FIFO|SYNC_POLICY_PREPOST);
  						kn->kn_fop->f_detach(kn);
  						knote_drop(kn, p);
  					}
  					proc_fdlock(p);
  					/* start over at beginning of list */
  					kn = SLIST_FIRST(&fdp->fd_knhash[i]);
  					continue;
  				}
  				kn = SLIST_NEXT(kn, kn_link);
  			}
  		}
  	}
  	proc_fdunlock(p);
  
  	/*
  	 * before freeing the wait queue set for this kqueue,
  	 * make sure it is unlinked from all its containing (select) sets.
  	 */
  	wait_queue_unlink_all((wait_queue_t)kq->kq_wqs);
  	wait_queue_set_free(kq->kq_wqs);
  	lck_spin_destroy(&kq->kq_lock, kq_lck_grp);
  	FREE_ZONE(kq, sizeof (struct kqueue), M_KQUEUE);
  }
  
  int
  kqueue_body(struct proc *p, fp_allocfn_t fp_zalloc, void *cra, int32_t *retval)

Activity

$ /bin/bash -lc "gh api 'repos/apple-oss-distributions/xnu/contents/osfmk/kern/wait_queue.c?ref=xnu-3248.60.10' --jq .content | base64 --decode > investigation/wait_queue-10.11.c && gh api 'repos/apple-oss-distributions/xnu/contents/bsd/kern/kern_event.c?ref=xnu-3248.60.10' --jq .content | base64 --decode > investigation/kern_event-10.11.c && gh api repos/blueboxd/chromium-legacy/commits/e0cff58db7f41e2b0b68e058ec49a98f215265c5 > investigation/revert-commit.json"
status: Failed · exit 65
  gh: Not Found (HTTP 404)
  Invalid character in input stream.

Activity

$ /bin/bash -lc "sed -n '2285,2362p' xnu-2422/osfmk/kern/sched_prim.c; sed -n '2690,2755p' xnu-2422/osfmk/kern/sched_prim.c; sed -n '2435,2465p' xnu-2422/osfmk/kern/sched_prim.c; rg -n 'SYNC_POLICY_PREPOST|clearrefs|prepost' xnu-2422/bsd/kern/kern_event.c; rg -n 'wait_result' xnu-2422/bsd/dev/i386/systemcalls.c xnu-2422/osfmk/i386/trap.c; python3 - <<'PY'import jsonx=json.load(open('investigation/revert-commit.json'))print(x['commit']['message'])for f in x.get('files',[]):print(f['filename'],f.get('patch',''))PY"
status: Failed · exit 1
  Traceback (most recent call last):
    File "<stdin>", line 2, in <module>
  FileNotFoundError: [Errno 2] No such file or directory: 'investigation/revert-commit.json'

Activity

$ /bin/bash -lc "gh api 'repos/apple-oss-distributions/xnu/git/matching-refs/tags/xnu-3248' --jq '.[].ref'"
status: Completed · exit 0
  refs/tags/xnu-3248.20.55
  refs/tags/xnu-3248.30.4
  refs/tags/xnu-3248.40.184
  refs/tags/xnu-3248.50.21
  refs/tags/xnu-3248.60.10

Activity

$ /bin/bash -lc "gh api 'repos/apple-oss-distributions/xnu/contents/osfmk/kern?ref=xnu-3248.60.10' --jq '.[].name' | rg 'wait|sched'"
status: Completed · exit 0
  sched.h
  sched_average.c
  sched_dualq.c
  sched_grrr.c
  sched_multiq.c
  sched_prim.c
  sched_prim.h
  sched_proto.c
  sched_traditional.c
  waitq.c
  waitq.h

Activity

$ /bin/bash -lc "sed -n '1140,1185p' xnu-2422/bsd/kern/kern_event.c; sed -n '1970,2100p' xnu-2422/bsd/kern/kern_event.c; sed -n '310,355p' xnu-2422/osfmk/kern/wait_queue.c; sed -n '825,875p' xnu-2422/osfmk/kern/sched_prim.c; sed -n '1000,1070p' xnu-2422/osfmk/kern/sched_prim.c; rg -n 'VM_FAULT_RETRY' xnu-2422/osfmk/vm/vm_fault.c"
status: Completed · exit 0
  	default:
  		panic("%s: - invalid type (%ld)", __func__, type);
  		break;
  	}
  }
  
  /*
   * JMM - placeholder for not-yet-implemented filters
   */
  static int
  filt_badattach(__unused struct knote *kn)
  {
  	return (ENOTSUP);
  }
  
  struct kqueue *
  kqueue_alloc(struct proc *p)
  {
  	struct filedesc *fdp = p->p_fd;
  	struct kqueue *kq;
  
  	MALLOC_ZONE(kq, struct kqueue *, sizeof (struct kqueue), M_KQUEUE,
  	    M_WAITOK);
  	if (kq != NULL) {
  		wait_queue_set_t wqs;
  
  		wqs = wait_queue_set_alloc(SYNC_POLICY_FIFO |
  		    SYNC_POLICY_PREPOST);
  		if (wqs != NULL) {
  			bzero(kq, sizeof (struct kqueue));
  			lck_spin_init(&kq->kq_lock, kq_lck_grp, kq_lck_attr);
  			TAILQ_INIT(&kq->kq_head);
  			kq->kq_wqs = wqs;
  			kq->kq_p = p;
  		} else {
  			FREE_ZONE(kq, sizeof (struct kqueue), M_KQUEUE);
  		}
  	}
  
  	if (fdp->fd_knlistsize < 0) {
  		proc_fdlock(p);
  		if (fdp->fd_knlistsize < 0)
  			fdp->fd_knlistsize = 0;	/* this process has had a kq */
  		proc_fdunlock(p);
  	}
  
  		}
  	} else if ((kn->kn_flags & (EV_CLEAR | EV_DISPATCH)) != 0) {
  		if ((kn->kn_flags & EV_DISPATCH) != 0) {
  			/* deactivate and disable all dispatch knotes */
  			knote_deactivate(kn);
  			kn->kn_status |= KN_DISABLED;
  		} else if (!touch || kn->kn_fflags == 0) {
  			/* only deactivate if nothing since the touch */
  			knote_deactivate(kn);
  		}
  		if (!touch && (kn->kn_flags & EV_CLEAR) != 0) {
  			/* manually clear non-touch knotes */
  			kn->kn_data = 0;
  			kn->kn_fflags = 0;
  		}
  		kqunlock(kq);
  	} else {
  		/*
  		 * leave on inprocess queue.  We'll
  		 * move all the remaining ones back
  		 * the kq queue and wakeup any
  		 * waiters when we are done.
  		 */
  		kqunlock(kq);
  	}
  
  	/* callback to handle each event as we find it */
  	error = (callback)(kq, &kev, data);
  
  	kqlock(kq);
  	return (error);
  }
  
  /*
   * Return 0 to indicate that processing should proceed,
   * -1 if there is nothing to process.
   *
   * Called with kqueue locked and returns the same way,
   * but may drop lock temporarily.
   */
  static int
  kqueue_begin_processing(struct kqueue *kq)
  {
  	for (;;) {
  		if (kq->kq_count == 0) {
  			return (-1);
  		}
  
  		/* if someone else is processing the queue, wait */
  		if (kq->kq_nprocess != 0) {
  			wait_queue_assert_wait((wait_queue_t)kq->kq_wqs,
  			    &kq->kq_nprocess, THREAD_UNINT, 0);
  			kq->kq_state |= KQ_PROCWAIT;
  			kqunlock(kq);
  			thread_block(THREAD_CONTINUE_NULL);
  			kqlock(kq);
  		} else {
  			kq->kq_nprocess = 1;
  			return (0);
  		}
  	}
  }
  
  /*
   * Called with kqueue lock held.
   */
  static void
  kqueue_end_processing(struct kqueue *kq)
  {
  	kq->kq_nprocess = 0;
  	if (kq->kq_state & KQ_PROCWAIT) {
  		kq->kq_state &= ~KQ_PROCWAIT;
  		wait_queue_wakeup_all((wait_queue_t)kq->kq_wqs,
  		    &kq->kq_nprocess, THREAD_AWAKENED);
  	}
  }
  
  /*
   * kqueue_process - process the triggered events in a kqueue
   *
   *	Walk the queued knotes and validate that they are
   *	really still triggered events by calling the filter
   *	routines (if necessary).  Hold a use reference on
   *	the knote to avoid it being detached. For each event
   *	that is still considered triggered, invoke the
   *	callback routine provided.
   *
   *	caller holds a reference on the kqueue.
   *	kqueue locked on entry and exit - but may be dropped
   *	kqueue list locked (held for duration of call)
   */
  
  static int
  kqueue_process(struct kqueue *kq,
      kevent_callback_t callback,
      void *data,
      int *countp,
      struct proc *p)
  {
  	struct kqtailq inprocess;
  	struct knote *kn;
  	int nevents;
  	int error;
  
  	TAILQ_INIT(&inprocess);
  
  	if (kqueue_begin_processing(kq) == -1) {
  		*countp = 0;
  		/* Nothing to process */
  		return (0);
  	}
  
  	/*
  	 * Clear any pre-posted status from previous runs, so we
  	 * only detect events that occur during this run.
  	 */
  	wait_queue_sub_clearrefs(kq->kq_wqs);
  
  	/*
  	 * loop through the enqueued knotes, processing each one and
  	 * revalidating those that need it. As they are processed,
  	 * they get moved to the inprocess queue (so the loop can end).
  	 */
  	error = 0;
  	nevents = 0;
  
  	while (error == 0 &&
  	    (kn = TAILQ_FIRST(&kq->kq_head)) != NULL) {
  		error = knote_process(kn, callback, data, &inprocess, p);
  		if (error == EJUSTRETURN)
  			error = 0;
  	else
  		wqset->wqs_wait_queue.wq_prepost = FALSE;
  	queue_init(&wqset->wqs_setlinks);
  	queue_init(&wqset->wqs_preposts);
  	return KERN_SUCCESS;
  }
  
  
  kern_return_t
  wait_queue_sub_init(
  	wait_queue_set_t wqset,
  	int policy)
  {
  	return wait_queue_set_init(wqset, policy);
  }
  
  kern_return_t
  wait_queue_sub_clearrefs(
          wait_queue_set_t wq_set)
  {
  	wait_queue_link_t wql;
  	queue_t q;
  	spl_t s;
  
  	if (!wait_queue_is_set(wq_set))
  		return KERN_INVALID_ARGUMENT;
  
  	s = splsched();
  	wqs_lock(wq_set);
  	q = &wq_set->wqs_preposts;
  	while (!queue_empty(q)) {
  		queue_remove_first(q, wql, wait_queue_link_t, wql_preposts);
  		assert(!wql_is_preposted(wql));
  	}
  	wqs_unlock(wq_set);
  	splx(s);
  	return KERN_SUCCESS;
  }
  
  /*
   *	Routine:        wait_queue_set_alloc
   *	Purpose:
   *		Allocate and initialize a wait queue set for
   *		use outside of the mach part of the kernel.
   *	Conditions:
   *		May block.
  	__unused void	*p1)
  {
  	thread_t		thread = p0;
  	spl_t			s;
  
  	s = splsched();
  	thread_lock(thread);
  	if (--thread->wait_timer_active == 0) {
  		if (thread->wait_timer_is_set) {
  			thread->wait_timer_is_set = FALSE;
  			clear_wait_internal(thread, THREAD_TIMED_OUT);
  		}
  	}
  	thread_unlock(thread);
  	splx(s);
  }
  
  /*
   *	thread_unblock:
   *
   *	Unblock thread on wake up.
   *
   *	Returns TRUE if the thread is still running.
   *
   *	Thread must be locked.
   */
  boolean_t
  thread_unblock(
  	thread_t		thread,
  	wait_result_t	wresult)
  {
  	boolean_t		result = FALSE;
  	thread_t		cthread = current_thread();
  
  	/*
  	 *	Set wait_result.
  	 */
  	thread->wait_result = wresult;
  
  	/*
  	 *	Cancel pending wait timer.
  	 */
  	if (thread->wait_timer_is_set) {
  		if (timer_call_cancel(&thread->wait_timer))
  			thread->wait_timer_active--;
  		thread->wait_timer_is_set = FALSE;
  	}
  
  	/*
  	 *	Update scheduling state: not waiting,
  	 *	set running.
  {
  	assert(thread->at_safe_point == FALSE);
  	assert(thread->wait_event == NO_EVENT64);
  	assert(thread->wait_queue == WAIT_QUEUE_NULL);
  
  	if ((thread->state & (TH_WAIT|TH_TERMINATE)) == TH_WAIT) {
  		if (!thread_unblock(thread, wresult))
  			thread_setrun(thread, SCHED_PREEMPT | SCHED_TAILQ);
  
  		return (KERN_SUCCESS);
  	}
  
  	return (KERN_NOT_WAITING);
  }
  
  /*
   *	Routine:	thread_mark_wait_locked
   *	Purpose:
   *		Mark a thread as waiting.  If, given the circumstances,
   *		it doesn't want to wait (i.e. already aborted), then
   *		indicate that in the return value.
   *	Conditions:
   *		at splsched() and thread is locked.
   */
  __private_extern__
  wait_result_t
  thread_mark_wait_locked(
  	thread_t			thread,
  	wait_interrupt_t 	interruptible)
  {
  	boolean_t		at_safe_point;
  
  	assert(thread == current_thread());
  
  	/*
  	 *	The thread may have certain types of interrupts/aborts masked
  	 *	off.  Even if the wait location says these types of interrupts
  	 *	are OK, we have to honor mask settings (outer-scoped code may
  	 *	not be able to handle aborts at the moment).
  	 */
  	if (interruptible > (thread->options & TH_OPT_INTMASK))
  		interruptible = thread->options & TH_OPT_INTMASK;
  
  	at_safe_point = (interruptible == THREAD_ABORTSAFE);
  
  	if (	interruptible == THREAD_UNINT			||
  			!(thread->sched_flags & TH_SFLAG_ABORT)	||
  			(!at_safe_point &&
  				(thread->sched_flags & TH_SFLAG_ABORTSAFELY))) {
  
  		if ( !(thread->state & TH_TERMINATE))
  			DTRACE_SCHED(sleep);
  
  		thread->state |= (interruptible) ? TH_WAIT : (TH_WAIT | TH_UNINT);
  		thread->at_safe_point = at_safe_point;
  		return (thread->wait_result = THREAD_WAITING);
  	}
  	else
  	if (thread->sched_flags & TH_SFLAG_ABORTSAFELY)
  		thread->sched_flags &= ~TH_SFLAG_ABORTED_MASK;
  
  	return (thread->wait_result = THREAD_INTERRUPTED);
  }
  
  /*
   *	Routine:	thread_interrupt_level
   *	Purpose:
   *	        Set the maximum interruptible state for the
   *		current thread.  The effective value of any
   *		interruptible flag passed into assert_wait
   *		will never exceed this.
  646:			return (VM_FAULT_RETRY);
  1044:						return (VM_FAULT_RETRY);
  1117:				return (VM_FAULT_RETRY);
  1291:					return (VM_FAULT_RETRY);
  1474:					return (VM_FAULT_RETRY);
  1513:					return (VM_FAULT_RETRY);
  1730:				return (VM_FAULT_RETRY);
  1931:					return (VM_FAULT_RETRY);
  2142:					return (VM_FAULT_RETRY);
  2177:					return (VM_FAULT_RETRY);
  2432:	return (VM_FAULT_RETRY);
  4246:		case VM_FAULT_RETRY:
  4765:			} while (result == VM_FAULT_RETRY);
  5196:		case VM_FAULT_RETRY:
  5292:				case VM_FAULT_RETRY:

Activity

$ /bin/bash -lc 'gh api repos/blueboxd/chromium-legacy/commits/e0cff58db7f41e2b0b68e058ec49a98f215265c5 > investigation/revert-commit.json'
status: Completed · exit 0

Activity

$ /bin/bash -lc "gh api 'repos/apple-oss-distributions/xnu/contents/osfmk/kern/wait_queue.c?ref=xnu-2782.1.97' --jq .content | base64 --decode > investigation/wait_queue-10.10.c"
status: Completed · exit 0

Activity

$ /bin/bash -lc "gh api 'repos/apple-oss-distributions/xnu/contents/bsd/kern/kern_event.c?ref=xnu-3248.60.10' --jq .content | base64 --decode > investigation/kern_event-10.11.c"
status: Completed · exit 0

Activity

$ /bin/bash -lc "gh api 'repos/apple-oss-distributions/xnu/contents/osfmk/kern/waitq.c?ref=xnu-3248.60.10' --jq .content | base64 --decode > investigation/waitq-10.11.c"
status: Completed · exit 0

Activity

$ /bin/bash -lc "rg -n -C 8 'return.*THREAD_AWAKENED|wait_result = THREAD_AWAKENED|prepost' investigation/waitq-10.11.c | tail -160; rg -n -C 10 'wqs_is_preposted' investigation/wait_queue-10.10.c; rg -n -C 6 'invalid wait_result|waitq_assert_wait64|THREAD_RESTART' investigation/kern_event-10.11.c; python3 - <<'PY'import jsonx=json.load(open('investigation/revert-commit.json'))print(x['commit']['message'])for f in x.get('files',[]):print(f['filename'],f.get('patch',''))PY"
status: Completed · exit 0
  Revert "Reland "Use a timer instead of a sleep loop.""
  
  This reverts commit 162efe98330e8d243d472889db81dd78b691156f.
  base/message_loop/message_pump_kqueue.cc @@ -12,7 +12,6 @@
   #include "base/mac/mach_logging.h"
   #include "base/mac/scoped_nsautorelease_pool.h"
   #include "base/posix/eintr_wrapper.h"
  -#include "base/time/time_override.h"
  
   namespace base {
  
  @@ -22,22 +21,10 @@ namespace {
   // port sets. MessagePumpKqueue will directly use Mach ports in the kqueue if
   // it is possible.
   bool KqueueNeedsPortSet() {
  -  static const bool kqueue_needs_port_set = mac::IsAtMostOS10_11();
  +  static bool kqueue_needs_port_set = mac::IsAtMostOS10_11();
     return kqueue_needs_port_set;
   }
  
  -#if DCHECK_IS_ON()
  -// Prior to macOS 10.14, kqueue timers may spuriously wake up, because earlier
  -// wake ups race with timer resets in the kernel. As of macOS 10.14, updating a
  -// timer from the thread that reads the kqueue does not cause spurious wakeups.
  -// Note that updating a kqueue timer from one thread while another thread is
  -// waiting in a kevent64 invocation is still (inherently) racy.
  -bool KqueueTimersSpuriouslyWakeUp() {
  -  static const bool kqueue_timers_spuriously_wakeup = mac::IsAtMostOS10_13();
  -  return kqueue_timers_spuriously_wakeup;
  -}
  -#endif
  -
   int ChangeOneEvent(const ScopedFD& kqueue, kevent64_s* event) {
     return HANDLE_EINTR(kevent64(kqueue.get(), event, 1, nullptr, 0, 0, nullptr));
   }
  @@ -378,13 +365,25 @@ bool MessagePumpKqueue::DoInternalWork(Delegate* delegate,
  
     bool poll = next_work_info == nullptr;
     int flags = poll ? KEVENT_FLAG_IMMEDIATE : 0;
  -  if (!poll && scheduled_wakeup_time_ != next_work_info->delayed_run_time) {
  -    UpdateWakeupTimer(next_work_info->delayed_run_time);
  -    DCHECK_EQ(scheduled_wakeup_time_, next_work_info->delayed_run_time);
  -  }
  -
  -  int rv = HANDLE_EINTR(kevent64(kqueue_.get(), nullptr, 0, events_.data(),
  -                                 events_.size(), flags, nullptr));
  +  bool indefinite =
  +      next_work_info != nullptr && next_work_info->delayed_run_time.is_max();
  +
  +  int rv = 0;
  +  do {
  +    timespec timeout{};
  +    if (!indefinite && !poll) {
  +      if (rv != 0) {
  +        // The wait was interrupted and made |next_work_info|'s view of
  +        // TimeTicks::Now() stale. Refresh it before doing another wait.
  +        next_work_info->recent_now = TimeTicks::Now();
  +      }
  +      timeout = next_work_info->remaining_delay().ToTimeSpec();
  +    }
  +    // This does not use HANDLE_EINTR, since retrying the syscall requires
  +    // adjusting the timeout to account for time already waited.
  +    rv = kevent64(kqueue_.get(), nullptr, 0, events_.data(), events_.size(),
  +                  flags, indefinite ? nullptr : &timeout);
  +  } while (rv < 0 && errno == EINTR);
  
     PCHECK(rv >= 0) << "kevent64";
     return ProcessEvents(delegate, rv);
  @@ -449,25 +448,6 @@ bool MessagePumpKqueue::ProcessEvents(Delegate* delegate, int count) {
           auto scoped_do_native_work = delegate->BeginNativeWork();
           controller->watcher()->OnMachMessageReceived(port);
         }
  -    } else if (event->filter == EVFILT_TIMER) {
  -      // The wakeup timer fired.
  -#if DCHECK_IS_ON()
  -      // On macOS 10.13 and earlier, kqueue timers may spuriously wake up.
  -      // When this happens, the timer will be re-scheduled the next time
  -      // DoInternalWork is entered, which means this doesn't lead to a
  -      // spinning wait.
  -      // When clock overrides are active, TimeTicks::Now may be decoupled from
  -      // wall-clock time, and can therefore not be used to validate whether the
  -      // expected wall-clock time has passed.
  -      if (!KqueueTimersSpuriouslyWakeUp() &&
  -          !subtle::ScopedTimeClockOverrides::overrides_active()) {
  -        // Given the caveats above, assert that the timer didn't fire early.
  -        DCHECK_LE(scheduled_wakeup_time_, base::TimeTicks::Now());
  -      }
  -#endif
  -      DCHECK_NE(scheduled_wakeup_time_, base::TimeTicks::Max());
  -      scheduled_wakeup_time_ = base::TimeTicks::Max();
  -      --event_count_;
       } else {
         NOTREACHED() << "Unexpected event for filter " << event->filter;
       }
  @@ -476,47 +456,4 @@ bool MessagePumpKqueue::ProcessEvents(Delegate* delegate, int count) {
     return did_work;
   }
  
  -void MessagePumpKqueue::UpdateWakeupTimer(const base::TimeTicks& wakeup_time) {
  -  DCHECK_NE(wakeup_time, scheduled_wakeup_time_);
  -
  -  // The ident of the wakeup timer. There's only the one timer as the pair
  -  // (ident, filter) is the identity of the event.
  -  constexpr uint64_t kWakeupTimerIdent = 0x0;
  -  if (wakeup_time == base::TimeTicks::Max()) {
  -    // Clear the timer.
  -    kevent64_s timer{};
  -    timer.ident = kWakeupTimerIdent;
  -    timer.filter = EVFILT_TIMER;
  -    timer.flags = EV_DELETE;
  -
  -    int rv = ChangeOneEvent(kqueue_, &timer);
  -    PCHECK(rv == 0) << "kevent64, delete timer";
  -    --event_count_;
  -  } else {
  -    // Set/reset the timer.
  -    kevent64_s timer{};
  -    timer.ident = kWakeupTimerIdent;
  -    timer.filter = EVFILT_TIMER;
  -    // This updates the timer if it already exists in |kqueue_|.
  -    timer.flags = EV_ADD | EV_ONESHOT;
  -    // Specify the sleep in microseconds to avoid undersleeping due to
  -    // numeric problems. The sleep is computed from TimeTicks::Now rather than
  -    // NextWorkInfo::recent_now because recent_now is strictly earlier than
  -    // current wall-clock. Using an earlier wall clock time  to compute the
  -    // delta to the next wakeup wall-clock time would guarantee oversleep.
  -    // If wakeup_time is in the past, the delta below will be negative and the
  -    // timer is set immediately.
  -    timer.fflags = NOTE_USECONDS;
  -    timer.data = (wakeup_time - base::TimeTicks::Now()).InMicroseconds();
  -    int rv = ChangeOneEvent(kqueue_, &timer);
  -    PCHECK(rv == 0) << "kevent64, set timer";
  -
  -    // Bump the event count if we just added the timer.
  -    if (scheduled_wakeup_time_ == base::TimeTicks::Max())
  -      ++event_count_;
  -  }
  -
  -  scheduled_wakeup_time_ = wakeup_time;
  -}
  -
   }  // namespace base
  base/message_loop/message_pump_kqueue.h @@ -137,10 +137,6 @@ class BASE_EXPORT MessagePumpKqueue : public MessagePump,
     // true if work was done, or false if no work was done.
     bool ProcessEvents(Delegate* delegate, int count);
  
  -  // Sets the wakeup timer to |wakeup_time|, or clears it if |wakeup_time| is
  -  // base::TimeTicks::Max(). Updates |scheduled_wakeup_time_| to follow.
  -  void UpdateWakeupTimer(const base::TimeTicks& wakeup_time);
  -
     // Receive right to which an empty Mach message is sent to wake up the pump
     // in response to ScheduleWork().
     mac::ScopedMachReceiveRight wakeup_;
  @@ -164,10 +160,6 @@ class BASE_EXPORT MessagePumpKqueue : public MessagePump,
     // Whether the pump has been Quit() or not.
     bool keep_running_ = true;
  
  -  // The currently scheduled wakeup, if any. If no wakeup is scheduled,
  -  // contains base::TimeTicks::Max().
  -  base::TimeTicks scheduled_wakeup_time_{base::TimeTicks::Max()};
  -
     // The number of events scheduled on the |kqueue_|. There is always at least
     // 1, for the |wakeup_| port (or |port_set_|).
     size_t event_count_ = 1;

Assistant

I found a much stronger lead: Mavericks’ wait-queue code has a fast path that returns THREAD_AWAKENED but leaves the thread’s stored wait result unchanged. The kqueue code ignores that return value and invokes its continuation using the stored value. Apple’s Yosemite source changes that exact line to update the stored result too. This could explain both the misleading THREAD_RESTART and why El Capitan avoided the panic despite retaining the same panic case.

Activity

$ /bin/bash -lc "rg -n -C 12 'wait_result = THREAD_AWAKENED' investigation/waitq-10.11.c; sed -n '2170,2220p' xnu-2422/osfmk/kern/sched_prim.c; sed -n '4200,4275p' xnu-2422/osfmk/vm/vm_fault.c; sed -n '4700,4785p' xnu-2422/osfmk/vm/vm_fault.c; sed -n '2580,2610p' xnu-2422/bsd/kern/kern_event.c; sed -n '530,600p' xnu-2422/osfmk/ipc/ipc_pset.c; sed -n '1595,1740p' xnu-2422/osfmk/kern/wait_queue.c"
status: Completed · exit 0
  3307-		 * that has already been pre-posted.
  3308-		 */
  3309-		if (wait_event == NO_EVENT64 && waitq_set_maybe_preposted(wqset)) {
  3310-			int ret;
  3311-			/*
  3312-			 * Run through the list of potential preposts. Because
  3313-			 * this is a hot path, we short-circuit the iteration
  3314-			 * if we find just one prepost object.
  3315-			 */
  3316-			ret = wq_prepost_foreach_locked(wqset, NULL,
  3317-							prepost_exists_cb);
  3318-			if (ret == WQ_ITERATE_FOUND) {
  3319:				thread->wait_result = THREAD_AWAKENED;
  3320-				return THREAD_AWAKENED;
  3321-			}
  3322-		}
  3323-	}
  3324-
  3325-	/*
  3326-	 * Realtime threads get priority for wait queue placements.
  3327-	 * This allows wait_queue_wakeup_one to prefer a waiting
  3328-	 * realtime thread, similar in principle to performing
  3329-	 * a wait_queue_wakeup_all and allowing scheduler prioritization
  3330-	 * to run the realtime thread, but without causing the
  3331-	 * lock contention of that scenario.
  	return (THREAD_NULL);
  }
  
  #endif /* defined(CONFIG_SCHED_TRADITIONAL) || defined(CONFIG_SCHED_FIXEDPRIORITY) */
  
  /*
   *	Perform a context switch and start executing the new thread.
   *
   *	Returns FALSE on failure, and the thread is re-dispatched.
   *
   *	Called at splsched.
   */
  
  #define funnel_release_check(thread, debug)				\
  MACRO_BEGIN												\
  	if ((thread)->funnel_state & TH_FN_OWNED) {			\
  		(thread)->funnel_state = TH_FN_REFUNNEL;		\
  		KERNEL_DEBUG(0x603242c | DBG_FUNC_NONE,			\
  			(thread)->funnel_lock, (debug), 0, 0, 0);	\
  		funnel_unlock((thread)->funnel_lock);			\
  	}													\
  MACRO_END
  
  #define funnel_refunnel_check(thread, debug)				\
  MACRO_BEGIN													\
  	if ((thread)->funnel_state & TH_FN_REFUNNEL) {			\
  		kern_return_t	result = (thread)->wait_result;		\
  															\
  		(thread)->funnel_state = 0;							\
  		KERNEL_DEBUG(0x6032428 | DBG_FUNC_NONE,				\
  			(thread)->funnel_lock, (debug), 0, 0, 0);		\
  		funnel_lock((thread)->funnel_lock);					\
  		KERNEL_DEBUG(0x6032430 | DBG_FUNC_NONE,				\
  			(thread)->funnel_lock, (debug), 0, 0, 0);		\
  		(thread)->funnel_state = TH_FN_OWNED;				\
  		(thread)->wait_result = result;						\
  	}														\
  MACRO_END
  
  /*
   * thread_invoke
   *
   * "self" is what is currently running on the processor,
   * "thread" is the new thread to context switch to
   * (which may be the same thread in some cases)
   */
  static boolean_t
  thread_invoke(
  	thread_t			self,
  	thread_t			thread,
  	ast_t				reason)
  
  	result_page = VM_PAGE_NULL;
  	kr = vm_fault_page(object, offset, fault_type,
  			   (change_wiring && !wired),
  			   FALSE, /* page not looked up */
  			   &prot, &result_page, &top_page,
  			   &type_of_fault,
  			   &error_code, map->no_zero_fill,
  			   FALSE, &fault_info);
  
  	/*
  	 * if kr != VM_FAULT_SUCCESS, then the paging reference
  	 * has been dropped and the object unlocked... the ref_count
  	 * is still held
  	 *
  	 * if kr == VM_FAULT_SUCCESS, then the paging reference
  	 * is still held along with the ref_count on the original object
  	 *
  	 *	the object is returned locked with a paging reference
  	 *
  	 *	if top_page != NULL, then it's BUSY and the
  	 *	object it belongs to has a paging reference
  	 *	but is returned unlocked
  	 */
  	if (kr != VM_FAULT_SUCCESS &&
  	    kr != VM_FAULT_SUCCESS_NO_VM_PAGE) {
  	        /*
  		 * we didn't succeed, lose the object reference immediately.
  		 */
  		vm_object_deallocate(object);
  
  		/*
  		 * See why we failed, and take corrective action.
  		 */
  		switch (kr) {
  		case VM_FAULT_MEMORY_SHORTAGE:
  			if (vm_page_wait((change_wiring) ?
  					 THREAD_UNINT :
  					 THREAD_ABORTSAFE))
  				goto RetryFault;
  			/*
  			 * fall thru
  			 */
  		case VM_FAULT_INTERRUPTED:
  			kr = KERN_ABORTED;
  			goto done;
  		case VM_FAULT_RETRY:
  			goto RetryFault;
  		case VM_FAULT_MEMORY_ERROR:
  			if (error_code)
  				kr = error_code;
  			else
  				kr = KERN_MEMORY_ERROR;
  			goto done;
  		default:
  			panic("vm_fault: unexpected error 0x%x from "
  			      "vm_fault_page()\n", kr);
  		}
  	}
  	m = result_page;
  
  	if (m != VM_PAGE_NULL) {
  		assert((change_wiring && !wired) ?
  	   	    (top_page == VM_PAGE_NULL) :
  	   	    ((top_page == VM_PAGE_NULL) == (m->object == object)));
  	}
  
  	/*
  	 * What to do with the resulting page from vm_fault_page
  	 * if it doesn't get entered into the physical map:
  	 */
  #define RELEASE_PAGE(m)					\
  	MACRO_BEGIN					\
  	PAGE_WAKEUP_DONE(m);				\
  	if (!m->active && !m->inactive && !m->throttled) {		\
  		vm_page_lockspin_queues();				\
  	 * anything to undo here.
  	 */
  
  	if (object != VM_OBJECT_NULL && object->phys_contiguous)
  		return;
  
  	fault_info.interruptible = THREAD_UNINT;
  	fault_info.behavior = entry->behavior;
  	fault_info.user_tag = entry->alias;
  	fault_info.lo_offset = entry->offset;
  	fault_info.hi_offset = (entry->vme_end - entry->vme_start) + entry->offset;
  	fault_info.no_cache = entry->no_cache;
  	fault_info.stealth = TRUE;
  	fault_info.io_sync = FALSE;
  	fault_info.cs_bypass = FALSE;
  	fault_info.mark_zf_absent = FALSE;
  	fault_info.batch_pmap_op = FALSE;
  
  	/*
  	 *	Since the pages are wired down, we must be able to
  	 *	get their mappings from the physical map system.
  	 */
  
  	for (va = entry->vme_start; va < end_addr; va += PAGE_SIZE) {
  
  		if (object == VM_OBJECT_NULL) {
  			if (pmap) {
  				pmap_change_wiring(pmap,
  						   pmap_addr + (va - entry->vme_start), FALSE);
  			}
  			(void) vm_fault(map, va, VM_PROT_NONE,
  					TRUE, THREAD_UNINT, pmap, pmap_addr);
  		} else {
  		 	vm_prot_t	prot;
  			vm_page_t	result_page;
  			vm_page_t	top_page;
  			vm_object_t	result_object;
  			vm_fault_return_t result;
  
  			if (end_addr - va > (vm_size_t) -1) {
  				/* 32-bit overflow */
  				fault_info.cluster_size = (vm_size_t) (0 - PAGE_SIZE);
  			} else {
  				fault_info.cluster_size = (vm_size_t) (end_addr - va);
  				assert(fault_info.cluster_size == end_addr - va);
  			}
  
  			do {
  				prot = VM_PROT_NONE;
  
  				vm_object_lock(object);
  				vm_object_paging_begin(object);
  				XPR(XPR_VM_FAULT,
  					"vm_fault_unwire -> vm_fault_page\n",
  					0,0,0,0,0);
  				result_page = VM_PAGE_NULL;
  			 	result = vm_fault_page(
  					object,
  					entry->offset + (va - entry->vme_start),
  					VM_PROT_NONE, TRUE,
  					FALSE, /* page not looked up */
  					&prot, &result_page, &top_page,
  					(int *)0,
  					NULL, map->no_zero_fill,
  					FALSE, &fault_info);
  			} while (result == VM_FAULT_RETRY);
  
  			/*
  			 * If this was a mapping to a file on a device that has been forcibly
  			 * unmounted, then we won't get a page back from vm_fault_page().  Just
  			 * move on to the next one in case the remaining pages are mapped from
  			 * different objects.  During a forced unmount, the object is terminated
  			 * so the alive flag will be false if this happens.  A forced unmount will
  			 * will occur when an external disk is unplugged before the user does an
  			 * eject, so we don't want to panic in that situation.
  			 */
  
  			if (result == VM_FAULT_MEMORY_ERROR && !object->alive)
  				continue;
  
  			if (result == VM_FAULT_MEMORY_ERROR &&
  			    object == kernel_object) {
  				/*
  				 * This must have been allocated with
  				 * KMA_KOBJECT and KMA_VAONLY and there's
  				 * no physical page at this offset.
  /*
   * For a given knote, link a provided wait queue directly with the kqueue.
   * Wakeups will happen via recursive wait queue support.  But nothing will move
   * the knote to the active list at wakeup (nothing calls knote()).  Instead,
   * we permanently enqueue them here.
   *
   * kqueue and knote references are held by caller.
   *
   * caller provides the wait queue link structure.
   */
  int
  knote_link_wait_queue(struct knote *kn, struct wait_queue *wq, wait_queue_link_t wql)
  {
  	struct kqueue *kq = kn->kn_kq;
  	kern_return_t kr;
  
  	kr = wait_queue_link_noalloc(wq, kq->kq_wqs, wql);
  	if (kr == KERN_SUCCESS) {
  		knote_markstayqueued(kn);
  		return (0);
  	} else {
  		return (EINVAL);
  	}
  }
  
  /*
   * Unlink the provided wait queue from the kqueue associated with a knote.
   * Also remove it from the magic list of directly attached knotes.
   *
   * Note that the unlink may have already happened from the other side, so
   * ignore any failures to unlink and just remove it from the kqueue list.
          default:
                  panic("filt_machporttouch() - invalid type (%ld)", type);
                  break;
          }
  }
  
  /*
   * Peek to see if the portset associated with the knote has any
   * events. This pre-hook is called when a filter uses the stay-
   * on-queue mechanism (as the knote_link_wait_queue mechanism
   * does).
   *
   * This is called with the kqueue that the knote belongs to still
   * locked (thus holding a reference on the knote, but restricting
   * also restricting our ability to take other locks).
   *
   * Just peek at the pre-post status of the portset's wait queue
   * to determine if it has anything interesting.  We can do it
   * without holding the lock, as it is just a snapshot in time
   * (if this is used as part of really waiting for events, we
   * will catch changes in this status when the event gets posted
   * up to the knote's kqueue).
   */
  static unsigned
  filt_machportpeek(struct knote *kn)
  {
          ipc_pset_t              pset = kn->kn_ptr.p_pset;
  	ipc_mqueue_t		set_mq = &pset->ips_messages;
  
  	return (ipc_mqueue_set_peek(set_mq));
  }
  	event64_t event,
  	wait_result_t result)
  {
  	kern_return_t ret;
  	spl_t s;
  
  	if (!wait_queue_is_valid(wq)) {
  		return KERN_INVALID_ARGUMENT;
  	}
  
  	s = splsched();
  	wait_queue_lock(wq);
  	ret = wait_queue_wakeup64_all_locked(wq, event, result, TRUE);
  	/* lock released */
  	splx(s);
  	return ret;
  }
  
  /*
   *	Routine:	_wait_queue_select64_one
   *	Purpose:
   *		Select the best thread off a wait queue that meet the
   *		supplied criteria.
   * 	Conditions:
   *		at splsched
   *		wait queue locked
   *		possibly recursive
   * 	Returns:
   *		a locked thread - if one found
   *	Note:
   *		This is where the sync policy of the wait queue comes
   *		into effect.  For now, we just assume FIFO/LIFO.
   */
  static thread_t
  _wait_queue_select64_one(
  	wait_queue_t wq,
  	event64_t event)
  {
  	wait_queue_element_t wq_element;
  	wait_queue_element_t wqe_next;
  	thread_t t = THREAD_NULL;
  	thread_t fifo_thread = THREAD_NULL;
  	boolean_t is_queue_fifo = TRUE;
  	boolean_t is_queue_global = FALSE;
  	boolean_t thread_imp_donor = FALSE;
  	boolean_t realtime = FALSE;
  	unsigned long eventmask = 0;
  	queue_t q;
  
  	if (wait_queue_global(wq)) {
  		eventmask = CAST_TO_EVENT_MASK(event);
  		if ((wq->wq_eventmask & eventmask) != eventmask) {
  			return THREAD_NULL;
  		}
  		eventmask = 0;
  		is_queue_global = TRUE;
  #if IMPORTANCE_INHERITANCE
  		is_queue_fifo = FALSE;
  #endif /* IMPORTANCE_INHERITANCE */
  	}
  
  	q = &wq->wq_queue;
  
  	wq_element = (wait_queue_element_t) queue_first(q);
  	while (!queue_end(q, (queue_entry_t)wq_element)) {
  		WAIT_QUEUE_ELEMENT_CHECK(wq, wq_element);
  		wqe_next = (wait_queue_element_t)
  			       queue_next((queue_t) wq_element);
  
  		/*
  		 * We may have to recurse if this is a compound wait queue.
  		 */
  		if (wq_element->wqe_type == WAIT_QUEUE_LINK ||
  		    wq_element->wqe_type == WAIT_QUEUE_LINK_NOALLOC) {
  			wait_queue_link_t wql = (wait_queue_link_t)wq_element;
  			wait_queue_set_t set_queue = wql->wql_setqueue;
  
  			/*
  			 * We have to check the set wait queue. If the set
  			 * supports pre-posting, it isn't already preposted,
  			 * and we didn't find a thread in the set, then mark it.
  			 *
  			 * If we later find a thread, there may be a spurious
  			 * pre-post here on this set.  The wait side has to check
  			 * for that either pre- or post-wait.
  			 */
  			wqs_lock(set_queue);
  			if (! wait_queue_empty(&set_queue->wqs_wait_queue)) {
  				t = _wait_queue_select64_one(&set_queue->wqs_wait_queue, event);
  			}
  			if (t != THREAD_NULL) {
  				wqs_unlock(set_queue);
  				return t;
  			}
  			if (event == NO_EVENT64 && set_queue->wqs_prepost && !wql_is_preposted(wql)) {
  				queue_t ppq = &set_queue->wqs_preposts;
  				queue_enter(ppq, wql, wait_queue_link_t, wql_preposts);
  			}
  			wqs_unlock(set_queue);
  
  		} else {
  
  			/*
  			 * Otherwise, its a thread.  If it is waiting on
  			 * the event we are posting to this queue, pull
  			 * it off the queue and stick it in out wake_queue.
  			 */
  			t = (thread_t)(void *)wq_element;
  			if (t->wait_event == event) {
  				if (fifo_thread == THREAD_NULL) {
  					fifo_thread = t;
  				}
  #if IMPORTANCE_INHERITANCE
  				/*
  				 * Checking imp donor bit does not need thread lock or
  				 * or task lock since we have the wait queue lock and
  				 * thread can not be removed from it without acquiring
  				 * wait queue lock. The imp donor bit may change
  				 * once we read its value, but it is ok to wake
  				 * a thread while someone drops importance assertion
  				 * on the that thread.
  				 */
  				thread_imp_donor = task_is_importance_donor(t->task);
  #endif /* IMPORTANCE_INHERITANCE */
  				realtime = (t->sched_pri >= BASEPRI_REALTIME);
  				if (is_queue_fifo || thread_imp_donor || realtime ||
  						(t->options & TH_OPT_VMPRIV)) {
  					thread_lock(t);
  					remqueue((queue_entry_t) t);
  					t->wait_queue = WAIT_QUEUE_NULL;
  					t->wait_event = NO_EVENT64;
  					t->at_safe_point = FALSE;
  					return t;	/* still locked */
  				}
  			}
  			if (is_queue_global) {
  				eventmask = eventmask | CAST_TO_EVENT_MASK(t->wait_event);
  			}
  			t = THREAD_NULL;
  		}
  		wq_element = wqe_next;
  	}
  
  	if (is_queue_global) {
  		wq->wq_eventmask = eventmask;
  	}

Activity

$ /bin/bash -lc "gh api 'repos/apple-oss-distributions/xnu/contents/osfmk/kern/wait_queue.c?ref=xnu-2422.115.4' --jq .content | base64 --decode > investigation/wait_queue-10.9.5.c"
status: Completed · exit 0

Activity

$ /bin/bash -lc 'gh api gists/a214411bb52d39bcee9497363a97558d > investigation/instrumented-kernel-gist.json'
status: Completed · exit 0

Activity

$ /bin/bash -lc "gh api 'repos/blueboxd/chromium-legacy/contents/base/message_loop/message_pump_kqueue.cc?ref=3d056a95e025ee808e5f75623f5b3a330e3088f2' --jq .content | base64 --decode > investigation/message_pump_kqueue-2022.cc"
status: Completed · exit 0

Activity

$ /bin/bash -lc "python3 - <<'PY'import json,zipfilex=json.load(open('investigation/instrumented-kernel-gist.json'))for n,f in x['files'].items(): print(n,'truncated:',f.get('truncated'));open('investigation/instrumented-'+n,'w').write(f.get('content',''))z=zipfile.ZipFile('investigation/original-panic.zip')for n in z.namelist(): if not n.startswith('__MACOSX') and not n.endswith('/'):  b=z.read(n);open('investigation/original-panic.txt','wb').write(b);print(b.decode(errors='replace'))print(open('investigation/2023-panic.log').read())PY"
status: Completed · exit 0
  ipc_mqueue truncated: False
  kern_event.c truncated: False
  wait_queue.c truncated: False
  Anonymous UUID:       145BC0A7-7198-5ADB-C385-68267A698C9E
  
  Tue Jan 11 18:26:53 2022
  panic(cpu 0 caller 0xffffff8007bc7ab4): "kqueue_scan_continue: - invalid wait_result (3)"@/SourceCache/xnu/xnu-2422.115.15/bsd/kern/kern_event.c:2167
  Backtrace (CPU 0), Frame : Return Address
  0xffffff8112513ef0 : 0xffffff8007823139
  0xffffff8112513f70 : 0xffffff8007bc7ab4
  0xffffff8112513fb0 : 0xffffff80078d7c67
  
  BSD process name corresponding to current thread: Chromium Helper
  
  Mac OS version:
  13F1911
  
  Kernel version:
  Darwin Kernel Version 13.4.0: Mon Jan 11 18:17:34 PST 2016; root:xnu-2422.115.15~1/RELEASE_X86_64
  Kernel UUID: 8926E512-6714-34FC-B27C-6AE90EB51D5E
  Kernel slide:     0x0000000007600000
  Kernel text base: 0xffffff8007800000
  System model name: MacBookAir6,1 (Mac-35C1E88140C3E6CF)
  
  System uptime in nanoseconds: 137570231962415
  last loaded kext at 117122794134843: com.apple.driver.IOBluetoothHIDDriver	4.2.7f5 (addr 0xffffff7f898ba000, size 73728)
  last unloaded kext at 130917731587858: com.apple.driver.IOBluetoothHIDDriver	4.2.7f5 (addr 0xffffff7f898ba000, size 73728)
  loaded kexts:
  me.hajo.HaHE.Driver	1.0.0
  com.protech.NoSleep	1.4.0
  com.apple.filesystems.smbfs	2.0.3
  com.apple.filesystems.autofs	3.0
  com.apple.driver.AppleUpstreamUserClient	3.5.13
  com.apple.driver.AppleHDA	2.6.3f7
  com.apple.iokit.IOBluetoothSerialManager	4.2.7f5
  com.apple.driver.X86PlatformShim	1.0.0
  com.apple.driver.AGPM	100.14.34
  com.apple.driver.ApplePlatformEnabler	2.0.9d7
  com.apple.driver.AudioAUUC	1.60
  com.apple.driver.AppleThunderboltIP	1.1.2
  com.apple.iokit.IOUserEthernet	1.0.0d1
  com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport	4.2.7f5
  com.apple.driver.AppleCameraInterface	4.26.0
  com.apple.driver.AppleLPC	1.7.0
  com.apple.driver.AppleSMCLMU	2.0.4d1
  com.apple.Dont_Steal_Mac_OS_X	7.0.0
  com.apple.driver.AppleHWAccess	1
  com.apple.driver.AppleBacklight	170.4.11
  com.apple.driver.AppleMCCSControl	1.2.5
  com.apple.driver.AppleIntelHD5000Graphics	8.2.8
  com.apple.driver.AppleIntelFramebufferAzul	8.2.8
  com.apple.AppleFSCompression.AppleFSCompressionTypeDataless	1.0.0d1
  com.apple.AppleFSCompression.AppleFSCompressionTypeLZVN	1.0.0d1
  com.apple.AppleFSCompression.AppleFSCompressionTypeZlib	1.0.0d1
  com.apple.BootCache	35
  com.apple.driver.AppleTopCaseHIDEventDriver	10.21
  com.apple.driver.AppleUSBHub	683.4.0
  com.apple.driver.XsanFilter	404
  com.apple.iokit.IOAHCIBlockStorage	2.6.0
  com.apple.driver.AppleAHCIPort	3.0.5
  com.apple.driver.AirPort.Brcm4360	842.21.65
  com.apple.driver.AppleUSBXHCI	683.4.0
  com.apple.driver.AppleSmartBatteryManager	161.0.0
  com.apple.driver.AppleRTC	2.0
  com.apple.driver.AppleACPIButtons	2.0
  com.apple.driver.AppleHPET	1.8
  com.apple.driver.AppleSMBIOS	2.1
  com.apple.driver.AppleACPIEC	2.0
  com.apple.driver.AppleAPIC	1.7
  com.apple.nke.applicationfirewall	153
  com.apple.security.quarantine	3
  com.apple.kext.triggers	1.0
  com.apple.iokit.IOSCSIArchitectureModelFamily	3.6.7
  com.apple.driver.DspFuncLib	2.6.3f7
  com.apple.vecLib.kext	1.0.0
  com.apple.iokit.IOSerialFamily	10.0.7
  com.apple.iokit.IOAudioFamily	1.9.7fc2
  com.apple.kext.OSvKernDSPLib	1.14
  com.apple.iokit.IOBluetoothFamily	4.2.7f5
  com.apple.iokit.IOBluetoothHostControllerUSBTransport	4.2.7f5
  com.apple.driver.AppleHDAController	2.6.3f7
  com.apple.iokit.IOHDAFamily	2.6.3f7
  com.apple.driver.X86PlatformPlugin	1.0.0
  com.apple.driver.AppleSMC	3.1.8
  com.apple.driver.IOPlatformPluginFamily	5.7.1d6
  com.apple.driver.AppleBacklightExpert	1.0.4
  com.apple.driver.AppleSMBusController	1.0.12d1
  com.apple.iokit.IOSurface	91.3
  com.apple.iokit.IONDRVSupport	2.4.1
  com.apple.AppleGraphicsDeviceControl	3.6.22
  com.apple.iokit.IOAcceleratorFamily2	98.26
  com.apple.iokit.IOGraphicsFamily	2.4.1
  com.apple.driver.AppleUSBMergeNub	650.4.0
  com.apple.driver.AppleUSBComposite	656.4.1
  com.apple.driver.AppleThunderboltDPInAdapter	3.1.7
  com.apple.driver.AppleThunderboltDPAdapterFamily	3.1.7
  com.apple.driver.AppleThunderboltPCIDownAdapter	1.4.5
  com.apple.iokit.IOUSBUserClient	660.4.2
  com.apple.driver.AppleHIDKeyboard	170.15
  com.apple.driver.AppleHSSPIHIDDriver	24.1
  com.apple.driver.AppleMultitouchDriver	245.13.1
  com.apple.iokit.IOAHCIFamily	2.6.5
  com.apple.driver.AppleThunderboltNHI	2.0.1
  com.apple.iokit.IOThunderboltFamily	3.3.1
  com.apple.iokit.IO80211Family	640.36
  com.apple.driver.mDNSOffloadUserClient	1.0.1b5
  com.apple.iokit.IONetworkingFamily	3.2
  com.apple.driver.AppleHSSPISupport	24.1
  com.apple.driver.AppleIntelLpssSpiController	2.0.34
  com.apple.driver.AppleIntelLpssGspi	2.0.34
  com.apple.iokit.IOUSBFamily	686.4.1
  com.apple.driver.AppleIntelLpssDmac	2.0.34
  com.apple.driver.AppleEFINVRAM	2.0
  com.apple.driver.AppleEFIRuntime	2.0
  com.apple.iokit.IOHIDFamily	2.0.0
  com.apple.iokit.IOSMBusFamily	1.1
  com.apple.security.sandbox	278.11.2
  com.apple.kext.AppleMatch	1.0.0d1
  com.apple.security.TMSafetyNet	7
  com.apple.driver.AppleKeyStore	2
  com.apple.driver.DiskImages	373
  com.apple.iokit.IOStorageFamily	1.9
  com.apple.iokit.IOReportFamily	23
  com.apple.driver.AppleFDEKeyStore	28.30
  com.apple.driver.AppleACPIPlatform	2.0
  com.apple.iokit.IOPCIFamily	2.9
  com.apple.iokit.IOACPIFamily	1.4
  com.apple.kec.corecrypto	1.0
  com.apple.kec.pthread	1
  
  Anonymous UUID:       58645209-3F22-8B42-01B7-0C62519750C7
  
  Sat Jan 14 18:43:39 2023
  panic(cpu 0 caller 0xffffff80071c6bb4): "kqueue_scan_continue: - invalid wait_result (3)"@/SourceCache/xnu/xnu-2422.110.17/bsd/kern/kern_event.c:2167
  Backtrace (CPU 0), Frame : Return Address
  0xffffff81f2053ef0 : 0xffffff8006e22f79
  0xffffff81f2053f70 : 0xffffff80071c6bb4
  0xffffff81f2053fb0 : 0xffffff8006ed7417
  
  BSD process name corresponding to current thread: Chromium Helper
  Boot args: kext-dev-mode=1
  
  Mac OS version:
  13E28
  
  Kernel version:
  Darwin Kernel Version 13.3.0: Tue Jun  3 21:27:35 PDT 2014; root:xnu-2422.110.17~1/RELEASE_X86_64
  Kernel UUID: BBFADD17-672B-35A2-9B7F-E4B12213E4B8
  Kernel slide:     0x0000000006c00000
  Kernel text base: 0xffffff8006e00000
  System model name: MacBookPro9,1 (Mac-4B7AC7E43945597E)
  
  System uptime in nanoseconds: 4066641044880
  last loaded kext at 3901636049533: com.apple.driver.AppleIntelMCEReporter	104 (addr 0xffffff7f8924c000, size 49152)
  last unloaded kext at 3966662167467: com.apple.driver.AppleIntelMCEReporter	104 (addr 0xffffff7f8924c000, size 32768)
  loaded kexts:
  com.apple.driver.AppleHWSensor	1.9.5d0
  com.apple.driver.AudioAUUC	1.60
  com.apple.filesystems.autofs	3.0
  com.apple.iokit.IOBluetoothSerialManager	4.2.6f1
  com.apple.driver.AppleMikeyHIDDriver	124
  com.apple.driver.AGPM	100.14.28
  com.apple.driver.X86PlatformShim	1.0.0
  com.apple.driver.AppleHDA	2.6.3f4
  com.apple.driver.AppleUpstreamUserClient	3.5.13
  com.apple.GeForce	8.2.6
  com.apple.iokit.IOUserEthernet	1.0.0d1
  com.apple.driver.AppleIntelHD4000Graphics	8.2.8
  com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport	4.2.6f1
  com.apple.driver.AppleMikeyDriver	2.6.3f4
  com.apple.Dont_Steal_Mac_OS_X	7.0.0
  com.apple.driver.AppleHWAccess	1
  com.apple.driver.AppleSMCPDRC	1.0.0
  com.apple.driver.AppleIntelFramebufferCapri	8.2.8
  com.apple.driver.AppleSMCLMU	2.0.4d1
  com.apple.driver.AppleLPC	1.7.0
  com.apple.driver.AppleThunderboltIP	1.1.2
  com.apple.driver.SMCMotionSensor	3.0.4d1
  com.apple.driver.AppleMuxControl	3.6.22
  com.apple.driver.AppleMCCSControl	1.2.5
  com.apple.driver.AppleUSBTCButtons	240.2
  com.apple.driver.AppleIRController	325.7
  com.apple.driver.AppleUSBTCKeyboard	240.2
  com.apple.AppleFSCompression.AppleFSCompressionTypeDataless	1.0.0d1
  com.apple.AppleFSCompression.AppleFSCompressionTypeLZVN	1.0.0d1
  com.apple.AppleFSCompression.AppleFSCompressionTypeZlib	1.0.0d1
  com.apple.BootCache	35
  com.apple.iokit.SCSITaskUserClient	3.6.6
  com.apple.driver.XsanFilter	404
  com.apple.iokit.IOAHCIBlockStorage	2.6.0
  com.apple.driver.AppleUSBHub	683.4.0
  com.apple.driver.AppleSDXC	1.5.2
  com.apple.iokit.AppleBCM5701Ethernet	3.8.1b2
  com.apple.driver.AirPort.Brcm4331	700.20.22
  com.apple.driver.AppleFWOHCI	5.0.2
  com.apple.driver.AppleAHCIPort	3.0.5
  com.apple.driver.AppleUSBEHCI	660.4.0
  com.apple.driver.AppleUSBXHCI	683.4.0
  com.apple.driver.AppleSmartBatteryManager	161.0.0
  com.apple.driver.AppleACPIButtons	2.0
  com.apple.driver.AppleRTC	2.0
  com.apple.driver.AppleHPET	1.8
  com.apple.driver.AppleSMBIOS	2.1
  com.apple.driver.AppleACPIEC	2.0
  com.apple.driver.AppleAPIC	1.7
  com.apple.driver.AppleIntelCPUPowerManagementClient	217.92.1
  com.apple.nke.applicationfirewall	153
  com.apple.security.quarantine	3
  com.apple.driver.AppleIntelCPUPowerManagement	217.92.1
  com.apple.kext.triggers	1.0
  com.apple.iokit.IOSerialFamily	10.0.7
  com.apple.driver.DspFuncLib	2.6.3f4
  com.apple.vecLib.kext	1.0.0
  com.apple.iokit.IOAudioFamily	1.9.7fc2
  com.apple.kext.OSvKernDSPLib	1.14
  com.apple.iokit.IOAcceleratorFamily	98.22
  com.apple.nvidia.driver.NVDAGK100Hal	8.2.6
  com.apple.nvidia.driver.NVDAResman	8.2.6
  com.apple.iokit.IOSurface	91.1
  com.apple.iokit.IOBluetoothFamily	4.2.6f1
  com.apple.iokit.IOBluetoothHostControllerUSBTransport	4.2.6f1
  com.apple.driver.AppleHDAController	2.6.3f4
  com.apple.iokit.IOHDAFamily	2.6.3f4
  com.apple.driver.X86PlatformPlugin	1.0.0
  com.apple.iokit.IOAcceleratorFamily2	98.22
  com.apple.AppleGraphicsDeviceControl	3.6.22
  com.apple.iokit.IOFireWireIP	2.2.6
  com.apple.driver.IOPlatformPluginFamily	5.7.1d6
  com.apple.driver.AppleSMBusPCI	1.0.12d1
  com.apple.driver.AppleSMC	3.1.8
  com.apple.driver.AppleGraphicsControl	3.6.22
  com.apple.driver.AppleBacklightExpert	1.0.4
  com.apple.iokit.IONDRVSupport	2.4.1
  com.apple.driver.AppleSMBusController	1.0.12d1
  com.apple.iokit.IOGraphicsFamily	2.4.1
  com.apple.driver.AppleUSBMultitouch	240.9
  com.apple.iokit.IOUSBHIDDriver	660.4.0
  com.apple.driver.AppleThunderboltDPInAdapter	3.1.7
  com.apple.driver.AppleThunderboltDPAdapterFamily	3.1.7
  com.apple.driver.AppleThunderboltPCIDownAdapter	1.4.5
  com.apple.driver.AppleUSBMergeNub	650.4.0
  com.apple.driver.AppleUSBComposite	656.4.1
  com.apple.iokit.IOSCSIMultimediaCommandsDevice	3.6.6
  com.apple.iokit.IOBDStorageFamily	1.7
  com.apple.iokit.IODVDStorageFamily	1.7.1
  com.apple.iokit.IOCDStorageFamily	1.7.1
  com.apple.driver.AppleThunderboltNHI	2.0.1
  com.apple.iokit.IOThunderboltFamily	3.3.1
  com.apple.iokit.IOAHCISerialATAPI	2.6.1
  com.apple.iokit.IOSCSIArchitectureModelFamily	3.6.6
  com.apple.iokit.IOEthernetAVBController	1.0.3b4
  com.apple.driver.mDNSOffloadUserClient	1.0.1b5
  com.apple.iokit.IO80211Family	640.36
  com.apple.iokit.IONetworkingFamily	3.2
  com.apple.iokit.IOFireWireFamily	4.5.5
  com.apple.iokit.IOUSBUserClient	660.4.2
  com.apple.iokit.IOAHCIFamily	2.6.5
  com.apple.iokit.IOUSBFamily	683.4.0
  com.apple.driver.AppleEFINVRAM	2.0
  com.apple.driver.AppleEFIRuntime	2.0
  com.apple.iokit.IOHIDFamily	2.0.0
  com.apple.iokit.IOSMBusFamily	1.1
  com.apple.security.sandbox	278.11.1
  com.apple.kext.AppleMatch	1.0.0d1
  com.apple.security.TMSafetyNet	7
  com.apple.driver.AppleKeyStore	2
  com.apple.driver.DiskImages	371.1
  com.apple.iokit.IOStorageFamily	1.9
  com.apple.iokit.IOReportFamily	23
  com.apple.driver.AppleFDEKeyStore	28.30
  com.apple.driver.AppleACPIPlatform	2.0
  com.apple.iokit.IOPCIFamily	2.9
  com.apple.iokit.IOACPIFamily	1.4
  com.apple.kec.corecrypto	1.0
  com.apple.kec.pthread	1

Activity

$ /bin/bash -lc "rg -n -C 5 'wqs_is_preposted' investigation/wait_queue-10.9.5.c; rg -n 'KqueueNeedsPortSet|mach_port_insert_member|kevent64\\(' investigation/message_pump_kqueue-2022.cc; rg -n 'wait_result|thread_exception_return' xnu-2422/osfmk/i386/bsd_i386.c xnu-2422/osfmk/kern/exception.c xnu-2422/bsd/dev/i386/systemcalls.c; rg -n 'wait_result' xnu-2422/osfmk/i386/*.s"
status: Failed · exit 1
  1193-		panic("wait_queue_assert_wait64_locked");
  1194-
  1195-	if (wq->wq_type == _WAIT_QUEUE_SET_inited) {
  1196-		wait_queue_set_t wqs = (wait_queue_set_t)wq;
  1197-
  1198:		if (event == NO_EVENT64 && wqs_is_preposted(wqs))
  1199-			return(THREAD_AWAKENED);
  1200-	}
  1201-
  1202-	/*
  1203-	 * Realtime threads get priority for wait queue placements.
  24:bool KqueueNeedsPortSet() {
  34:  return HANDLE_EINTR(kevent64(kqueue.get(), event, 1, nullptr, 0, 0, nullptr));
  123:  if (KqueueNeedsPortSet()) {
  128:    kr = mach_port_insert_member(mach_task_self(), wakeup_.get(),
  130:    MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_port_insert_member";
  137:    // directly receive the Mach message as part of the kevent64() syscall.
  226:  if (KqueueNeedsPortSet()) {
  228:        mach_port_insert_member(mach_task_self(), port, port_set_.get());
  230:      MACH_LOG(ERROR, kr) << "mach_port_insert_member";
  285:  int rv = HANDLE_EINTR(kevent64(kqueue_.get(), events.data(), events.size(),
  349:  if (KqueueNeedsPortSet()) {
  396:  int rv = HANDLE_EINTR(kevent64(kqueue_.get(), events.data(), events.size(),
  438:    rv = kevent64(kqueue_.get(), nullptr, 0, events_.data(), events_.size(),
  483:      mach_port_t port = KqueueNeedsPortSet() ? event->data : event->ident;
  488:        if (KqueueNeedsPortSet()) {
  xnu-2422/osfmk/i386/bsd_i386.c:266:		thread_exception_return();
  xnu-2422/osfmk/i386/bsd_i386.c:277:			thread_exception_return();
  xnu-2422/osfmk/i386/bsd_i386.c:322:	thread_exception_return();
  xnu-2422/osfmk/i386/bsd_i386.c:345:		thread_exception_return();
  xnu-2422/osfmk/i386/bsd_i386.c:367:	thread_exception_return();
  xnu-2422/osfmk/i386/bsd_i386.c:450:			thread_exception_return();
  xnu-2422/osfmk/i386/bsd_i386.c:475:	thread_exception_return();
  xnu-2422/osfmk/i386/bsd_i386.c:523:			thread_exception_return();
  xnu-2422/osfmk/i386/bsd_i386.c:542:	thread_exception_return();
  xnu-2422/bsd/dev/i386/systemcalls.c:107:		thread_exception_return();
  xnu-2422/bsd/dev/i386/systemcalls.c:124:		thread_exception_return();
  xnu-2422/bsd/dev/i386/systemcalls.c:156:			thread_exception_return();
  xnu-2422/bsd/dev/i386/systemcalls.c:262:	thread_exception_return();
  xnu-2422/bsd/dev/i386/systemcalls.c:284:		thread_exception_return();
  xnu-2422/bsd/dev/i386/systemcalls.c:300:		thread_exception_return();
  xnu-2422/bsd/dev/i386/systemcalls.c:343:				thread_exception_return();
  xnu-2422/bsd/dev/i386/systemcalls.c:451:	thread_exception_return();
  xnu-2422/bsd/dev/i386/systemcalls.c:598:	thread_exception_return();
  xnu-2422/osfmk/kern/exception.c:119: *		thread_exception_return and thread_kdb_return
  xnu-2422/osfmk/kern/exception.c:307: *		thread_exception_return and thread_kdb_return
  xnu-2422/osfmk/kern/exception.c:363:		thread_exception_return();

Activity

$ /bin/bash -lc "diff -u xnu-2422/osfmk/kern/wait_queue.c investigation/instrumented-wait_queue.c | head -150; diff -u xnu-2422/bsd/kern/kern_event.c investigation/instrumented-kern_event.c | head -140; shasum xnu-2422/osfmk/kern/wait_queue.c investigation/wait_queue-10.9.5.c; sed -n '215,260p' chromium-legacy-master/mojo/core/channel_mac.cc; sed -n '65,84p' xnu-2422/osfmk/kern/kern_types.h"
status: Completed · exit 0
  788c3a9b945fc59f61d5b8e3749a6e2b41d78025  xnu-2422/osfmk/kern/wait_queue.c
  788c3a9b945fc59f61d5b8e3749a6e2b41d78025  investigation/wait_queue-10.9.5.c
        }
        SendHandshake();
      } else if (receive_port_ != MACH_PORT_NULL) {
        DCHECK(send_port_ == MACH_PORT_NULL);
        // Wait for the received message via the MessageLoop.
      } else {
        NOTREACHED_IN_MIGRATION();
      }
  
      base::CurrentThread::Get()->AddDestructionObserver(this);
      base::CurrentIOThread::Get()->WatchMachReceivePort(
          receive_port_.get(), &watch_controller_, this);
    }
  
    void ShutDownOnIOThread() {
      base::CurrentThread::Get()->RemoveDestructionObserver(this);
  
      watch_controller_.StopWatchingMachPort();
  
      {
        base::AutoLock lock(write_lock_);
        send_buffer_.reset();
        reject_writes_ = true;
      }
      receive_buffer_.reset();
      incoming_handles_.clear();
  
      if (leak_handles_) {
        std::ignore = receive_port_.release();
        std::ignore = send_port_.release();
      } else {
        receive_port_.reset();
        send_port_.reset();
      }
  
      // May destroy the |this| if it was the last reference.
      self_ = nullptr;
    }
  
    // Requests that the kernel notify the |receive_port_| when the receive right
    // connected to |send_port_| becomes a dead name. This should be called as
    // soon as the Channel establishes both the send and receive ports.
    bool RequestSendDeadNameNotification() {
      base::apple::ScopedMachSendRight previous;
      kern_return_t kr = mach_port_request_notification(
          mach_task_self(), send_port_.get(), MACH_NOTIFY_DEAD_NAME, 0,
  typedef	void *event_t;		/* wait event */
  #define		NO_EVENT			((event_t) 0)
  
  typedef uint64_t event64_t;		/* 64 bit wait event */
  #define		NO_EVENT64		((event64_t) 0)
  #define		CAST_EVENT64_T(a_ptr)	((event64_t)((uintptr_t)(a_ptr)))
  
  /*
   *	Possible wait_result_t values.
   */
  typedef int wait_result_t;
  #define THREAD_WAITING		-1		/* thread is waiting */
  #define THREAD_AWAKENED		0		/* normal wakeup */
  #define THREAD_TIMED_OUT	1		/* timeout expired */
  #define THREAD_INTERRUPTED	2		/* aborted/interrupted */
  #define THREAD_RESTART		3		/* restart operation entirely */
  #define THREAD_NOT_WAITING      10              /* thread didn't need to wait */
  
  typedef	void (*thread_continue_t)(void *, wait_result_t);
  #define	THREAD_CONTINUE_NULL	((thread_continue_t) 0)

Activity

$ /bin/bash -lc "gh api 'repos/apple-oss-distributions/xnu/contents/osfmk/kern/wait_queue.c?ref=xnu-1699.32.7' --jq .content | base64 --decode > investigation/wait_queue-10.7.c"
status: Completed · exit 0

Activity

$ /bin/bash -lc "gh api 'repos/apple-oss-distributions/xnu/contents/osfmk/kern/wait_queue.c?ref=xnu-2050.48.11' --jq .content | base64 --decode > investigation/wait_queue-10.8.c"
status: Completed · exit 0

Activity

$ /bin/bash -lc "rg -n -C 3 'wqs_is_preposted' investigation/wait_queue-10.7.c investigation/wait_queue-10.8.c; sed -n '185,285p' investigation/helper-crash.txt; sed -n '285,410p' investigation/helper-crash.txt"
status: Completed · exit 0
  investigation/wait_queue-10.8.c-1176-	if (wq->wq_type == _WAIT_QUEUE_SET_inited) {
  investigation/wait_queue-10.8.c-1177-		wait_queue_set_t wqs = (wait_queue_set_t)wq;
  investigation/wait_queue-10.8.c-1178-
  investigation/wait_queue-10.8.c:1179:		if (event == NO_EVENT64 && wqs_is_preposted(wqs))
  investigation/wait_queue-10.8.c-1180-			return(THREAD_AWAKENED);
  investigation/wait_queue-10.8.c-1181-	}
  investigation/wait_queue-10.8.c-1182-
  --
  investigation/wait_queue-10.7.c-937-	if (wq->wq_type == _WAIT_QUEUE_SET_inited) {
  investigation/wait_queue-10.7.c-938-		wait_queue_set_t wqs = (wait_queue_set_t)wq;
  investigation/wait_queue-10.7.c-939-
  investigation/wait_queue-10.7.c:940:		if (event == NO_EVENT64 && wqs_is_preposted(wqs))
  investigation/wait_queue-10.7.c-941-			return(THREAD_AWAKENED);
  investigation/wait_queue-10.7.c-942-	}
  investigation/wait_queue-10.7.c-943-
         0x103daa000 -        0x103dc6ff7  libsystem_kernel.dylib (2422.115.15) <34ABAF79-E147-3C34-B05D-46A566E689CC> /usr/lib/system/libsystem_kernel.dylib
         0x103ded000 -        0x103e1cfd2  libsystem_m.dylib (3047.16) <B7F0E2E4-2777-33FC-A787-D6430B630D54> /usr/lib/system/libsystem_m.dylib
         0x103e28000 -        0x103e43ff7  libsystem_malloc.dylib (23.10.1) <A695B4E4-38E9-332E-A772-29D31E3F1385> /usr/lib/system/libsystem_malloc.dylib
         0x103e4f000 -        0x103e76ff7  libsystem_network.dylib (241.4) <0D630D53-C772-3EC5-8257-EFB0ACCE3153> /usr/lib/system/libsystem_network.dylib
         0x103e99000 -        0x103ea2ffb  libsystem_notify.dylib (121.20.1) <9B34B4FE-F5AD-3F09-A5F0-46AFF3571323> /usr/lib/system/libsystem_notify.dylib
         0x103eb2000 -        0x103eb8ff7  libsystem_platform.dylib (24.90.1) <3C3D3DA8-32B9-3243-98EC-D89B9A1670B3> /usr/lib/system/libsystem_platform.dylib
         0x103ecb000 -        0x103ed2ff7  libsystem_pthread.dylib (53.1.4) <AB498556-B555-310E-9041-F67EC9E00E2C> /usr/lib/system/libsystem_pthread.dylib
         0x103ee2000 -        0x103ee3fff  libsystem_sandbox.dylib (278.11.2) <0C93EB23-7364-3670-B511-212A7A524695> /usr/lib/system/libsystem_sandbox.dylib
         0x103ee9000 -        0x103eedff7  libsystem_stats.dylib (93.90.3) <2304C7C2-BE45-35DE-BCC6-707D61B7AE7E> /usr/lib/system/libsystem_stats.dylib
         0x103ef4000 -        0x103ef5fff  libunc.dylib (28) <62682455-1862-36FE-8A04-7A6B91256438> /usr/lib/system/libunc.dylib
         0x103efb000 -        0x103f00ff7  libunwind.dylib (35.3) <78DCC358-2FC1-302E-B395-0155B47CB547> /usr/lib/system/libunwind.dylib
         0x103f07000 -        0x103f2bfff  libxpc.dylib (300.90.2) <AB40CD57-F454-3FD4-B415-63B3C0D5C624> /usr/lib/system/libxpc.dylib
         0x103f4a000 -        0x1040f7f27  libobjc.A.dylib (551.1) <AD7FD984-271E-30F4-A361-6B20319EC73B> /usr/lib/libobjc.A.dylib
         0x10411f000 -        0x104161ff7  libauto.dylib (185.5) <F45C36E8-B606-3886-B5B1-B6745E757CA8> /usr/lib/libauto.dylib
         0x10417d000 -        0x1041a6ff7  libc++abi.dylib (49.1) <21A807D3-6732-3455-B77F-743E9F916DF0> /usr/lib/libc++abi.dylib
         0x1041ba000 -        0x10420cfff  libc++.1.dylib (120) <4F68DFC5-2077-39A8-A449-CAC5FDEE7BDE> /usr/lib/libc++.1.dylib
         0x10426b000 -        0x10426cff7  libDiagnosticMessagesClient.dylib (100) <4CDB0F7B-C0AF-3424-BC39-495696F0DB1E> /usr/lib/libDiagnosticMessagesClient.dylib
         0x104276000 -        0x10442effb  libicucore.A.dylib (511.36) <9AAC5980-2C1F-3B86-8A16-DB533F5E7C84> /usr/lib/libicucore.A.dylib
         0x1044d6000 -        0x1044e7ff7  libz.1.dylib (53) <42E0C8C6-CA38-3CA4-8619-D24ED5DD492E> /usr/lib/libz.1.dylib
         0x10451b000 -        0x10ff76f97 +org.chromium.Chromium.framework (99.0.4844.51 - 4844.51) <D1160355-AA4E-3838-B297-705E1F1E0E31> /Applications/Chromium.app/Contents/Frameworks/Chromium Framework.framework/Versions/99.0.4844.51/Chromium Framework
         0x11e8ca000 -        0x11ed18fef  com.apple.VideoToolbox (1.0 - 1273.57) <AA4D613A-1066-3E85-8BE0-7806566652B4> /System/Library/Frameworks/VideoToolbox.framework/Versions/A/VideoToolbox
         0x11ed73000 -        0x11ee95fff  com.apple.avfoundation (2.0 - 651.12.1) <FDCF1F41-E0BD-3F8C-974A-3F48A0A85B00> /System/Library/Frameworks/AVFoundation.framework/Versions/A/AVFoundation
         0x11efad000 -        0x11efb2fff  com.apple.DiskArbitration (2.6 - 2.6) <A4165553-770E-3D27-B217-01FC1F852B87> /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration
         0x11efbc000 -        0x11f028fff  com.apple.framework.IOKit (2.0.1 - 907.100.14) <10932113-9F7E-38A0-A158-A019A555CAC3> /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit
         0x11f05d000 -        0x11f0a8fff  com.apple.ImageCaptureCore (5.0 - 5.0) <F529EDDC-E2F5-30CA-9938-AF23296B5C5B> /System/Library/Frameworks/ImageCaptureCore.framework/Versions/A/ImageCaptureCore
         0x11f0ea000 -        0x11f0f8fff  com.apple.opengl (9.6.5 - 9.6.5) <4FAEADD8-EEB3-3FD9-ADC6-BA65806228CC> /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL
         0x11f100000 -        0x11f29cff3  com.apple.QuartzCore (1.8 - 332.4) <CFB972D1-FA37-380C-9A47-2A67A84B7442> /System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore
         0x11f373000 -        0x11f3a1ff7  com.apple.securityinterface (9.0 - 55047) <0346D8A9-2CAA-38F3-A741-5FBA5E9F1E7C> /System/Library/Frameworks/SecurityInterface.framework/Versions/A/SecurityInterface
         0x11f3cf000 -        0x11ff45ff7  com.apple.AppKit (6.9 - 1265.21) <9DC13B27-841D-3839-93B2-3EDE66157BDE> /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit
         0x1206cc000 -        0x1206d8ff7  com.apple.OpenDirectory (10.9 - 173.90.1) <383F96FF-1DF3-37E8-8540-03A697C873F6> /System/Library/Frameworks/OpenDirectory.framework/Versions/A/OpenDirectory
         0x1206ed000 -        0x12095dffd  com.apple.security (7.0 - 55471.14.40) <58F50B4A-FC1E-3AE0-A5DB-DD737E50AC17> /System/Library/Frameworks/Security.framework/Versions/A/Security
         0x120aac000 -        0x120dacff7  com.apple.Foundation (6.9 - 1056.17) <E0B0FAF6-5CA8-3EEB-8BF2-104C0AEEF925> /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation
         0x120fea000 -        0x120ff4ff7  com.apple.bsd.ServiceManagement (2.0 - 2.0) <2D27B498-BB9C-3D88-B05A-76908A8A26F3> /System/Library/Frameworks/ServiceManagement.framework/Versions/A/ServiceManagement
         0x120fff000 -        0x121024ff7  com.apple.CoreVideo (1.8 - 117.2) <4674339E-26D0-35FA-9958-422832B39B12> /System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo
         0x121040000 -        0x1210a3ffb  com.apple.SystemConfiguration (1.13.1 - 1.13.1) <339A2A90-DA25-33AF-88E5-2FB38A758FEE> /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration
         0x1210de000 -        0x1210e1ffc  com.apple.IOSurface (91.3 - 91.3) <E93485CC-12B1-318E-BAE3-AB532B264935> /System/Library/Frameworks/IOSurface.framework/Versions/A/IOSurface
         0x1210ea000 -        0x121133fff  com.apple.CoreMedia (1.0 - 1273.57) <74FA3D80-A6DB-331A-B32A-683C8E0CC0A6> /System/Library/Frameworks/CoreMedia.framework/Versions/A/CoreMedia
         0x121161000 -        0x1212b5ff3  com.apple.audio.toolbox.AudioToolbox (1.10 - 1.10) <69B273E8-5A8E-3FC7-B807-C16B657662FE> /System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox
         0x12134b000 -        0x12139cff7  com.apple.audio.CoreAudio (4.2.1 - 4.2.1) <07F2B103-AE29-3118-BBC4-9A72E13B013B> /System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio
         0x1213c2000 -        0x121456ff7  com.apple.Bluetooth (4.2.7 - 4.2.7f5) <A7F0360A-DBDA-32EA-AA37-6937B94E6A72> /System/Library/Frameworks/IOBluetooth.framework/Versions/A/IOBluetooth
         0x1214c7000 -        0x121502ff2  com.apple.audio.midi.CoreMIDI (1.10 - 88) <D9D7F8A1-B30F-324D-AAFD-5DB9EECDAA48> /System/Library/Frameworks/CoreMIDI.framework/Versions/A/CoreMIDI
         0x12152a000 -        0x121538fff  com.apple.GameController (1.0 - 1) <0082D276-BE12-317C-852D-D9309E47CD12> /System/Library/Frameworks/GameController.framework/Versions/A/GameController
         0x12154d000 -        0x1215acfff  com.apple.framework.CoreWLAN (4.3.3 - 433.48) <1F17FA12-6E84-309D-9808-C536D445FA6E> /System/Library/Frameworks/CoreWLAN.framework/Versions/A/CoreWLAN
         0x1215ea000 -        0x121648ff7  com.apple.corelocation (1486.17 - 1486.24.1) <69C6AD7D-BA34-3F40-B73F-D66DB9C2BBE9> /System/Library/Frameworks/CoreLocation.framework/Versions/A/CoreLocation
         0x121685000 -        0x1216ccff7  libcups.2.dylib (372.6) <CBD2F0CF-FA10-36E1-A1D5-1B946B45B3B3> /usr/lib/libcups.2.dylib
         0x1216e1000 -        0x1216f1fff  libbsm.0.dylib (33) <2CAC00A2-1352-302A-88FA-C567D4D69179> /usr/lib/libbsm.0.dylib
         0x1216fa000 -        0x121716fff  libresolv.9.dylib (54) <11C2C826-F1C6-39C6-B4E8-6E0C41D4FA95> /usr/lib/libresolv.9.dylib
         0x121721000 -        0x12172eff0  libbz2.1.0.dylib (29) <0B98AC35-B138-349C-8063-2B987A75D24C> /usr/lib/libbz2.1.0.dylib
         0x121734000 -        0x12173aff7 +libChromiumModifier.dylib (1) <F90CC783-94FD-37EC-88B4-A93DB29CDBB1> /Applications/Chromium.app/Contents/Frameworks/Chromium Framework.framework/Versions/99.0.4844.51/Libraries/libChromiumModifier.dylib
         0x121744000 -        0x121791fff  com.apple.AppleVAFramework (5.0.27 - 5.0.27) <B28D0F5C-EEDD-3586-8986-33BC79E8DE56> /System/Library/PrivateFrameworks/AppleVA.framework/Versions/A/AppleVA
         0x12179c000 -        0x1220c55ab  com.apple.CoreGraphics (1.600.0 - 599.35.15) <ED5E3C37-7E2F-3885-8091-DFC9B44B38E8> /System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics
         0x1221f3000 -        0x1222b5ffd  com.apple.CoreText (367.23 - 367.23) <C799261E-2E19-3D69-8A8D-098B7DD8D31D> /System/Library/Frameworks/CoreText.framework/Versions/A/CoreText
         0x122324000 -        0x12242bff7  com.apple.ImageIO.framework (3.3.0 - 1052) <6BFA69B9-A607-39BC-B302-E2E92E5BC7F3> /System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO
         0x122493000 -        0x122500ff1  com.apple.ApplicationServices.ATS (360 - 363.6) <828C2711-4577-3F75-B436-3BDF328DFB11> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/ATS
         0x12252c000 -        0x1225b5fff  com.apple.ColorSync (4.9.0 - 4.9.0) <B756B908-9AD1-3F5D-83F9-7A0B068387D2> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ColorSync.framework/Versions/A/ColorSync
         0x1225fc000 -        0x122641ff6  com.apple.HIServices (1.23 - 468) <FD17FE8C-A355-3B6B-B8B7-E56E5C595EDE> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/HIServices
         0x122674000 -        0x122683ff8  com.apple.LangAnalysis (1.7.0 - 1.7.0) <8FE131B6-1180-3892-98F5-C9C9B79072D4> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LangAnalysis.framework/Versions/A/LangAnalysis
         0x122691000 -        0x1226deff2  com.apple.print.framework.PrintCore (9.0 - 428) <8D8253E3-302F-3DB2-9C5C-572CB974E8B3> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/PrintCore
         0x12270b000 -        0x122744ff7  com.apple.QD (3.50 - 298) <C1F20764-DEF0-34CF-B3AB-AB5480D64E66> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/QD
         0x122760000 -        0x122769fff  com.apple.speech.synthesis.framework (4.7.1 - 4.7.1) <383FB557-E88E-3239-82B8-15F9F885B702> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/SpeechSynthesis.framework/Versions/A/SpeechSynthesis
         0x12277c000 -        0x122787fff  libkxld.dylib (2422.115.15) <8850BC2B-EB64-3B0F-8047-DCC113021292> /usr/lib/system/libkxld.dylib
         0x12278c000 -        0x122927ff8  com.apple.CFNetwork (673.6 - 673.6) <CAA196FE-BF5A-384F-975E-E0F81359805B> /System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork
         0x122a2e000 -        0x122d18fff  com.apple.CoreServices.CarbonCore (1077.17 - 1077.17) <3A2E92FD-DEE2-3D45-9619-11500801A61C> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore
         0x122d95000 -        0x122e25ff7  com.apple.Metadata (10.7.0 - 800.30) <E107CE36-FBC3-35A5-84E0-864B4178FC5D> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Metadata
         0x122e8c000 -        0x122f03fff  com.apple.CoreServices.OSServices (600.4 - 600.4) <6BC86B46-AFD3-3F06-8659-2C954CBEBD43> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/OSServices.framework/Versions/A/OSServices
         0x122fa6000 -        0x123013fff  com.apple.SearchKit (1.4.0 - 1.4.0) <B9B8D510-A27E-36B0-93E9-17146D9E9045> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SearchKit.framework/Versions/A/SearchKit
         0x123057000 -        0x1230b2ffb  com.apple.AE (665.5 - 665.6) <9B17E7B7-D493-346A-827E-6DF1474E4977> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/AE
         0x1230e1000 -        0x1231abff7  com.apple.LaunchServices (572.32 - 572.32) <A4699DED-5101-3068-94F8-8D0B7A84BC79> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/LaunchServices
         0x123220000 -        0x123249fff  com.apple.DictionaryServices (1.2 - 208) <A539A058-BA57-35EE-AA08-D0B0E835127D> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/DictionaryServices.framework/Versions/A/DictionaryServices
         0x12326c000 -        0x123354fff  libxml2.2.dylib (26.11) <282EF071-71D7-3C56-9FFD-543F2A083F18> /usr/lib/libxml2.2.dylib
         0x12338a000 -        0x123397ff7  libxar.1.dylib (202) <5572AA71-E98D-3FE1-9402-BB4A84E0E71E> /usr/lib/libxar.1.dylib
         0x12339f000 -        0x1233a3fff  libpam.2.dylib (20) <B93CE8F5-DAA8-30A1-B1F6-F890509513CB> /usr/lib/libpam.2.dylib
         0x1233a8000 -        0x1233affff  com.apple.NetFS (6.0 - 4.0) <8E26C099-CE9D-3819-91A2-64EA929C6137> /System/Library/Frameworks/NetFS.framework/Versions/A/NetFS
         0x1233b7000 -        0x1233c2ff7  com.apple.NetAuth (5.0 - 5.0) <C811E662-9EC3-3B74-808A-A75D624F326B> /System/Library/PrivateFrameworks/NetAuth.framework/Versions/A/NetAuth
         0x1233ce000 -        0x1233e9ff7  libCRFSuite.dylib (34) <FFAE75FA-C54E-398B-AA97-18164CD9789D> /usr/lib/libCRFSuite.dylib
         0x1233f3000 -        0x123457fff  com.apple.datadetectorscore (5.0 - 354.5) <D4DBCCF4-9622-3AB9-9076-32579FCC2E39> /System/Library/PrivateFrameworks/DataDetectorsCore.framework/Versions/A/DataDetectorsCore
         0x123496000 -        0x123499fff  com.apple.TCC (1.0 - 1) <32A075D9-47FD-3E71-95BC-BFB0D583F41C> /System/Library/PrivateFrameworks/TCC.framework/Versions/A/TCC
         0x1234a0000 -        0x1234b7ff7  com.apple.CFOpenDirectory (10.9 - 173.90.1) <D7F2E159-CF6B-3EB1-9806-3BC59E63D24F> /System/Library/Frameworks/OpenDirectory.framework/Versions/A/Frameworks/CFOpenDirectory.framework/Versions/A/CFOpenDirectory
         0x1234d5000 -        0x1234fdff3  libxslt.1.dylib (13.12) <38FD3D1E-5335-398F-A663-47298EDDA231> /usr/lib/libxslt.1.dylib
         0x12350a000 -        0x1237defc7  com.apple.vImage (7.0 - 7.0) <D241DBFA-AC49-31E2-893D-EAAC31890C90> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vImage.framework/Versions/A/vImage
         0x123821000 -        0x1238ecfff  libvDSP.dylib (423.32) <3BF732BE-DDE0-38EB-8C54-E4E3C64F77A7> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvDSP.dylib
         0x1238f7000 -        0x1239a7ff7  libvMisc.dylib (423.32) <049C0735-1808-39B9-943F-76CB8021744F> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvMisc.dylib
         0x1239b3000 -        0x123d94ffe  libLAPACK.dylib (1094.5) <7E7A9B8D-1638-3914-BAE0-663B69865986> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib
         0x123df7000 -        0x123f65ff7  libBLAS.dylib (1094.5) <DE93A590-5FA5-32A2-A16C-5D7D7361769F> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
         0x123f8e000 -        0x124088fff  libFontParser.dylib (111.1.6) <77253632-B3F6-3151-ABA0-C1EF458668A8> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontParser.dylib
         0x12410a000 -        0x124151ffb  libFontRegistry.dylib (127.0.1) <F267F500-6E4A-3BE3-97C1-08AAA649E02E> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontRegistry.dylib
         0x124177000 -        0x12419bff7  libJPEG.dylib (1052) <6836134F-8701-3A6B-82F3-19A0A72CE21C> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJPEG.dylib
         0x1241a3000 -        0x1241fcff7  libTIFF.dylib (1052) <909BF5F6-6FC5-3126-9028-593130CAEBE6> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib
         0x12420b000 -        0x124226ff7  libPng.dylib (1052) <6A2D3E6E-AA2E-3B6F-9E3B-8D08A5A3B9C1> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib
         0x12422f000 -        0x124233ff7  libGIF.dylib (1052) <E51B4EFE-F99B-35F4-BE33-0456635EC7B3> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libGIF.dylib
         0x124238000 -        0x124326fff  libJP2.dylib (1052) <CB242C3E-F10C-38C5-A090-B757F9269143> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJP2.dylib
         0x124350000 -        0x124369ff7  com.apple.Kerberos (3.0 - 1) <F108AFEB-198A-3BAF-BCA5-9DFCE55EFF92> /System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos
         0x124382000 -        0x1243b1ff9  com.apple.GSS (4.0 - 2.0) <27FCA2B4-0767-3002-8755-862B19B5CF92> /System/Library/Frameworks/GSS.framework/Versions/A/GSS
         0x1243d0000 -        0x1244c1ff9  libiconv.2.dylib (41) <BB44B115-AC32-3877-A0ED-AEC6232A4563> /usr/lib/libiconv.2.dylib
         0x1244d1000 -        0x124536ffb  com.apple.Heimdal (4.0 - 2.0) <C28DBCAE-01AC-363A-9046-3BD33F225526> /System/Library/PrivateFrameworks/Heimdal.framework/Versions/A/Heimdal
         0x124562000 -        0x124566ff7  libheimdal-asn1.dylib (323.92.2) <979AEAA0-59B3-3E99-94B1-9BB9C6C45273> /usr/lib/libheimdal-asn1.dylib
         0x12456c000 -        0x124575ffd  com.apple.CommonAuth (4.0 - 2.0) <BD720379-757B-305C-A7BE-E00E680F8218> /System/Library/PrivateFrameworks/CommonAuth.framework/Versions/A/CommonAuth
         0x12457c000 -        0x1245effff  com.apple.securityfoundation (6.0 - 55122.3) <0AFCF575-97C3-3458-A72E-39DA07804EB9> /System/Library/Frameworks/SecurityFoundation.framework/Versions/A/SecurityFoundation
         0x12462f000 -        0x12466efff  libGLU.dylib (9.6.5) <7463B411-2DB0-3338-BC8D-403293E2CA34> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib
         0x12467d000 -        0x124685ffc  libGFXShared.dylib (9.6.5) <FCCD0CD3-02FD-3A79-B048-A14745D76CC8> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGFXShared.dylib
         0x12468c000 -        0x124697fff  libGL.dylib (9.6.5) <A5F36623-33E8-379D-A423-8F873018CD79> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib
         0x12468c000 -        0x124697fff  libGL.dylib (9.6.5) <A5F36623-33E8-379D-A423-8F873018CD79> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib
         0x1246ab000 -        0x1246e9ff7  libGLImage.dylib (9.6.5) <C242B319-6F4B-3FB3-8FCE-0B77424F0BED> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLImage.dylib
         0x1246f1000 -        0x1246f4fff  libCoreVMClient.dylib (58.1) <EBC36C69-C896-3C3D-8589-3E9023E7E56F> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCoreVMClient.dylib
         0x1246fa000 -        0x124711ffa  libAVFAudio.dylib (32.2) <DAE7465E-DE8E-3900-84E7-F5DE72560E76> /System/Library/Frameworks/AVFoundation.framework/Versions/A/Resources/libAVFAudio.dylib
         0x124723000 -        0x124a59fff  com.apple.MediaToolbox (1.0 - 1273.57) <26FB55D1-11B8-3CEF-A8E1-40BC215B610F> /System/Library/Frameworks/MediaToolbox.framework/Versions/A/MediaToolbox
         0x124b07000 -        0x124b53ffe  com.apple.CoreMediaIO (408.0 - 4570) <292C2C20-E3D6-39EA-AEF8-CB2AC4934136> /System/Library/Frameworks/CoreMediaIO.framework/Versions/A/CoreMediaIO
         0x124b7b000 -        0x124b91fff  com.apple.CoreMediaAuthoring (2.2 - 947) <6317ACCD-98DB-3ACB-B662-98DEBF38F5BF> /System/Library/PrivateFrameworks/CoreMediaAuthoring.framework/Versions/A/CoreMediaAuthoring
         0x124ba9000 -        0x124cd8fef  com.apple.MediaControlSender (2.0 - 200.34.4) <FC24EC8D-2E46-3F76-AF63-749F30857B96> /System/Library/PrivateFrameworks/MediaControlSender.framework/Versions/A/MediaControlSender
         0x124d10000 -        0x124d3fff7  com.apple.CoreAVCHD (5.7.0 - 5700.4.3) <404369C0-ED9F-3010-8D2F-BC55285F7808> /System/Library/PrivateFrameworks/CoreAVCHD.framework/Versions/A/CoreAVCHD
         0x124d4a000 -        0x124d4fff7  com.apple.MediaAccessibility (1.0 - 43) <D309D83D-5FAE-37A4-85ED-FFBDA8B66B82> /System/Library/Frameworks/MediaAccessibility.framework/Versions/A/MediaAccessibility
         0x124d5a000 -        0x124d5cfff  com.apple.Mangrove (1.0 - 1) <72F5CBC7-4E78-374E-98EA-C3700136904E> /System/Library/PrivateFrameworks/Mangrove.framework/Versions/A/Mangrove
         0x124d62000 -        0x125139fef  CoreAUC (197.5) <2D7DC96C-BA83-3220-A03F-C790D50A23D8> /System/Library/PrivateFrameworks/CoreAUC.framework/Versions/A/CoreAUC
         0x125146000 -        0x125163ff7  com.apple.framework.Apple80211 (9.4 - 940.60) <043C7CFD-B57B-3F9D-B0FE-CA4B97C43968> /System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Apple80211
         0x12516f000 -        0x125177ff7  com.apple.AppleSRP (5.0 - 1) <ABC7F088-1FD5-3768-B9F3-847F355E90B3> /System/Library/PrivateFrameworks/AppleSRP.framework/Versions/A/AppleSRP
         0x12517e000 -        0x1251e5ff7  com.apple.CoreUtils (2.0 - 200.34.4) <E53B97FE-E067-33F6-A9C1-D4EC2A20FB9F> /System/Library/PrivateFrameworks/CoreUtils.framework/Versions/A/CoreUtils
         0x125211000 -        0x12523bff7  libpcap.A.dylib (42) <91D3FF51-D6FE-3C05-98C9-1182E0EC3D58> /usr/lib/libpcap.A.dylib
         0x125249000 -        0x1252affff  com.apple.framework.CoreWiFi (2.0 - 200.21.1) <5491896D-78C5-30B6-96E9-D8DDECF3BE73> /System/Library/Frameworks/CoreWiFi.framework/Versions/A/CoreWiFi
         0x12530e000 -        0x125556ff7  com.apple.CoreData (107 - 481.3) <E78734AA-E3D0-33CB-A014-620BBCAB2E96> /System/Library/Frameworks/CoreData.framework/Versions/A/CoreData
         0x12567e000 -        0x1256b6ff7  com.apple.RemoteViewServices (2.0 - 94) <3F34D630-3DDB-3411-BC28-A56A9B55EBDA> /System/Library/PrivateFrameworks/RemoteViewServices.framework/Versions/A/RemoteViewServices
         0x1256ef000 -        0x12581fff7  com.apple.desktopservices (1.8.3 - 1.8.3) <225BEC20-F8E0-3F22-9560-890A1A5B9050> /System/Library/PrivateFrameworks/DesktopServicesPriv.framework/Versions/A/DesktopServicesPriv
         0x12589f000 -        0x125b49ff5  com.apple.HIToolbox (2.1.1 - 698) <26FF0E2C-1CD7-311F-ACF0-84F3D5273AD6> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox
         0x125ca1000 -        0x125ca9ff7  com.apple.speech.recognition.framework (4.2.4 - 4.2.4) <98BBB3E4-6239-3EF1-90B2-84EA0D3B8D61> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SpeechRecognition.framework/Versions/A/SpeechRecognition
         0x125cb3000 -        0x125d97ff7  com.apple.coreui (2.2 - 231.1) <187DF89C-8A64-366D-8782-F90315FA3CD7> /System/Library/PrivateFrameworks/CoreUI.framework/Versions/A/CoreUI
         0x125e59000 -        0x125e6bff7  com.apple.MultitouchSupport.framework (245.13.1 - 245.13.1) <38262B92-C63F-35A0-997D-AD2EBF2F8338> /System/Library/PrivateFrameworks/MultitouchSupport.framework/Versions/A/MultitouchSupport
         0x125e7a000 -        0x125ebbfff  com.apple.PerformanceAnalysis (1.47 - 47) <95435F84-C251-3C48-B6CD-9EE7A63D6E26> /System/Library/PrivateFrameworks/PerformanceAnalysis.framework/Versions/A/PerformanceAnalysis
         0x12670c000 -        0x126724ff7  com.apple.GenerationalStorage (2.0 - 160.3) <64749B08-0212-3AC8-9B49-73D662B09304> /System/Library/PrivateFrameworks/GenerationalStorage.framework/Versions/A/GenerationalStorage
         0x126734000 -        0x126741fff  com.apple.Sharing (132.2 - 132.2) <F983394A-226D-3244-B511-FA51FDB6ADDA> /System/Library/PrivateFrameworks/Sharing.framework/Versions/A/Sharing
         0x126752000 -        0x126816ff7  com.apple.backup.framework (1.5.5 - 1.5.5) <CA77A4FC-7B76-30C7-94BE-FF4B8140D05A> /System/Library/PrivateFrameworks/Backup.framework/Versions/A/Backup
         0x12689e000 -        0x12692aff7  com.apple.ink.framework (10.9 - 207) <8A50B893-AD03-3826-8555-A54FEAF08F47> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Ink.framework/Versions/A/Ink
         0x12695d000 -        0x126998fff  com.apple.bom (14.0 - 193.1) <EF24A562-6D3C-379E-8B9B-FAE0E4A0EF7C> /System/Library/PrivateFrameworks/Bom.framework/Versions/A/Bom
         0x1269ab000 -        0x126c7cffc  com.apple.CoreImage (9.4.1) <7B28C3F3-8EB3-3150-A55D-EBCDBDCA4977> /System/Library/Frameworks/QuartzCore.framework/Versions/A/Frameworks/CoreImage.framework/Versions/A/CoreImage
         0x126d71000 -        0x126dc4fff  com.apple.ScalableUserInterface (1.0 - 1) <CF745298-7373-38D2-B3B1-727D5A569E48> /System/Library/Frameworks/QuartzCore.framework/Versions/A/Frameworks/ScalableUserInterface.framework/Versions/A/ScalableUserInterface
         0x126de9000 -        0x12721cffb  com.apple.vision.FaceCore (3.0.0 - 3.0.0) <F42BFC9C-0B16-35EF-9A07-91B7FDAB7FC5> /System/Library/PrivateFrameworks/FaceCore.framework/Versions/A/FaceCore
         0x127434000 -        0x12743eff7  com.apple.CrashReporterSupport (10.9 - 539) <B25A09EC-A021-32EC-86F8-05B4837E0EDE> /System/Library/PrivateFrameworks/CrashReporterSupport.framework/Versions/A/CrashReporterSupport
         0x12744c000 -        0x12749aff7  com.apple.opencl (2.3.59 - 2.3.59) <E37E2219-6EA7-3666-8DB5-8FC60EFB0BC9> /System/Library/Frameworks/OpenCL.framework/Versions/A/OpenCL
         0x1274b2000 -        0x1274beffb  com.apple.AppleFSCompression (56.92.2 - 1.0) <16542F97-9D21-317D-8A50-4C34AAD35F41> /System/Library/PrivateFrameworks/AppleFSCompression.framework/Versions/A/AppleFSCompression
         0x1274c6000 -        0x1274dfff7  com.apple.Ubiquity (1.3 - 289) <C7F1B734-CE81-334D-BE41-8B20D95A1F9B> /System/Library/PrivateFrameworks/Ubiquity.framework/Versions/A/Ubiquity
         0x1274f2000 -        0x127522fff  com.apple.IconServices (25 - 25.17) <4751127E-FBD5-3ED5-8510-08D4E4166EFE> /System/Library/PrivateFrameworks/IconServices.framework/Versions/A/IconServices
         0x12754b000 -        0x127570ff7  com.apple.ChunkingLibrary (2.0 - 155.1) <B845DC7A-D1EA-31E2-967C-D1FE0C628036> /System/Library/PrivateFrameworks/ChunkingLibrary.framework/Versions/A/ChunkingLibrary
         0x12757c000 -        0x1275fdfff  com.apple.CoreSymbolication (3.0.1 - 141.0.6) <D46DE002-1FEB-38B7-8583-3DF3496274F5> /System/Library/PrivateFrameworks/CoreSymbolication.framework/Versions/A/CoreSymbolication
         0x12764e000 -        0x1276a6ff7  com.apple.Symbolication (1.4 - 129.0.2) <3DCCAB8A-6FA1-3BB9-B4D3-A3CBDB3BDF04> /System/Library/PrivateFrameworks/Symbolication.framework/Versions/A/Symbolication
         0x1276ed000 -        0x12771cfff  com.apple.DebugSymbols (106 - 106) <E1BDED08-523A-36F4-B2DA-9D5C712F0AC7> /System/Library/PrivateFrameworks/DebugSymbols.framework/Versions/A/DebugSymbols
         0x127737000 -        0x12773dff7  com.apple.XPCService (2.0 - 1) <2CE632D7-FE57-36CF-91D4-C57D0F2E0BFE> /System/Library/PrivateFrameworks/XPCService.framework/Versions/A/XPCService
         0x127747000 -        0x127751ff7  com.apple.AppSandbox (3.0 - 1) <9F27DC25-C566-3AEF-92D3-DCFE7836916D> /System/Library/PrivateFrameworks/AppSandbox.framework/Versions/A/AppSandbox
         0x12775c000 -        0x12776fff7  com.apple.AppContainer (3.0 - 1) <BD342039-430E-39FE-BC2D-8F97B557548E> /System/Library/PrivateFrameworks/AppContainer.framework/Versions/A/AppContainer
         0x127784000 -        0x127786fff  com.apple.SecCodeWrapper (3.0 - 1) <DE7CA981-2B8B-34AC-845D-06D5C8F10441> /System/Library/PrivateFrameworks/SecCodeWrapper.framework/Versions/A/SecCodeWrapper
         0x12778c000 -        0x127790fff  com.apple.CommonPanels (1.2.6 - 96) <6B434AFD-50F8-37C7-9A56-162C17E375B3> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/CommonPanels.framework/Versions/A/CommonPanels
         0x127797000 -        0x12779afff  com.apple.help (1.3.3 - 46) <AE763646-D07A-3F9A-ACD4-F5CBD734EE36> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Help.framework/Versions/A/Help
         0x1277a0000 -        0x1277b2fff  com.apple.ImageCapture (9.0 - 9.0) <BE0B65DA-3031-359B-8BBA-B9803D4ADBF4> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/ImageCapture.framework/Versions/A/ImageCapture
         0x1277cd000 -        0x1277e5fff  com.apple.openscripting (1.4.1 - 157.1) <2C6C6498-D88E-3D9B-B933-9873890F382E> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/OpenScripting.framework/Versions/A/OpenScripting
         0x1277f7000 -        0x1277f9ff7  com.apple.securityhi (9.0 - 55005) <0CB82072-BA4B-357B-BE46-A96D317C1D91> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SecurityHI.framework/Versions/A/SecurityHI
         0x1277ff000 -        0x127d22fff  com.apple.QuartzComposer (5.1 - 319.2) <E8D9D10C-D5E7-3C7A-9923-D5305578E6BF> /System/Library/Frameworks/Quartz.framework/Versions/A/Frameworks/QuartzComposer.framework/Versions/A/QuartzComposer
         0x128044000 -        0x1280dfff7  com.apple.PDFKit (2.9.2 - 2.9.2) <DF2CE219-6256-3A8A-BDB1-51EF556F5BC8> /System/Library/Frameworks/Quartz.framework/Versions/A/Frameworks/PDFKit.framework/Versions/A/PDFKit
         0x128152000 -        0x128176fff  com.apple.quartzfilters (1.8.0 - 1.7.0) <39C08086-9866-372F-9420-81F5689149DF> /System/Library/Frameworks/Quartz.framework/Versions/A/Frameworks/QuartzFilters.framework/Versions/A/QuartzFilters
         0x1281a5000 -        0x128406fff  com.apple.imageKit (2.5 - 774) <AACDE16E-ED9F-3B3F-A792-69BA1942753B> /System/Library/Frameworks/Quartz.framework/Versions/A/Frameworks/ImageKit.framework/Versions/A/ImageKit
         0x128651000 -        0x128722fff  com.apple.QuickLookUIFramework (5.0 - 622.7) <13841701-34C2-353D-868D-3E08D020C90F> /System/Library/Frameworks/Quartz.framework/Versions/A/Frameworks/QuickLookUI.framework/Versions/A/QuickLookUI
         0x1287d4000 -        0x128b4bff6  com.apple.JavaScriptCore (9537 - 9537.78.1) <8623A109-9E9D-3E3B-A8E1-6EE447C0110C> /System/Library/Frameworks/JavaScriptCore.framework/Versions/A/JavaScriptCore
         0x128c44000 -        0x128d85fff  com.apple.QTKit (7.7.3 - 2826.34) <3BB88D64-71FA-3824-A52A-D51C761E6EE0> /System/Library/Frameworks/QTKit.framework/Versions/A/QTKit
         0x128e9a000 -        0x128e9dfff  com.apple.AppleSystemInfo (3.0 - 3.0) <61FE171D-3D88-313F-A832-280AEC8F4AB7> /System/Library/PrivateFrameworks/AppleSystemInfo.framework/Versions/A/AppleSystemInfo
         0x128ea4000 -        0x128f2dff7  com.apple.CorePDF (4.0 - 4) <ADCCD075-2572-3C64-9C40-67A30C9CB07D> /System/Library/PrivateFrameworks/CorePDF.framework/Versions/A/CorePDF
         0x128f82000 -        0x128fd3fff  com.apple.QuickLookFramework (5.0 - 622.7) <17685CEC-C94B-3F83-ADE1-B24840B35E44> /System/Library/Frameworks/QuickLook.framework/Versions/A/QuickLook
         0x12900f000 -        0x129018fff  com.apple.DisplayServicesFW (2.8 - 360.8.14) <816A9CED-1BC0-3C76-8103-1B9BE0F723BB> /System/Library/PrivateFrameworks/DisplayServices.framework/Versions/A/DisplayServices
         0x129023000 -        0x129027ff7  com.apple.ServerInformation (2.1.1 - 1) <7FAF2B82-FE90-3398-98D8-0F84C6FE6A4A> /System/Library/PrivateFrameworks/ServerInformation.framework/Versions/A/ServerInformation
         0x12902e000 -        0x129040ff7  com.apple.CoreBluetooth (1.0 - 1) <67A00F44-563E-3C55-9187-34D502D84DDE> /System/Library/Frameworks/IOBluetooth.framework/Versions/A/Frameworks/CoreBluetooth.framework/Versions/A/CoreBluetooth
         0x129055000 -        0x12906dfff  libexpat.1.dylib (12) <97F4A9A7-CB3E-3BBF-9314-4997FC770E52> /usr/lib/libexpat.1.dylib
         0x129077000 -        0x129235fff  com.apple.GeoServices (1.0 - 702.15.12) <850DC458-20CC-3E16-BB50-7C9FDBA308D3> /System/Library/PrivateFrameworks/GeoServices.framework/Versions/A/GeoServices
         0x12938d000 -        0x129397ff7  com.apple.ProtocolBuffer (1 - 182.1.3) <82E68598-A8AA-3AF1-843E-2A64F19472D4> /System/Library/PrivateFrameworks/ProtocolBuffer.framework/Versions/A/ProtocolBuffer
         0x12dce2000 -        0x12dd0efff  com.apple.CoreServicesInternal (184.9 - 184.9) <4DEA54F9-81D6-3EDB-AA3C-1F9C497B3379> /System/Library/PrivateFrameworks/CoreServicesInternal.framework/CoreServicesInternal
      0x7fff6e82c000 -     0x7fff6e85f887  dyld (239.5) <1D3130FE-FE7E-3C4C-8E74-EB51895B6BA5> /usr/lib/dyld
  
  External Modification Summary:
    Calls made by other processes targeting this process:
      task_for_pid: 0
      thread_create: 0
      thread_set_state: 0
    Calls made by this process:
      task_for_pid: 0
      thread_create: 0
      thread_set_state: 0
    Calls made by all processes on this machine:
      task_for_pid: 2664943
      thread_create: 0
      thread_set_state: 0
  
  VM Region Summary:
  ReadOnly portion of Libraries: Total=569.3M resident=317.3M(56%) swapped_out_or_unallocated=252.0M(44%)
  Writable regions: Total=186.0M written=19.0M(10%) resident=24.0M(13%) swapped_out=0K(0%) unallocated=161.9M(87%)
  
  REGION TYPE                      VIRTUAL
  ===========                      =======
  Dispatch continuations             16.0M
  Kernel Alloc Once                     4K
  MALLOC                             93.1M
  MALLOC (admin)                       32K
  Mach message                         24K
  Memory Tag 241                      296K
  STACK GUARD                        56.0M
  Stack                              57.1M
  VM_ALLOCATE                        2712K
  __DATA                             35.6M
  __IMAGE                             528K
  __LINKEDIT                        259.8M
  __TEXT                            309.6M
  __UNICODE                           544K
  mapped file                        43.0M
  shared memory                         4K
  ===========                      =======
  TOTAL                             874.4M

Activity

$ /bin/bash -lc "nl -ba xnu-2422/osfmk/kern/wait_queue.c | sed -n '1187,1205p'; nl -ba xnu-2422/bsd/kern/kern_event.c | sed -n '2239,2259p'; nl -ba investigation/wait_queue-10.10.c | sed -n '1190,1202p'; nl -ba investigation/message_pump_kqueue-2022.cc | sed -n '15,31p'; nl -ba investigation/message_pump_kqueue-2022.cc | sed -n '105,155p'; nl -ba investigation/message_pump_kqueue-2022.cc | sed -n '411,448p'; rg -n '"'^thread_unblock|''^thread_block_reason|call_continuation'"\\(continuation, parameter, self->wait_result\\)|thread_wakeup_with_result\\(\\(event_t\\) m, THREAD_RESTART\\)' xnu-2422/osfmk/kern/sched_prim.c xnu-2422/osfmk/vm/vm_fault.c"
status: Completed · exit 0
    1187		thread_t thread)
    1188	{
    1189		wait_result_t wait_result;
    1190		boolean_t realtime;
    1191
    1192		if (!wait_queue_assert_possible(thread))
    1193			panic("wait_queue_assert_wait64_locked");
    1194
    1195		if (wq->wq_type == _WAIT_QUEUE_SET_inited) {
    1196			wait_queue_set_t wqs = (wait_queue_set_t)wq;
    1197
    1198			if (event == NO_EVENT64 && wqs_is_preposted(wqs))
    1199				return(THREAD_AWAKENED);
    1200		}
    1201
    1202		/*
    1203		 * Realtime threads get priority for wait queue placements.
    1204		 * This allows wait_queue_wakeup_one to prefer a waiting
    1205		 * realtime thread, similar in principle to performing
    2239					cont_args->deadline = deadline;
    2240					cont_args->data = data;
    2241					cont = kqueue_scan_continue;
    2242				}
    2243			}
    2244
    2245			/* go ahead and wait */
    2246			wait_queue_assert_wait_with_leeway((wait_queue_t)kq->kq_wqs,
    2247			    KQ_EVENT, THREAD_ABORTSAFE, TIMEOUT_URGENCY_USER_NORMAL,
    2248			    deadline, 0);
    2249			kq->kq_state |= KQ_SLEEP;
    2250			kqunlock(kq);
    2251			wait_result = thread_block_parameter(cont, kq);
    2252			/* NOTREACHED if (continuation != NULL) */
    2253
    2254			switch (wait_result) {
    2255			case THREAD_AWAKENED:
    2256				continue;
    2257			case THREAD_TIMED_OUT:
    2258				return (EWOULDBLOCK);
    2259			case THREAD_INTERRUPTED:
    1190		boolean_t realtime;
    1191
    1192		if (!wait_queue_assert_possible(thread))
    1193			panic("wait_queue_assert_wait64_locked");
    1194
    1195		if (wq->wq_type == _WAIT_QUEUE_SET_inited) {
    1196			wait_queue_set_t wqs = (wait_queue_set_t)wq;
    1197
    1198			if (event == NO_EVENT64 && wqs_is_preposted(wqs))
    1199				return (thread->wait_result = THREAD_AWAKENED);
    1200		}
    1201
    1202		/*
      15	#include "base/posix/eintr_wrapper.h"
      16
      17	namespace base {
      18
      19	namespace {
      20
      21	// Prior to macOS 10.12, a kqueue could not watch individual Mach ports, only
      22	// port sets. MessagePumpKqueue will directly use Mach ports in the kqueue if
      23	// it is possible.
      24	bool KqueueNeedsPortSet() {
      25	#if BUILDFLAG(IS_MAC)
      26	  static const bool kqueue_needs_port_set = mac::IsAtMostOS10_11();
      27	  return kqueue_needs_port_set;
      28	#else
      29	  return false;
      30	#endif
      31	}
     105
     106	MessagePumpKqueue::MessagePumpKqueue()
     107	    : kqueue_(kqueue()),
     108	      is_ludicrous_timer_slack_enabled_(base::IsLudicrousTimerSlackEnabled()),
     109	      ludicrous_timer_slack_was_suspended_(
     110	          base::IsLudicrousTimerSlackSuspended()),
     111	      weak_factory_(this) {
     112	  PCHECK(kqueue_.is_valid()) << "kqueue";
     113
     114	  // Create a Mach port that will be used to wake up the pump by sending
     115	  // a message in response to ScheduleWork(). This is significantly faster than
     116	  // using an EVFILT_USER event, especially when triggered across threads.
     117	  kern_return_t kr = mach_port_allocate(
     118	      mach_task_self(), MACH_PORT_RIGHT_RECEIVE,
     119	      base::mac::ScopedMachReceiveRight::Receiver(wakeup_).get());
     120	  MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_port_allocate";
     121
     122	  kevent64_s event{};
     123	  if (KqueueNeedsPortSet()) {
     124	    kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET,
     125	                            mac::ScopedMachPortSet::Receiver(port_set_).get());
     126	    MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_port_allocate PORT_SET";
     127
     128	    kr = mach_port_insert_member(mach_task_self(), wakeup_.get(),
     129	                                 port_set_.get());
     130	    MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_port_insert_member";
     131
     132	    event.ident = port_set_.get();
     133	    event.filter = EVFILT_MACHPORT;
     134	    event.flags = EV_ADD;
     135	  } else {
     136	    // When not using a port set, the wakeup port event can be specified to
     137	    // directly receive the Mach message as part of the kevent64() syscall.
     138	    // This is not done when using a port set, since that would potentially
     139	    // receive client MachPortWatchers' messages.
     140	    event.ident = wakeup_.get();
     141	    event.filter = EVFILT_MACHPORT;
     142	    event.flags = EV_ADD;
     143	    event.fflags = MACH_RCV_MSG;
     144	    event.ext[0] = reinterpret_cast<uint64_t>(&wakeup_buffer_);
     145	    event.ext[1] = sizeof(wakeup_buffer_);
     146	  }
     147
     148	  int rv = ChangeOneEvent(kqueue_, &event);
     149	  PCHECK(rv == 0) << "kevent64";
     150	}
     151
     152	MessagePumpKqueue::~MessagePumpKqueue() {}
     153
     154	void MessagePumpKqueue::Run(Delegate* delegate) {
     155	  AutoReset<bool> reset_keep_running(&keep_running_, true);
     411	  return rv >= 0;
     412	}
     413
     414	bool MessagePumpKqueue::DoInternalWork(Delegate* delegate,
     415	                                       Delegate::NextWorkInfo* next_work_info) {
     416	  if (events_.size() < event_count_) {
     417	    events_.resize(event_count_);
     418	  }
     419
     420	  bool poll = next_work_info == nullptr;
     421	  int flags = poll ? KEVENT_FLAG_IMMEDIATE : 0;
     422	  bool indefinite =
     423	      next_work_info != nullptr && next_work_info->delayed_run_time.is_max();
     424
     425	  int rv = 0;
     426	  do {
     427	    timespec timeout{};
     428	    if (!indefinite && !poll) {
     429	      if (rv != 0) {
     430	        // The wait was interrupted and made |next_work_info|'s view of
     431	        // TimeTicks::Now() stale. Refresh it before doing another wait.
     432	        next_work_info->recent_now = TimeTicks::Now();
     433	      }
     434	      timeout = next_work_info->remaining_delay().ToTimeSpec();
     435	    }
     436	    // This does not use HANDLE_EINTR, since retrying the syscall requires
     437	    // adjusting the timeout to account for time already waited.
     438	    rv = kevent64(kqueue_.get(), nullptr, 0, events_.data(), events_.size(),
     439	                  flags, indefinite ? nullptr : &timeout);
     440	  } while (rv < 0 && errno == EINTR);
     441
     442	  PCHECK(rv >= 0) << "kevent64";
     443	  if (rv == 0) {
     444	    // No events to dispatch so no need to call ProcessEvents().
     445	    return false;
     446	  }
     447
     448	  return ProcessEvents(delegate, rv);
  xnu-2422/osfmk/vm/vm_fault.c:2354:				thread_wakeup_with_result((event_t) m, THREAD_RESTART);
  xnu-2422/osfmk/kern/sched_prim.c:852:thread_unblock(
  xnu-2422/osfmk/kern/sched_prim.c:2353:			call_continuation(continuation, parameter, self->wait_result);
  xnu-2422/osfmk/kern/sched_prim.c:2457:		call_continuation(continuation, parameter, self->wait_result);
  xnu-2422/osfmk/kern/sched_prim.c:2705:thread_block_reason(
  xnu-2422/osfmk/kern/sched_prim.c:2839:	call_continuation(continuation, parameter, self->wait_result);

Assistant

I think Chromium Legacy was exposing a stale per-thread wait-result bug in XNU. A legitimate THREAD_RESTART from an earlier operation could survive in the thread’s state and later be mistaken for the result of a kqueue wait.

I found a specific missing assignment that explains this mechanism—and Apple’s Yosemite source fixes that exact assignment. That also provides a convincing answer to the conversation’s central puzzle: why El Capitan could retain the supposedly problematic panic statement without exhibiting the same failures.

I read the issue body and all 96 comments, including the collapsed discussions, embedded screenshots, attached crash reports, and later kernel-patch follow-ups. This diagnosis is based on that evidence and source inspection; I have not reproduced it on a running Mavericks kernel.

The strongest evidence is in wait_queue.c, line 1198:

if (event == NO_EVENT64 && wqs_is_preposted(wqs))
    return(THREAD_AWAKENED);

In Yosemite’s XNU 2782.1.97, the equivalent code is:

if (event == NO_EVENT64 && wqs_is_preposted(wqs))
    return (thread->wait_result = THREAD_AWAKENED);

The difference is thread->wait_result =. Mavericks returns the correct result to its immediate caller, but leaves a separate, persistent copy of the result unchanged. Apple’s Yosemite source

Here is why that seemingly tiny difference matters.

A kernel thread has a wait_result field recording how a wait ended. Separately, wait_queue_assert_wait…() returns a C function result indicating whether a wait was established or was unnecessary.

Those are two different places to store an answer. Most paths keep them consistent. For example, establishing a wait writes THREAD_WAITING into the thread, and waking it writes the appropriate completion result. But the Mavericks fast path above only returns a value.

“Preposted” means the wait-queue set already records a notification. This handles the familiar event-loop race:

  1. A thread checks for work and finds none.
  2. Work arrives just before the thread starts waiting.
  3. The wait operation notices the recorded notification and declines to put the thread to sleep.

That behavior is correct. The omission is failing to update the thread’s stored result when taking that shortcut.

Now consider the caller in kqueue_scan():

wait_queue_assert_wait_with_leeway(...);
kq->kq_state |= KQ_SLEEP;
kqunlock(kq);
wait_result = thread_block_parameter(cont, kq);

It ignores the return value from wait_queue_assert_wait_with_leeway(). It proceeds through the scheduler, expecting the result to be available in the thread.

The scheduler then calls the continuation using that stored field:

call_continuation(continuation, parameter, self->wait_result);

There is even an explicit path for invoking a continuation when the selected thread is the same thread. Calling thread_block_parameter() does not guarantee that a new wait actually occurred and supplied a fresh result. See thread_invoke() and thread_block_reason().

Consequently, this sequence is possible:

Step Actual event Stored thread->wait_result
1 An earlier kernel wait finishes with a restart indication. THREAD_RESTART
2 That operation handles the restart and continues successfully. Can remain THREAD_RESTART
3 Chromium enters kevent64; the kernel finds no immediately deliverable event. Still THREAD_RESTART
4 A Mach notification arrives before the wait is established. Still THREAD_RESTART
5 The preposted fast path returns THREAD_AWAKENED, without updating the field. Still THREAD_RESTART
6 The scheduler invokes kqueue_scan_continue using the field. Continuation receives 3
7 The continuation rejects that value. Kernel panic

Under this explanation, nobody has to send a restart notification to the kqueue at all. It is an old result being consumed in the wrong context.

That distinction is what I think the original investigation missed.

Chromium’s implementation makes this path particularly relevant. I checked the historical 2022 source linked in the conversation, as well as your local Chromium source. On the older operating systems, MessagePumpKqueue creates a Mach receive port, puts it into a port set, and registers that set with EVFILT_MACHPORT. Other threads wake the pump by sending a Mach message. Historical Chromium implementation

XNU implements that filter by linking the Mach port set’s wait queue directly into the kqueue’s wait-queue set. The code explicitly describes this arrangement as allowing Mach wakeups to propagate through the wait-queue machinery. Kqueues are allocated with preposting enabled. See filt_machportattach(), knote_link_wait_queue(), and kqueue_alloc().

Thus Chromium is repeatedly exercising precisely the combination this bug requires: Mach-port notifications, preposted wait-queue sets, and kqueue continuations.

This does not require malformed syscall arguments, a prematurely destroyed message pump, or an invalid file descriptor.

The operating-system comparison is particularly persuasive. I checked these Apple source releases:

OS source inspected Behavior of the preposted fast path
Lion, XNU 1699.32.7 Returns THREAD_AWAKENED without updating the thread field.
Mountain Lion, XNU 2050.48.11 Same omission.
Mavericks, XNU 2422.115.4 Same omission.
Yosemite, XNU 2782.1.97 Updates the thread field before returning.
El Capitan, XNU 3248.60.10 Its rewritten wait-queue implementation also updates the field.

These are directly inspectable in Apple’s Lion, Mountain Lion, Mavericks, Yosemite, and El Capitan sources.

El Capitan’s kqueue_scan_continue still has the panic for unrecognized results. The presence of that panic does not establish that El Capitan contains the bug that feeds it a stale result. The lower-level correction already prevents this particular route to the panic. El Capitan kqueue source

This makes the later addition of case THREAD_RESTART: error = EBADF much less decisive than it appeared in the thread. That addition handles a result at the receiving end; the earlier missing assignment explains how an inappropriate result could arrive there.

The remaining question is where the stale 3 originally came from.

My leading candidate is an earlier virtual-memory fault on the same thread, although this part is less certain than the missing-assignment mechanism.

Mavericks’ vm_fault.c explicitly wakes threads with THREAD_RESTART during a copy-on-write operation:

thread_wakeup_with_result((event_t) m, THREAD_RESTART);

The surrounding comment explains that moving a page through the VM object hierarchy requires waiting faults to restart. The awakened thread can consume this result, return VM_FAULT_RETRY, retry the fault, and ultimately succeed. The code handling that result does not itself reset thread->wait_result to zero. See the fault-wait handling.

That provides a legitimate source of 3 that has nothing to do with broken kqueues. It could occur before the syscall, or during an earlier part of kernel work involving pageable memory. It need only survive until the preposted shortcut, without another operation overwriting the field.

Other legitimate restart-producing waits are possible. The historical reports do not identify which one supplied the value. In particular, seeing WaitableEvent::TimedWait on other threads in a crash dump does not establish the origin: this hypothesis concerns the history of the specific thread that eventually panicked.

The VM explanation is compatible with the tentative observation about lower-memory machines, but that observation was never established experimentally. Copy-on-write faults also do not require exhausted RAM or swapping. I would treat memory pressure as a possible influence on frequency, not a necessary condition.

Several otherwise puzzling observations now fit together:

  • The invalid-queue logging stayed silent. A valid, preposted queue takes the buggy shortcut. None of the invalid-queue checks should fire. The March 4–5 reports are therefore positive evidence for this explanation, rather than merely failed diagnostics.
  • The debugger found ordinary kevent64 arguments. The important state is internal to the thread and the wait queue, consistent with the maintainer’s findings.
  • Changing WaitableEvent to PORT_SET did not help. That experiment left MessagePumpKqueue and its own Mach-port wakeup mechanism in place. Experiment result
  • Frequency varied dramatically. A stale restart result must coincide with the preposted shortcut. If the stored result happens to be THREAD_AWAKENED, the omission is invisible. Stale timeout or interruption results can also be much less conspicuous than 3.
  • Different pages and switches changed the symptoms. They change scheduling, memory activity, and IPC traffic, all of which can alter the coincidence rate without being separate root causes.

The original “somebody closed the kqueue” theory is weaker for another concrete reason. In the supplied Mavericks source, kqueue_drain() calls kqueue_wakeup(kq, 1), and the latter selects:

(closed) ? THREAD_INTERRUPTED : THREAD_AWAKENED

Ordinary closure is explicitly routed to THREAD_INTERRUPTED. That does not rule out every conceivable lifetime bug, but it contradicts the simple assumption that closing this kqueue normally produces THREAD_RESTART. Mavericks close-wakeup implementation

Similarly, Mach-port destruction initially looks promising because ipc_mqueue_changed() generates THREAD_RESTART. But tracing further shows that receive-right teardown removes port-set memberships before issuing the restart wakeup, and port-set teardown also removes wait-queue links. A claim that ordinary destruction simply propagates 3 into Chromium’s kqueue needs to explain how it bypasses that unlinking. The stale-result explanation needs no such additional failure. See receive-right teardown and wait-queue-set unlinking.

The EBADF workaround also becomes easier to interpret.

The patched kernel’s “Bad file descriptor” message was not evidence that a file descriptor was actually bad. The patch manufactured EBADF whenever the continuation received THREAD_RESTART.

Chromium then encountered an error that its event-loop code treats as fatal. The attached crash report confirms a deliberate EXC_BREAKPOINT on Chrome_ChildIOThread, through the logging machinery and MessagePumpKqueue::DoInternalWork. The corresponding historical source has PCHECK(rv >= 0) immediately after the syscall’s retry loop. Crash report, historical fatal check

So the observed progression was:

Stale kernel wait result
    → original kernel: panic
    → patched kernel: artificial EBADF
        → Chromium's fatal check
            → helper process exits

The network-service restart identifies a service affected by that exit. It does not establish that networking created an invalid descriptor.

Under this diagnosis, repairing the stored result should allow normal event processing to continue, potentially eliminating both the panic and the consequent helper crash. There need not be a separate Chromium correctness bug requiring its own repair.

To confirm this on an affected system, I would instrument the preposted branch itself. The decisive observation would be:

wait queue valid:                    yes
wait queue preposted:               yes
thread->wait_result before return:   THREAD_RESTART
function's returned result:          THREAD_AWAKENED

That should be correlated by thread identity with the subsequent continuation. A small in-memory diagnostic buffer would be preferable to logging every IPC operation, which already proved too noisy in the original investigation.

Then I would test only the Yosemite-style assignment, retaining the original panic as a detector:

 if (event == NO_EVENT64 && wqs_is_preposted(wqs))
-    return(THREAD_AWAKENED);
+    return (thread->wait_result = THREAD_AWAKENED);

This is the specific source change I would investigate first. I would not initially replace all restart results with success, because a genuinely new restart notification could have different semantics. The correction belongs at the branch that knows the actual result is THREAD_AWAKENED.

My confidence is high that this is a real defect in the supplied XNU code and that it provides a coherent mechanism for issue #44. The exact earlier operation that supplied 3, and confirmation against the affected shipping kernel binaries, remain unproven. The missing assignment, its correction by Yosemite, and the issue’s negative logging results together make this substantially stronger than a generic race-condition hypothesis.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment