변수 가이드

소개

개요 페이지에 설명된 대로 호스트 코드는 샌드박스 처리된 라이브러리에 RPC 호출을 실행합니다. 샌드박스로 인해 프로세스 간에 메모리가 분리되므로 호스트 코드가 샌드박스 처리된 라이브러리의 메모리에 직접 액세스할 수 없습니다.

호스트 코드가 원격 프로세스의 변수 및 메모리 블록에 액세스할 수 있도록 하고 기본 로직 코드를 더 간단하게 구현할 수 있도록 SAPI는 포괄적인 C++ 클래스 세트를 제공합니다. 그러나 많은 경우 네이티브 C 유형을 사용할 수도 있습니다.

포인터를 단순 유형과 메모리 블록 (구조, 배열)으로 전달할 때 특수 유형 (SAPI 유형)이 필요합니다.

예를 들어 포인터를 사용하는 함수를 호출할 때 포인터는 샌드박스 환경의 메모리 내 상응하는 포인터로 변환해야 합니다. 아래 코드 스니펫은 이 시나리오를 시각화한 것입니다. 세 개의 정수 배열 대신 ::sapi::v::Array<int> 객체가 생성되어 샌드박스 라이브러리의 API 호출에 전달할 수 있습니다.

int arr[3] = {1, 2, 3};
sapi::v::Array<int> sarr(arr, ABSL_ARRAYSIZE(arr));

사용 가능한 모든 SAPI 유형의 포괄적인 개요는 SAPI 프로젝트 소스 코드var_*.h 헤더 파일을 검토하세요. 이러한 헤더 파일은 다양한 유형의 데이터를 나타내는 클래스와 템플릿을 제공합니다.예를 들면 다음과 같습니다.

  • ::sapi::v::UChar는 잘 알려진 부호 없는 문자를 나타냅니다.
  • ::sapi::v::Array<int>는 정수 배열을 나타냅니다.

SAPI 유형

이 섹션에서는 호스트 코드에서 흔히 볼 수 있는 세 가지 SAPI 유형을 소개합니다.

SAPI 포인터

샌드박스 처리할 함수에서 포인터를 전달해야 하는 경우 이 포인터는 아래 PtrXXX() 메서드 중 하나에서 가져와야 합니다. 이러한 메서드는 SAPI 변수 클래스로 구현됩니다.

포인터 유형
::PtrNone() 샌드박스 API 함수에 전달될 때 호스트 코드 프로세스와 샌드박스 라이브러리 프로세스 간에 기본 메모리를 동기화하지 않습니다.
::PtrBefore() 샌드박스 처리된 API 함수 호출이 실행되기 전에 포인터가 가리키는 객체의 메모리를 동기화합니다. 즉, 지정된 변수의 로컬 메모리는 호출이 시작되기 전에 샌드박스 라이브러리 프로세스로 전송됩니다.
::PtrAfter() 샌드박스 처리된 API 함수 호출이 발생한 후에 포인터가 가리키는 객체의 메모리를 동기화합니다. 즉, 지정된 변수의 원격 메모리가 호출이 완료된 호스트 코드 프로세스 메모리로 전송됩니다.
::PtrBoth() ::PtrBefore()::PtrAfter()의 기능을 결합합니다.

SAPI 포인터에 관한 문서는 여기에서 확인할 수 있습니다.

SAPI 구조

::sapi::v::Struct 템플릿은 var_struct.h에 설명되어 있습니다. 이 템플릿은 기존 구조를 래핑하는 데 사용할 수 있는 생성자를 제공합니다. SAPI 구조체는 SAPI 포인터에 설명된 모든 메서드를 제공하여 샌드박스 처리된 라이브러리 호출에 사용할 수 있는 ::sapi::v::Ptr 객체를 가져옵니다.

아래의 코드 스니펫은 zlib 예에서 시작된 후 샌드박스 함수 호출에 전달되는 구조를 보여줍니다.

sapi::v::Struct<sapi::zlib::z_stream> strm;
…
if (ret = api.deflateInit_(strm.PtrBoth(), Z_DEFAULT_COMPRESSION,
                             version.PtrBefore(), sizeof(sapi::zlib::z_stream));
…

기존 구조체에 포인터가 포함되어 있으면 이러한 포인터는 Sandboxee의 주소를 가리킵니다. 따라서 Sandboxee 데이터를 이전해야 호스트 코드에 액세스할 수 있습니다.

SAPI 배열

템플릿 ::sapi::v::Arrayvar_array.h에 설명되어 있습니다. 이 생성자는 두 가지 생성자를 제공합니다. 하나는 기존 요소 배열을 래핑하는 데 사용할 수 있고 다른 하나는 동적으로 배열을 만드는 데 사용할 수 있습니다.

다음 코드 스니펫 (sum 예에서 가져옴)은 이 객체가 소유하지 않은 배열을 래핑하는 생성자의 사용을 보여줍니다.

int arr[10];
sapi::v::Array<int> iarr(arr, ABSL_ARRAYSIZE(arr));

다음 코드 스니펫은 동적으로 배열을 만드는 데 사용되는 생성자의 예를 보여줍니다.

sapi::v::Array<uint8_t> buffer(PNG_IMAGE_SIZE(*image.mutable_data()));

SAPI 배열은 SAPI 포인터에 설명된 모든 메서드를 제공하여 샌드박스 처리된 라이브러리 호출에 사용할 수 있는 ::sapi::v::Ptr 객체를 가져옵니다.