Apache-Httpd

如何找出 Apache 嘗試“execmem”的原因?

  • April 6, 2019

我從 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 為我修復了它。

詳細步驟

  1. 以 root 身份登錄您的電腦
  2. 從https://etbe.coker.com.au/2010/07/12/write-execute-mmap-ld-preload/下載 mmap.c 原始碼到 /root/mmap.c
  3. 建構程式碼gcc -shared -g -fPIC mmap.c -o mmap.so
  4. 現在通過 gdb 執行 Apache,攔截 mmap() 呼叫:LD_PRELOAD=/root/mmap.so gdb /usr/sbin/httpd
  5. 你被扔進了gdb。set follow-fork-mode child因為 Apache fork 子程序,重要的是通過在 (gdb) 提示符後鍵入來告訴 gdb 跳轉到它們
  6. run現在通過在 (gdb) 提示符後鍵入來啟動 Apache
  7. 耐心等待,直到某個 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);
  1. 鍵入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
  1. 罪魁禍首很容易確定。堆棧條目 11 為您提供檢查 PCRE 的提示,條目 5 是出錯的實際呼叫。

引用自:https://unix.stackexchange.com/questions/287831