fork within Cocoa application - cocoa

My problem is not the best scenario for fork(). However, this is the best func I can get.
I am working on a Firefox plugin on Mac OSX. To make it robust, I need to create a new process to run my plugin. The problem is, when I forked a new process, much like this:
if (fork() == 0) exit(other_main());
However, since the state is not cleaned, I cannot properly initialized my new process (call NSApplicationLoad etc.). Any ideas? BTW, I certainly don't want create a new binary and exec it.

In general, you need to exec() after fork() on Mac OS X.
From the fork(2) man page:
There are limits to what you can do in the child process. To be totally safe you should restrict your-self to only executing async-signal safe operations until such time as one of the exec functions is called. All APIs, including global data symbols, in any framework or library should be assumed to be unsafe after a fork() unless explicitly documented to be safe or async-signal safe. If you need to use these frameworks in the child process, you must exec. In this situation it is reasonable to exec yourself.
TN2083 also comments on this subject:
Many Mac OS X frameworks do not work reliably if you call fork but do not call exec. The only exception is the System framework and, even there, the POSIX standard places severe constraints on what you can do between a fork and an exec.
IMPORTANT: In fact, in Mac OS X 10.5 and later, Core Foundation will detect this situation and print the warning message shown in Listing 13.
Listing 13: Core Foundation complaining about fork-without-exec
The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec().
Break on __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__() to debug.

fork without exec is basically entirely unsafe on OSX. You will end up with stale mach ports for example.

I'm writing the FreeWRL plugin for Firefox (Linux at the moment, Mac & Windows soon).
http://freewrl.sourceforge.net/
It's based on fork+exec to launch FreeWRL and swallow its window into Firefox.
You'll have to use a pipe to correctly handle the possible failure of fork+exec or the failure of your child process :
How to handle execvp(...) errors after fork()?
Cheers,
C

Related

Which frameworks am I allowed to link to from a macOS launch daemon?

