• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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