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

Gentoo

필수 커널 옵션:

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

Gentoo

필수 커널 옵션:

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++ 라이브러리를 샌드박스 처리하려면 프로젝트에 다음 두 항목을 준비해야 합니다.

여기에서 전체 프로그램(zpipe.c)이 샌드박스 처리된 Sandbox2 예의 zlib을 잘 알고 계실 수도 있습니다. 다음 단계에서는 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 유형은 일반 C 유형이 작동하지 않는 경우가 있으므로 SAPI에서 제공하는 C++ 클래스 형태의 특수 유형입니다.

SAPI 유형의 첫 번째 사용은 SAPI 구조체가 사용되는 strm 선언에서 확인할 수 있습니다. 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팀이 이미 준비한 몇 가지 라이브러리를 확인할 수 있습니다.