Commit Graph

33 Commits

Author SHA1 Message Date
Ariel Abreu
db65a1b009
Add a new tool for debugging darlingserver
This new tool (`dserverdbg`) runs on the host but connects to
darlingserver and makes unmanaged calls to retrieve debugging
information.

The initial set of subcommands available in this tool are `ps`,
`lsport`, `lspset`, and `lsmsg`:
  * `ps` lists processes currently registered with the server and how
    many Mach ports they have
  * `lsport` lists the ports of a given process (via PID) and their
    rights and messages counts (for receive rights)
  * `lspset` lists the members of a given portset (via PID and port
    name) and provides the same information about each port as `lsport`
  * `lsmsg` lists the messages of a given port (via PID and port name),
    providing sender PID (if available) and size

This tool may be expanded later to allow e.g. modifying logging settings
while darlingserver is running or perhaps searching through and
filtering the logs.
2023-10-04 00:23:56 -04:00
Ariel Abreu
5a3e170bf6
Introduce supplementary group tracking
This works very much like our UID/GID tracking.
2023-09-20 21:25:39 -04:00
Ariel Abreu
0a58b40d68
[rpc] Don't set the control buffer if we have no FDs to send
If `valid_fd_count` is 0, we can simply not set a control buffer. This
is necessary because empty control buffers with no content are invalid.
It seems that, due to some coincidence with struct sizes, this went
undetected on x86_64. However, the issue is present on i386.
2023-03-13 13:38:57 -04:00
Ariel Abreu
dac0e1333f
[rpc] Ensure consistent definitions across architectures
This commit disallows non-fixed-width types in private types and also
adds explicit alignment for 8-byte-wide types. This ensures that RPC
structure definitions are the same across different architectures.
In particular, this is necessary to fix 32-bit support.
2023-03-13 13:34:18 -04:00
Thomas A
697fa6e643 [generate-rpc-wrappers.py] Use explict casting when dealing with different types.
FIxes int-conversion error
2022-11-20 15:09:14 -08:00
Trung Nguyen
2ad420c633
feat: Initial WSL1 support
- Implemented an alternative to pidfd_open for kernels older than 5.3.
mldr should send a "lifetime pipe" to darlingserver during process start.
When the process dies, darlingserver should receive a POLLHUP event.
- Set increased_limit.rlim_cur to default_limit.rlim_max on systems without
/proc/sys/fs/nr_open. On WSL1, this greatly increases the number of open file
descriptors available.
- For systems without NSpid in /proc/self/status, implemented a way to manage
thread IDs in darlingserver during checkin. darlingserver should receive a hint
address on the thread's stack, and then compare it with a stack pointer retrieved using
PTRACE_GETREGS
- Avoided sending socket messages when msg_hdr.msg_name->sun_path is an empty string.
A null msg_name is used instead, otherwise, on some systems, this would fail with EINVAL.
2022-08-21 20:59:24 +07:00
Trung Nguyen
226610318c
chore: Address comments 2022-04-05 12:43:27 +07:00
Trung Nguyen
c5a32023f3
feat: Manage executable path in darlingserver 2022-04-05 09:25:23 +07:00
Ariel Abreu
be203fd569
Allow threads to perform S2C calls at any time
This is possible now because we can signal threads with a real-time
signal that libsystem_kernel handles.
2022-04-01 02:11:17 -04:00
Ariel Abreu
d5aa92fb5c
Add a thread_suspended call 2022-03-24 14:03:35 -04:00
Ariel Abreu
94c0528f72
Add a ptrace_thupdate call 2022-03-24 14:02:37 -04:00
Ariel Abreu
337935e64c
Add a ptrace_sigexc call 2022-03-24 14:02:08 -04:00
Ariel Abreu
be9afe1fa5
Add a tid_for_thread call 2022-03-24 13:58:45 -04:00
Ariel Abreu
a4364df97b
Add a stop_after_exec call 2022-03-24 13:58:18 -04:00
Ariel Abreu
f1ba799ba9
Add a set_dyld_info call 2022-03-24 13:57:07 -04:00
Ariel Abreu
8bb81313a0
Add a set_tracer call (and implement get_tracer) 2022-03-24 13:47:32 -04:00
Ariel Abreu
a82cff6069
RPC changes for better interrupt/signal handling 2022-03-21 00:29:29 -04:00
Ariel Abreu
db67387fcd
Allow calls to be unmanaged
Unmanaged calls are those that can come from unmanaged processes,
i.e. processes that the server does not control. They can also come from
managed processes, but they don't have to.