I'm writing a macOS launch daemon (in C++). It works for the most part, except that I am noticing some random crashes via SIGABRT (in the log.)
I've asked earlier about the use of the Core Graphics framework, which it turns out was not allowed in a launch daemon. I removed it, but I still get very rare crashes.
Thus I'm wondering which of the following frameworks am I allowed to use from a launch daemon?
There's no technical restriction on specific frameworks you're allowed or not allowed to link. Merely linking a library will not cause crashes. Some APIs need to be called from specific contexts, such as much of Core Graphics only making sense if a process is part of a windowing session, as you've found out. But even there, some of the off-screen drawing APIs which don't interface with the windowing system directly ought to work from a Launch Daemon context.
If you're seeing crashes calling specific APIs, you'll need to investigate those one by one. If you're seeing "random" crashes, I suspect you have a bug (memory overwrite? multithreading error?) in your code. Note that Apple's toolchain provides a bunch of different diagnostic options which you can use even when not running in the debugger, such as ASan, UBSan, and Thread Sanitizer. These may help you track down issues.
As you've specifically tagged this question with the IOKit tag and it's shown in your screenshot, I'll add that using IOKit from a launch daemon is very common. It's even possible to use IOKit matching events as a launch trigger for the daemon using XPC events/xpc_set_event_stream_handler - this way, your daemon can be started on-demand when a specific (type of) device is connected, for example. (As opposed to starting up at every system boot and consuming system resources even if it's not needed or doing anything.)

Using posix_spawn() with setuid() & setgid()

There appears to be a bug in my version of glibc 2.13 that make repeated calls to fork()/execv() dangerous, resulting in crash and memory corruption. This seems to occur roughly 1-2% of the time. The current code flow is as follow
parent forks child process
child closes all inherited file descriptors except for stdin, stdout, stderr
child runs setgid and setuid to not be running as root any longer
Execv binary which should be run
If I replace the above 4 steps with just the use of posix_spawn(), my program never crashes. This seems to validate my hypothesis that my current glibc has a bug in it with fork/execv.
The issue with replacing steps 1-4 with posix_spawn() is that it provides no mechanism for me to accomplish steps 2 & 3, which are extremely important for resource management and security. Is there any alternative solution or something i have not considered in order to get a stable version working?
If I replace the above 4 steps with just the use of posix_spawn(), my program never crashes. This seems to validate my hypothesis that my current glibc has a bug in it with fork/execv.
glibc 2.13 uses fork and execve in the implementation of posix_spawn. It is probably a different bug in your code. Only in glibc 2.24 and later, posix_spawn avoids using fork by default (which implies not running fork handlers at all, and those can be a source of crashes or hangs).
The issue with replacing steps 1-4 with posix_spawn() is that it provides no mechanism for me to accomplish steps 2 & 3, which are extremely important for resource management and security. Is there any alternative solution
The only way to do this is to introduce a wrapper program which closes all file descriptors, switches IDs, and then launches the actual target program.

How to call system open from bash script

I've hooked the system call to typedef int (*orig_open_f_type)(const char *__file, int __oflag, ...); and thus, whenever a file gets opened, my code gets the event before it is passed on to the system. I created a dynamic library that overrides the open call and inject this library using DYLD_INSERT_LIBRARIES - working on a Mac machine and using XCode. It is a standard step that enables me to hook calls.
Now, I have bash script in which I have some files that I want to open. I have tried xdg-open , cat, exec - but they are not triggering the system call to open the file.
How should I invoke this open call in my bash script?
Please note that I have tested my open call hook, by opening files in C code.
I believe you're running foul of Apple's SIP (System Integrity Protection) which is designed to stop people doing things like that with system-provided executables. SIP was added to Mac OS X El Capitan (10.11) and continues in macOS Sierra (10.12).
To demonstrate whether this is the problem, consider copying /bin/cat to /usr/local/bin/cat and then try hooking (running) the local copy. You might get away with it there. This 'workaround' is purely for demonstration purposes. Basically, if I'm right, SIP is Apple's way of saying "don't go messing with our software".
You can follow links from Can Mac OS X El Capitan run software compiled for Yosemite that expects libraries in /usr/gnu/lib? to find out more about SIP. Following links via What is the "rootless" feature in El Capitan, really? on Ask Different to a blog article on System Integrity Protection, it says explicitly:
Runtime protection
SIP’s protections are not limited to protecting the system from filesystem changes. There are also system calls which are now restricted in their functionality.
task_for_pid() / processor_set_tasks() fail with EPERM
Mach special ports are reset on exec(2)
dyld environment variables are ignored
DTrace probes unavailable
However, SIP does not block inspection by the developer of their own applications while they’re being developed. Xcode’s tools will continue to allow apps to be inspected and debugged during the development process.
For more details on this, I recommend taking a look at Apple’s developer documentation for SIP.
Emphasis added
Basically, this means that you won't be able to hook calls to the open() system call for Apple-supplied software installed in the system directories. You will need to rethink what you are trying to do.
Running any normal command -- like cat -- that processes a file will cause the file to be opened. You can also open a file (and immediately close it) using the shell syntax:
: < /path/to/file
If your system call hook isn't getting called, something must be wrong with your hook -- there's no way these commands are working without opening the file. Alas, you haven't explained how you implemented your hook, so we have no way of debugging that.
The file command opens the file to look at its contents.
$ file /path/to/file
I have suggested this because it eventually leads to having the system call open which can be confirmed using strace.
$ strace file /path/to/file 2>&1 | grep open
I thought one of the good things about using file is that it opens the file in read only mode. In comparison to other ideas, unlike cat, it will not have to run through the entire file, just part of it, so the time complexity using file may be constant. Unlike vim, which someone has suggested, file will return when finished and not block like a text editor would.

Do work out of process in a cocoa app?

I've got a cocoa app that needs to do some work in a second process (because it might crash due to buggy libraries). I'd like to keep my project as simple as possible, so ideally I would use the same binary as the parent process and just control the child with command line parameters. It would also be nice if the parent could get handles to the new process's stdin & stdout so that they can communicate (although something I create with pipe() would work too). Has anyone solved this problem before? What did you learn? I come from a Win32/Linux background, so I'm not sure if there are any special capabilities I get with Cocoa/OS X that I should be using.
I'd like to keep my project as simple as possible, so ideally I would use the same binary as the parent process and just control the child with command line parameters.
fork and exec work the same on Mac OS X as on Linux and other POSIX environments, with one catch: In a Cocoa app, you can't just fork and not exec, because Core Foundation will not allow you to use any CF- or Cocoa-based APIs in the new process. If you fork in a Cocoa app, you must exec pretty much immediately afterward.
You can exec the same binary by using your own argv[0] in the [0] of the argv that you pass to exec.
There is a Cocoa version of fork+exec: Create an NSTask and set its launch path to your own [[[NSProcessInfo processInfo] arguments] objectAtIndex:0]. There is no way to fork and not exec with NSTask, for the above reason.
It would also be nice if the parent could get handles to the new process's stdin & stdout so that they can communicate (although something I create with pipe() would work too).
pipe also works as you would expect.
If you use NSTask, the Cocoa version of pipe is [NSPipe pipe].

How to pause / resume any external process under Windows?

I am looking for different ways to pause and resume programmatically a particular process via its process ID under Windows XP.
Process suspend/resume tool does it with SuspendThread / ResumeThread but warns about multi-threaded programs and deadlock problems.
PsSuspend looks okay, but I wonder if it does anything special about deadlocks or uses another method?
Prefered languages : C++ / Python
If you "debug the debugger" (for instance, using logger.exe to trace all API calls made by windbg.exe), it appears that the debugger uses SuspendThread()/ResumeThread() to suspend all of the threads in the process being debugged.
PsSuspend may use a different way of suspending processes (I'm not sure), but it is still possible to hang other processes: if the process you're suspending is holding a shared synchronization object that is needed by another process, you may block that other process from making any progress. If both programs are well-written, they should recover when you resume the one that you suspended, but not all programs are well-written. And if this causes your program that is doing the suspending to hang, then you have a deadlock.
I'm not sure if this does the job, but with ProcessExplorer from MS Systernals you can suspend a process.
It's been said here: https://superuser.com/a/155263 and I found it there too.
read here and you also have psutil for python that you can use it like that:
>>> import psutil
>>> pid = 7012
>>> p = psutil.Process(pid)
>>> p.suspend()
>>> p.resume()
I tested http://www.codeproject.com/KB/threads/pausep.aspx on few softwares:
it works fine.
PsSuspend and Pausep are two valid options.
So, after I found about UniversalPauseButton, Googling for this ("windows SIGSTOP"), getting this question as the first search result (thanks Ilia K. your comment did its job), and reading the answers, I went back to checkout the code.
Apparently, it uses undocumented NT kernel and Win32 APIs _NtSuspendProcess, _NtResumeProcess and _HungWindowFromGhostWindow.
PsSuspend, the utility you mentioned and linked to probably uses these APIs, I couldn't verify this, the source code isn't supplied, only executables and a EULA, you can probably figure that out by disassembling the binary but it's against the EULA.
so, to answer your specific question, checkout UniversalPauseButton's main.cpp, basically you call _NtSuspendProcess(ProcessHandle) and _NtResumeProcess(ProcessHandle), ProcessHandle being the handle of the process you want to pause or resume.
I think there is a good reason why there is no SuspendProcess() function in Windows. Having such a function opens the door for an unstable system. You shall not suspend a process unless you created that process yourself.
If you wrote that process yourself, you could use an event (see ::SetEvent() etc. in MSDN) or another kind of messaging to trigger a pause command in the process.

Resources