Apache-Httpd
如何找出 Apache 嘗試“execmem”的原因?
我從 SELinux 收到審計消息,說它拒絕 Apache 執行 execmem:
type=AVC msg=audit(05/06/16 19:51:43.058:181060) : avc: denied { execmem } for pid=123456 comm=httpd scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:system_r:httpd_t:s0 tclass=process
PID 是 Apache PID 之一,它在程序之間不斷循環。
根據我的閱讀,Apache 的 execmem 通常是不正常的,並且是Bad Idea™,這是有道理的。
我嘗試通過使用 Apache 日誌記錄時間戳來跟踪來源,但是如果影響跨各種站點的各種請求(基於 PHP 的有和沒有 MySQL、基於 Python/mod_wsgi 以及內部 Apache“OPTION”請求),我不能找到任何一致的東西。
與其試圖解釋我的設置以讓人們調試它,我想知道的是如何確定 execmem 呼叫的來源,以便確定它是否重要?
(注意:我知道有一個 SELinux 布爾值可以設置為允許它,但我不想在沒有先了解它為什麼嘗試它的情況下這樣做。如果你打算把它變成一個篩子,就像沒有防火牆,然後打開每個抱怨的埠而不檢查它是否重要一樣)。
我最近在使用 PHP7 的 Amazon Linux 上遇到了 SELinux 的這個問題。我結合使用 Russell Coker 出色的 LD_PRELOAD 技巧(攔截 mmap() 呼叫並觸發斷言失敗)和 gdb(在觸發斷言失敗後立即查看呼叫堆棧)來檢查要執行的函式。
我還得出結論,PHP7 PCRE JIT 是罪魁禍首。將 pcre.jit=0 放入 php.ini 為我修復了它。
詳細步驟
- 以 root 身份登錄您的電腦
- 從https://etbe.coker.com.au/2010/07/12/write-execute-mmap-ld-preload/下載 mmap.c 原始碼到 /root/mmap.c
- 建構程式碼
gcc -shared -g -fPIC mmap.c -o mmap.so
- 現在通過 gdb 執行 Apache,攔截 mmap() 呼叫:
LD_PRELOAD=/root/mmap.so gdb /usr/sbin/httpd
- 你被扔進了gdb。
set follow-fork-mode child
因為 Apache fork 子程序,重要的是通過在 (gdb) 提示符後鍵入來告訴 gdb 跳轉到它們run
現在通過在 (gdb) 提示符後鍵入來啟動 Apache- 耐心等待,直到某個 HTTP 請求觸發程式碼,該程式碼又觸發 mmap 中的斷言,然後您又回到 gdb 中。
程序收到信號 SIGABRT,已中止。 [切換到執行緒 0x7ffff7fe9840 (LWP 28370)] 0x00007ffff638d5f7 in __GI_raise (sig = sig @ entry = 6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 56 返回 INLINE_SYSCALL (tgkill, 3, pid, selftid, sig);
- 鍵入
bt
(backtrace) 以查看呼叫堆棧:(gdb) BT # 0 0x00007ffff638d5f7 in __GI_raise (sig = sig @ entry = 6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 #1 0x00007ffff638ece8 in __GI_abort () at abort.c:90 #2 0x00007ffff6386566 in __assert_fail_base (fmt=0x7ffff64d6ca8 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=assertion@entry=0x7ffff7bda990 "!(prot & 0x4) || !(prot & 0x2)", 文件=file@entry=0x7ffff7bda985 "mmap.c", line=line@entry=27, function=function@entry=0x7ffff7bda9af "mmap") at assert.c:92 #3 0x00007ffff6386612 in __GI___assert_fail (assertion=0x7ffff7bda990 "!(prot & 0x4) || !(prot & 0x2)", file=0x7ffff7bda985 "mmap.c", line=27, function=0x7ffff7bda9af "mmap") 在 assert.c:101 #4 0x00007ffff7bda93e in mmap (addr=0x0, length=65536, prot=7, flags=34, fd=-1, offset=0) at mmap.c:27 #5 0x00007ffff79a6b86 in alloc_chunk (size=65536) at sljit/sljitExecAllocator.c:101 #6 sljit_malloc_exec (size=4440) at sljit/sljitExecAllocator.c:204 #7 sljit_generate_code (compiler=compiler@entry=0x555555b14ad0) 在 sljit/sljitNativeX86_common.c:296 #8 0x00007ffff79bf74e in _pcre_jit_compile (re=re@entry=0x555555b14650, extra=extra@entry=0x555555b14750) 在 pcre_jit_compile.c:6434 #9 0x00007ffff79c1fc3 in pcre_study (external_re=external_re@entry=0x555555b14650, options=1, errorptr=errorptr@entry=0x7fffffffa3c8) 在 pcre_study.c:1354 #10 0x00007fffed2edcbc in pcre_get_compiled_regex_cache (regex=0x7fffd8a04000) at /usr/src/debug/php-7.0.9/ext/pcre/php_pcre.c:487 #11 0x00007ffffed2ef21f in php_do_pcre_match (execute_data=0x7fffec419ab0, return_value=0x7fffec419870, global=1) at /usr/src/debug/php-7.0.9/ext/pcre/php_pcre.c:655
- 罪魁禍首很容易確定。堆棧條目 11 為您提供檢查 PCRE 的提示,條目 5 是出錯的實際呼叫。