intercept more forking functions in same way as fork()
commitf3fe1fa17a442af38b0d7026eb2fda3b28f44abf
authorDaniel Neiter <dneiter@fb.com>
Thu, 10 May 2018 17:54:53 +0000 (10 10:54 -0700)
committerHhvm Bot <hhvm-bot@users.noreply.github.com>
Thu, 10 May 2018 18:01:36 +0000 (10 11:01 -0700)
tree89560956f170baa5c40e4d948f3a6a338823f1b3
parentc56795a45c8ecb6af3858a4bbd602febbe661766
intercept more forking functions in same way as fork()

Summary:
D7816198 added HHVM support for intercepting and blocking `fork()` calls within the main process.

However, we need to intercept more functions to get comprehensive protection:
- system()
- popen()
- posix_spawn()
- posix_spawnp()

With exception of `posix_spawn()`, all these functions have relocations in hhvm binary (i.e. some code, linked into hhvm, contains calls to these functions). E.g. `nm /usr/local/hphpi/bin/hphpi |grep 'U popen'`.

There are 2 reasons, why these functions need to be intercepted explicitly:
1. system() does not actually call fork() but makes an equivalent system call directly. The reason has something to do with thread cancelation support
2. other code in glibc call glibc fork via `__fork()`, so it is not caught by our fork intercept. We need to either intercept other functions explicitly or also intercept `__fork()` [and deal with potential inlining inside glibc]. The former approach is simpler and more robust.

There are few more glibc functions which can fork, but these are exotic and not linked into hhvm (I discovered this by grepping for fork through glibc source code):
- daemon() - it calls exit(0) in parent process, so it's extremely unlikely to show up in a library
- wordexp() - I can't even...
- grantpt() - "grant access to slave pseudo-terminal"

For now, I haven't added wrappers for these, since all of them seem unlikely to ever show up in HHVM, but I'm happy to add wrappers if someone feels the other way.
+ chipturner, who prompted me to look for more potential wuntions to intercept by asking me about popen.

I refactored the code a bit to minimize copy-pasting between 5 similar wrappers and potential for copy-paste errors. The current setup (with delegating disable check and dlsym resolution into helper function) is the best option, I could come up with. I'm open to alternative ideas on how to reduce code duplication here.

Initially I tried to keep weak symbol + fallback to dlsym approach from D7816198. However, I ended up switching to dlsym-only approach, because I couldn't make weak symbols approach work for popen, posix_spawn and posix_spawnp. The problem: glibc doesn't export corresponding "real" symbols (e.g. `__posix_spawn`, `__new_popen`).

Reviewed By: markw65

Differential Revision: D7922693

fbshipit-source-id: 519f29e24590164fcccc84816bca4c9cd4eaa4d2
hphp/hhvm/main.cpp
hphp/runtime/server/http-server.cpp