5. Sandboxee ile iletişim kurma
Varsayılan olarak, yürütücü dosya tanımlayıcıları aracılığıyla Sandboxee ile iletişim kurabilir. Örneğin, yalnızca bir dosyayı Sandboxee ile paylaşmak veya Sandboxee'nin standart çıkışını okumak istiyorsanız bu yeterli olabilir.
Ancak, yürütücü ile Sandboxee arasında daha karmaşık bir iletişim mantığına ihtiyacınız olabilir. İletişim API'si (bkz. comms.h üstbilgi dosyası) tam sayılar, dizeler, bayt arabellekleri, protobuf'lar veya dosya tanımlayıcıları göndermek için kullanılabilir.
Dosya tanımlayıcılarını paylaşma
Süreçler Arası İletişim API'sini (bkz. ipc.h) kullanarak MapFd()
veya ReceiveFd()
'yi kullanabilirsiniz:
Yürütücüden Sandboxee'ye dosya tanımlayıcılarını eşlemek için
MapFd()
kullanın. Bu, Sandboxee'de kullanılmak üzere yürütücüden açılan bir dosyayı paylaşmak için kullanılabilir. Örnek bir kullanım static içinde görülebilir.// The executor opened /proc/version and passes it to the sandboxee as stdin executor->ipc()->MapFd(proc_version_fd, STDIN_FILENO);
Socketpair uç noktası oluşturmak için
ReceiveFd()
öğesini kullanın. Bu, Sandboxee'nin standart çıkışını veya standart hatalarını okumak için kullanılabilir. Örnek kullanımı araçta görebilirsiniz.// The executor receives a file descriptor of the sandboxee stdout int recv_fd1 = executor->ipc())->ReceiveFd(STDOUT_FILENO);
İletişim API'sini kullanma
Sandbox2, kullanışlı bir comms API sağlar. Bu, yürütücü ile Sandboxee arasında tam sayıları, dizeleri veya bayt arabelleklerini paylaşmanın basit ve kolay bir yoludur. Aşağıda, crc4 örneğinde bulabileceğiniz bazı kod snippet'leri verilmiştir.
İletişim API'sini kullanmaya başlamak için önce Sandbox2 nesnesinden iletişim nesnesini almanız gerekir:
sandbox2::Comms* comms = s2.comms();
İletişim nesnesi kullanılabilir hale geldiğinde, Send* işlev ailesinden biri kullanılarak Sandboxee'ye veri gönderilebilir. İletişim API'sinin örnek kullanımını crc4 örneğinde bulabilirsiniz. Aşağıdaki kod snippet'inde bu örnekten bir alıntı gösterilmektedir. Vasiyet tenfiz memuru, SendBytes(buf, size)
ile birlikte unsigned char
buf[size]
gönderir:
if (!(comms->SendBytes(static_cast<const uint8_t*>(buf), sz))) {
/* handle error */
}
Sandboxee'den veri almak için Recv*
işlevlerinden birini kullanın. Aşağıdaki kod snippet'i, crc4 örneğinden alınmıştır. Yürütücü, sağlama toplamını 32 bitlik işaretsiz bir tam sayı olarak alır: uint32_t crc4;
if (!(comms->RecvUint32(&crc4))) {
/* handle error */
}
Verileri arabelleklerle paylaşma
Diğer bir veri paylaşımı işlevi, büyük miktarda veri paylaşmak ve yürütücü ile Sandboxee arasında gönderilip alınan pahalı kopyaları önlemek için buffer API'yi kullanmaktır.
Yürütücü, boyuta ve aktarılacak verilere göre veya doğrudan bir dosya tanımlayıcıdan bir arabellek oluşturur ve yürütücüde comms->SendFD()
, Sandboxee'de ise comms->RecvFD()
kullanarak Sandboxee'ye iletir.
Aşağıdaki kod snippet'inde uygulayıcının tarafını görebilirsiniz. Korumalı alan, eşzamansız olarak çalışır ve verileri Sandboxee ile arabellek üzerinden paylaşır:
// 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());
Sandboxee tarafında da bir arabellek nesnesi oluşturmanız ve yürütücü tarafından gönderilen dosya tanımlayıcısından verileri okumanız gerekir:
// 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 */