Improve curl example

- Update sandbox policy (bring back inclusion of `/lib` to enable glibc
  resolver
- Better error handling using new `curl_util` library

Signed-off-by: Christian Blichmann <cblichmann@google.com>
This commit is contained in:
Christian Blichmann 2021-01-26 15:58:06 +01:00
parent 6f33cef716
commit d1e8ad94a8
No known key found for this signature in database
GPG Key ID: 19DC5E747974E966
11 changed files with 184 additions and 88 deletions

View File

@ -45,6 +45,7 @@ add_subdirectory(
# Generate SAPI header # Generate SAPI header
add_sapi_library(curl_sapi add_sapi_library(curl_sapi
SOURCES sandbox.h
# List of all the methods in https://curl.haxx.se/libcurl/c/allfuncs.html # List of all the methods in https://curl.haxx.se/libcurl/c/allfuncs.html
# Some are added or modified because the original ones are not supported # Some are added or modified because the original ones are not supported
@ -127,10 +128,16 @@ add_sapi_library(curl_sapi
NAMESPACE curl NAMESPACE curl
) )
# Include generated SAPI header
target_include_directories(curl_sapi INTERFACE target_include_directories(curl_sapi INTERFACE
"${PROJECT_BINARY_DIR}" "${PROJECT_BINARY_DIR}" # Include generated SAPI header
)
add_library(curl_util STATIC
curl_util.cc
curl_util.h
)
target_link_libraries(curl_util PUBLIC
curl_sapi
) )
# Add examples # Add examples

View File

@ -0,0 +1,37 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "curl_util.h" // NOLINT(build/include)
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
namespace curl {
std::string StrError(curl::CurlApi* api, int curl_error) {
absl::StatusOr<void*> remote_error_message =
api->curl_easy_strerror(static_cast<CURLcode>(curl_error));
if (!remote_error_message.ok()) {
return absl::StrCat("Code ", curl_error, " (curl_easy_strerror failed)");
}
absl::StatusOr<std::string> error_message =
api->sandbox()->GetCString(sapi::v::RemotePtr(*remote_error_message));
if (!error_message.ok()) {
return absl::StrCat("Code ", curl_error, " (error getting error message)");
}
return *error_message;
}
} // namespace curl

View File

@ -0,0 +1,30 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CURL_UTIL_H_
#define CURL_UTIL_H_
#include <string>
#include "curl_sapi.sapi.h" // NOLINT(build/include)
namespace curl {
// Calls into the sandbox to retrieve the error message for the curl error code
// in curl_error.
std::string StrError(curl::CurlApi* api, int curl_error);
} // namespace curl
#endif // CURL_UTIL_H_

View File

@ -22,6 +22,7 @@ add_executable(example1
) )
target_link_libraries(example1 PRIVATE target_link_libraries(example1 PRIVATE
curl_sapi curl_sapi
curl_util
sapi::sapi sapi::sapi
) )
@ -32,6 +33,7 @@ add_executable(example2
) )
target_link_libraries(example2 PRIVATE target_link_libraries(example2 PRIVATE
curl_sapi curl_sapi
curl_util
sapi::sapi sapi::sapi
) )
@ -42,6 +44,7 @@ add_executable(example3
) )
target_link_libraries(example3 PRIVATE target_link_libraries(example3 PRIVATE
curl_sapi curl_sapi
curl_util
sapi::sapi sapi::sapi
) )
@ -52,6 +55,7 @@ add_executable(example4
) )
target_link_libraries(example4 PRIVATE target_link_libraries(example4 PRIVATE
curl_sapi curl_sapi
curl_util
sapi::sapi sapi::sapi
) )
@ -62,6 +66,7 @@ add_executable(example5
) )
target_link_libraries(example5 PRIVATE target_link_libraries(example5 PRIVATE
curl_sapi curl_sapi
curl_util
sapi::sapi sapi::sapi
) )
@ -72,5 +77,6 @@ add_executable(example6
) )
target_link_libraries(example6 PRIVATE target_link_libraries(example6 PRIVATE
curl_sapi curl_sapi
curl_util
sapi::sapi sapi::sapi
) )

View File

