xref: /aosp_15_r20/frameworks/native/libs/binder/tests/binderRecordReplayTest.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
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 <BnBinderRecordReplayTest.h>
18 #include <android-base/logging.h>
19 #include <binder/Binder.h>
20 #include <binder/BpBinder.h>
21 #include <binder/IBinder.h>
22 #include <binder/IPCThreadState.h>
23 #include <binder/IServiceManager.h>
24 #include <binder/RecordedTransaction.h>
25 #include <binder/unique_fd.h>
26 
27 #include <cutils/ashmem.h>
28 
29 #include <fuzzbinder/libbinder_driver.h>
30 #include <fuzzbinder/random_binder.h>
31 #include <fuzzer/FuzzedDataProvider.h>
32 #include <fuzzseeds/random_parcel_seeds.h>
33 
34 #include <gtest/gtest.h>
35 
36 #include <sys/prctl.h>
37 
38 #include "../file.h"
39 #include "parcelables/SingleDataParcelable.h"
40 
41 using namespace android;
42 using android::generateSeedsFromRecording;
43 using android::RandomBinder;
44 using android::binder::borrowed_fd;
45 using android::binder::Status;
46 using android::binder::unique_fd;
47 using android::binder::debug::RecordedTransaction;
48 using parcelables::SingleDataParcelable;
49 
50 const String16 kServerName = String16("binderRecordReplay");
51 extern std::string kRandomInterfaceName;
52 
53 #define GENERATE_GETTER_SETTER_PRIMITIVE(name, T) \
54     Status set##name(T input) {                   \
55         m##name = input;                          \
56         return Status::ok();                      \
57     }                                             \
58                                                   \
59     Status get##name(T* output) {                 \
60         *output = m##name;                        \
61         return Status::ok();                      \
62     }                                             \
63     T m##name
64 
65 #define GENERATE_GETTER_SETTER(name, T) \
66     Status set##name(const T& input) {  \
67         m##name = input;                \
68         return Status::ok();            \
69     }                                   \
70                                         \
71     Status get##name(T* output) {       \
72         *output = m##name;              \
73         return Status::ok();            \
74     }                                   \
75     T m##name
76 
77 class MyRecordReplay : public BnBinderRecordReplayTest {
78 public:
79     GENERATE_GETTER_SETTER_PRIMITIVE(Boolean, bool);
80     GENERATE_GETTER_SETTER_PRIMITIVE(Byte, int8_t);
81     GENERATE_GETTER_SETTER_PRIMITIVE(Int, int);
82     GENERATE_GETTER_SETTER_PRIMITIVE(Char, char16_t);
83     GENERATE_GETTER_SETTER_PRIMITIVE(Long, int64_t);
84     GENERATE_GETTER_SETTER_PRIMITIVE(Float, float);
85     GENERATE_GETTER_SETTER_PRIMITIVE(Double, double);
86 
87     GENERATE_GETTER_SETTER(String, String16);
88     GENERATE_GETTER_SETTER(SingleDataParcelable, SingleDataParcelable);
89     GENERATE_GETTER_SETTER(Binder, sp<IBinder>);
90 
91     GENERATE_GETTER_SETTER(BooleanArray, std::vector<bool>);
92     GENERATE_GETTER_SETTER(ByteArray, std::vector<uint8_t>);
93     GENERATE_GETTER_SETTER(IntArray, std::vector<int>);
94     GENERATE_GETTER_SETTER(CharArray, std::vector<char16_t>);
95     GENERATE_GETTER_SETTER(LongArray, std::vector<int64_t>);
96     GENERATE_GETTER_SETTER(FloatArray, std::vector<float>);
97     GENERATE_GETTER_SETTER(DoubleArray, std::vector<double>);
98     GENERATE_GETTER_SETTER(StringArray, std::vector<::android::String16>);
99     GENERATE_GETTER_SETTER(SingleDataParcelableArray, std::vector<SingleDataParcelable>);
100 
setFileDescriptor(unique_fd input)101     Status setFileDescriptor(unique_fd input) {
102         mFd = unique_fd(dup(input));
103         return Status::ok();
104     }
105 
getFileDescriptor(unique_fd * output)106     Status getFileDescriptor(unique_fd* output) {
107         *output = unique_fd(dup(mFd));
108         return Status::ok();
109     }
110     unique_fd mFd;
111 };
112 
retrieveData(borrowed_fd fd)113 std::vector<uint8_t> retrieveData(borrowed_fd fd) {
114     struct stat fdStat;
115     EXPECT_TRUE(fstat(fd.get(), &fdStat) != -1);
116 
117     std::vector<uint8_t> buffer(fdStat.st_size);
118     auto readResult = android::base::ReadFully(fd, buffer.data(), fdStat.st_size);
119     EXPECT_TRUE(readResult != 0);
120     return buffer;
121 }
122 
replayFuzzService(const sp<BpBinder> & binder,const RecordedTransaction & transaction)123 void replayFuzzService(const sp<BpBinder>& binder, const RecordedTransaction& transaction) {
124     unique_fd seedFd(open("/data/local/tmp/replayFuzzService",
125                           O_RDWR | O_CREAT | O_CLOEXEC | O_TRUNC, 0666));
126     ASSERT_TRUE(seedFd.ok());
127 
128     // generate corpus from this transaction.
129     generateSeedsFromRecording(seedFd, transaction);
130 
131     // Read the data which has been written to seed corpus
132     ASSERT_EQ(0, lseek(seedFd.get(), 0, SEEK_SET));
133     std::vector<uint8_t> seedData = retrieveData(seedFd);
134     EXPECT_TRUE(seedData.size() != 0);
135 
136     // use fuzzService to replay the corpus
137     FuzzedDataProvider provider(seedData.data(), seedData.size());
138     fuzzService(binder, std::move(provider));
139 }
140 
replayBinder(const sp<BpBinder> & binder,const RecordedTransaction & transaction)141 void replayBinder(const sp<BpBinder>& binder, const RecordedTransaction& transaction) {
142     // TODO: move logic to replay RecordedTransaction into RecordedTransaction
143     Parcel data;
144     data.setData(transaction.getDataParcel().data(), transaction.getDataParcel().dataSize());
145     auto result = binder->transact(transaction.getCode(), data, nullptr, transaction.getFlags());
146 
147     // make sure recording does the thing we expect it to do
148     EXPECT_EQ(OK, result);
149 }
150 
151 class BinderRecordReplayTest : public ::testing::Test {
152 public:
SetUp()153     void SetUp() override {
154         // get the remote service
155 #pragma clang diagnostic push
156 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
157         auto binder = defaultServiceManager()->getService(kServerName);
158 #pragma clang diagnostic pop
159         ASSERT_NE(nullptr, binder);
160         mInterface = interface_cast<IBinderRecordReplayTest>(binder);
161         mBpBinder = binder->remoteBinder();
162         ASSERT_NE(nullptr, mBpBinder);
163     }
164 
165     template <typename T, typename U>
recordReplay(Status (IBinderRecordReplayTest::* set)(T),U recordedValue,Status (IBinderRecordReplayTest::* get)(U *),U changedValue)166     void recordReplay(Status (IBinderRecordReplayTest::*set)(T), U recordedValue,
167                       Status (IBinderRecordReplayTest::*get)(U*), U changedValue) {
168         using ReplayFunc = decltype(&replayFuzzService);
169         vector<ReplayFunc> replayFunctions = {&replayFuzzService};
170         if (!std::is_same_v<U, unique_fd> && !std::is_same_v<U, sp<IBinder>>) {
171             // Parcel retrieved from record replay doesn't have object information. use it for
172             // replaying primitive types only.
173             replayFunctions.push_back(&replayBinder);
174         }
175 
176         for (auto replayFunc : replayFunctions) {
177             unique_fd fd(open("/data/local/tmp/binderRecordReplayTest.rec",
178                               O_RDWR | O_CREAT | O_CLOEXEC, 0666));
179             ASSERT_TRUE(fd.ok());
180 
181             // record a transaction
182             mBpBinder->startRecordingBinder(fd);
183             auto status = (*mInterface.*set)(std::move(recordedValue));
184             EXPECT_TRUE(status.isOk());
185             mBpBinder->stopRecordingBinder();
186 
187             // test transaction does the thing we expect it to do
188             U output;
189             status = (*mInterface.*get)(&output);
190             EXPECT_TRUE(status.isOk());
191 
192             // Expect this equal only if types are primitives
193             if (!std::is_same_v<U, unique_fd> && !std::is_same_v<U, sp<IBinder>>) {
194                 EXPECT_EQ(output, recordedValue);
195             }
196 
197             // write over the existing state
198             status = (*mInterface.*set)(std::move(changedValue));
199             EXPECT_TRUE(status.isOk());
200 
201             status = (*mInterface.*get)(&output);
202             EXPECT_TRUE(status.isOk());
203 
204             if (!std::is_same_v<U, unique_fd> && !std::is_same_v<U, sp<IBinder>>) {
205                 EXPECT_EQ(output, changedValue);
206             }
207 
208             // replay transaction
209             ASSERT_EQ(0, lseek(fd.get(), 0, SEEK_SET));
210             std::optional<RecordedTransaction> transaction = RecordedTransaction::fromFile(fd);
211             ASSERT_NE(transaction, std::nullopt);
212 
213             const RecordedTransaction& recordedTransaction = *transaction;
214             // call replay function with recorded transaction
215             (*replayFunc)(mBpBinder, recordedTransaction);
216 
217             status = (*mInterface.*get)(&output);
218             EXPECT_TRUE(status.isOk());
219 
220             // FDs and binders will be replaced with random fd and random binders
221             if constexpr (std::is_same_v<U, unique_fd>) {
222                 // verify that replayed fd is /dev/null. This is being replayed from random_fd.cpp
223                 // and choosing /dav/null while generating seed in binder2corpus
224                 std::string fdPath = "/proc/self/fd/" + std::to_string(output.get());
225                 char path[PATH_MAX];
226                 ASSERT_GT(readlink(fdPath.c_str(), path, sizeof(path)), 0);
227                 EXPECT_EQ(strcmp("/dev/null", path), 0);
228             } else if constexpr (std::is_same_v<U, sp<IBinder>>) {
229                 // This is binder is replayed from random_binder.cpp using seed data which writes
230                 // this interface.
231                 EXPECT_EQ(String16(kRandomInterfaceName.c_str(), kRandomInterfaceName.size()),
232                           output->getInterfaceDescriptor());
233             } else {
234                 ASSERT_EQ(recordedValue, output);
235             }
236         }
237     }
238 
239 private:
240     sp<BpBinder> mBpBinder;
241     sp<IBinderRecordReplayTest> mInterface;
242 };
243 
TEST_F(BinderRecordReplayTest,ReplayByte)244 TEST_F(BinderRecordReplayTest, ReplayByte) {
245     recordReplay(&IBinderRecordReplayTest::setByte, int8_t{122}, &IBinderRecordReplayTest::getByte,
246                  int8_t{90});
247 }
248 
TEST_F(BinderRecordReplayTest,ReplayBoolean)249 TEST_F(BinderRecordReplayTest, ReplayBoolean) {
250     recordReplay(&IBinderRecordReplayTest::setBoolean, true, &IBinderRecordReplayTest::getBoolean,
251                  false);
252 }
253 
TEST_F(BinderRecordReplayTest,ReplayChar)254 TEST_F(BinderRecordReplayTest, ReplayChar) {
255     recordReplay(&IBinderRecordReplayTest::setChar, char16_t{'G'},
256                  &IBinderRecordReplayTest::getChar, char16_t{'K'});
257 }
258 
TEST_F(BinderRecordReplayTest,ReplayInt)259 TEST_F(BinderRecordReplayTest, ReplayInt) {
260     recordReplay(&IBinderRecordReplayTest::setInt, 3, &IBinderRecordReplayTest::getInt, 5);
261 }
262 
TEST_F(BinderRecordReplayTest,ReplayFloat)263 TEST_F(BinderRecordReplayTest, ReplayFloat) {
264     recordReplay(&IBinderRecordReplayTest::setFloat, 1.1f, &IBinderRecordReplayTest::getFloat,
265                  22.0f);
266 }
267 
TEST_F(BinderRecordReplayTest,ReplayLong)268 TEST_F(BinderRecordReplayTest, ReplayLong) {
269     recordReplay(&IBinderRecordReplayTest::setLong, int64_t{1LL << 55},
270                  &IBinderRecordReplayTest::getLong, int64_t{1LL << 12});
271 }
272 
TEST_F(BinderRecordReplayTest,ReplayDouble)273 TEST_F(BinderRecordReplayTest, ReplayDouble) {
274     recordReplay(&IBinderRecordReplayTest::setDouble, 0.00, &IBinderRecordReplayTest::getDouble,
275                  1.11);
276 }
277 
TEST_F(BinderRecordReplayTest,ReplayString)278 TEST_F(BinderRecordReplayTest, ReplayString) {
279     const ::android::String16& input1 = String16("This is saved string");
280     const ::android::String16& input2 = String16("This is changed string");
281     recordReplay(&IBinderRecordReplayTest::setString, input1, &IBinderRecordReplayTest::getString,
282                  input2);
283 }
284 
TEST_F(BinderRecordReplayTest,ReplaySingleDataParcelable)285 TEST_F(BinderRecordReplayTest, ReplaySingleDataParcelable) {
286     SingleDataParcelable saved, changed;
287     saved.data = 3;
288     changed.data = 5;
289     recordReplay(&IBinderRecordReplayTest::setSingleDataParcelable, saved,
290                  &IBinderRecordReplayTest::getSingleDataParcelable, changed);
291 }
292 
TEST_F(BinderRecordReplayTest,ReplayByteArray)293 TEST_F(BinderRecordReplayTest, ReplayByteArray) {
294     std::vector<uint8_t> savedArray = {uint8_t{255}, uint8_t{0}, uint8_t{127}};
295     std::vector<uint8_t> changedArray = {uint8_t{2}, uint8_t{7}, uint8_t{117}};
296     recordReplay(&IBinderRecordReplayTest::setByteArray, savedArray,
297                  &IBinderRecordReplayTest::getByteArray, changedArray);
298 }
299 
TEST_F(BinderRecordReplayTest,ReplayBooleanArray)300 TEST_F(BinderRecordReplayTest, ReplayBooleanArray) {
301     std::vector<bool> savedArray = {true, false, true};
302     std::vector<bool> changedArray = {false, true, false};
303     recordReplay(&IBinderRecordReplayTest::setBooleanArray, savedArray,
304                  &IBinderRecordReplayTest::getBooleanArray, changedArray);
305 }
306 
TEST_F(BinderRecordReplayTest,ReplayCharArray)307 TEST_F(BinderRecordReplayTest, ReplayCharArray) {
308     std::vector<char16_t> savedArray = {char16_t{'G'}, char16_t{'L'}, char16_t{'K'}, char16_t{'T'}};
309     std::vector<char16_t> changedArray = {char16_t{'X'}, char16_t{'Y'}, char16_t{'Z'}};
310     recordReplay(&IBinderRecordReplayTest::setCharArray, savedArray,
311                  &IBinderRecordReplayTest::getCharArray, changedArray);
312 }
313 
TEST_F(BinderRecordReplayTest,ReplayIntArray)314 TEST_F(BinderRecordReplayTest, ReplayIntArray) {
315     std::vector<int> savedArray = {12, 45, 178};
316     std::vector<int> changedArray = {32, 14, 78, 1899};
317     recordReplay(&IBinderRecordReplayTest::setIntArray, savedArray,
318                  &IBinderRecordReplayTest::getIntArray, changedArray);
319 }
320 
TEST_F(BinderRecordReplayTest,ReplayFloatArray)321 TEST_F(BinderRecordReplayTest, ReplayFloatArray) {
322     std::vector<float> savedArray = {12.14f, 45.56f, 123.178f};
323     std::vector<float> changedArray = {0.00f, 14.0f, 718.1f, 1899.122f, 3268.123f};
324     recordReplay(&IBinderRecordReplayTest::setFloatArray, savedArray,
325                  &IBinderRecordReplayTest::getFloatArray, changedArray);
326 }
327 
TEST_F(BinderRecordReplayTest,ReplayLongArray)328 TEST_F(BinderRecordReplayTest, ReplayLongArray) {
329     std::vector<int64_t> savedArray = {int64_t{1LL << 11}, int64_t{1LL << 55}, int64_t{1LL << 45}};
330     std::vector<int64_t> changedArray = {int64_t{1LL << 1}, int64_t{1LL << 21}, int64_t{1LL << 33},
331                                          int64_t{1LL << 62}};
332     recordReplay(&IBinderRecordReplayTest::setLongArray, savedArray,
333                  &IBinderRecordReplayTest::getLongArray, changedArray);
334 }
335 
TEST_F(BinderRecordReplayTest,ReplayDoubleArray)336 TEST_F(BinderRecordReplayTest, ReplayDoubleArray) {
337     std::vector<double> savedArray = {12.1412313, 45.561232, 123.1781111};
338     std::vector<double> changedArray = {0.00111, 14.32130, 712312318.19, 1899212.122,
339                                         322168.122123};
340     recordReplay(&IBinderRecordReplayTest::setDoubleArray, savedArray,
341                  &IBinderRecordReplayTest::getDoubleArray, changedArray);
342 }
343 
TEST_F(BinderRecordReplayTest,ReplayStringArray)344 TEST_F(BinderRecordReplayTest, ReplayStringArray) {
345     std::vector<String16> savedArray = {String16("This is saved value"), String16(),
346                                         String16("\0\0", 2), String16("\xF3\x01\xAC\xAD\x21\xAF")};
347 
348     std::vector<String16> changedArray = {String16("This is changed value"),
349                                           String16("\xF0\x90\x90\xB7\xE2\x82\xAC")};
350     recordReplay(&IBinderRecordReplayTest::setStringArray, savedArray,
351                  &IBinderRecordReplayTest::getStringArray, changedArray);
352 }
353 
TEST_F(BinderRecordReplayTest,ReplaySingleDataParcelableArray)354 TEST_F(BinderRecordReplayTest, ReplaySingleDataParcelableArray) {
355     SingleDataParcelable s1, s2, s3, s4, s5;
356     s1.data = 5213;
357     s2.data = 1512;
358     s3.data = 4233;
359     s4.data = 123124;
360     s5.data = 0;
361     std::vector<SingleDataParcelable> saved = {s1, s2, s3};
362     std::vector<SingleDataParcelable> changed = {s4, s5};
363 
364     recordReplay(&IBinderRecordReplayTest::setSingleDataParcelableArray, saved,
365                  &IBinderRecordReplayTest::getSingleDataParcelableArray, changed);
366 }
367 
TEST_F(BinderRecordReplayTest,ReplayBinder)368 TEST_F(BinderRecordReplayTest, ReplayBinder) {
369     vector<uint8_t> data = {0x8A, 0x19, 0x0D, 0x44, 0x37, 0x0D, 0x38, 0x5E, 0x9B, 0xAA, 0xF3, 0xDA};
370     sp<IBinder> saved = new RandomBinder(String16("random_interface"), std::move(data));
371     sp<IBinder> changed = IInterface::asBinder(defaultServiceManager());
372     recordReplay(&IBinderRecordReplayTest::setBinder, saved, &IBinderRecordReplayTest::getBinder,
373                  changed);
374 }
375 
TEST_F(BinderRecordReplayTest,ReplayFd)376 TEST_F(BinderRecordReplayTest, ReplayFd) {
377     // Write something to both fds we are setting
378     unique_fd saved(open("/data/local/tmp/test_fd", O_RDWR | O_CREAT | O_CLOEXEC, 0666));
379     std::string contentSaved = "This will be never read again for recorded fd!";
380     CHECK(android::base::WriteFully(saved, contentSaved.data(), contentSaved.size()))
381             << saved.get();
382 
383     unique_fd changed(open("/data/local/tmp/test_des", O_RDWR | O_CREAT | O_CLOEXEC, 0666));
384     std::string contentChanged = "This will be never read again from changed fd!";
385     CHECK(android::base::WriteFully(changed, contentChanged.data(), contentChanged.size()))
386             << changed.get();
387 
388     // When fds are replayed, it will be replaced by /dev/null..reading from it should yield
389     // null data
390     recordReplay(&IBinderRecordReplayTest::setFileDescriptor, unique_fd(dup(saved)),
391                  &IBinderRecordReplayTest::getFileDescriptor, unique_fd(dup(changed)));
392 }
393 
main(int argc,char ** argv)394 int main(int argc, char** argv) {
395     ::testing::InitGoogleTest(&argc, argv);
396 
397     if (fork() == 0) {
398         prctl(PR_SET_PDEATHSIG, SIGHUP);
399 
400         auto server = sp<MyRecordReplay>::make();
401         android::defaultServiceManager()->addService(kServerName, server.get());
402 
403         IPCThreadState::self()->joinThreadPool(true);
404         exit(1); // should not reach
405     }
406 
407     // not racey, but getService sleeps for 1s
408     usleep(100000);
409 
410     return RUN_ALL_TESTS();
411 }
412