본문 바로가기

CNUproject/코드 동일성 검사 도구

19_Docker와 KLEE 개념 및 설치

1. Docker란?

애플리케이션을 신속하게 구축, 테스트 및 배포할 수 있는 소프트웨어 플랫폼이다.

Docker는 소프트웨어를 컨테이너라는 표준화된 유닛으로 패키징하며, 이 컨테이너에는 라이브러리, 시스템 도구, 코드, 런타임 등 소프트웨어를 실행하는 데 필요한 모든 것이 포함되어 있다.

 

컨테이너는 Docker 이미지를 실행한 상태이다. 컨테이너를 생성하면, 이미지의 목적에 맞는 파일이 들어있는 파일 시스템과 격리된 시스템 자원 및 네트워크를 사용할 수 있는 독립적인 공간이 생성된다.

 

이미지는 컨테이너를 만드는데 사용되는 read only 템플릿이다. 컨테이너 실행에 필요한 파일과 설정값 등을 포함하고 있는 docker 파일을 만든 후 빌드하여 이미지를 만든다.

 

하나의 이미지로 여러 개의 컨테이너를 만들 수 있다.

 

Docker 컨테이너와 VM의 차이를 살펴보자면,

Hypervisor 기반의 가상화 방식(VM)은 Host OS 위에 Hypervisor 엔진, 그 위에 OS를 올려 사용한다. 즉, 애플리케이션이 돌아갈 수 있는 OS 환경이 포함되고, Host OS와 완전히 분리되어 있다.

하지만 컨테이너 기반의 가상화 방식은 프로세스 간 벽을 만들어 애플리케이션이 구동되는 환경이 격리(컨테이너화)되어 있다. 즉 하나의 OS 커널을 공유한다.


2. Docker 설치

https://docs.docker.com/desktop/install/mac-install/

이 사이트에 들어가면 Mac 전용 Docker를 쉽게 설치할 수 있다.

CPU가 Intel칩을 사용하는 경우 Docker Desktop for Mac with Intel chip을 눌러 다운 받고,

m1, m2 칩을 사용하는 경우 Docker Desktop for Mac with Apple silicon 버튼을 눌러 다운받으면 된다.

 

다운로드한 docker.dmg를 열면 drag and drop 할 수 있는 창이 뜬다. 그려진 모습대로 드래그 앤 드롭해주면 설치가 완료된다.

 

 

Docker 열었을 때 화면

Docker를 정상적으로 설치한 후 Docker를 실행하면 상단 메뉴바에 Docker 아이콘이 생성된다.

해당 아이콘을 누르면 Docker Desktop is running 이라는 문구처럼 정상적으로 실행되고 있음을 알 수 있다.


3. KLEE란? 

KLEE는 LLVM 기반의 symbolic execution 도구로 소프트웨어 검증 및 테스트 분야에서 활용되는 도구이다.

자동으로 테스트 케이스를 생성해주며, symbolic execution을 진행하면서 버그를 찾아낼 수 있다.


3. KLEE 설치

http://klee.github.io/docker/

해당 사이트에 들어가면 Docker 를 이용하여 KLEE를 간단히 설치할 수 있다.

 

1) 이미지 다운로드

docker pull klee/klee

KLEE 이미지 다운로드

 

2) 컨테이너 생성

docker run -ti --name=my_first_klee_container --ulimit='stack=-1:-1' klee/klee

KLEE 컨테이너 생성

이때 --rm 옵션을 주면 컨테이너에서 실행 중인 애플리케이션이 종료되면 해당 컨테이너가 삭제된다.

나는 종료해도 삭제하지 않기 위해 --rm 옵션을 주지 않고 컨테이너를 생성했다.

--ulimit : 컨테이너 내부의 스택 크기를 무제한으로 설정한다. 이는 KLEE를 실행할 때 스택 오버플로우 문제를 방지하기 위한 것이다.

 

컨테이너가 올바르게 작동한다면, whoami 라고 입력했을 때 klee가 뜬다.

 

 

