2424#include < binder/RecordedTransaction.h>
2525#include < binder/unique_fd.h>
2626
27+ #include < cutils/ashmem.h>
28+
2729#include < fuzzbinder/libbinder_driver.h>
30+ #include < fuzzbinder/random_binder.h>
2831#include < fuzzer/FuzzedDataProvider.h>
2932#include < fuzzseeds/random_parcel_seeds.h>
3033
3740
3841using namespace android ;
3942using android::generateSeedsFromRecording;
43+ using android::RandomBinder;
4044using android::binder::borrowed_fd;
4145using android::binder::Status;
4246using android::binder::unique_fd;
4347using android::binder::debug::RecordedTransaction;
4448using parcelables::SingleDataParcelable;
4549
4650const String16 kServerName = String16(" binderRecordReplay" );
51+ extern std::string kRandomInterfaceName ;
4752
4853#define GENERATE_GETTER_SETTER_PRIMITIVE (name, T ) \
4954 Status set##name(T input) { \
@@ -81,6 +86,7 @@ class MyRecordReplay : public BnBinderRecordReplayTest {
8186
8287 GENERATE_GETTER_SETTER (String, String16);
8388 GENERATE_GETTER_SETTER (SingleDataParcelable, SingleDataParcelable);
89+ GENERATE_GETTER_SETTER (Binder, sp<IBinder>);
8490
8591 GENERATE_GETTER_SETTER (BooleanArray, std::vector<bool >);
8692 GENERATE_GETTER_SETTER (ByteArray, std::vector<uint8_t >);
@@ -91,12 +97,22 @@ class MyRecordReplay : public BnBinderRecordReplayTest {
9197 GENERATE_GETTER_SETTER (DoubleArray, std::vector<double >);
9298 GENERATE_GETTER_SETTER (StringArray, std::vector<::android::String16>);
9399 GENERATE_GETTER_SETTER (SingleDataParcelableArray, std::vector<SingleDataParcelable>);
100+
101+ Status setFileDescriptor (unique_fd input) {
102+ mFd = std::move (unique_fd (dup (input)));
103+ return Status::ok ();
104+ }
105+
106+ Status getFileDescriptor (unique_fd* output) {
107+ *output = std::move (unique_fd (dup (mFd )));
108+ return Status::ok ();
109+ }
110+ unique_fd mFd ;
94111};
95112
96113std::vector<uint8_t > retrieveData (borrowed_fd fd) {
97114 struct stat fdStat;
98115 EXPECT_TRUE (fstat (fd.get (), &fdStat) != -1 );
99- EXPECT_TRUE (fdStat.st_size != 0 );
100116
101117 std::vector<uint8_t > buffer (fdStat.st_size );
102118 auto readResult = android::base::ReadFully (fd, buffer.data (), fdStat.st_size );
@@ -115,6 +131,7 @@ void replayFuzzService(const sp<BpBinder>& binder, const RecordedTransaction& tr
115131 // Read the data which has been written to seed corpus
116132 ASSERT_EQ (0 , lseek (seedFd.get (), 0 , SEEK_SET));
117133 std::vector<uint8_t > seedData = retrieveData (seedFd);
134+ EXPECT_TRUE (seedData.size () != 0 );
118135
119136 // use fuzzService to replay the corpus
120137 FuzzedDataProvider provider (seedData.data (), seedData.size ());
@@ -148,32 +165,45 @@ class BinderRecordReplayTest : public ::testing::Test {
148165 template <typename T, typename U>
149166 void recordReplay (Status (IBinderRecordReplayTest::*set)(T), U recordedValue,
150167 Status (IBinderRecordReplayTest::*get)(U*), U changedValue) {
151- auto replayFunctions = {&replayBinder, &replayFuzzService};
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+
152176 for (auto replayFunc : replayFunctions) {
153177 unique_fd fd (open (" /data/local/tmp/binderRecordReplayTest.rec" ,
154178 O_RDWR | O_CREAT | O_CLOEXEC, 0666 ));
155179 ASSERT_TRUE (fd.ok ());
156180
157181 // record a transaction
158182 mBpBinder ->startRecordingBinder (fd);
159- auto status = (*mInterface .*set)(recordedValue);
183+ auto status = (*mInterface .*set)(std::move ( recordedValue) );
160184 EXPECT_TRUE (status.isOk ());
161185 mBpBinder ->stopRecordingBinder ();
162186
163187 // test transaction does the thing we expect it to do
164188 U output;
165189 status = (*mInterface .*get)(&output);
166190 EXPECT_TRUE (status.isOk ());
167- EXPECT_EQ (output, recordedValue);
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+ }
168196
169197 // write over the existing state
170- status = (*mInterface .*set)(changedValue);
198+ status = (*mInterface .*set)(std::move ( changedValue) );
171199 EXPECT_TRUE (status.isOk ());
172200
173201 status = (*mInterface .*get)(&output);
174202 EXPECT_TRUE (status.isOk ());
175203
176- EXPECT_EQ (output, changedValue);
204+ if (!std::is_same_v<U, unique_fd> && !std::is_same_v<U, sp<IBinder>>) {
205+ EXPECT_EQ (output, changedValue);
206+ }
177207
178208 // replay transaction
179209 ASSERT_EQ (0 , lseek (fd.get (), 0 , SEEK_SET));
@@ -186,7 +216,23 @@ class BinderRecordReplayTest : public ::testing::Test {
186216
187217 status = (*mInterface .*get)(&output);
188218 EXPECT_TRUE (status.isOk ());
189- EXPECT_EQ (output, recordedValue);
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+ }
190236 }
191237 }
192238
@@ -319,6 +365,32 @@ TEST_F(BinderRecordReplayTest, ReplaySingleDataParcelableArray) {
319365 &IBinderRecordReplayTest::getSingleDataParcelableArray, changed);
320366}
321367
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+
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, std::move (unique_fd (dup (saved))),
391+ &IBinderRecordReplayTest::getFileDescriptor, std::move (unique_fd (dup (changed))));
392+ }
393+
322394int main (int argc, char ** argv) {
323395 ::testing::InitGoogleTest (&argc, argv);
324396
0 commit comments