Skip to content

Commit 7fb7078

Browse files
committed
Fix for heap-use-after-free in GPUService.cpp
This adds a unit test and fix for the bug reported by libfuzzer. Changes made: * Expose GPUService as testable code. * Update main_gpuservice.cpp to use the new GpuService now located at gpuservice/GpuService.h * Make initializer threads members of GpuService * Join the threads in destructor to prevent heap-use-after-free. * Add unit test that waits 3 seconds after deallocation to ensure no wrong access is made. Merged-In: I4d1d2d4658b575bf2c8f425f91f68f03114ad029 Bug: 282919145 Test: Added unit test and ran on device with ASAN Change-Id: I4d1d2d4658b575bf2c8f425f91f68f03114ad029 (cherry picked from commit 3c00cbc)
1 parent d6684f4 commit 7fb7078

6 files changed

Lines changed: 69 additions & 6 deletions

File tree

services/gpuservice/Android.bp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ filegroup {
7171
cc_library_shared {
7272
name: "libgpuservice",
7373
defaults: ["libgpuservice_production_defaults"],
74+
export_include_dirs: ["include"],
7475
srcs: [
7576
":libgpuservice_sources",
7677
],

services/gpuservice/GpuService.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
1818

19-
#include "GpuService.h"
19+
#include "gpuservice/GpuService.h"
2020

2121
#include <android-base/stringprintf.h>
2222
#include <binder/IPCThreadState.h>
@@ -34,6 +34,7 @@
3434
#include <vkjson.h>
3535

3636
#include <thread>
37+
#include <memory>
3738

3839
namespace android {
3940

@@ -55,18 +56,21 @@ GpuService::GpuService()
5556
mGpuStats(std::make_unique<GpuStats>()),
5657
mGpuMemTracer(std::make_unique<GpuMemTracer>()) {
5758

58-
std::thread gpuMemAsyncInitThread([this]() {
59+
mGpuMemAsyncInitThread = std::make_unique<std::thread>([this] (){
5960
mGpuMem->initialize();
6061
mGpuMemTracer->initialize(mGpuMem);
6162
});
62-
gpuMemAsyncInitThread.detach();
6363

64-
std::thread gpuWorkAsyncInitThread([this]() {
64+
mGpuWorkAsyncInitThread = std::make_unique<std::thread>([this]() {
6565
mGpuWork->initialize();
6666
});
67-
gpuWorkAsyncInitThread.detach();
6867
};
6968

69+
GpuService::~GpuService() {
70+
mGpuWorkAsyncInitThread->join();
71+
mGpuMemAsyncInitThread->join();
72+
}
73+
7074
void GpuService::setGpuStats(const std::string& driverPackageName,
7175
const std::string& driverVersionName, uint64_t driverVersionCode,
7276
int64_t driverBuildTime, const std::string& appPackageName,

services/gpuservice/GpuService.h renamed to services/gpuservice/include/gpuservice/GpuService.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <serviceutils/PriorityDumper.h>
2525

2626
#include <mutex>
27+
#include <thread>
2728
#include <vector>
2829

2930
namespace android {
@@ -41,6 +42,7 @@ class GpuService : public BnGpuService, public PriorityDumper {
4142
static const char* const SERVICE_NAME ANDROID_API;
4243

4344
GpuService() ANDROID_API;
45+
~GpuService();
4446

4547
protected:
4648
status_t shellCommand(int in, int out, int err, std::vector<String16>& args) override;
@@ -86,6 +88,8 @@ class GpuService : public BnGpuService, public PriorityDumper {
8688
std::unique_ptr<GpuMemTracer> mGpuMemTracer;
8789
std::mutex mLock;
8890
std::string mDeveloperDriverPath;
91+
std::unique_ptr<std::thread> mGpuMemAsyncInitThread;
92+
std::unique_ptr<std::thread> mGpuWorkAsyncInitThread;
8993
};
9094

9195
} // namespace android

services/gpuservice/main_gpuservice.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#include <binder/IServiceManager.h>
1919
#include <binder/ProcessState.h>
2020
#include <sys/resource.h>
21-
#include "GpuService.h"
21+
#include "gpuservice/GpuService.h"
2222

2323
using namespace android;
2424

services/gpuservice/tests/unittests/Android.bp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ cc_test {
3131
"GpuMemTest.cpp",
3232
"GpuMemTracerTest.cpp",
3333
"GpuStatsTest.cpp",
34+
"GpuServiceTest.cpp",
3435
],
3536
header_libs: ["bpf_headers"],
3637
shared_libs: [
@@ -47,6 +48,7 @@ cc_test {
4748
"libstatslog",
4849
"libstatspull",
4950
"libutils",
51+
"libgpuservice",
5052
],
5153
static_libs: [
5254
"libgmock",
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#undef LOG_TAG
2+
#define LOG_TAG "gpuservice_unittest"
3+
4+
#include "gpuservice/GpuService.h"
5+
6+
#include <gtest/gtest.h>
7+
#include <log/log_main.h>
8+
9+
#include <chrono>
10+
#include <thread>
11+
12+
namespace android {
13+
namespace {
14+
15+
class GpuServiceTest : public testing::Test {
16+
public:
17+
GpuServiceTest() {
18+
const ::testing::TestInfo* const test_info =
19+
::testing::UnitTest::GetInstance()->current_test_info();
20+
ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
21+
}
22+
23+
~GpuServiceTest() {
24+
const ::testing::TestInfo* const test_info =
25+
::testing::UnitTest::GetInstance()->current_test_info();
26+
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
27+
}
28+
29+
};
30+
31+
32+
/*
33+
* The behaviour before this test + fixes was UB caused by threads accessing deallocated memory.
34+
*
35+
* This test creates the service (which initializes the culprit threads),
36+
* deallocates it immediately and sleeps.
37+
*
38+
* GpuService's destructor gets called and joins the threads.
39+
* If we haven't crashed by the time the sleep time has elapsed, we're good
40+
* Let the test pass.
41+
*/
42+
TEST_F(GpuServiceTest, onInitializeShouldNotCauseUseAfterFree) {
43+
sp<GpuService> service = new GpuService();
44+
service.clear();
45+
std::this_thread::sleep_for(std::chrono::seconds(3));
46+
47+
// If we haven't crashed yet due to threads accessing freed up memory, let the test pass
48+
EXPECT_TRUE(true);
49+
}
50+
51+
} // namespace
52+
} // namespace android

0 commit comments

Comments
 (0)