Sandboxed API 시작하기

이 페이지에서는 샌드박스 API (SAPI)를 사용하여 자체 샌드박스 처리된 C/C++ 라이브러리를 만드는 방법을 알아봅니다. 헤더 파일의 예시 및 코드 문서와 함께 가이드로 사용하세요.

빌드 종속 항목

다음 종속 항목이 시스템에 설치되어 있어야 합니다.

  • UTS, IPC, 사용자, PID, 네트워크 네임스페이스를 지원하는 Linux 커널
  • Linux 사용자 공간 API 헤더
  • 코드 컴파일 방법: GCC 6(버전 7 이상 권장) 또는 Clang 7 이상
  • 헤더 파일 자동 생성: Clang Python 바인딩
  • Python 3.5 이상
  • Bazel 버전 2.2.0 또는 CMake 버전 3.12 이상
    • CMake만 해당: GNU Make 또는 libcap 라이브러리 헤더 버전과 Ninja와 같은 빌드 도구 (권장)

Bazel 사용

Bazel은 권장되는 빌드 시스템이며 통합하기 가장 쉬운 시스템입니다.

이 문서에서는 Clang 컴파일러를 사용합니다. 특정 도구 모음 (예: 컴파일러, 링커 등)이 필요한 경우 Bazel 문서에서 기본 컴파일러 도구 모음을 변경하는 방법을 알아보세요.

Debian 10(Buster)

빌드 종속 항목을 설치하려면 다음 안내를 따르세요.

echo "deb http://storage.googleapis.com/bazel-apt stable jdk1.8" | \
  sudo tee /etc/apt/sources.list.d/bazel.list
wget -qO - https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -
sudo apt-get update
sudo apt-get install -qy build-essential linux-libc-dev bazel python3 \
  python3-pip libclang-dev
pip3 install clang

젠투

필요한 커널 옵션은 다음과 같습니다.

General setup  --->
-*- Namespaces support
[*]   UTS namespace
[*]   IPC namespace
[*]   User namespace (EXPERIMENTAL)
[*]   PID Namespaces
[*]   Network namespace

빌드 종속 항목을 설치하려면 다음 안내를 따르세요.

emerge dev-util/bazel dev-python/typing dev-python/clang-python

CMake 사용

CMakeNinja 또는 Make와 같은 빌드 도구용 프로젝트 파일을 생성하는 인기 있는 오픈소스 메타 빌드 시스템입니다.

Debian 10(Buster)

빌드 종속 항목을 설치하려면 다음 안내를 따르세요.

sudo apt-get install -qy build-essential linux-libc-dev cmake ninja-build \
  python3 python3-pip libclang-dev libcap-dev
pip3 install absl-py clang

젠투

필요한 커널 옵션은 다음과 같습니다.

General setup  --->
-*- Namespaces support
[*]   UTS namespace
[*]   IPC namespace
[*]   User namespace (EXPERIMENTAL)
[*]   PID Namespaces
[*]   Network namespace

빌드 종속 항목을 설치하려면 다음 안내를 따르세요.

emerge sys-kernel/linux-headers dev-util/cmake dev-util/ninja \
dev-python/clang-python

개발 프로세스

C/C++ 라이브러리를 샌드박스하려면 프로젝트를 위해 다음 두 가지 항목을 준비해야 합니다.

여기서 Sandbox2 예시의 zlib에 익숙하실 수도 있습니다. 전체 프로그램 (zpipe.c)이 샌드박스 처리되었습니다. 다음 단계에서는 SAPI를 사용하여 zlib 라이브러리를 샌드박스하고 샌드박스 처리된 라이브러리를 활용하는 방법을 알아봅니다.

1. 필요한 기능 결정

zlib 호스트 코드 (main_zlib.cc)를 살펴보면 도구의 기능이 stdin에서 데이터를 읽고 zlib의 deflate() 함수를 사용하여 EOF 마커를 읽을 때까지 데이터를 압축하는 것임을 확인할 수 있습니다. 이 프로그램은 zlib의 총 세 가지 함수를 사용합니다.

  • deflateInit_(): 압축을 위해 초기화합니다.
  • deflate(): 데이터 청크에 압축 작업을 실행합니다.
  • deflateEnd(): 압축을 종료하고 동적으로 할당된 데이터 구조를 해제합니다.

