프로젝트에 어셈블리 파일이 포함 된 경우 잘못된 mmap 동작
나는 이것으로 내 머리를 벽에 두 드린다.
내 프로젝트 mmap
에서 매핑 ( /proc/self/maps
)을 사용 하여 메모리를 할당 할 때 읽을 수있는 메모리 만 요청 했음에도 불구하고 읽을 수 있고 실행 가능한 영역임을 보여줍니다 .
strace (좋아 보였습니다) 및 기타 디버깅을 조사한 후,이 이상한 문제를 피하는 것처럼 보이는 유일한 방법을 식별 할 수있었습니다. 프로젝트에서 어셈블리 파일을 제거하고 순수한 C 만 남겨 둡니다. (뭐?!)
그래서 여기 이상한 예가 있습니다. 저는 Ubunbtu 19.04 및 기본 gcc에서 작업하고 있습니다.
ASM 파일 (비어 있음)로 대상 실행 파일을 컴파일하면 mmap
읽을 수 있고 실행 가능한 영역이 반환되고, 그렇지 않은 경우 빌드하면 올바르게 작동합니다. /proc/self/maps
내 예제에 포함 된 출력을 참조하십시오 .
example.c
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
int main()
{
void* p;
p = mmap(NULL, 8192,PROT_READ,MAP_ANONYMOUS|MAP_PRIVATE,-1,0);
{
FILE *f;
char line[512], s_search[17];
snprintf(s_search,16,"%lx",(long)p);
f = fopen("/proc/self/maps","r");
while (fgets(line,512,f))
{
if (strstr(line,s_search)) fputs(line,stderr);
}
fclose(f);
}
return 0;
}
example.s : 빈 파일입니다!
출력
ASM 포함 버전
VirtualBox:~/mechanics/build$ gcc example.c example.s -o example && ./example
7f78d6e08000-7f78d6e0a000 r-xp 00000000 00:00 0
ASM 포함 버전없이
VirtualBox:~/mechanics/build$ gcc example.c -o example && ./example
7f1569296000-7f1569298000 r--p 00000000 00:00 0
리눅스는이 실행 도메인 이라고 READ_IMPLIES_EXEC
할당 모든 페이지 원인 PROT_READ
도 주어질를 PROT_EXEC
. 이 프로그램은 자체적으로 활성화되었는지 여부를 보여줍니다.
#include <stdio.h>
#include <sys/personality.h>
int main(void) {
printf("Read-implies-exec is %s\n", personality(0xffffffff) & READ_IMPLIES_EXEC ? "true" : "false");
return 0;
}
If you compile that along with an empty .s
file, you'll see that it's enabled, but without one, it'll be disabled. The initial value of this comes from the ELF meta-information in your binary. Do readelf -Wl example
. You'll see this line when you compiled without the empty .s
file:
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
But this one when you compiled with it:
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RWE 0x10
Note RWE
instead of just RW
. The reason for this is that the linker assumes that your assembly files require read-implies-exec unless it's explicitly told that they don't, and if any part of your program requires read-implies-exec, then it's enabled for your whole program. The assembly files that GCC compiles tell it that it doesn't need this, with this line (you'll see this if you compile with -S
):
.section .note.GNU-stack,"",@progbits
Put that line in example.s
, and it will serve to tell the linker that it doesn't need it either, and your program will then work as expected.
As an alternative to modifying your assembly files with GNU-specific section directive variants, you can add -Wa,--noexecstack
to your command line for building assembly files. For example, see how I do it in musl's configure
:
https://git.musl-libc.org/cgit/musl/commit/configure?id=adefe830dd376be386df5650a09c313c483adf1a
I believe at least some versions of clang with integrated-assembler may require it to be passed as --noexecstack
(without the -Wa
), so your configure script should probably check both and see which is accepted.
You can also use -Wl,-z,noexecstack
at link time (in LDFLAGS
) to get the same result. The disadvantage of this is that it doesn't help if your project produces static (.a
) library files for use by other software, since you then don't control the link-time options when it's used by other programs.
'IT Share you' 카테고리의 다른 글
데이터웨어 하우스 대 OLAP 큐브? (0) | 2020.12.08 |
---|---|
오류 : 잡히지 않음 (약속에서) : 오류 : 어떤 경로도 일치 할 수 없습니다 Angular 2 (0) | 2020.12.08 |
HRESULT : 0x80131040 : 찾은 어셈블리의 매니페스트 정의가 어셈블리 참조와 일치하지 않습니다. (0) | 2020.12.08 |
Postgres : varchar를 텍스트로 변환 (0) | 2020.12.08 |
가격 변경을 통해 프로그래밍 방식으로 장바구니에 제품 추가 (0) | 2020.12.08 |