1 /*
2  * Copyright (C) 2019 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 "install/package.h"
18 
19 #include <string.h>
20 #include <unistd.h>
21 
22 #include <android-base/file.h>
23 #include <android-base/logging.h>
24 #include <android-base/stringprintf.h>
25 #include <android-base/unique_fd.h>
26 
27 #include "otautil/error_code.h"
28 #include "otautil/sysutil.h"
29 
30 // This class wraps the package in memory, i.e. a memory mapped package, or a package loaded
31 // to a string/vector.
32 class MemoryPackage : public Package {
33  public:
34   // Constructs the class from a file. We will memory maps the file later.
35   MemoryPackage(const std::string& path, std::unique_ptr<MemMapping> map,
36                 const std::function<void(float)>& set_progress);
37 
38   // Constructs the class from the package bytes in |content|.
39   MemoryPackage(std::vector<uint8_t> content, const std::function<void(float)>& set_progress);
40 
41   ~MemoryPackage() override;
42 
GetType() const43   PackageType GetType() const override {
44     return PackageType::kMemory;
45   }
46 
47   // Memory maps the package file if necessary. Initializes the start address and size of the
48   // package.
GetPackageSize() const49   uint64_t GetPackageSize() const override {
50     return package_size_;
51   }
52 
GetPath() const53   std::string GetPath() const override {
54     return path_;
55   }
56 
57   bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override;
58 
59   ZipArchiveHandle GetZipArchiveHandle() override;
60 
61   bool UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers, uint64_t start,
62                           uint64_t length) override;
63 
64  private:
65   const uint8_t* addr_;    // Start address of the package in memory.
66   uint64_t package_size_;  // Package size in bytes.
67 
68   // The memory mapped package.
69   std::unique_ptr<MemMapping> map_;
70   // A copy of the package content, valid only if we create the class with the exact bytes of
71   // the package.
72   std::vector<uint8_t> package_content_;
73   // The physical path to the package, empty if we create the class with the package content.
74   std::string path_;
75 
76   // The ZipArchiveHandle of the package.
77   ZipArchiveHandle zip_handle_;
78 };
79 
SetProgress(float progress)80 void Package::SetProgress(float progress) {
81   if (set_progress_) {
82     set_progress_(progress);
83   }
84 }
85 
86 class FilePackage : public Package {
87  public:
88   FilePackage(android::base::unique_fd&& fd, uint64_t file_size, const std::string& path,
89               const std::function<void(float)>& set_progress);
90 
91   ~FilePackage() override;
92 
GetType() const93   PackageType GetType() const override {
94     return PackageType::kFile;
95   }
96 
GetPackageSize() const97   uint64_t GetPackageSize() const override {
98     return package_size_;
99   }
100 
GetPath() const101   std::string GetPath() const override {
102     return path_;
103   }
104 
105   bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override;
106 
107   ZipArchiveHandle GetZipArchiveHandle() override;
108 
109   bool UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers, uint64_t start,
110                           uint64_t length) override;
111 
112  private:
113   android::base::unique_fd fd_;  // The underlying fd to the open package.
114   uint64_t package_size_;
115   std::string path_;  // The physical path to the package.
116 
117   ZipArchiveHandle zip_handle_;
118 };
119 
CreateMemoryPackage(const std::string & path,const std::function<void (float)> & set_progress)120 std::unique_ptr<Package> Package::CreateMemoryPackage(
121     const std::string& path, const std::function<void(float)>& set_progress) {
122   std::unique_ptr<MemMapping> mmap = std::make_unique<MemMapping>();
123   if (!mmap->MapFile(path)) {
124     LOG(ERROR) << "failed to map file";
125     return nullptr;
126   }
127 
128   return std::make_unique<MemoryPackage>(path, std::move(mmap), set_progress);
129 }
130 
CreateFilePackage(const std::string & path,const std::function<void (float)> & set_progress)131 std::unique_ptr<Package> Package::CreateFilePackage(
132     const std::string& path, const std::function<void(float)>& set_progress) {
133   android::base::unique_fd fd(open(path.c_str(), O_RDONLY));
134   if (fd == -1) {
135     PLOG(ERROR) << "Failed to open " << path;
136     return nullptr;
137   }
138 
139   off64_t file_size = lseek64(fd.get(), 0, SEEK_END);
140   if (file_size == -1) {
141     PLOG(ERROR) << "Failed to get the package size";
142     return nullptr;
143   }
144 
145   return std::make_unique<FilePackage>(std::move(fd), file_size, path, set_progress);
146 }
147 
CreateMemoryPackage(std::vector<uint8_t> content,const std::function<void (float)> & set_progress)148 std::unique_ptr<Package> Package::CreateMemoryPackage(
149     std::vector<uint8_t> content, const std::function<void(float)>& set_progress) {
150   return std::make_unique<MemoryPackage>(std::move(content), set_progress);
151 }
152 
MemoryPackage(const std::string & path,std::unique_ptr<MemMapping> map,const std::function<void (float)> & set_progress)153 MemoryPackage::MemoryPackage(const std::string& path, std::unique_ptr<MemMapping> map,
154                              const std::function<void(float)>& set_progress)
155     : map_(std::move(map)), path_(path), zip_handle_(nullptr) {
156   addr_ = map_->addr;
157   package_size_ = map_->length;
158   set_progress_ = set_progress;
159 }
160 
MemoryPackage(std::vector<uint8_t> content,const std::function<void (float)> & set_progress)161 MemoryPackage::MemoryPackage(std::vector<uint8_t> content,
162                              const std::function<void(float)>& set_progress)
163     : package_content_(std::move(content)), zip_handle_(nullptr) {
164   CHECK(!package_content_.empty());
165   addr_ = package_content_.data();
166   package_size_ = package_content_.size();
167   set_progress_ = set_progress;
168 }
169 
~MemoryPackage()170 MemoryPackage::~MemoryPackage() {
171   if (zip_handle_) {
172     CloseArchive(zip_handle_);
173   }
174 }
175 
ReadFullyAtOffset(uint8_t * buffer,uint64_t byte_count,uint64_t offset)176 bool MemoryPackage::ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) {
177   if (byte_count > package_size_ || offset > package_size_ - byte_count) {
178     LOG(ERROR) << "Out of bound read, offset: " << offset << ", size: " << byte_count
179                << ", total package_size: " << package_size_;
180     return false;
181   }
182   memcpy(buffer, addr_ + offset, byte_count);
183   return true;
184 }
185 
UpdateHashAtOffset(const std::vector<HasherUpdateCallback> & hashers,uint64_t start,uint64_t length)186 bool MemoryPackage::UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers,
187                                        uint64_t start, uint64_t length) {
188   if (length > package_size_ || start > package_size_ - length) {
189     LOG(ERROR) << "Out of bound read, offset: " << start << ", size: " << length
190                << ", total package_size: " << package_size_;
191     return false;
192   }
193 
194   for (const auto& hasher : hashers) {
195     hasher(addr_ + start, length);
196   }
197   return true;
198 }
199 
GetZipArchiveHandle()200 ZipArchiveHandle MemoryPackage::GetZipArchiveHandle() {
201   if (zip_handle_) {
202     return zip_handle_;
203   }
204 
205   if (auto err = OpenArchiveFromMemory(const_cast<uint8_t*>(addr_), package_size_, path_.c_str(),
206                                        &zip_handle_);
207       err != 0) {
208     LOG(ERROR) << "Can't open package" << path_ << " : " << ErrorCodeString(err);
209     return nullptr;
210   }
211 
212   return zip_handle_;
213 }
214 
FilePackage(android::base::unique_fd && fd,uint64_t file_size,const std::string & path,const std::function<void (float)> & set_progress)215 FilePackage::FilePackage(android::base::unique_fd&& fd, uint64_t file_size, const std::string& path,
216                          const std::function<void(float)>& set_progress)
217     : fd_(std::move(fd)), package_size_(file_size), path_(path), zip_handle_(nullptr) {
218   set_progress_ = set_progress;
219 }
220 
~FilePackage()221 FilePackage::~FilePackage() {
222   if (zip_handle_) {
223     CloseArchive(zip_handle_);
224   }
225 }
226 
ReadFullyAtOffset(uint8_t * buffer,uint64_t byte_count,uint64_t offset)227 bool FilePackage::ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) {
228   if (byte_count > package_size_ || offset > package_size_ - byte_count) {
229     LOG(ERROR) << "Out of bound read, offset: " << offset << ", size: " << byte_count
230                << ", total package_size: " << package_size_;
231     return false;
232   }
233 
234   if (!android::base::ReadFullyAtOffset(fd_.get(), buffer, byte_count, offset)) {
235     PLOG(ERROR) << "Failed to read " << byte_count << " bytes data at offset " << offset;
236     return false;
237   }
238 
239   return true;
240 }
241 
UpdateHashAtOffset(const std::vector<HasherUpdateCallback> & hashers,uint64_t start,uint64_t length)242 bool FilePackage::UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers,
243                                      uint64_t start, uint64_t length) {
244   if (length > package_size_ || start > package_size_ - length) {
245     LOG(ERROR) << "Out of bound read, offset: " << start << ", size: " << length
246                << ", total package_size: " << package_size_;
247     return false;
248   }
249 
250   uint64_t so_far = 0;
251   while (so_far < length) {
252     uint64_t read_size = std::min<uint64_t>(length - so_far, 16 * MiB);
253     std::vector<uint8_t> buffer(read_size);
254     if (!ReadFullyAtOffset(buffer.data(), read_size, start + so_far)) {
255       return false;
256     }
257 
258     for (const auto& hasher : hashers) {
259       hasher(buffer.data(), read_size);
260     }
261     so_far += read_size;
262   }
263 
264   return true;
265 }
266 
GetZipArchiveHandle()267 ZipArchiveHandle FilePackage::GetZipArchiveHandle() {
268   if (zip_handle_) {
269     return zip_handle_;
270   }
271 
272   if (auto err = OpenArchiveFd(fd_.get(), path_.c_str(), &zip_handle_, false); err != 0) {
273     LOG(ERROR) << "Can't open package" << path_ << " : " << ErrorCodeString(err);
274     return nullptr;
275   }
276 
277   return zip_handle_;
278 }
279