This commit does not introduce any unmanaged calls, however.
During local development, I created one and later decided to discard it.
However, this does seem like a useful feature, so it's being added with
this commit.
2022-03-09 17:33:33 -05:00
Ariel Abreu
06f9612fa2
Fix race for call destruction when sleeping a microthread
When a microthread went to sleep with a continuation, we discarded its
call. This would lead to the call being disposed before we had a chance
to reply to it. Instead, now we keep a reference to it in the thread
until we send a reply for it.
2022-03-04 00:29:21 -05:00
Ariel Abreu
97e36ba645
calls: De-duplicate generated internal code a bit 2022-03-02 23:46:32 -05:00
Ariel Abreu
02e1023db1
calls: Add console_open
This RPC call gives the caller a socket to which it can write to to log
to the server's log stream.

This is used to give userspace a place to put messages for "/dev/console".
Most notably, launchd tries to log to this device for important log
messages. This allows us to capture those messages.
2022-03-02 23:44:00 -05:00
Ariel Abreu
edfad52389
Attempt to handle signals while call is active
This is an early attempt at getting signal handling working when there is a call already active.
2022-02-26 10:38:45 -05:00
Ariel Abreu
7274224d44
Implement psynch using pthread kext
This is an initial implementation that will probably need more tweaking and fixing down the line, but it seems to work for now.
2022-02-23 00:55:03 -05:00
Ariel Abreu
9dc6253fa0
Implement task_is_64_bit RPC call 2022-02-20 01:30:11 -05:00
Ariel Abreu
d9bf20afc9
Implement remote mmap/munmap + various fixes
The most important change here is the ability to perform `mmap` and `munmap` in managed Darling processes. This is enabled via the new S2C call system.

Other notable changes:
  * Move the server socket to the prefix root because launchctl clears `var/run` on startup
  * Create an IPC importance structure for each duct-taped task; this is required by `ipc_importance_send`
  * Initialize the MPSC thread deallocation daemon; this is also used by turnstiles
  * Clean up a thread's timers and waits when destroying it
  * Check whether we should actually block in `thread_block_parameter` before doing so; this helps avoid missed wakeups
  * Support creating kernel threads without immediately starting them
  * Update a thread's address when receiving a message from it; this fixes an issue with keeping an outdated thread address when a process performs an exec (since we re-use its main thread)
2022-02-17 19:12:44 -05:00
Ariel Abreu
316ce5db20
Initial signal reprocessing implementation
Largely just ported over from the current LKM code.

Also, set XNU_TARGET_OS_OSX=1 to fix an incorrect default setting that was causing Mach messaging to fail trying to send a task control port (the task self port).

Additionally, with regards to RPC:
  * Send architecture information along with RPC calls
  * Log replies sent on the server side
  * Allow replies expecting FDs to handle the case when no valid FDs were sent back
2022-02-14 02:32:55 -05:00
Ariel Abreu
b4de4d55a9
Implement process kqueue channels + RPC wrapper fixes
In our previous in-kernel kqueue implementation, we followed suit with newer macOS version and dropped support for NOTE_TRACK and NOTE_CHILD. This implementation, however, reintroduces support for those flags to allow for backwards compatiblity with older software that makes use of these features.

Additionally, the RPC wrappers have been fixed to allow either side (both the client and the server) to specify a negative value for an FD parameter (in order to leave it absent and avoid actually sending an FD).
2022-02-12 00:44:45 -05:00
Ariel Abreu
52f1d6a4d1
Implement fork-waiting
This is almost a direct port of what we were previously doing in the LKM, except that we need to use duct-taped semaphores in order to put the calling microthread to sleep (rather than a real semaphore that would put the worker thread to sleep).
2022-02-10 21:15:55 -05:00
Ariel Abreu
7f02040c47
Implement Mach port kqueue channels + a few more things
Mach port kqchannels allow libkqueue to listen in on Mach port events that happen on the server side. The implementation consists of a socket pair used to communicate between the client and the server for that particular channel.