@ -17,8 +17,11 @@
#include <cstdlib> #include <cstdlib>
#include "../sandbox.h" // NOLINT(build/include) #include "../curl_util.h" // NOLINT(build/include)
#include "../sandbox.h" // NOLINT(build/include)
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "curl_sapi.sapi.h" // NOLINT(build/include)
#include "sandboxed_api/util/status_macros.h"
namespace { namespace {
@ -33,7 +36,7 @@ absl::Status Example1() {
SAPI_ASSIGN_OR_RETURN(curl_handle, api.curl_easy_init()); SAPI_ASSIGN_OR_RETURN(curl_handle, api.curl_easy_init());
sapi::v::RemotePtr curl(curl_handle); sapi::v::RemotePtr curl(curl_handle);
if (!curl_handle) { if (!curl_handle) {
return absl::UnavailableError("curl_easy_init failed: curl is NULL"); return absl::UnknownError("curl_easy_init failed: Invalid curl handle");
} }
int curl_code; int curl_code;
@ -44,8 +47,8 @@ absl::Status Example1() {
curl_code, curl_code,
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, url.PtrBefore())); api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, url.PtrBefore()));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnknownError(absl::StrCat("curl_easy_setopt_ptr failed: ",
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code)); curl::StrError(&api, curl_code)));
} }
// Set the library to follow a redirection // Set the library to follow a redirection
@ -53,8 +56,8 @@ absl::Status Example1() {
curl_code, curl_code,
api.curl_easy_setopt_long(&curl, curl::CURLOPT_FOLLOWLOCATION, 1l)); api.curl_easy_setopt_long(&curl, curl::CURLOPT_FOLLOWLOCATION, 1l));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnknownError(absl::StrCat("curl_easy_setopt_long failed: ",
absl::StrCat("curl_easy_setopt_long failed: ", curl_code)); curl::StrError(&api, curl_code)));
} }
// Disable authentication of peer certificate // Disable authentication of peer certificate
@ -62,15 +65,15 @@ absl::Status Example1() {
curl_code, curl_code,
api.curl_easy_setopt_long(&curl, curl::CURLOPT_SSL_VERIFYPEER, 0l)); api.curl_easy_setopt_long(&curl, curl::CURLOPT_SSL_VERIFYPEER, 0l));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnknownError(absl::StrCat("curl_easy_setopt_long failed: ",
absl::StrCat("curl_easy_setopt_long failed: ", curl_code)); curl::StrError(&api, curl_code)));
} }
// Perform the request // Perform the request
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl)); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnknownError(absl::StrCat("curl_easy_perform failed: ",
absl::StrCat("curl_easy_perform failed: ", curl_code)); curl::StrError(&api, curl_code)));
} }
// Cleanup curl // Cleanup curl

View File

@ -16,10 +16,11 @@
// HTTP GET request using callbacks // HTTP GET request using callbacks
#include <cstdlib> #include <cstdlib>
#include <iostream>
#include "../sandbox.h" // NOLINT(build/include) #include "../curl_util.h" // NOLINT(build/include)
#include "../sandbox.h" // NOLINT(build/include)
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "sandboxed_api/util/status_macros.h"
namespace { namespace {
@ -40,7 +41,7 @@ absl::Status Example2() {
SAPI_ASSIGN_OR_RETURN(curl_handle, api.curl_easy_init()); SAPI_ASSIGN_OR_RETURN(curl_handle, api.curl_easy_init());
sapi::v::RemotePtr curl(curl_handle); sapi::v::RemotePtr curl(curl_handle);
if (!curl_handle) { if (!curl_handle) {
return absl::UnavailableError("curl_easy_init failed: curl is NULL"); return absl::UnavailableError("curl_easy_init failed: Invalid curl handle");
} }
int curl_code; int curl_code;
@ -51,8 +52,8 @@ absl::Status Example2() {
curl_code, curl_code,
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, url.PtrBefore())); api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, url.PtrBefore()));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code)); "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
} }
// Set WriteMemoryCallback as the write function // Set WriteMemoryCallback as the write function
@ -60,8 +61,8 @@ absl::Status Example2() {
curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_WRITEFUNCTION, curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_WRITEFUNCTION,
&write_to_memory)); &write_to_memory));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code)); "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
} }
// Pass 'chunk' struct to the callback function // Pass 'chunk' struct to the callback function
@ -70,8 +71,8 @@ absl::Status Example2() {
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_WRITEDATA, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_WRITEDATA,
chunk.PtrBoth())); chunk.PtrBoth()));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code)); "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
} }
// Set a user agent // Set a user agent
@ -80,15 +81,15 @@ absl::Status Example2() {
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_USERAGENT, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_USERAGENT,
user_agent.PtrBefore())); user_agent.PtrBefore()));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code)); "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
} }
// Perform the request // Perform the request
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl)); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_easy_perform failed: ", curl_code)); "curl_easy_perform failed: ", curl::StrError(&api, curl_code)));
} }
// Retrieve memory size // Retrieve memory size