실제 예에서는 C/C++ 라이브러리를 검토하고 필요한 함수를 결정합니다. 가능한 전략은 호스트 코드로 시작하고 샌드박스 처리되지 않은 라이브러리를 사용하는 것입니다. 그런 다음 두 번째 단계에서는 샌드박스 처리된 라이브러리를 생성하고 샌드박스 처리된 함수 호출을 사용하도록 호스트 코드를 조정할 수 있습니다.

2. sapi_library 빌드 규칙 작성

샌드박스 처리된 zlib 라이브러리에서 필요한 세 가지 zlib 함수를 식별한 후 BUILD 파일에서 빌드 규칙을 정의할 수 있습니다. sapi_library 빌드 규칙에 관한 문서는 빌드 규칙 페이지에서 찾을 수 있습니다.

아래의 코드 스니펫은 zlib SAPI 예의 sapi_library 정의를 보여줍니다. lib 속성을 사용하여 Bazel은 WORKSPACE 파일에서 zlib 라이브러리를 찾도록 지시합니다.

sapi_library(
    name = "zlib-sapi",
    srcs = [],
    hdrs = [],
    functions = [
        "deflateInit_",
        "deflate",
        "deflateEnd",
    ],
    lib = "@net_zlib//:zlib",
    lib_name = "Zlib",
    namespace = "sapi::zlib",
)

결과적으로 샌드박스 처리된 zlib 라이브러리가 생성됩니다. 출력은 호스트 코드에 포함될 수 있고 RPC 호출을 통해 샌드박스 처리된 라이브러리와 통신하는 데 사용할 수 있는 SAPI 객체입니다. 이 예시에서 사용된 샌드박스 정책은 기본 정책입니다.

3. 호스트 코드 작성 또는 변경

이제 생성된 SAPI 라이브러리를 호스트 코드에 통합해 보겠습니다.

샌드박스 만들기

sapi::Sandbox sandbox(sapi::zlib::zlib_sapi_embed_create());를 사용하여 샌드박스 객체를 만듭니다.

sapi::zlib::ZlibApi api(&sandbox);를 사용하여 SAPI 객체를 인스턴스화합니다. 그러면 샌드박스 처리된 함수를 사용할 수 있습니다.

SAPI 유형 사용

SAPI 유형은 SAPI가 제공하는 C++ 클래스 형식의 특수 유형입니다. 일반 C 유형이 작동하지 않을 때도 있기 때문입니다.

SAPI 유형의 첫 사용은 strm 선언에서 확인할 수 있으며, 여기서 SAPI 구조체는 sapi::v::Struct<sapi::zlib::z_stream> strm;입니다.

템플릿 유형 (sapi::zlib::z_stream)은 빌드 규칙에 의해 자동으로 생성되는 코드의 좋은 예입니다.

자세한 내용은 변수 페이지를 참고하세요.

API 호출

defalteInit_, deflate 또는 deflateEnd를 호출하려면 SAPI 객체를 사용합니다. '변경' 접근 방식을 사용하기로 결정한 경우 함수 매개변수가 예상 값과 일치하는지 확인해야 합니다.

zlib 예에서 각 호출의 예:

  • api.deflateInit_(strm.PtrBoth(), Z_DEFAULT_COMPRESSION,
        version.PtrBefore(), sizeof(sapi::zlib::z_stream));
  • api.deflate(strm.PtrBoth(), flush);
  • api.deflateEnd(strm.PtrBoth()).IgnoreError();

SAPI 트랜잭션 사용

SAPI는 샌드박스 라이브러리에서 호스트 코드를 격리하고 호출자가 문제가 있는 데이터 처리 요청을 다시 시작하거나 취소할 수 있도록 합니다. SAPI 트랜잭션은 한 단계 더 나아가 실패한 프로세스를 자동으로 반복합니다.

자세한 내용은 SAPI 거래 페이지를 참고하세요.

예시에서는 SAPI팀에서 이미 준비한 몇 가지 라이브러리를 확인할 수 있습니다.