When the server receives an event, it sends a notification message on the socket, which makes the socket readable to the client and thus wakes up epoll. When the client is ready to read the event, it sends a message to the server asking it to read the event and send back the necessary data.

This is done this way (rather than proactively sending the event data over the socket) to closely mimic the actual process that kevent does when reading events. This is even more important when the client specifies MACH_MSG_RECEIVE, which asks the server to try to receive the message directly into a buffer (if there is enough space) when reading the event. In that case, we would *definitely* not want to read the Mach message before the client is actually ready to do so, as it could starve others from reading the Mach message while the client hasn't even acknowledged the event yet--or worse, the client could have died before reading our event and that message is now lost forever.

In other news, many different parts of the code have been updated to function properly now.

For example, all of the direct Mach traps can call thread_syscall_return now. This allows things like semaphores to work.

Timers (with timer_call) are also working now and have been tested in conjunction with timed semaphore waits.

Threads are now able to impersonate other threads for the purposes of running duct-taped code. The primary use case for this is for running code in a kernel microthread but pretending to be user microthread (e.g. kqchan does this). This makes current_map() and friends return the information for the thread we're impersonating (useful for e.g. copyout).
2022-02-10 13:57:21 -05:00
Ariel Abreu
89e7afe22e
Add a ton of RPC calls
This commit adds a bunch of RPC calls, mostly XNU trap calls (calls that go directly to duct-taped XNU Mach trap calls).

The wrapper generator can now automatically generate server-side wrapper/boilerplate code  these XNU trap calls.

These calls have not yet been tested and some (most of the non-IPC calls) probably require functions that haven't been implemented yet.
2022-01-28 00:07:03 -05:00
Ariel Abreu
a5627fddf1
Quite a few changes; check the description
Implement some general RPC calls (corresponding to calls from the LKM): mach_port_deallocate, thread_set_handles, uidgid (a combination of get_uidgid and set_uidgid), and vchroot.

Additionally, we now have some RPC calls that do pass descriptors. Surprisingly, the code I had previously written was *almost* functional (just 2 minor generation and compilation errors). However, that code has now been tested for sending FDs from clients to the server, not vice versa, so that other direction might have issues.

Additionally, a few fixes have been made in the duct-tape code. For example, tasks now handle audit and security tokens like we used to do in the LKM. They also properly initialize and destroy their semaphore queues. Both threads and tasks now properly free their allocated structures.

More importantly, threads and tasks are now properly destroyed. In order to do this, a "kernel" microthread had to be introduced to perform "kernel" work from the managing code (since certain duct-tape destruction operations expect to be running in a microthread context). Additionally, this had to be an additional microthread because the managing code can't use thread calls, since those already expect a microthread context.

The Server can now easily monitor arbitrary descriptors using Monitors. Process monitoring has been converted to this system as well.

Most importantly, however, is that we can now detect `execve`s. libsystem_kernel opens a close-on-exec pipe and sends the read end to the server. When `execve` succeeds, the pipe is simply closed. When `execve` fails, libsystem_kernel writes a single byte to the pipe and then closes it. On the server side, we listen for a hang-up (this indicates the write end of the pipe has been closed). If we are able to read a byte, we know the execve failed; otherwise, if we read nothing (EOF), then we know it succeeded.

Together with changes in libsystem_kernel, this commit allows startup to progress to vchroot doing its thing (vchrooting) and then executing launchd. launchd then proceeds to die when trying to open a kqueue (as this still uses the LKM API).
2022-01-23 22:41:55 -05:00
Ariel Abreu
be93cc46b7
Many additions + stubs; basic kernel MIG RPC working
Most of the newly added functions are just stubs for MIG calls. However, we now properly initialize IPC and related subsystems and we now have copyin/copyout that allows basic `mach_msg_overwrite_trap` usage.

dyld now progresses to `getHostInfo` and successfully retrieves `host_info` with a kernel MIG call (and then proceeds to die on `mach_port_deallocate`, since it hasn't been updated yet).
2022-01-20 00:11:51 -05:00
Ariel Abreu
3bfc652c9b
Initial commit 2022-01-18 00:46:28 -05:00