View File

@ -17,7 +17,11 @@
#include <cstdlib> #include <cstdlib>
#include "../sandbox.h" // NOLINT(build/include) #include "../curl_util.h" // NOLINT(build/include)
#include "../sandbox.h" // NOLINT(build/include)
#include "absl/strings/str_cat.h"
#include "curl_sapi.sapi.h" // NOLINT(build/include)
#include "sandboxed_api/util/status_macros.h"
namespace { namespace {
@ -25,9 +29,9 @@ class CurlSapiSandboxEx3 : public curl::CurlSapiSandbox {
public: public:
CurlSapiSandboxEx3(std::string ssl_certificate, std::string ssl_key, CurlSapiSandboxEx3(std::string ssl_certificate, std::string ssl_key,
std::string ca_certificates) std::string ca_certificates)
: ssl_certificate(ssl_certificate), : ssl_certificate(std::move(ssl_certificate)),
ssl_key(ssl_key), ssl_key(std::move(ssl_key)),
ca_certificates(ca_certificates) {} ca_certificates(std::move(ca_certificates)) {}
private: private:
std::unique_ptr<sandbox2::Policy> ModifyPolicy( std::unique_ptr<sandbox2::Policy> ModifyPolicy(
@ -35,11 +39,9 @@ class CurlSapiSandboxEx3 : public curl::CurlSapiSandbox {
// Add the syscalls and files missing in CurlSandbox to a new PolicyBuilder // Add the syscalls and files missing in CurlSandbox to a new PolicyBuilder
auto policy_builder = std::make_unique<sandbox2::PolicyBuilder>(); auto policy_builder = std::make_unique<sandbox2::PolicyBuilder>();
(*policy_builder) (*policy_builder)
.AllowFutexOp(FUTEX_WAIT_PRIVATE)
.AllowGetPIDs() .AllowGetPIDs()
.AllowGetRandom() .AllowGetRandom()
.AllowHandleSignals() .AllowHandleSignals()
.AllowSyscall(__NR_sysinfo)
.AddFile(ssl_certificate) .AddFile(ssl_certificate)
.AddFile(ssl_key) .AddFile(ssl_key)
.AddFile(ca_certificates); .AddFile(ca_certificates);
@ -52,9 +54,10 @@ class CurlSapiSandboxEx3 : public curl::CurlSapiSandbox {
std::string ca_certificates; std::string ca_certificates;
}; };
absl::Status Example3(std::string ssl_certificate, std::string ssl_key, absl::Status Example3(const std::string& ssl_certificate,
std::string ssl_key_password, const std::string& ssl_key,
std::string ca_certificates) { const std::string& ssl_key_password,
const std::string& ca_certificates) {
// Initialize sandbox2 and sapi // Initialize sandbox2 and sapi
CurlSapiSandboxEx3 sandbox(ssl_certificate, ssl_key, ca_certificates); CurlSapiSandboxEx3 sandbox(ssl_certificate, ssl_key, ca_certificates);
SAPI_RETURN_IF_ERROR(sandbox.Init()); SAPI_RETURN_IF_ERROR(sandbox.Init());
@ -65,8 +68,8 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
// Initialize curl (CURL_GLOBAL_DEFAULT = 3) // Initialize curl (CURL_GLOBAL_DEFAULT = 3)
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l)); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_global_init failed: ", curl_code)); "curl_global_init failed: ", curl::StrError(&api, curl_code)));
} }
// Initialize curl easy handle // Initialize curl easy handle
@ -74,7 +77,7 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
SAPI_ASSIGN_OR_RETURN(curl_handle, api.curl_easy_init()); SAPI_ASSIGN_OR_RETURN(curl_handle, api.curl_easy_init());
sapi::v::RemotePtr curl(curl_handle); sapi::v::RemotePtr curl(curl_handle);
if (!curl_handle) { if (!curl_handle) {
return absl::UnavailableError("curl_easy_init failed: curl is NULL"); return absl::UnavailableError("curl_easy_init failed: Invalid curl handle");
} }
// Specify URL to get (using HTTPS) // Specify URL to get (using HTTPS)
@ -83,8 +86,8 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
curl_code, curl_code,
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, url.PtrBefore())); api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, url.PtrBefore()));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code)); "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
} }
// Set the SSL certificate type to "PEM" // Set the SSL certificate type to "PEM"
@ -93,8 +96,8 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_SSLCERTTYPE, curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_SSLCERTTYPE,
ssl_cert_type.PtrBefore())); ssl_cert_type.PtrBefore()));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code)); "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
} }
// Set the certificate for client authentication // Set the certificate for client authentication
@ -103,8 +106,8 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_SSLCERT, curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_SSLCERT,
sapi_ssl_certificate.PtrBefore())); sapi_ssl_certificate.PtrBefore()));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code)); "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
} }
// Set the private key for client authentication // Set the private key for client authentication
@ -113,8 +116,8 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_SSLKEY, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_SSLKEY,
sapi_ssl_key.PtrBefore())); sapi_ssl_key.PtrBefore()));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code)); "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
} }
// Set the password used to protect the private key // Set the password used to protect the private key
@ -123,8 +126,8 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_KEYPASSWD, curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_KEYPASSWD,
sapi_ssl_key_password.PtrBefore())); sapi_ssl_key_password.PtrBefore()));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code)); "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
} }
// Set the file with the certificates vaildating the server // Set the file with the certificates vaildating the server
@ -133,8 +136,8 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_CAINFO, curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_CAINFO,
sapi_ca_certificates.PtrBefore())); sapi_ca_certificates.PtrBefore()));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code)); "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
} }
// Verify the authenticity of the server // Verify the authenticity of the server
@ -142,15 +145,15 @@ absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
curl_code, curl_code,
api.curl_easy_setopt_long(&curl, curl::CURLOPT_SSL_VERIFYPEER, 1L)); api.curl_easy_setopt_long(&curl, curl::CURLOPT_SSL_VERIFYPEER, 1L));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_easy_setopt_long failed: ", curl_code)); "curl_easy_setopt_long failed: ", curl::StrError(&api, curl_code)));
} }
// Perform the request // Perform the request
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl)); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_easy_perform failed: ", curl_code)); "curl_easy_perform failed: ", curl::StrError(&api, curl_code)));
} }
// Cleanup curl easy handle // Cleanup curl easy handle