3) 살아있는 컨테이너 목록 보기

docker ps -a

exit 를 입력해 종료 후 해당 명령어를 입력하면 컨테이너가 아직 존재하는지 확인할 수 있다.

4) 컨테이너 재시작하기

docker start -ai my_first_klee_container

이 명령어를 입력하여 컨테이너를 다시 실행할 수 있다.

 

 

5) 컨테이너 제거하기

docker rm my_first_klee_container

컨테이너 작업이 끝나면 해당 명령어를 입력해 컨테이너를 제거할 수 있다.

컨테이너가 제거된 모습


4. KLEE 사용해보기

1) 컨테이너를 실행한다.

docker run -ti --name=my_first_klee_container --ulimit='stack=-1:-1' klee/klee

나는 아까 컨테이너를 삭제했기 때문에 다시 만들어주었다.

 

2) klee를 사용할 테스트 코드를 작성한다.

#include <stdio.h>
#include "klee/klee.h"

int get_sign(int x) {
        if (x == 0)
                return 0;
        
        else if (x < 0)
                return -1;
        else
                return 1;
}       

int main() {
        int a;
        klee_make_symbolic(&a, sizeof(a), "a");
        return get_sign(a);
}

 

3) clang을 이용하여 bc파일(LLVM 비트코드)로 컴파일한다.

clang -I ../../include -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone test.c

clang -emit-llvm -c test.c

위에 명령어가 더 정확한 파일을 생성하지만, 디버그 정보 및 최적화에 관심이 없다면 아래 명령어로도 컴파일 가능하다.

난 이번엔 아래 명령어로 실행했다.

4) klee를 실행한다.

klee test.bc

실행해보면 여러 문구들이 뜨는 것을 볼 수 있다.

output directory : test case들이 담긴 폴더

completed paths : 탐색된 경로

partially completed paths : 부분적으로 탐색된 경로 (큰 프로그램의 경우 KLEE는 시간이나 메모리 제약으로 인해 중단될 수 있다.)

generated tests : 탐색된 경로에 대한 테스트 사례

 

우리가 작성한 코드는 경로가 총 3개였다. a가 0일 경우, 0보다 작을 경우, 0보다 클 경우. 그래서 completed paths가 3개로 나온 것이고, 이렇게 탐색된 경로에 따른 테스트 사례를 각 한 개씩 생성한 것이다.

 

5) KLEE가 생성한 테스트 케이스 확인

klee@7ef6c33fad87:~/test/klee-out-0$ ls               
assembly.ll  messages.txt  run.stats         test000002.ktest  warnings.txt
info         run.istats    test000001.ktest  test000003.ktest

4번에서 생성된 output directory로 이동한 후 ls로 test파일들을 확인한다.

 

ktest-tool test000001.ktest
ktest-tool test000002.ktest
ktest-tool test000003.ktest

ktest-tool을 이용하면 ktest 바이너리 파일을 읽을 수 있다.

 

ktest 파일을 읽어본 결과 해당 경로의 symbolic object의 개수와 이름(a), 크기와 그 object에 담기는 테스트 값이 담겨있다.

첫 번째 테스트 파일은 0, 두 번째 테스트 파일은 16843009로 양수, 세 번째 테스트 파일은 -2147483648로 음수였다.

예상대로 KLEE는 0일 때, 0보다 클 때, 0보다 작을 때의 테스트 케이스를 생성했다는 것을 알 수 있다.


참고

Docker

https://docs.docker.com/get-started/overview/

https://cloudmt.co.kr/?p=3927 

https://khj93.tistory.com/entry/Docker-Docker-%EA%B0%9C%EB%85%90

https://kibua20.tistory.com/135

https://tech.cloudmt.co.kr/2022/06/29/%EB%8F%84%EC%BB%A4%EC%99%80-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EC%9D%98-%EC%9D%B4%ED%95%B4-1-3-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-%EC%82%AC%EC%9A%A9%EB%B2%95/

 

KLEE

https://klee.github.io/

https://klee.github.io/tutorials/testing-function/