Skip to content

Commit b7f4594

Browse files
Charlie Cookfacebook-github-bot
authored andcommitted
Utility to intercept fork() system calls
Summary: Creates a utility that will intercept any and all calls to the fork system method. This is a test only library. Reviewed By: vitaut Differential Revision: D79674149 fbshipit-source-id: a44da2794ed5e61d3b54848dc197d66c7a9510c6
1 parent c1c40f0 commit b7f4594

File tree

3 files changed

+118
-0
lines changed

3 files changed

+118
-0
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include <pthread.h>
18+
#include <folly/lang/Exception.h>
19+
#include <thrift/compiler/test/fork_intercept.h>
20+
21+
bool fork_intercept::intercept = []() {
22+
bool installed = false;
23+
#if FOLLY_HAVE_PTHREAD_ATFORK
24+
25+
pthread_atfork(
26+
[]() {
27+
if (!fork_intercept::get_intercept()) {
28+
// Call the real fork
29+
return;
30+
}
31+
folly::terminate_with<std::runtime_error>(
32+
"INTERCEPTED: Direct fork() override - intercepted fork() call\n");
33+
},
34+
nullptr,
35+
nullptr);
36+
installed = true;
37+
#endif
38+
return installed;
39+
}();
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
/**
20+
* This class interfaces with the fork_intercept library to control if forking
21+
* is allowed or not. By default it disallows forking and should remain so
22+
* during normal operation. However, during testing, forking can be allowed for
23+
* testing purposes.
24+
*/
25+
class fork_intercept {
26+
static bool intercept;
27+
28+
public:
29+
void static set_intercept(bool should_crash) { intercept = should_crash; }
30+
31+
bool static get_intercept() { return intercept; }
32+
};
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include <gtest/gtest.h>
18+
19+
#include <sys/types.h>
20+
#include <folly/Subprocess.h>
21+
#include <thrift/compiler/test/fork_intercept.h>
22+
23+
namespace apache::thrift::compiler {
24+
namespace {
25+
26+
TEST(ForkInterceptTest, DirectForkInterception) {
27+
// The death test itself needs to fork, so we allow it here but the process
28+
// executing the death test will reinstall the intercept
29+
fork_intercept::set_intercept(false);
30+
ASSERT_DEATH(
31+
([]() {
32+
fork_intercept::set_intercept(true);
33+
fork();
34+
})(),
35+
"INTERCEPTED: Direct fork\\(\\) override - intercepted fork\\(\\) call");
36+
}
37+
38+
TEST(ForkInterceptTest, FollySubprocessInterception) {
39+
// This should be allowed by the fork intercept override since
40+
// folly::Subprocess does not use fork()
41+
std::vector<std::string> args = {"/bin/echo", "Hello world!"};
42+
auto proc = folly::Subprocess(args);
43+
proc.wait();
44+
}
45+
46+
} // namespace
47+
} // namespace apache::thrift::compiler

0 commit comments

Comments
 (0)