View File

@ -17,10 +17,11 @@
#include <cstdlib> #include <cstdlib>
#include "../sandbox.h" // NOLINT(build/include) #include "../curl_util.h" // NOLINT(build/include)
#include "curl_sapi.sapi.h" // NOLINT(build/include) #include "../sandbox.h" // NOLINT(build/include)
#include "sandboxed_api/util/flag.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "curl_sapi.sapi.h" // NOLINT(build/include)
#include "sandboxed_api/util/status_macros.h"
namespace { namespace {
@ -38,8 +39,8 @@ absl::Status Example4() {
// Initialize curl (CURL_GLOBAL_DEFAULT = 3) // Initialize curl (CURL_GLOBAL_DEFAULT = 3)
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l)); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_global_init failed: ", curl_code)); "curl_global_init failed: ", curl::StrError(&api, curl_code)));
} }
// Initialize http_handle // Initialize http_handle
@ -47,7 +48,7 @@ absl::Status Example4() {
SAPI_ASSIGN_OR_RETURN(curl_handle, api.curl_easy_init()); SAPI_ASSIGN_OR_RETURN(curl_handle, api.curl_easy_init());
sapi::v::RemotePtr http_handle(curl_handle); sapi::v::RemotePtr http_handle(curl_handle);
if (!curl_handle) { if (!curl_handle) {
return absl::UnavailableError("curl_easy_init failed: curl is NULL"); return absl::UnavailableError("curl_easy_init failed: Invalid curl handle");
} }
// Specify URL to get // Specify URL to get
@ -56,8 +57,8 @@ absl::Status Example4() {
curl_code, api.curl_easy_setopt_ptr(&http_handle, curl::CURLOPT_URL, curl_code, api.curl_easy_setopt_ptr(&http_handle, curl::CURLOPT_URL,
url.PtrBefore())); url.PtrBefore()));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code)); "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
} }
// Initialize multi_handle // Initialize multi_handle
@ -66,15 +67,15 @@ absl::Status Example4() {
sapi::v::RemotePtr multi_handle(curlm_handle); sapi::v::RemotePtr multi_handle(curlm_handle);
if (!curlm_handle) { if (!curlm_handle) {
return absl::UnavailableError( return absl::UnavailableError(
"curl_multi_init failed: multi_handle is NULL"); "curl_multi_init failed: multi_handle is invalid");
} }
// Add http_handle to the multi stack // Add http_handle to the multi stack
SAPI_ASSIGN_OR_RETURN(curl_code, SAPI_ASSIGN_OR_RETURN(curl_code,
api.curl_multi_add_handle(&multi_handle, &http_handle)); api.curl_multi_add_handle(&multi_handle, &http_handle));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_multi_add_handle failed: ", curl_code)); "curl_multi_add_handle failed: ", curl::StrError(&api, curl_code)));
} }
while (still_running.GetValue()) { while (still_running.GetValue()) {
@ -85,8 +86,8 @@ absl::Status Example4() {
curl_code, curl_code,
api.curl_multi_perform(&multi_handle, still_running.PtrBoth())); api.curl_multi_perform(&multi_handle, still_running.PtrBoth()));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_mutli_perform failed: ", curl_code)); "curl_mutli_perform failed: ", curl::StrError(&api, curl_code)));
} }
if (still_running.GetValue()) { if (still_running.GetValue()) {
@ -96,8 +97,8 @@ absl::Status Example4() {
curl_code, api.curl_multi_poll_sapi(&multi_handle, &null_ptr, 0, 1000, curl_code, api.curl_multi_poll_sapi(&multi_handle, &null_ptr, 0, 1000,
numfds.PtrBoth())); numfds.PtrBoth()));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_multi_poll_sapi failed: ", curl_code)); "curl_multi_poll_sapi failed: ", curl::StrError(&api, curl_code)));
} }
} }
} }
@ -106,8 +107,8 @@ absl::Status Example4() {
SAPI_ASSIGN_OR_RETURN( SAPI_ASSIGN_OR_RETURN(
curl_code, api.curl_multi_remove_handle(&multi_handle, &http_handle)); curl_code, api.curl_multi_remove_handle(&multi_handle, &http_handle));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_multi_remove_handle failed: ", curl_code)); "curl_multi_remove_handle failed: ", curl::StrError(&api, curl_code)));
} }
// Cleanup http_handle // Cleanup http_handle
@ -116,8 +117,8 @@ absl::Status Example4() {
// Cleanup multi_handle // Cleanup multi_handle
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_multi_cleanup(&multi_handle)); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_multi_cleanup(&multi_handle));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_multi_cleanup failed: ", curl_code)); "curl_multi_cleanup failed: ", curl::StrError(&api, curl_code)));
} }
// Cleanup curl // Cleanup curl

