summaryrefslogtreecommitdiffstats
path: root/sandbox
diff options
context:
space:
mode:
authorjln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-23 23:36:39 +0000
committerjln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-23 23:36:39 +0000
commita73ed203c32bbc70cf57e0a87a0fd79d9791fa7a (patch)
treed533423258feb0dc657b323555dfdc3b09fe934b /sandbox
parent9f5b0fdb85dbc429ec99b7e0af9380f85bba2932 (diff)
downloadchromium_src-a73ed203c32bbc70cf57e0a87a0fd79d9791fa7a.zip
chromium_src-a73ed203c32bbc70cf57e0a87a0fd79d9791fa7a.tar.gz
chromium_src-a73ed203c32bbc70cf57e0a87a0fd79d9791fa7a.tar.bz2
Create a new SetuidSandboxClient class.
We move the setuid sandbox "client" code to its own location in /sandbox/linux/suid/client and we create a SetuidSandboxClient class to use it. NOTRY=true Review URL: https://chromiumcodereview.appspot.com/10807059 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@147993 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox')
-rw-r--r--sandbox/linux/sandbox_linux.gypi24
-rw-r--r--sandbox/linux/suid/client/setuid_sandbox_client.cc168
-rw-r--r--sandbox/linux/suid/client/setuid_sandbox_client.h54
-rw-r--r--sandbox/linux/suid/client/setuid_sandbox_client_unittest.cc78
-rw-r--r--sandbox/linux/suid/common/sandbox.h43
-rw-r--r--sandbox/linux/suid/common/suid_unsafe_environment_variables.h (renamed from sandbox/linux/suid/suid_unsafe_environment_variables.h)18
-rw-r--r--sandbox/linux/suid/sandbox.c28
-rw-r--r--sandbox/linux/suid/sandbox.h23
8 files changed, 389 insertions, 47 deletions
diff --git a/sandbox/linux/sandbox_linux.gypi b/sandbox/linux/sandbox_linux.gypi
index 5286921..e124007 100644
--- a/sandbox/linux/sandbox_linux.gypi
+++ b/sandbox/linux/sandbox_linux.gypi
@@ -11,6 +11,9 @@
{
'target_name': 'sandbox',
'type': 'none',
+ 'dependencies': [
+ 'suid_sandbox_client',
+ ],
'conditions': [
# Only compile in the seccomp mode 1 code for the flag combination
# where we support it.
@@ -38,6 +41,7 @@
],
'sources': [
'tests/unit_tests.cc',
+ 'suid/client/setuid_sandbox_client_unittest.cc',
],
'include_dirs': [
'../..',
@@ -71,11 +75,12 @@
'target_name': 'chrome_sandbox',
'type': 'executable',
'sources': [
+ 'suid/common/sandbox.h',
+ 'suid/common/suid_unsafe_environment_variables.h',
'suid/linux_util.c',
'suid/linux_util.h',
'suid/process_util.h',
'suid/process_util_linux.c',
- 'suid/sandbox.h',
'suid/sandbox.c',
],
'cflags': [
@@ -100,5 +105,22 @@
'..',
],
},
+ {
+ 'target_name': 'suid_sandbox_client',
+ 'type': 'static_library',
+ 'sources': [
+ 'suid/common/sandbox.h',
+ 'suid/common/suid_unsafe_environment_variables.h',
+ 'suid/client/setuid_sandbox_client.cc',
+ 'suid/client/setuid_sandbox_client.h',
+ ],
+ 'dependencies': [
+ '../base/base.gyp:base',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ },
+
],
}
diff --git a/sandbox/linux/suid/client/setuid_sandbox_client.cc b/sandbox/linux/suid/client/setuid_sandbox_client.cc
new file mode 100644
index 0000000..07bff73
--- /dev/null
+++ b/sandbox/linux/suid/client/setuid_sandbox_client.cc
@@ -0,0 +1,168 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "base/eintr_wrapper.h"
+#include "base/environment.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/string_number_conversions.h"
+
+#include "sandbox/linux/suid/common/sandbox.h"
+#include "sandbox/linux/suid/common/suid_unsafe_environment_variables.h"
+#include "setuid_sandbox_client.h"
+
+namespace {
+
+// Set an environment variable that reflects the API version we expect from the
+// setuid sandbox. Old versions of the sandbox will ignore this.
+void SetSandboxAPIEnvironmentVariable(base::Environment* env) {
+ env->SetVar(sandbox::kSandboxEnvironmentApiRequest,
+ base::IntToString(sandbox::kSUIDSandboxApiNumber));
+}
+
+// Wrapper around a shared C function.
+// Returns the "saved" environment variable name corresponding to |envvar|
+// in a new string or NULL.
+std::string* CreateSavedVariableName(const char* envvar) {
+ char* const saved_env_var = SandboxSavedEnvironmentVariable(envvar);
+ if (!saved_env_var)
+ return NULL;
+ std::string* saved_env_var_copy = new std::string(saved_env_var);
+ // SandboxSavedEnvironmentVariable is the C function that we wrap and uses
+ // malloc() to allocate memory.
+ free(saved_env_var);
+ return saved_env_var_copy;
+}
+
+// The ELF loader will clear many environment variables so we save them to
+// different names here so that the SUID sandbox can resolve them for the
+// renderer.
+void SaveSUIDUnsafeEnvironmentVariables(base::Environment* env) {
+ for (unsigned i = 0; kSUIDUnsafeEnvironmentVariables[i]; ++i) {
+ const char* const env_var = kSUIDUnsafeEnvironmentVariables[i];
+ // Get the saved environment variable corresponding to envvar.
+ scoped_ptr<std::string> saved_env_var(CreateSavedVariableName(env_var));
+ if (saved_env_var == NULL)
+ continue;
+
+ std::string value;
+ if (env->GetVar(env_var, &value))
+ env->SetVar(saved_env_var->c_str(), value);
+ else
+ env->UnSetVar(saved_env_var->c_str());
+ }
+}
+
+int GetHelperApi(base::Environment* env) {
+ std::string api_string;
+ int api_number = 0; // Assume API version 0 if no environment was found.
+ if (env->GetVar(sandbox::kSandboxEnvironmentApiProvides, &api_string) &&
+ !base::StringToInt(api_string, &api_number)) {
+ // It's an error if we could not convert the API number.
+ api_number = -1;
+ }
+ return api_number;
+}
+
+// Convert |var_name| from the environment |env| to an int.
+// Return -1 if the variable does not exist or the value cannot be converted.
+int EnvToInt(base::Environment* env, const char* var_name) {
+ std::string var_string;
+ int var_value = -1;
+ if (env->GetVar(var_name, &var_string) &&
+ !base::StringToInt(var_string, &var_value)) {
+ var_value = -1;
+ }
+ return var_value;
+}
+
+pid_t GetHelperPID(base::Environment* env) {
+ return EnvToInt(env, sandbox::kSandboxHelperPidEnvironmentVarName);
+}
+
+// Get the IPC file descriptor used to communicate with the setuid helper.
+int GetIPCDescriptor(base::Environment* env) {
+ return EnvToInt(env, sandbox::kSandboxDescriptorEnvironmentVarName);
+}
+
+} // namespace
+
+namespace sandbox {
+
+SetuidSandboxClient* SetuidSandboxClient::Create() {
+ base::Environment* environment(base::Environment::Create());
+ SetuidSandboxClient* sandbox_client(new(SetuidSandboxClient));
+
+ CHECK(environment);
+ sandbox_client->env_ = environment;
+ return sandbox_client;
+}
+
+SetuidSandboxClient::SetuidSandboxClient() {
+ env_ = NULL;
+}
+
+SetuidSandboxClient::~SetuidSandboxClient() {
+ delete env_;
+}
+
+bool SetuidSandboxClient::ChrootMe() {
+ int fd = GetIPCDescriptor(env_);
+
+ if (fd < 0) {
+ LOG(ERROR) << "Failed to obtain the sandbox IPC descriptor";
+ return false;
+ }
+
+ if (HANDLE_EINTR(write(fd, &kMsgChrootMe, 1)) != 1) {
+ PLOG(ERROR) << "Failed to write to chroot pipe";
+ return false;
+ }
+
+ // We need to reap the chroot helper process in any event.
+ pid_t helper_pid = GetHelperPID(env_);
+ // If helper_pid is -1 we wait for any child.
+ if (waitpid(helper_pid, NULL, 0) < 0) {
+ PLOG(ERROR) << "Failed to wait for setuid helper to die";
+ return false;
+ }
+
+ char reply;
+ if (HANDLE_EINTR(read(fd, &reply, 1)) != 1) {
+ PLOG(ERROR) << "Failed to read from chroot pipe";
+ return false;
+ }
+
+ if (reply != kMsgChrootSuccessful) {
+ LOG(ERROR) << "Error code reply from chroot helper";
+ return false;
+ }
+ return true;
+}
+
+bool SetuidSandboxClient::IsSuidSandboxUpToDate() const {
+ return GetHelperApi(env_) == kSUIDSandboxApiNumber;
+}
+
+bool SetuidSandboxClient::IsSuidSandboxChild() const {
+ return GetIPCDescriptor(env_) >= 0;
+}
+
+bool SetuidSandboxClient::IsInNewPIDNamespace() const {
+ return env_->HasVar(kSandboxPIDNSEnvironmentVarName);
+}
+
+bool SetuidSandboxClient::IsInNewNETNamespace() const {
+ return env_->HasVar(kSandboxNETNSEnvironmentVarName);
+}
+
+void SetuidSandboxClient::SetupLaunchEnvironment() {
+ SaveSUIDUnsafeEnvironmentVariables(env_);
+ SetSandboxAPIEnvironmentVariable(env_);
+}
+
+} // namespace sandbox
diff --git a/sandbox/linux/suid/client/setuid_sandbox_client.h b/sandbox/linux/suid/client/setuid_sandbox_client.h
new file mode 100644
index 0000000..afbde0a
--- /dev/null
+++ b/sandbox/linux/suid/client/setuid_sandbox_client.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_LINUX_SUID_SETUID_SANDBOX_CLIENT_H_
+#define SANDBOX_LINUX_SUID_SETUID_SANDBOX_CLIENT_H_
+
+#include "base/basictypes.h"
+#include "base/environment.h"
+
+namespace sandbox {
+
+// Helper class to use the setuid sandbox. This class is to be used both
+// before launching the setuid helper and after being executed through the
+// setuid helper.
+//
+// A typical use would be:
+// 1. The browser calls SetupLaunchEnvironment()
+// 2. The browser launches a renderer through the setuid sandbox.
+// 3. The renderer requests being chroot-ed through ChrootMe() and
+// requests other sandboxing status via the status functions.
+class SetuidSandboxClient {
+ public:
+ // All instantation should go through this factory method.
+ static class SetuidSandboxClient* Create();
+ ~SetuidSandboxClient();
+
+ // Ask the setuid helper over the setuid sandbox IPC channel to chroot() us
+ // to an empty directory.
+ // Will only work if we have been launched through the setuid helper.
+ bool ChrootMe();
+
+ // Did we get launched through an up to date setuid binary ?
+ bool IsSuidSandboxUpToDate() const;
+ // Did we get launched through the setuid helper ?
+ bool IsSuidSandboxChild() const;
+ // Did the setuid helper create a new PID namespace ?
+ bool IsInNewPIDNamespace() const;
+ // Did the setuid helper create a new network namespace ?
+ bool IsInNewNETNamespace() const;
+
+ // Set-up the environment. This should be done prior to launching the setuid
+ // helper.
+ void SetupLaunchEnvironment();
+
+ private:
+ // Holds the environment. Will never be NULL.
+ base::Environment* env_;
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SetuidSandboxClient);
+};
+
+} // namespace sandbox
+
+#endif // SANDBOX_LINUX_SUID_SETUID_SANDBOX_CLIENT_H_
diff --git a/sandbox/linux/suid/client/setuid_sandbox_client_unittest.cc b/sandbox/linux/suid/client/setuid_sandbox_client_unittest.cc
new file mode 100644
index 0000000..59b02eb
--- /dev/null
+++ b/sandbox/linux/suid/client/setuid_sandbox_client_unittest.cc
@@ -0,0 +1,78 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/environment.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/string_number_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include "sandbox/linux/suid/common/sandbox.h"
+#include "setuid_sandbox_client.h"
+
+namespace sandbox {
+
+TEST(SetuidSandboxClient, SetupLaunchEnvironment) {
+ const char kTestValue[] = "This is a test";
+ scoped_ptr<base::Environment> env(base::Environment::Create());
+ EXPECT_TRUE(env != NULL);
+
+ // Setup environment variables to save or not save.
+ EXPECT_TRUE(env->SetVar("LD_PRELOAD", kTestValue));
+ EXPECT_TRUE(env->UnSetVar("LD_ORIGIN_PATH"));
+
+ scoped_ptr<SetuidSandboxClient>
+ sandbox_client(SetuidSandboxClient::Create());
+ EXPECT_TRUE(sandbox_client != NULL);
+
+ // Make sure the environment is clean.
+ EXPECT_TRUE(env->UnSetVar(kSandboxEnvironmentApiRequest));
+ EXPECT_TRUE(env->UnSetVar(kSandboxEnvironmentApiProvides));
+
+ sandbox_client->SetupLaunchEnvironment();
+
+ // Check if the requested API environment was set.
+ std::string api_request;
+ EXPECT_TRUE(env->GetVar(kSandboxEnvironmentApiRequest, &api_request));
+ int api_request_num;
+ EXPECT_TRUE(base::StringToInt(api_request, &api_request_num));
+ EXPECT_EQ(api_request_num, kSUIDSandboxApiNumber);
+
+ // Now check if LD_PRELOAD was saved to SANDBOX_LD_PRELOAD.
+ std::string sandbox_ld_preload;
+ EXPECT_TRUE(env->GetVar("SANDBOX_LD_PRELOAD", &sandbox_ld_preload));
+ EXPECT_EQ(sandbox_ld_preload, kTestValue);
+
+ // Check that LD_ORIGIN_PATH was not saved.
+ EXPECT_FALSE(env->HasVar("SANDBOX_LD_ORIGIN_PATH"));
+}
+
+TEST(SetuidSandboxClient, SandboxedClientAPI) {
+ scoped_ptr<base::Environment> env(base::Environment::Create());
+ EXPECT_TRUE(env != NULL);
+
+ scoped_ptr<SetuidSandboxClient>
+ sandbox_client(SetuidSandboxClient::Create());
+ EXPECT_TRUE(sandbox_client != NULL);
+
+ // Set-up a fake environment as if we went through the setuid sandbox.
+ EXPECT_TRUE(env->SetVar(kSandboxEnvironmentApiProvides,
+ base::IntToString(kSUIDSandboxApiNumber)));
+ EXPECT_TRUE(env->SetVar(kSandboxDescriptorEnvironmentVarName, "1"));
+ EXPECT_TRUE(env->SetVar(kSandboxPIDNSEnvironmentVarName, "1"));
+ EXPECT_TRUE(env->UnSetVar(kSandboxNETNSEnvironmentVarName));
+
+ // Check the API.
+ EXPECT_TRUE(sandbox_client->IsSuidSandboxUpToDate());
+ EXPECT_TRUE(sandbox_client->IsSuidSandboxChild());
+ EXPECT_TRUE(sandbox_client->IsInNewPIDNamespace());
+ EXPECT_FALSE(sandbox_client->IsInNewNETNamespace());
+
+ // Forge an incorrect API version and check.
+ EXPECT_TRUE(env->SetVar(kSandboxEnvironmentApiProvides,
+ base::IntToString(kSUIDSandboxApiNumber + 1)));
+ EXPECT_FALSE(sandbox_client->IsSuidSandboxUpToDate());
+}
+
+} // namespace sandbox
diff --git a/sandbox/linux/suid/common/sandbox.h b/sandbox/linux/suid/common/sandbox.h
new file mode 100644
index 0000000..aad4ff8
--- /dev/null
+++ b/sandbox/linux/suid/common/sandbox.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_LINUX_SUID_SANDBOX_H_
+#define SANDBOX_LINUX_SUID_SANDBOX_H_
+
+#if defined(__cplusplus)
+namespace sandbox {
+#endif
+
+// These are command line switches that may be used by other programs
+// (e.g. Chrome) to construct a command line for the sandbox.
+static const char kAdjustOOMScoreSwitch[] = "--adjust-oom-score";
+#if defined(OS_CHROMEOS)
+static const char kAdjustLowMemMarginSwitch[] = "--adjust-low-mem";
+#endif
+
+static const char kSandboxDescriptorEnvironmentVarName[] = "SBX_D";
+static const char kSandboxHelperPidEnvironmentVarName[] = "SBX_HELPER_PID";
+
+static const long kSUIDSandboxApiNumber = 1;
+static const char kSandboxEnvironmentApiRequest[] = "SBX_CHROME_API_RQ";
+static const char kSandboxEnvironmentApiProvides[] = "SBX_CHROME_API_PRV";
+
+// This number must be kept in sync with common/zygote_commands_linux.h
+static const int kZygoteIdFd = 7;
+
+// These are the magic byte values which the sandboxed process uses to request
+// that it be chrooted.
+static const char kMsgChrootMe = 'C';
+static const char kMsgChrootSuccessful = 'O';
+
+// These are set if we have respectively switched to a new PID or NET namespace
+// by going through the setuid binary helper.
+static const char kSandboxPIDNSEnvironmentVarName[] = "SBX_PID_NS";
+static const char kSandboxNETNSEnvironmentVarName[] = "SBX_NET_NS";
+
+#if defined(__cplusplus)
+} // namespace sandbox
+#endif
+
+#endif // SANDBOX_LINUX_SUID_SANDBOX_H_
diff --git a/sandbox/linux/suid/suid_unsafe_environment_variables.h b/sandbox/linux/suid/common/suid_unsafe_environment_variables.h
index 4e3329f..ee4db76 100644
--- a/sandbox/linux/suid/suid_unsafe_environment_variables.h
+++ b/sandbox/linux/suid/common/suid_unsafe_environment_variables.h
@@ -16,6 +16,14 @@
#ifndef SANDBOX_LINUX_SUID_SUID_UNSAFE_ENVIRONMENT_VARIABLES_H_
#define SANDBOX_LINUX_SUID_SUID_UNSAFE_ENVIRONMENT_VARIABLES_H_
+#if defined(__cplusplus)
+#include <limits>
+#define SIZE_MAX std::numeric_limits<size_t>::max()
+#endif
+
+#include <stdlib.h> // malloc
+#include <string.h> // memcpy
+
static const char* kSUIDUnsafeEnvironmentVariables[] = {
"LD_AOUT_LIBRARY_PATH",
"LD_AOUT_PRELOAD",
@@ -48,8 +56,12 @@ static const char* kSUIDUnsafeEnvironmentVariables[] = {
// name for a given environment variable.
static inline char* SandboxSavedEnvironmentVariable(const char* envvar) {
const size_t envvar_len = strlen(envvar);
+
+ if (envvar_len > SIZE_MAX - 1 -8)
+ return NULL;
+
const size_t saved_envvarlen = envvar_len + 1 /* NUL terminator */ +
- 8 /* strlen("SANDBOX_") */;
+ 8 /* strlen("SANDBOX_") */;
char* const saved_envvar = (char*) malloc(saved_envvarlen);
if (!saved_envvar)
return NULL;
@@ -61,4 +73,8 @@ static inline char* SandboxSavedEnvironmentVariable(const char* envvar) {
return saved_envvar;
}
+#if defined(__cplusplus)
+#undef SIZE_MAX
+#endif
+
#endif // SANDBOX_LINUX_SUID_SUID_UNSAFE_ENVIRONMENT_VARIABLES_H_
diff --git a/sandbox/linux/suid/sandbox.c b/sandbox/linux/suid/sandbox.c
index 9c2ecde..32435a7 100644
--- a/sandbox/linux/suid/sandbox.c
+++ b/sandbox/linux/suid/sandbox.c
@@ -4,7 +4,7 @@
// http://code.google.com/p/chromium/wiki/LinuxSUIDSandbox
-#include "sandbox.h"
+#include "common/sandbox.h"
#define _GNU_SOURCE
#include <asm/unistd.h>
@@ -31,7 +31,7 @@
#include "linux_util.h"
#include "process_util.h"
-#include "suid_unsafe_environment_variables.h"
+#include "common/suid_unsafe_environment_variables.h"
#if !defined(CLONE_NEWPID)
#define CLONE_NEWPID 0x20000000
@@ -40,22 +40,6 @@
#define CLONE_NEWNET 0x40000000
#endif
-static const char kSandboxDescriptorEnvironmentVarName[] = "SBX_D";
-static const char kSandboxHelperPidEnvironmentVarName[] = "SBX_HELPER_PID";
-
-// Should be kept in sync with base/linux_util.h
-static const long kSUIDSandboxApiNumber = 1;
-static const char kSandboxEnvironmentApiRequest[] = "SBX_CHROME_API_RQ";
-static const char kSandboxEnvironmentApiProvides[] = "SBX_CHROME_API_PRV";
-
-// This number must be kept in sync with common/zygote_commands_linux.h
-static const int kZygoteIdFd = 7;
-
-// These are the magic byte values which the sandboxed process uses to request
-// that it be chrooted.
-static const char kMsgChrootMe = 'C';
-static const char kMsgChrootSuccessful = 'O';
-
static bool DropRoot();
#define HANDLE_EINTR(x) TEMP_FAILURE_RETRY(x)
@@ -280,15 +264,15 @@ static bool MoveToNewNamespaces() {
FatalError("close");
if (kCloneExtraFlags[i] & CLONE_NEWPID) {
- setenv("SBX_PID_NS", "", 1 /* overwrite */);
+ setenv(kSandboxPIDNSEnvironmentVarName, "", 1 /* overwrite */);
} else {
- unsetenv("SBX_PID_NS");
+ unsetenv(kSandboxPIDNSEnvironmentVarName);
}
if (kCloneExtraFlags[i] & CLONE_NEWNET) {
- setenv("SBX_NET_NS", "", 1 /* overwrite */);
+ setenv(kSandboxNETNSEnvironmentVarName, "", 1 /* overwrite */);
} else {
- unsetenv("SBX_NET_NS");
+ unsetenv(kSandboxNETNSEnvironmentVarName);
}
break;
diff --git a/sandbox/linux/suid/sandbox.h b/sandbox/linux/suid/sandbox.h
deleted file mode 100644
index 066003a..0000000
--- a/sandbox/linux/suid/sandbox.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SANDBOX_LINUX_SUID_SANDBOX_H_
-#define SANDBOX_LINUX_SUID_SANDBOX_H_
-
-#if defined(__cplusplus)
-namespace sandbox {
-#endif
-
-// These are command line switches that may be used by other programs
-// (e.g. Chrome) to construct a command line for the sandbox.
-static const char kAdjustOOMScoreSwitch[] = "--adjust-oom-score";
-#if defined(OS_CHROMEOS)
-static const char kAdjustLowMemMarginSwitch[] = "--adjust-low-mem";
-#endif
-
-#if defined(__cplusplus)
-} // namespace sandbox
-#endif
-
-#endif // SANDBOX_LINUX_SUID_SANDBOX_H_