]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/unixchild.cpp
Security-57740.1.18.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / unixchild.cpp
1 /*
2 * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 //
26 // unixchild - low-level UNIX process child management.
27 //
28 // Note that the map-of-children (mChildren) only holds children presumed to
29 // be alive. Neither unborn nor dead children are included. This is important
30 // for how children are reaped and death notifications dispatched, and should
31 // not be changed without prior deep contemplation.
32 //
33 // A note on locking:
34 // All Child objects in this subsystem are mutated under control of a single
35 // lock (mChildren). This means that children will not step on each other.
36 // However, death callbacks (Child::dying) are made outside the lock's scope
37 // to avoid deadlock scenarios with outside locking hierarchies. When Child::dying
38 // is called, the child has already transitioned to "dead" state and is no longer
39 // in the (live) children map.
40 //
41 #include "unixchild.h"
42 #include <security_utilities/debugging.h>
43 #include <signal.h>
44
45
46 namespace Security {
47 namespace UnixPlusPlus {
48
49
50 //
51 // All our globals are in a ModuleNexus, for that special lazy-init goodness
52 //
53 ModuleNexus<Child::Children> Child::mChildren;
54
55
56 //
57 // Make and break Children
58 //
59 Child::Child()
60 : mState(unborn), mPid(0), mStatus(0)
61 {
62 }
63
64
65 Child::~Child()
66 {
67 assert(mState != alive); // not allowed by protocol
68 }
69
70
71 //
72 // Take a Child object that is not alive (i.e. is either unborn or dead),
73 // and reset it to unborn, so you can fork() it again.
74 // This call forgets everything about the previous process.
75 //
76 void Child::reset()
77 {
78 switch (mState) {
79 case alive:
80 assert(false); // bad boy; can't do that
81 case unborn:
82 break; // s'okay
83 default:
84 secinfo("unixchild", "%p reset (from state %d)", this, mState);
85 mState = unborn;
86 mPid = 0;
87 mStatus = 0;
88 break;
89 }
90 }
91
92
93 //
94 // Global inquiries and setup
95 //
96 void Child::sharedChildren(bool s)
97 {
98 StLock<Mutex> _(mChildren());
99 mChildren().shared = s;
100 }
101
102 bool Child::sharedChildren()
103 {
104 StLock<Mutex> _(mChildren());
105 return mChildren().shared;
106 }
107
108
109 //
110 // Check status for one Child
111 //
112 Child::State Child::check()
113 {
114 Child::State state;
115 bool reaped = false;
116 {
117 StLock<Mutex> _(mChildren());
118 state = mState;
119 switch (mState) {
120 case alive:
121 reaped = checkStatus(WNOHANG);
122 break;
123 default:
124 break;
125 }
126 }
127 if (reaped)
128 this->dying();
129 return state;
130 }
131
132
133 //
134 // Wait for a particular child to be dead.
135 // This call cannot wait for multiple children; you'll have
136 // to program that yourself using whatever event loop you're using.
137 //
138 void Child::wait()
139 {
140 bool reaped = false;
141 {
142 StLock<Mutex> _(mChildren());
143 switch (mState) {
144 case alive:
145 reaped = checkStatus(0); // wait for it
146 break;
147 case unborn:
148 assert(false); // don't do that
149 default:
150 break;
151 }
152 }
153 if (reaped)
154 this->dying();
155 }
156
157
158 //
159 // Common kill code.
160 // Requires caller to hold mChildren() lock.
161 //
162 void Child::tryKill(int signal)
163 {
164 assert(mState == alive); // ... or don't bother us
165 secinfo("unixchild", "%p (pid %d) sending signal(%d)", this, pid(), signal);
166 if (::kill(pid(), signal))
167 switch (errno) {
168 case ESRCH: // someone else reaped ths child; or things are just wacky
169 secinfo("unixchild", "%p (pid %d) has disappeared!", this, pid());
170 mState = invalid;
171 mChildren().erase(pid());
172 // fall through
173 default:
174 UnixError::throwMe();
175 }
176 }
177
178
179 //
180 // Send a signal to the Child.
181 // This will succeed (and do nothing) if the Child is not alive.
182 //
183 void Child::kill(int signal)
184 {
185 StLock<Mutex> _(mChildren());
186 if (mState == alive)
187 tryKill(signal);
188 else
189 secinfo("unixchild", "%p (pid %d) not alive; cannot send signal %d",
190 this, pid(), signal);
191 }
192
193
194 //
195 // Kill with prejudice.
196 // This will make a serious attempt to *synchronously* kill the process before
197 // returning. If that doesn't work for some reason, abandon the child.
198 // This is one thing you can do in the destructor of your subclass to legally
199 // dispose of your Child's process.
200 //
201 void Child::kill()
202 {
203 // note that we mustn't hold the lock across these calls
204 switch (this->state()) {
205 case alive:
206 if (this->state() == alive) {
207 this->kill(SIGTERM); // shoot it once
208 checkChildren(); // check for quick death
209 if (this->state() == alive) {
210 usleep(200000); // give it some time to die
211 if (this->state() == alive) { // could have been reaped by another thread
212 checkChildren(); // check again
213 if (this->state() == alive) { // it... just... won't... die...
214 this->kill(SIGKILL); // take THAT!
215 checkChildren();
216 if (this->state() == alive) // stuck zombie
217 this->abandon(); // leave the body behind
218 }
219 }
220 }
221 }
222 break;
223 case dead:
224 secinfo("unixchild", "%p (pid %d) already dead; ignoring kill request", this, pid());
225 break;
226 default:
227 secinfo("unixchild", "%p state %d; ignoring kill request", this, this->state());
228 break;
229 }
230 }
231
232
233 //
234 // Take a living child and cut it loose. This sets its state to abandoned
235 // and removes it from the child registry.
236 // This is one thing you can do in the destructor of your subclass to legally
237 // dispose of your child's process.
238 //
239 void Child::abandon()
240 {
241 StLock<Mutex> _(mChildren());
242 if (mState == alive) {
243 secinfo("unixchild", "%p (pid %d) abandoned", this, pid());
244 mState = abandoned;
245 mChildren().erase(pid());
246 } else {
247 secinfo("unixchild", "%p (pid %d) is not alive; abandon() ignored",
248 this, pid());
249 }
250 }
251
252
253 //
254 // Forensic examination of the Child's cadaver.
255 // Not interlocked because you have to check for state() == dead first,
256 // and these values are const ever after.
257 //
258 int Child::waitStatus() const
259 {
260 assert(mState == dead);
261 return mStatus;
262 }
263
264 bool Child::bySignal() const
265 {
266 assert(mState == dead);
267 return WIFSIGNALED(mStatus);
268 }
269
270 int Child::exitCode() const
271 {
272 assert(mState == dead);
273 assert(WIFEXITED(mStatus));
274 return WEXITSTATUS(mStatus);
275 }
276
277 int Child::exitSignal() const
278 {
279 assert(mState == dead);
280 assert(WIFSIGNALED(mStatus));
281 return WTERMSIG(mStatus);
282 }
283
284 bool Child::coreDumped() const
285 {
286 assert(mState == dead);
287 assert(WIFSIGNALED(mStatus));
288 return WCOREDUMP(mStatus);
289 }
290
291
292 //
293 // Find a child in the child map, by pid
294 // This will only find live children, and return NULL for all others.
295 //
296 Child *Child::findGeneric(pid_t pid)
297 {
298 StLock<Mutex> _(mChildren());
299 Children::iterator it = mChildren().find(pid);
300 if (it == mChildren().end())
301 return NULL;
302 else
303 return it->second;
304 }
305
306
307 //
308 // Do the actual fork job.
309 // At this layer, the client side does nothing but run childAction(). Any plumbing
310 // or cleanup is up to that function (which runs in the child) and the caller (after
311 // fork() returns). If childAction() returns at all, we will call exit(1) to get
312 // rid of the child.
313 //
314 void Child::fork()
315 {
316 static const unsigned maxDelay = 30; // seconds increment, i.e. 5 retries
317
318 assert(mState == unborn);
319 for (unsigned delay = 1; ;) {
320 switch (pid_t pid = ::fork()) {
321 case -1: // fork failed
322 switch (errno) {
323 case EINTR:
324 secinfo("unixchild", "%p fork EINTR; retrying", this);
325 continue; // no problem
326 case EAGAIN:
327 if (delay < maxDelay) {
328 secinfo("unixchild", "%p fork EAGAIN; delaying %d seconds",
329 this, delay);
330 sleep(delay);
331 delay *= 2;
332 continue;
333 }
334 // fall through
335 default:
336 UnixError::throwMe();
337 }
338 assert(false); // unreached
339
340 case 0: // child
341 //@@@ bother to clean child map?
342 try {
343 this->childAction();
344 } catch (...) {
345 }
346 _exit(1);
347
348 default: // parent
349 {
350 StLock<Mutex> _(mChildren());
351 mState = alive;
352 mPid = pid;
353 mChildren().insert(make_pair(pid, this));
354 }
355 secinfo("unixchild", "%p (parent) running parent action", this);
356 this->parentAction();
357 break;
358 }
359 break;
360 }
361 }
362
363
364 //
365 // Check the status of this child by explicitly probing it.
366 // Caller must hold master lock.
367 //
368 bool Child::checkStatus(int options)
369 {
370 assert(state() == alive);
371 secinfo("unixchild", "checking %p (pid %d)", this, this->pid());
372 int status;
373 again:
374 switch (IFDEBUG(pid_t pid =) ::wait4(this->pid(), &status, options, NULL)) {
375 case pid_t(-1):
376 switch (errno) {
377 case EINTR:
378 goto again; // retry
379 case ECHILD:
380 secinfo("unixchild", "%p (pid=%d) unknown to kernel", this, this->pid());
381 mState = invalid;
382 mChildren().erase(this->pid());
383 return false;
384 default:
385 UnixError::throwMe();
386 }
387 break; // placebo
388 case 0:
389 return false; // child not ready (do nothing)
390 default:
391 assert(pid == this->pid());
392 bury(status);
393 return true;
394 }
395 }
396
397
398 //
399 // Perform an idempotent check for dead children, as per the UNIX wait() system calls.
400 // This can be called at any time, and will reap all children that have died since
401 // last time. The obvious time to call this is after a SIGCHLD has been received;
402 // however signal dispatch is so - uh, interesting - in UNIX that we don't even try
403 // to deal with it at this level. Suffice to say that calling checkChildren directly
404 // from within a signal handler is NOT generally safe due to locking constraints.
405 //
406 // If the shared() flag is on, we explicitly poll each child known to be recently
407 // alive. That is less efficient than reaping any and all, but leaves any children
408 // alone that someone else may have created without our knowledge. The default is
409 // not shared(), which will reap (and discard) any unrelated children without letting
410 // the caller know about it.
411 //
412 void Child::checkChildren()
413 {
414 Bier casualties;
415 {
416 StLock<Mutex> _(mChildren());
417 if (mChildren().shared) {
418 for (Children::iterator it = mChildren().begin(); it != mChildren().end(); it++)
419 if (it->second->checkStatus(WNOHANG))
420 casualties.add(it->second);
421 } else if (!mChildren().empty()) {
422 int status;
423 while (pid_t pid = ::wait4(0, &status, WNOHANG, NULL)) {
424 secinfo("unixchild", "universal child check (%ld children known alive)", mChildren().size());
425 switch (pid) {
426 case pid_t(-1):
427 switch (errno) {
428 case EINTR:
429 secinfo("unixchild", "EINTR on wait4; retrying");
430 continue; // benign, but retry the wait()
431 case ECHILD:
432 // Should not normally happen (there *is* a child around),
433 // but gets returned anyway if the child is stopped in the debugger.
434 // Treat like a zero return (no children ready to be buried).
435 secinfo("unixchild", "ECHILD with filled nursery (ignored)");
436 goto no_more;
437 default:
438 UnixError::throwMe();
439 }
440 break;
441 default:
442 if (Child *child = mChildren()[pid]) {
443 child->bury(status);
444 casualties.add(child);
445 } else
446 secinfo("unixchild", "reaping feral child pid=%d", pid);
447 if (mChildren().empty())
448 goto no_more; // none left
449 break;
450 }
451 }
452 no_more: ;
453 } else {
454 secinfo("unixchild", "spurious checkChildren (the nursery is empty)");
455 }
456 } // release master lock
457 casualties.notify();
458 }
459
460
461 //
462 // Perform the canonical last rites for a formerly alive child.
463 // Requires master lock held throughout.
464 //
465 void Child::bury(int status)
466 {
467 assert(mState == alive);
468 mState = dead;
469 mStatus = status;
470 mChildren().erase(mPid);
471 #if !defined(NDEBUG)
472 if (bySignal())
473 secinfo("unixchild", "%p (pid %d) died by signal %d%s",
474 this, mPid, exitSignal(),
475 coreDumped() ? " and dumped core" : "");
476 else
477 secinfo("unixchild", "%p (pid %d) died by exit(%d)",
478 this, mPid, exitCode());
479 #endif //NDEBUG
480 }
481
482
483 //
484 // Default hooks
485 //
486 void Child::parentAction()
487 { /* nothing */ }
488
489 void Child::dying()
490 { /* nothing */ }
491
492
493 //
494 // Biers
495 //
496 void Child::Bier::notify()
497 {
498 for (const_iterator it = begin(); it != end(); ++it)
499 (*it)->dying();
500 }
501
502
503 } // end namespace IPPlusPlus
504 } // end namespace Security