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의 excmem은 일반적으로 다음과 같습니다.특이한그리고나쁜 아이디어™, 말이 됩니다.
Apache 로그의 타임스탬프를 세어 소스 추적을 시도했지만 다양한 사이트(MySQL 유무에 관계없이 PHP 기반, Python/mod_wsgi 기반 및 내부 Apache "OPTION")에 대한 다양한 요청에 영향을 미치는지 확인할 수 없습니다. 요청) 일관된 것.
사람들이 디버깅할 수 있도록 내 설정을 설명하기보다는내가 알고 싶은 것은 execmem 호출이 어디서 오는지 확인하여 그것이 중요한지 판단할 수 있는 방법입니다.
(참고: 이를 허용하도록 설정할 수 있는 SELinux 부울이 있다는 것을 알고 있지만 먼저 이를 시도하는 이유를 이해하지 않고는 그렇게 하고 싶지 않습니다. 이를 체로 바꾸려면 다음이 있습니다. 그런 다음 중요한지 확인하지 않고 모든 불만 포트를 여는 것과 같은 방화벽을 가질 필요가 없습니다.
답변1
최근 PHP7을 사용하여 Amazon Linux에서 SELinux를 사용하는 동안 이 문제가 발생했습니다. 나는 다음 조합을 사용했다러셀 코커의 대단한 LD_PRELOAD
트릭( mmap()
호출을 가로채고 어설션 실패를 트리거함) 및 gdb(어설션 실패를 트리거한 후 즉시 호출 스택 보기)가 원하는 함수를 확인합니다.실행 메모리.
나는 또한 PHP7 PCRE JIT가 범인이라고 결론지었습니다. 나를 위해 pcre.jit=0
해결했습니다 php.ini
.
세부 단계
- 루트로 컴퓨터에 로그인
mmap.c
다음에서 소스 코드를 다운로드하세요.여기/root/mmap.c를 입력하세요.- 빌드 코드
gcc -shared -g -fPIC mmap.c -o mmap.so
- 이제 mmap() 호출을 가로채서 gdb를 통해 Apache를 실행합니다.
LD_PRELOAD=/root/mmap.so gdb /usr/sbin/httpd
- 당신은 gdb에 던져졌습니다. Apache는 하위 프로세스를 분기하므로 프롬프트
set follow-fork-mode child
다음에 입력하여 이러한 하위 프로세스로 이동하도록 gdb에 지시하는 것이 중요합니다.(gdb)
- 이제 프롬프트 다음에 입력하여
run
Apache를 시작하십시오.(gdb)
- 일부 HTTP 요청이 코드를 트리거할 때까지 참을성 있게 기다리십시오. 코드는 차례로 gdb 에서 어설션을 트리거
mmap()
하고 gdb로 돌아갑니다.
Program received signal SIGABRT, Aborted.
[Switching to Thread 0x7ffff7fe9840 (LWP 28370)]
0x00007ffff638d5f7 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56 return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig);
</pre>
8. Type `bt` (backtrace) to see the call stack:
<pre>(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=file@entry=0x7ffff7bda985 "mmap.c", line=line@entry=27, function=function@entry=0x7ffff7bda9af <__PRETTY_FUNCTION__.2774> "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 <__PRETTY_FUNCTION__.2774> "mmap")
at 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) at sljit/sljitNativeX86_common.c:296
#8 0x00007ffff79bf74e in _pcre_jit_compile (re=re@entry=0x555555b14650, extra=extra@entry=0x555555b14750) at pcre_jit_compile.c:6434
#9 0x00007ffff79c1fc3 in pcre_study (external_re=external_re@entry=0x555555b14650, options=1, errorptr=errorptr@entry=0x7fffffffa3c8) at 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 0x00007fffed2ef21f 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는 실패한 실제 호출입니다.