When generating headers from libraries that export functions as `extern "C"`
but still use namespaces (C-compatible C++ libraries), we want to generate
a Sandboxed API that includes fully-qualified namespace names as well.
In addition, we want the generated API to have the same source order as the
original library. Not only is this less surprising when reading the generated
code, it's also more accurate. Previously, we'd bundle all definitions in a
namespace and sort those alphabetically, but for code that relies on symbols
from another namespace to be available, generation will fail:
```c++
namespace zzz {
using entity_count_t = uint64_t;
} // namespace zzz
namespace sheep_counter {
using sheep_count_t = :💤:entity_count_t;
extern "C" void IncreaseSheepCounter(sheep_count_t increment);
} // namespace sheep_counter
```
PiperOrigin-RevId: 486586024
Change-Id: I419c9db8e9cb5b904364b353e2dc3d7f1030fab3
An `absl::StatusCode` of `kCancelled` now indicates warnings inside the emitter.
PiperOrigin-RevId: 485851898
Change-Id: I10a57cbc1b6c2d4b708c3c19aa0fa71451845a22
The libclang based header generator disallows functions that pass structs (or
more generally "record types") by value. While this can be implemented, the
such functions as emitted by the clang_generator never worked.
We should revisit this when we implement support for passing 128-bit integer
types directly, as those will work the same as small structs.
PiperOrigin-RevId: 485522603
Change-Id: Iae8284720da52496d7a48fe3ca3c3c8605e6d19d
This makes it easier to write tests with expected compilation/parsing failures.
PiperOrigin-RevId: 485331205
Change-Id: Ia545934849d38bded9320537c71e970fb4730cb6
Follow-up changes might be required to fully fix up the contrib sandboxes.
PiperOrigin-RevId: 482475998
Change-Id: Iff631eb838a024b2f047a1be61bb27e35a8ff2f4
This change allows Sandbox2 to change how the default FD for comms is chosen.
PiperOrigin-RevId: 479526309
Change-Id: I69add85a244bc0385eaa164ab0ea3b036503c6d3
This change allows Sandbox2 to change how the default FD for comms is chosen.
PiperOrigin-RevId: 479521810
Change-Id: Ia2ca1df95eb21783207ffb625c924790de20480d
This is to abstract the FD number away, so that we can change the way the FD number is chosen/communicated.
PiperOrigin-RevId: 479282707
Change-Id: Ic6726bcd0a17e97bde60804476ecbca2ffbf6525
We have removed an internal-only sandbox mechanism that has been deprecated
for years. Some formatting/include changes may leak into the OSS version.
PiperOrigin-RevId: 475230500
Change-Id: Ib4efdf3282529ea50e8302e5ef7acfdd7d4c68e5
This is the first in a series of changes that will remove our custom logging
implementation in favor of the newly released Abseil log library.
PiperOrigin-RevId: 475221012
Change-Id: I5d21ad104049dc70abe2a8d49659128e9cf3e9c0
When not requesting any particular function, `sapi_library()` will try and
make available _all_ functions it finds. In this case, system headers should
be skipped to avoid inflating the API surface. Standard library functions
can still be manually requested by adding them to the `functions` (Bazel)/
`FUNCTIONS` (CMake) argument.
PiperOrigin-RevId: 472272506
Change-Id: I8f8d79796d3044e598eebb7f87ce4cf464b47ed7
If it isn't, assume that the process has exited and the event msg contains an exit code.
PiperOrigin-RevId: 471258449
Change-Id: I44408c30fe7fb39e20b55cea871f3efb68fcde67
Instead of doing waitpid() and processing one thread at a time, gather all waiting threads and then process them.
This avoids starving older threads when newer threads raise a lot of events.
PiperOrigin-RevId: 466366533
Change-Id: I81a878f038feac86407a8e961ecba181004f0f8a
This finally prevents Ninja from rebuilding everything needlessly each time a
CMake reconfiguration was triggered. The root cause is that we used
`file(WRITE ...)`, which always unconditionally overwrites, so Ninja sees
those files as "dirty".
PiperOrigin-RevId: 453849514
Change-Id: Ib878df21371387baa7bf791a0a054e1ea5d6b6ae
E.g. a failed `KillSandboxee` for a timeout would already set the exit status code while there could be an external kill pending at the same time which would try to `KillSandboxee` again and thus set exit status code again.
PiperOrigin-RevId: 448464765
Change-Id: Ic5744a576c4255504bfb1d5c4f33253b5bb32b6f
This should make multithreaded sandboxees that exec (or send `SIGKILL`) behave more reliably.
PiperOrigin-RevId: 447458426
Change-Id: Ifdace340462199dc24c8cdf25d589ef6b24991e1
Instead of calling `google::InitGoogleLogging()` directly, introduce an
indirection via a new utility library. After this change, Sandboxed API
should consistently use `sapi::InitLogging()` everywhere.
For now, `sapi::InitLogging()` simply calls its glog equivalent. However,
this enables us to migrate away from the gflags dependency and use Abseil
flags. Once a follow-up change lands, `sapi::InitLogging()` will instead
initialize the google logging library with flags defined from Aseil.
Later still, once Abseil releases logging, we can then drop the glog
dependency entirely.
PiperOrigin-RevId: 445363592
Change-Id: Ia23a7dc88b8ffe65a422ea4d5233bba7bdd1303a
Also revert the `.bazelversion` file again, as this will enforce a fixed
version, not a minimum version, which does not work well with our BazelCI.
PiperOrigin-RevId: 444178761
Change-Id: Ib6d1d126d850640ca7d692543784263790b8c418
Internally, we rely on clang-tidy to warn about using deprecated declarations.
And for using deprecated declarations within SAPI itself, we should not warn.
Drive-by:
- Fix warning in `mounts_test.cc`
PiperOrigin-RevId: 443634512
Change-Id: I7ef66f0ba77201026490baab07766510c1c55c6a
`BUILD_TESTING` is a CMake provided option and we should use similar naming,
just like how Abseil does it.
- `SAPI_ENABLE_TESTS` -> `SAPI_BUILD_TESTING`
- `SAPI_ENABLE_CONTRIB_TESTS` -> `SAPI_CONTRIB_BUILD_TESTING`
- `SAPI_ENABLE_EXAMPLES` -> `SAPI_BUILD_EXAMPLES`
Drive-by:
- Fix option name in GitHub action
PiperOrigin-RevId: 443305932
Change-Id: Ice2b42be1229a0f9ae7c2ceda9ce87187baf22c4
Including the `CTest` modules ensures that the `BUILD_TESTING` option is
defined and automatically calls `enable_testing()` if needed. It does not
change the default or introduce any dependencies on its own.
This follows what Abseil already does in their top-level `CMakeLists.txt`.
PiperOrigin-RevId: 443305646
Change-Id: If067c17470f497437c7748aab4aab5227c26e84f
Bazel's `Runfiles::Create()` does not actually need a value for `argv0` in
order to find runfiles for the current `cc_binary`.
- Rename `runfiles.cc` to `runfiles_nobazel.cc`
PiperOrigin-RevId: 443061178
Change-Id: I31e16d69d24aecbc403f9407fc08c615bb1e8f9f
The corresponding command-line option `sapi_isystem` will be ignored for
compatibility.
PiperOrigin-RevId: 439806387
Change-Id: I8ad6d7feed2fba5fca9940281f03cfc757ada5be
This makes `sapi_library()` more compatible with Bazel's native `cc_library()`
rule.
PiperOrigin-RevId: 439512659
Change-Id: If731f600d56db56f78d2897e0c41a200daa93b75
This should fix the build on Debian 10 with LLVM 11.
- Keep order of files to look up in `ls` invocation
- Use `--start-group`/`--end-group` linker options
- Drive-by: use `splitlines()` instead of manual `split("\n")[:-1]`
PiperOrigin-RevId: 439248079
Change-Id: I919bb292ac8a5f514431aa004345f1c6478b1cc9
This change introduces an experimental `generator_version` attribute to the
`sapi_library()` rule. Version `1` will select the current interface
generator, which is based on libclang and Python. Setting the attribute to
version `2`, will select the newer interface generator written in C++ that
uses a full clang compiler frontend for parsing. Both emit equivalent header
output, differences in parsing and/or edge cases notwithstanding.
The default, as of now, is still the old version `1` generator.
Note: CMake allows to select the new interface generator globally by setting
`SAPI_ENABLE_GENERATOR`.
PiperOrigin-RevId: 438765013
Change-Id: I69c49a6bcf1751724edb0bce5c3b2beea2097138
This adds a workspace rule that inspects the current system first and
downloads a suitable version of LLVM/Clang from GitHub if it can't
find one. In the latter case, the necessary parts are build from source,
which can take a while (~10-15m, depending on the build machine).
In order to be found, LLVM/Clang system libraries must be version 11
or higher. On Debian/Ubuntu, install `llvm-13-dev` and `libclang-13-dev`.
The new `llvm_config.bzl` implements this logic. It is loosely based on
upstream's https://github.com/llvm/llvm-project/blob/main/utils/bazel/configure.bzl.
Note that due to the way Bazel separates local repositories, we have to
duplictate some of this code.
PiperOrigin-RevId: 438759950
Change-Id: Ia65f473b4cdef6507e3816bf09794ea10963d87a
This will allow us to experiment with (and subsequently migrate to)
changes to the generated API, possibly incompatible ones.
This change should be a no-op for current builds, as there is only
a single version of Sandboxed API.
PiperOrigin-RevId: 438003314
Change-Id: Ia23ea4360bee0227692d9f5220ab20d85f089ba7
This change merges the internal version of `sapi.bzl` with the external version again:
- Add more docstrings to the various macros
- Skip creation of `.isystem` file, get info from toolchain instead
PiperOrigin-RevId: 437730588
Change-Id: I6f670d32e3d7177a6a160fd24cbee6f8f3ca9503
This fixes the main issue (#118) with stack traces on Fedora, which uses a
`/lib64` and `/usr/lib64`.
PiperOrigin-RevId: 437717858
Change-Id: I6986aa84c2be57ae1d9f8d0cb9b508768d27f1c1
This uses the Google formatting style to format the prototype comments, with an
internal line length of 75, which accomodates the indentation in the generated
API class.
PiperOrigin-RevId: 435303665
Change-Id: I4dcdf0ed773a79ebc55ead3843f07ca8556fd985
This implements a custom compilation database to conditionally add the correct
language flags to the compiler frontend. Otherwise, a C header might receive
`--std=c++17` and fail.
Note: All headers are always processed in C++ mode. We expect that headers of
well-behaved C libraries contain `#ifdef __cplusplus`/`extern "C" {}` guards.
PiperOrigin-RevId: 435302048
Change-Id: Ib84e6e1f301ba434999846a012b3f8c16884648e
The enclosing type is enough to reconstruct the AST when writing the header and this
change avoids emitting the same struct twice.
PiperOrigin-RevId: 435300029
Change-Id: I34bd660db5ba5c68b64cce73ecf2f026727ac57b
This is a follow up to fa9e6e8a5c.
Drive-by:
- Replace deprecated calls to `getNameAsString()`
PiperOrigin-RevId: 435287759
Change-Id: I81d8c2f93b1ab23c781421b114779b7a241e4a7e
We have a SAPI_ASSERT_OK_AND_ASSIGN which corespondents to
SAPI_ASSIGN_OR_RETURN.
We also have SAPI_RETURN_IF_ERROR but we don't have a coresponding
macro for ASSERT.
I think that this completes the API and makes writting tests a little
bit simpler.
The feature is pure optimization, but it requires
additional syscalls.
PiperOrigin-RevId: 432954277
Change-Id: I1f345f8a26c86e09611fd575cb6ee080f24cc717
There are a lot of internal users depending on the old behavior of the
libclang-based generator.
PiperOrigin-RevId: 432281224
Change-Id: If82333fc3001f52de59e57a874f28bf8815d0877
The constexpr functions can be used to ensure that all branches actually compile
(unlike plain preprocessor `#ifdef`s).
PiperOrigin-RevId: 432186834
Change-Id: I1a8d97dac8480fe9d4543b0e9e39540ca1efc8fa
munmap is widely used by sanitizer, but it
probably works for Asan/Msan because it's enabled
by unrelated Allow* call.
Move mprotect to shared part as well. It will be
needed for compress_stack_depot.
PiperOrigin-RevId: 431989551
Change-Id: I7695a2de81d8d0b2112d3308778b2e9a9c7cb596
Use [`direct_headers`](https://bazel.build/rules/lib/CompilationContext#direct_headers)
from the Bazel/Blaze compilation context instead of _all_ transitive headers.
For the clang based generator, this means we don't try to parse
`textual_headers`, which will fail (they are by definition not
stand-alone, after all).
PiperOrigin-RevId: 431899423
Change-Id: I7a9dfa0dd93eba14b506b0e7ca6db3ed59b55dd6
Linking glibc in fully static mode is mostly unsupported. While such binaries
can easily be produced, conflicting symbols will often make them crash at
runtime. This happens because glibc will always (try to) load some dynamically
linked libraries, even when statically linked. This includes things like the
resolver, unicode/locale handling and others.
Internally at Google, this is not a concern due to the way glibc is being built
there. But in order to make all of our tests run in the open-source version of
this code, we need to change strategy a bit.
As a rule of thumb, glibc can safely be linked statically if a program is
resonably simple and does not use any networking of locale dependent
facilities. Calling syscalls directly instead of the corresponding libc
wrappers works as well, of course.
This change adjusts linker flags and sandbox policies to be more compatible
with regular Linux distributions.
Tested:
- `ctest -R '[A-Z].*'` (all SAPI/Sandbox2 tests)
PiperOrigin-RevId: 429025901
Change-Id: I46b677d9eb61080a8fe868002a34a77de287bf2d
- Link `zipe.c` statically (safe)
- Update policy to allow any use of `stat()`
PiperOrigin-RevId: 428971638
Change-Id: Ib0f5f496ea2389582986b41a8830592e6c1d4390
Instead of C++17 structured bindings, use a plain `const auto&` and annotate
arguments with comments instead.
We still support Clang 6.0, as that is the compiler that ships with Ubuntu
18.04 LTS by default.
PiperOrigin-RevId: 428016214
Change-Id: I3a43b2d47c6825ac4425d22018750282cfe23c1b
This fixes a couple of tests in the open source version of the code.
Internally, since we are using a different ELF loader, the page offset
will always be zero. Hence we never notices this was broken.
PiperOrigin-RevId: 427996428
Change-Id: I44c5b5610b074cf69b9f0c5eeb051be50923e351
Note that `//sandboxed_api/sandbox2:stack_trace_test` may still fail for
unrelated reasons, as we are linking libc statically, which is brittle. A
follow-up change will fix this.
PiperOrigin-RevId: 427175045
Change-Id: Ifb5ec2ac3d60f4bcc9708f26c834c83b75e769d7
This partially reverts the zlib change in 41e0ca0. Turns out the
`CMakeLists.txt` that ships with zlib leaves much to be desired.
PiperOrigin-RevId: 424800727
Change-Id: I356e3bb8d18461a52f845baa4913adff6549ef00
Plain `readdir` is preferred and while not (yet) specified in POSIX it is thread-safe for different directory streams in popular implementations.
PiperOrigin-RevId: 423321528
Change-Id: I4e1e842f338ff7d690c36e7f699b2f3637609524
Newer versions of libunwind use `PTRACE_GETREGSET` to obtain register data.
This change should make it easier to upgrade the libunwind dependency.
PiperOrigin-RevId: 420057842
Change-Id: Ib9abbeff574e457009709715f912ba5962033c5d
Raw `SAPI_RAW_PCHECK` may dump core, depending on environment settings
(issue #89).
This is undesirable in the face of invalid command-line arguments.
Signed-off-by: Christian Blichmann <cblichmann@google.com>
- Allow to specify multiple syscalls with `BlockSyscallsWithErrno()`
- Add functions to allow `unlink()` and `rename()` in all their spellings
PiperOrigin-RevId: 414987303
Change-Id: Ic0e680b785e8e3a3498f20e6a7403737e63fe876
__sanitizer_sandbox_on_notify is not tsan specific.
It's empty for other sanitizers now, but we are going to need it soon.
PiperOrigin-RevId: 414873197
Change-Id: I251ac38e5c886980b4baa7f05306643599a25090
Move VecStringToCharPtrArr before fork, so that it cannot deadlock when other thread holds allocation lock.
PiperOrigin-RevId: 414661912
Change-Id: Ie8aa5c36693e6f86c69d67a1da51b7e7ff1ec30b
This change is a first step to make the SAPI variable hierarchy more sensible.
It turns the `Reg<T>` class into a descendant of `Pointable`, but without
making its `PtrXXX()` methods public (hence the `using` statements). Further
changes are needed to restructure this.
There are no functional changes and the class sizes, including vtables, should
not change.
PiperOrigin-RevId: 413333120
Change-Id: I90ceeaeb7aea482016f8f4bee81489d5a9db9ade
Different versions of the `elf.h` header define their own integer types. For
example, even on LP64 systems, a 64-bit ELF integer types may decay into
`unsigned long long` instead of `unsigned long`.
This change replaces the various overloads with a single function template
that is well-defined for all integral types.
PiperOrigin-RevId: 410746713
Change-Id: I4b560f7541802372f01ae3d6f4a56554e51d70c8
Generate syscall jump table without using bpf_helper.
Check that any jump in the user provided policy is within the provided policy.
PiperOrigin-RevId: 409362089
Change-Id: I31493e52cf868e4b184ff79fcb26beeb75f49773
This is mainly so that the structure of the examples follows what we do
internally (not having separate directories).
PiperOrigin-RevId: 402298115
Change-Id: I0f542607b88597572de39532364816f80a076697
This is the first change in a series that will eventually remove Sandboxed
API's use of multiple inheritance.
Drive-by:
- Rename short member names to full words
- Some reformatting
PiperOrigin-RevId: 402270954
Change-Id: I8af46b887921265a371b85603fd158ef3a8fab50
Note: This change allows `MAP_NORESERVE` generally, not just for MSAN. This follows
what we do for `AllowTcMalloc()/AllowSystemMalloc()`
PiperOrigin-RevId: 402231980
Change-Id: Ifa1c6b9f61f636dd6db231dde3765c3b4a40911b
These were previously dependent on an internal-only testing target.
For now, this only works with Bazel, but should enable us to have better test coverage in GitHub actions.
Eventually, all of these shell-based tests should be converted to `cc_test`s.
PiperOrigin-RevId: 400713615
Change-Id: I1cabb5b72977987ef4a1803480f699b58c4d56e9
For OSS, this change should be mostly a no-op. Visible edits are due to
changed order of code and/or includes.
PiperOrigin-RevId: 394177395
Change-Id: I1d32f9fd175579e8f05c051b1307953b249d139d
This mainly a debugging facility.
It makes diagnosing problems where sandboxed process just randomly exits whereas unsandboxed one runs to completion due to differences in the setup/environment much easier.
PiperOrigin-RevId: 391005548
Change-Id: Ia19fe6632748da93c1f4291bb55e895f50a4e2b0
Otherwise starting forkserver multiple times will result in zombie processes lingering around.
PiperOrigin-RevId: 388926497
Change-Id: Ia9947cce3d9e909edd709b0d3525e1ae8b8bbc51
Also really own `exec_fd_` as previously if the executor is destructed without calling `StartSubProcess` the file descriptor would leak.
PiperOrigin-RevId: 388901766
Change-Id: I6bbb15ced37a0a832ec5a5228452a3d54ef46ee9
This was missing a friend declaration in order to actually compile.
It's now being used in the "stringop" example, so we test it as well.
Drive-by:
- Do not copy the proto's bytes the constructor, but use `std::move`
PiperOrigin-RevId: 387774353
Change-Id: Ic8824af911ac744e2e68130e1f4673c4dddd4939
Calling `Terminate()` issues additional syscalls that may clobber the `errno`
value. Reordering the log statements ensures we actually log the initial error
in `read()`/`write()`.
PiperOrigin-RevId: 387576942
Change-Id: I0f9c8c6001e6dc4ca098abe02cd251029f92a737
1. In many cases, sandboxes need to allow /proc/stat and /proc/cpuinfo so that
get_nprocs(3) will work; otherwise, per-CPU logic can't determine how many CPUs
there are. Unfortunately, some of those sandboxes also disable namespaces. The
solution is to provide two functions: AllowRestartableSequencesWithProcFiles(),
which allows syscalls and files; and AllowRestartableSequences(), which allows
syscalls only. Sandboxes should usually call the former; sandboxes that disable
namespaces should instead call the latter and are responsible for allowing the
files via the deprecated Fs mechanism.
2. Make the mmap(2) policy evaluate prot AND flags, not prot OR flags.
3. Order the code and the comments identically for better readability.
PiperOrigin-RevId: 386414028
Change-Id: I016b1854ed1da9c9bcff7b351c5e0041093b8193
Ideally, we'd seal the embedded SAPI binary using fcntl(). However, in rare
cases, adding the file seals `F_SEAL_SEAL | F_SEAL_SHRINK | F_SEAL_GROW |
F_SEAL_WRITE` results in `EBUSY` errors.
This is likely because of an interaction of `SEAL_WRITE` with pending writes
to the mapped memory region (see `memfd_wait_for_pins()` in Linux'
`mm/memfd.c`). Since `fsync()` is a no-op on memfds, it doesn't help to
ameliorate the problem.
On systems where it is enabled, ksmd might also be a source of pending writes.
PiperOrigin-RevId: 385741435
Change-Id: I21bd6a9039be4b6298774e837ce3628180ed91a8
The existing function signature took a `unique_ptr<>` owning a vector, and
took `nullptr` to mean an empty set of capabilities. This is more naturally
modeled by taking the vector directly and `std::move`-ing it.
PiperOrigin-RevId: 384214849
Change-Id: I177f04a06803ae00429b19a1f3f12e7be04d2908
- Assign to `*mutable_XXX()` instead of looping
- Use a const ref for capabilities
PiperOrigin-RevId: 384192675
Change-Id: I4db3d0c8ce0d7f6acc9fd486a2409962516b5fe7