Skip to content

Commit

Permalink
Merge pull request #12 from googleprojectzero/concurrence_release
Browse files Browse the repository at this point in the history
Add Concurrence
  • Loading branch information
nedwill authored Oct 25, 2022
2 parents 801269c + a6ca837 commit 1bf18a7
Show file tree
Hide file tree
Showing 70 changed files with 5,436 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
BasedOnStyle: Google
AllowShortBlocksOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
ReflowComments: false
32 changes: 32 additions & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
Checks: >
*,
-altera-*,
-bugprone-easily-swappable-parameters,
-bugprone-reserved-identifier,
-cert-*,
-cppcoreguidelines-*,
-fuchsia-*,
-hicpp-*,
-llvm-*,
-llvmlibc-*,
-google-objc-function-naming,
-misc-const-correctness,
-misc-no-recursion,
-misc-non-private-member-variables-in-classes,
-misc-unused-parameters,
-modernize-avoid-c-arrays,
-modernize-deprecated-headers,
-modernize-use-nodiscard,
-modernize-use-trailing-return-type,
-modernize-use-using,
-performance-no-int-to-ptr,
-readability-function-cognitive-complexity,
-readability-identifier-length,
-readability-implicit-bool-conversion,
-readability-magic-numbers,
WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
FormatStyle: none
User: sockfuzzer
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,13 @@ __pycache__
*.d
*.filelist
/build

### Automatically added by Hedron's Bazel Compile Commands Extractor: https://github.com/hedronvision/bazel-compile-commands-extractor
# Ignore the `external` link (that is added by `bazel-compile-commands-extractor`). The link differs between macOS/Linux and Windows, so it shouldn't be checked in. The pattern must not end with a trailing `/` because it's a symlink on macOS/Linux.
/external
# Ignore links to Bazel's output. The pattern needs the `*` because people can change the name of the directory into which your repository is cloned (changing the `bazel-<workspace_name>` symlink), and must not end with a trailing `/` because it's a symlink on macOS/Linux.
/bazel-*
# Ignore generated output. Although valuable (after all, the primary purpose of `bazel-compile-commands-extractor` is to produce `compile_commands.json`!), it should not be checked in.
/compile_commands.json
# Ignore the directory in which `clangd` stores its local index.
/.cache/
41 changes: 41 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Copyright 2022 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.

# third_party ignored
files: ^((?!third_party).)*$
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: check-merge-conflict
- id: requirements-txt-fixer
- repo: https://github.com/psf/black
rev: '22.8.0'
hooks:
- id: black
- repo: https://github.com/jlebar/pre-commit-hooks.git
rev: 62ca83ba4958da48ea44d9f24cd0aa58633376c7
hooks:
- id: bazel-buildifier
- id: clang-format-whole-file
types_or: [c++, c, proto]
- repo: https://github.com/koalaman/shellcheck-precommit
rev: v0.7.2
hooks:
- id: shellcheck
args: ["--severity=warning"]
14 changes: 14 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
# Copyright 2022 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.

# This Dockerfile prepares a simple Debian build environment.

# docker build --pull -t builder .
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ for fuzzing the network stack in userland on macOS and Linux-based hosts.

# Building and Using the Fuzzer

NOTE: The project is moving to a Bazel-based build system. The following steps
work for now but will be updated once the new build system is published.

Build the fuzzer the same way you would typically build a project using CMake
for your platform. For example:

Expand Down
51 changes: 51 additions & 0 deletions fuzz/executor/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Copyright 2022 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.

cc_library(
name = "headers",
srcs = ["coroutine_executor.h"],
visibility = [
"//fuzz/host:__pkg__",
],
deps = [
"//third_party/libco:co",
],
)

cc_library(
name = "coroutine_executor",
srcs = ["coroutine_executor.cc"],
hdrs = ["coroutine_executor.h"],
visibility = [
"//fuzz/host:__pkg__",
],
deps = [
":headers",
"//executor",
"//scheduler:fuzzed_scheduler",
"@com_google_absl//absl/container:flat_hash_map",
],
)

cc_test(
name = "coroutine_executor_test",
size = "small",
srcs = ["coroutine_executor_test.cc"],
deps = [
":coroutine_executor",
"//executor:executor_test_template",
"//scheduler:fuzzed_scheduler_test_template",
"@com_google_googletest//:gtest_main",
],
)
137 changes: 137 additions & 0 deletions fuzz/executor/coroutine_executor.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// Copyright 2022 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.

// #define _GNU_SOURCE
#include "fuzz/executor/coroutine_executor.h"

#include <functional>
#include <string>
#include <utility>

#include "absl/meta/type_traits.h"

#if __has_feature(address_sanitizer)
#include <sanitizer/common_interface_defs.h>
#endif

const int KERNEL_STACK_SIZE = 4096 * 16;

