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 "../../FileUtils.h"
18
19 #include <android-base/logging.h>
20 #include <binder/RecordedTransaction.h>
21 #include <binder/unique_fd.h>
22
23 #include <fuzzseeds/random_parcel_seeds.h>
24
25 #include <sys/prctl.h>
26 #include <sys/stat.h>
27
28 using android::generateSeedsFromRecording;
29 using android::status_t;
30 using android::binder::unique_fd;
31 using android::binder::debug::RecordedTransaction;
32
generateCorpus(const char * recordingPath,const char * corpusDir)33 status_t generateCorpus(const char* recordingPath, const char* corpusDir) {
34 unique_fd fd(open(recordingPath, O_RDONLY));
35 if (!fd.ok()) {
36 std::cerr << "Failed to open recording file at path " << recordingPath
37 << " with error: " << strerror(errno) << '\n';
38 return android::BAD_VALUE;
39 }
40
41 if (auto res = mkdir(corpusDir, 0766); res != 0) {
42 std::cerr
43 << "Failed to create corpus directory at path. Delete directory if already exists: "
44 << corpusDir << std::endl;
45 return android::BAD_VALUE;
46 }
47
48 int transactionNumber = 0;
49 while (auto transaction = RecordedTransaction::fromFile(fd)) {
50 ++transactionNumber;
51 std::string filePath = std::string(corpusDir) + std::string("transaction_") +
52 std::to_string(transactionNumber);
53 constexpr int openFlags = O_WRONLY | O_CREAT | O_BINARY | O_CLOEXEC;
54 unique_fd corpusFd(open(filePath.c_str(), openFlags, 0666));
55 if (!corpusFd.ok()) {
56 std::cerr << "Failed to open fd. Path " << filePath
57 << " with error: " << strerror(errno) << std::endl;
58 return android::UNKNOWN_ERROR;
59 }
60 generateSeedsFromRecording(corpusFd, transaction.value());
61 }
62
63 if (transactionNumber == 0) {
64 std::cerr << "No valid transaction has been found in recording file: " << recordingPath
65 << std::endl;
66 return android::BAD_VALUE;
67 }
68
69 return android::NO_ERROR;
70 }
71
printHelp(const char * toolName)72 void printHelp(const char* toolName) {
73 std::cout << "Usage: \n\n"
74 << toolName
75 << " <recording_path> <destination_directory> \n\n*Use "
76 "record_binder tool for recording binder transactions."
77 << std::endl;
78 }
79
main(int argc,char ** argv)80 int main(int argc, char** argv) {
81 if (argc != 3) {
82 printHelp(argv[0]);
83 return 1;
84 }
85 const char* sourcePath = argv[1];
86 const char* corpusDir = argv[2];
87 if (android::NO_ERROR != generateCorpus(sourcePath, corpusDir)) {
88 std::cerr << "Failed to generate fuzzer corpus." << std::endl;
89 return 1;
90 }
91 return 0;
92 }
93