[해키피디아] Linux Memory Layout

프로그램이 실행될 시 효율적인 메모리 사용을 위해 할당하는 메모리를 용도별로 나누게 됩니다. 세그먼트(Segment)라는 단위로 구분되어 있는데, 세그먼트란 메모리에 적재되는 데이터를 용도별로 나누어 저장한 영역을 의미합니다.

Untitled.jpg

Linux 메모리 구조에서는 코드 세그먼트, 데이터 세그먼트, BSS 세그먼트,힙 세그먼트, 스택 세그먼트, 이렇게 총 5가지의 세그먼트로 구분되어져 있습니다. 세그먼트를 사용하면 각 영역에 맞게 읽기, 쓰기, 실행에 대한 권한을 부여할 수 있어 메모리 커럽션 취약점을 어느 정도 방지 가능하다는 장점이 있습니다. 여기서의 권한은 CPU가 해당 메모리에 대해 가능한 동작들에 대한 권한을 말합니다. 예를 들자면, 읽기 권한만 있는 메모리에서는 CPU가 실행하는 동작이 불가능해 누군가 실행 가능한 코드를 삽입하더라도 실행은 하지는 못해 메모리 커렵션이 발생하더라도 취약점으로 이어지지는 않습니다. 이제 각 세그먼트에 대해 살펴보도록 하겠습니다.

코드 세그먼트

코드 세그먼트는 텍스트 세그먼트라고도 불립니다. 프로그램에서 실행 가능한 코드 데이터가 위치하게 됩니다. 그러므로 코드 세그먼트는 CPU가 코드를 읽고 실행할 수 있도록 읽기, 실행 권한이 부여됩니다. 하지만 코드를 누군가 삽입해 악의적으로 실행 흐름을 바꿀 수도 있기 때문에 쓰기 권한은 부여되지 않습니다.

데이터 세그먼트

데이터 세그먼트는 컴파일할 때 값이 정해지는 전역 변수나 전역 상수 데이터가 위치합니다. 기본적으로 해당 세그먼트에는 읽기 권한이 부여가 되고 다시 또 안에서 쓰기 권한이 있는 세그먼트와 쓰기 권한이 없이 읽기 권한만 존재하는 세그먼트인 rodata 세그먼트로 나뉘게 됩니다.

BSS 세그먼트

다음으로는 BSS 세그먼트입니다. BSS 세그먼트는 컴파일 시에 값이 정해지지 않는 전역 변수가 위치하는 메모리 영역입니다. 해당 세그먼트에는 읽기, 쓰기 권한이 부여되며 프로그램 시작 시에는 모두 메모리에서 값이 0으로 초기화되어 들어갑니다.

스택 세그먼트

스택과 힙 세그먼트는 그림에서 점선으로 표시했는데요. 스택과 힙은 상황에 맞게 확장되는 세그먼트이기 때문입니다.

스택 세그먼트는 말 그대로 프로세스에서 사용하는 스택이 위치하는 메모리 영역 입니다. 데이터에 접근해 사용하고 수정해야하기 때문에 읽기, 쓰기 권한이 부여되고 메모리의 끝에 위치해 높은 주소에서 낮은 주소 방향으로 가변적으로 확장되는 가변적인 세그먼트 입니다.

가변적인 세그먼트 형식으로 사용하는 이유에 대해 알아보겠습니다. 스택 세그먼트는 스택 프레임이라는 단위로 사용이 되는데, 이 스택 프레임은 함수 호출시에 생성이 되고 반환시에 해제가 되게 됩니다. 그렇기 때문에 프로그램의 실행흐름에 따라 함수가 호출될 수도 있고 안될 수도 있다면 실질적으로 스택 세그먼트가 얼마나 필요로 할지는 정확히 계산하기 어려울겁니다. 그래서 스택 세그먼트는 이렇게 필요에 따라 확장하는 가변적인 세그먼트 형식을 채택하여 사용하게 되었습니다.

힙 세그먼트

힙 세그먼트는, C언어에서 malloc(), calloc()과 같은 함수를 통해 프로그램 실행중 동적으로 할당받는 메모리가 위치하는 영역입니다.

스택과 마찬가지로 접근해 사용하고 수정이 가능해야하기 때문에 읽기와 쓰기 권한이 부여되며, 필요시마다 스택과 같은 이유로 가변적인 세그먼트 형식으로 사용해 힙 세그먼트를 확장하게 됩니다.

하지만 힙과 스택 세그먼트 모두 확장이 가능한 가변적인 세그먼트이고 그로 인해 서로의 메모리를 침범할 가능성이 있기 때문에 힙 세그먼트는 낮은 주소 방향에서 높은 주소 방향으로 확장을 합니다. 스택이 메모리 끝에 위치하는 것도 힙 영역과 반대로 자라게 하여 비교적으로 서로의 메모리가 침범되는 문제로 부터 자유롭게 하기 위함입니다.