#include "third_party/libco/libco.h"
#include <stdint.h>
#include <stdlib.h>
#include <sys/mman.h>

static CoroutineExecutor *g_coroutine_executor;

static void ThreadStart() {
g_coroutine_executor->CallPendingFunctionThenSwap();
}

CoroutineExecutor::CoroutineExecutor() : main_thread_(co_active()) {
g_current_thread = reinterpret_cast<ThreadHandle>(co_active());
g_coroutine_executor = this;
}

CoroutineExecutor::~CoroutineExecutor() { g_coroutine_executor = nullptr; }

ThreadHandle CoroutineExecutor::CreateThread(std::function<void()> target) {
void *mapping =
mmap(nullptr, 0x1000 + KERNEL_STACK_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (mapping == MAP_FAILED) {
abort();
}
if (mprotect(mapping, 0x1000, PROT_NONE)) {
abort();
}
cothread_t thread = co_derive(static_cast<uint8_t *>(mapping) + 0x1000,
KERNEL_STACK_SIZE, ThreadStart);
pending_functions_[thread] = std::move(target);
return reinterpret_cast<ThreadHandle>(thread);
}

void CoroutineExecutor::CallPendingFunctionThenSwap() {
#if __has_feature(address_sanitizer)
__sanitizer_finish_switch_fiber(nullptr, nullptr, nullptr);
#endif
cothread_t active = co_active();
g_current_thread = reinterpret_cast<ThreadHandle>(active);
if (active == main_thread_) {
abort();
}

auto it = pending_functions_.find(active);
if (it == pending_functions_.end()) {
abort();
}

auto pending_function = std::move(it->second);
pending_functions_.erase(it);

pending_function();

// TODO(nedwill): only notify destroyed once the thread actually gets
// destroyed explicitly
callbacks()->ThreadDestroyed(reinterpret_cast<ThreadHandle>(active));
SwitchToMainThread();
}

void CoroutineExecutor::DeleteThread(ThreadHandle handle) {
// co_delete(cothread);
DeleteBacktrace(handle);
munmap(reinterpret_cast<uint8_t *>(handle - 0x1000),
KERNEL_STACK_SIZE + 0x1000);
}

void CoroutineExecutor::SwitchToMainThread() {
SwitchTo(reinterpret_cast<ThreadHandle>(main_thread_));
}

void CoroutineExecutor::SwitchTo(ThreadHandle handle) {
auto *cothread = reinterpret_cast<cothread_t>(handle);

if (co_active() == cothread) {
// Already on requested thread
return;
}

#if __has_feature(address_sanitizer)
// TODO(nedwill): track first argument to support stack use after return
// detection
__sanitizer_start_switch_fiber(nullptr, cothread, KERNEL_STACK_SIZE);
#endif
co_switch(cothread);
g_current_thread = reinterpret_cast<ThreadHandle>(co_active());
#if __has_feature(address_sanitizer)
__sanitizer_finish_switch_fiber(nullptr, nullptr, nullptr);
#endif
}

ThreadHandle CoroutineExecutor::GetCurrentThreadHandle() {
// For performance, prefer to access g_current_thread directly.
// This global is set in SwitchTo.
return g_current_thread;
}

ThreadHandle CoroutineExecutor::GetMainThreadHandle() {
return reinterpret_cast<ThreadHandle>(main_thread_);
}

// TODO(nedwill): support naming fibers
void CoroutineExecutor::SetThreadName(ThreadHandle handle,
const std::string &name) {}

std::string CoroutineExecutor::DescribeThreadHandle(ThreadHandle handle) {
return {};
}
54 changes: 54 additions & 0 deletions fuzz/executor/coroutine_executor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2022 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 COROUTINE_EXECUTOR_H_
#define COROUTINE_EXECUTOR_H_

#include <functional>
#include <string>

#include "absl/container/flat_hash_map.h"
#include "executor/executor.h"
#include "third_party/libco/libco.h"

class CoroutineExecutor : public Executor {
public:
explicit CoroutineExecutor();
~CoroutineExecutor() override;

ThreadHandle CreateThread(std::function<void()> target) override;
void DeleteThread(ThreadHandle handle) override;

void SwitchToMainThread() override;
void SwitchTo(ThreadHandle handle) override;

ThreadHandle GetCurrentThreadHandle() override;
ThreadHandle GetMainThreadHandle() override;

void SetThreadName(ThreadHandle handle, const std::string &name) override;

std::string DescribeThreadHandle(ThreadHandle handle) override;

void CallPendingFunctionThenSwap();

private:
cothread_t main_thread_;

// Map from cothread_t to target functions
absl::flat_hash_map<cothread_t, std::function<void()>> pending_functions_;
};

#endif /* COROUTINE_EXECUTOR_H_ */
Loading

0 comments on commit 1bf18a7

Please sign in to comment.