View File

@ -19,8 +19,11 @@
#include <future> // NOLINT(build/c++11) #include <future> // NOLINT(build/c++11)
#include <thread> // NOLINT(build/c++11) #include <thread> // NOLINT(build/c++11)
#include "../sandbox.h" // NOLINT(build/include) #include "../curl_util.h" // NOLINT(build/include)
#include "../sandbox.h" // NOLINT(build/include)
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "curl_sapi.sapi.h" // NOLINT(build/include)
#include "sandboxed_api/util/status_macros.h"
namespace { namespace {
@ -30,7 +33,7 @@ absl::Status pull_one_url(const std::string& url, curl::CurlApi& api) {
SAPI_ASSIGN_OR_RETURN(curl_handle, api.curl_easy_init()); SAPI_ASSIGN_OR_RETURN(curl_handle, api.curl_easy_init());
sapi::v::RemotePtr curl(curl_handle); sapi::v::RemotePtr curl(curl_handle);
if (!curl_handle) { if (!curl_handle) {
return absl::UnavailableError("curl_easy_init failed: curl is NULL"); return absl::UnavailableError("curl_easy_init failed: Invalid curl handle");
} }
int curl_code; int curl_code;
@ -41,15 +44,15 @@ absl::Status pull_one_url(const std::string& url, curl::CurlApi& api) {
curl_code, curl_code,
api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, sapi_url.PtrBefore())); api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, sapi_url.PtrBefore()));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_easy_setopt_ptr failed: ", curl_code)); "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
} }
// Perform the request // Perform the request
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl)); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_easy_perform failed: ", curl_code)); "curl_easy_perform failed: ", curl::StrError(&api, curl_code)));
} }
// Cleanup curl easy handle // Cleanup curl easy handle
@ -58,10 +61,6 @@ absl::Status pull_one_url(const std::string& url, curl::CurlApi& api) {
return absl::OkStatus(); return absl::OkStatus();
} }
const std::vector<std::string> urls = {
"http://example.com", "http://example.edu", "http://example.net",
"http://example.org"};
absl::Status Example5() { absl::Status Example5() {
// Initialize sandbox2 and sapi // Initialize sandbox2 and sapi
curl::CurlSapiSandbox sandbox; curl::CurlSapiSandbox sandbox;
@ -73,11 +72,14 @@ absl::Status Example5() {
// Initialize curl (CURL_GLOBAL_DEFAULT = 3) // Initialize curl (CURL_GLOBAL_DEFAULT = 3)
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l)); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l));
if (curl_code != 0) { if (curl_code != 0) {
return absl::UnavailableError( return absl::UnavailableError(absl::StrCat(
absl::StrCat("curl_global_init failed: ", curl_code)); "curl_global_init failed: ", curl::StrError(&api, curl_code)));
} }
// Create the threads (by using futures) // Create the threads (by using futures)
const std::vector<std::string> urls = {
"http://example.com", "http://example.edu", "http://example.net",
"http://example.org"};
std::vector<std::future<absl::Status>> futures; std::vector<std::future<absl::Status>> futures;
for (auto& url : urls) { for (auto& url : urls) {
futures.emplace_back( futures.emplace_back(

View File

@ -17,8 +17,12 @@
#include <cstdlib> #include <cstdlib>
#include "../sandbox.h" // NOLINT(build/include) #include "../curl_util.h" // NOLINT(build/include)
#include "../sandbox.h" // NOLINT(build/include)
#include "absl/strings/str_cat.h"
#include "curl_sapi.sapi.h" // NOLINT(build/include)
#include "sandboxed_api/transaction.h" #include "sandboxed_api/transaction.h"
#include "sandboxed_api/util/status_macros.h"
namespace { namespace {

View File

@ -29,16 +29,17 @@ namespace curl {
class CurlSapiSandbox : public curl::CurlSandbox { class CurlSapiSandbox : public curl::CurlSandbox {
protected: protected:
std::unique_ptr<sandbox2::Policy> ModifyPolicy( std::unique_ptr<sandbox2::Policy> ModifyPolicy(
sandbox2::PolicyBuilder* policy_builder) override { sandbox2::PolicyBuilder*) override {
// Return a new policy // Return a new policy
return sandbox2::PolicyBuilder() return sandbox2::PolicyBuilder()
.AllowDynamicStartup() .AllowDynamicStartup()
.AllowExit() .AllowExit()
.AllowFork() .AllowFork()
.AllowFutexOp(FUTEX_WAIT_PRIVATE)
.AllowFutexOp(FUTEX_WAKE_PRIVATE) .AllowFutexOp(FUTEX_WAKE_PRIVATE)
.AllowFutexOp(FUTEX_REQUEUE_PRIVATE)
.AllowMmap() .AllowMmap()
.AllowOpen() .AllowOpen()
.AllowRead()
.AllowSafeFcntl() .AllowSafeFcntl()
.AllowWrite() .AllowWrite()
.AllowAccess() .AllowAccess()
@ -62,6 +63,7 @@ class CurlSapiSandbox : public curl::CurlSandbox {
__NR_socket, __NR_socket,
__NR_sysinfo, __NR_sysinfo,
}) })
.AddDirectory("/lib")
.AllowUnrestrictedNetworking() .AllowUnrestrictedNetworking()
.BuildOrDie(); .BuildOrDie();
} }