5. Komunikacja z osobą testującą
Domyślnie wykonawca może komunikować się z piaskownicą za pomocą deskryptorów plików. Może to być wszystko, czego potrzebujesz, np. jeśli chcesz tylko udostępnić plik Sandboxee lub odczytać standardowe dane wyjściowe Sandboxee.
Najprawdopodobniej jednak potrzebujesz bardziej złożonej logiki komunikacji między wykonawcą a piaskownicą. Interfejs Comms API (patrz plik nagłówkowy comms.h) umożliwia wysyłanie liczb całkowitych, ciągów znaków, buforów bajtów, protobufów lub deskryptorów plików.
Udostępnianie deskryptorów plików
Korzystając z interfejsu Inter-Process Communication API (patrz ipc.h), możesz użyć MapFd()
lub ReceiveFd()
:
Użyj
MapFd()
, aby zmapować deskryptory plików z wykonawcy na Sandboxee. Można go użyć do udostępnienia pliku otwartego z wykonawcy do użycia w Sandboxee. Przykład użycia znajdziesz w sekcji static.// The executor opened /proc/version and passes it to the sandboxee as stdin executor->ipc()->MapFd(proc_version_fd, STDIN_FILENO);
Użyj
ReceiveFd()
, aby utworzyć punkt końcowy pary gniazd. Można go używać do odczytywania standardowych danych wyjściowych lub standardowych błędów piaskownicy. Przykład użycia znajdziesz w narzędziu.// The executor receives a file descriptor of the sandboxee stdout int recv_fd1 = executor->ipc())->ReceiveFd(STDOUT_FILENO);
Korzystanie z interfejsu Comms API
Sandbox2 udostępnia wygodny interfejs API komunikacji. Jest to prosty i łatwy sposób udostępniania liczb całkowitych, ciągów znaków lub buforów bajtów między wykonawcą a Sandboxee. Poniżej znajdziesz fragmenty kodu, które możesz znaleźć w przykładzie crc4.
Aby rozpocząć korzystanie z interfejsu Comms API, musisz najpierw pobrać obiekt Comms z obiektu Sandbox2:
sandbox2::Comms* comms = s2.comms();
Gdy obiekt komunikacji jest dostępny, dane można wysyłać do piaskownicy za pomocą jednej z funkcji z rodziny Send*. Przykład użycia interfejsu Comms API znajdziesz w przykładzie crc4. Fragment kodu
poniżej zawiera wyciąg z tego przykładu. Wykonawca testamentu wysyła unsigned char
buf[size]
z SendBytes(buf, size)
:
if (!(comms->SendBytes(static_cast<const uint8_t*>(buf), sz))) {
/* handle error */
}
Aby otrzymywać dane z piaskownicy, użyj jednej z funkcji Recv*
. Fragment kodu poniżej pochodzi z przykładu crc4. Wykonawca otrzymuje sumę kontrolną w postaci 32-bitowej liczby całkowitej bez znaku: uint32_t crc4;
if (!(comms->RecvUint32(&crc4))) {
/* handle error */
}
Udostępnianie danych buforom
Inną funkcją udostępniania danych jest użycie interfejsu Buffer API do udostępniania dużych ilości danych i unikania kosztownych kopii, które są przesyłane między wykonawcą a piaskownicą.
Wykonawca tworzy bufor, określając jego rozmiar i dane do przekazania lub bezpośrednio z deskryptora pliku, i przekazuje go do piaskownicy za pomocą funkcji comms->SendFD()
w wykonawcy i comms->RecvFD()
w piaskownicy.
W poniższym fragmencie kodu możesz zobaczyć stronę wykonawcy. Piaskownica działa asynchronicznie i udostępnia dane za pomocą bufora:
// start the sandbox asynchronously
s2.RunAsync();
// instantiate the comms object
sandbox2::Comms* comms = s2.comms();
// random buffer data we want to send
constexpr unsigned char buffer_data[] = /* random data */;
constexpr unsigned int buffer_dataLen = 34;
// create sandbox2 buffer
absl::StatusOr<std::unique_ptr<sandbox2::Buffer>> buffer =
sandbox2::Buffer::CreateWithSize(1ULL << 20 /* 1Mib */);
std::unique_ptr<sandbox2::Buffer> buffer_ptr = std::move(buffer).value();
// point to the sandbox2 buffer and fill with data
uint8_t* buf = buffer_ptr‑>data();
memcpy(buf, buffer_data, buffer_data_len);
// send the data to the sandboxee
comms‑>SendFd(buffer_ptr‑>fd());
Po stronie Sandboxee musisz też utworzyć obiekt bufora i odczytać dane z deskryptora pliku wysłanego przez wykonawcę:
// establish the communication with the executor
int fd;
comms.RecvFD(&fd);
// create the buffer
absl::StatusOr<std::unique_ptr<sandbox2::Buffer>> buffer =
sandbox2::Buffer::createFromFd(fd);
// get the data
auto buffer_ptr = std::move(buffer).value();
uint8_t* buf = buffer_ptr‑>data();
/* work with the buf object */