• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
43   // Memory maps the package file if necessary. Initializes the start address and size of the
44   // package.
GetPackageSize() const45   uint64_t GetPackageSize() const override {
46     return package_size_;
47   }
48 
49   bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override;
50 
51   ZipArchiveHandle GetZipArchiveHandle() override;
52 
53   bool UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers, uint64_t start,
54                           uint64_t length) override;
55 
56  private:
57   const uint8_t* addr_;    // Start address of the package in memory.
58   uint64_t package_size_;  // Package size in bytes.
59 
60   // The memory mapped package.
61   std::unique_ptr<MemMapping> map_;
62   // A copy of the package content, valid only if we create the class with the exact bytes of
63   // the package.
64   std::vector<uint8_t> package_content_;
65   // The physical path to the package, empty if we create the class with the package content.
66   std::string path_;
67 
68   // The ZipArchiveHandle of the package.
69   ZipArchiveHandle zip_handle_;
70 };
71 
SetProgress(float progress)72 void Package::SetProgress(float progress) {
73   if (set_progress_) {
74     set_progress_(progress);
75   }
76 }
77 
78 class FilePackage : public Package {
79  public:
80   FilePackage(android::base::unique_fd&& fd, uint64_t file_size, const std::string& path,
81               const std::function<void(float)>& set_progress);
82 
83   ~FilePackage() override;
84 
GetPackageSize() const85   uint64_t GetPackageSize() const override {
86     return package_size_;
87   }
88 
89   bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override;
90 
91   ZipArchiveHandle GetZipArchiveHandle() override;
92 
93   bool UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers, uint64_t start,
94                           uint64_t length) override;
95 
96  private:
97   android::base::unique_fd fd_;  // The underlying fd to the open package.
98   uint64_t package_size_;
99   std::string path_;  // The physical path to the package.
100 
101   ZipArchiveHandle zip_handle_;
102 };
103 
CreateMemoryPackage(const std::string & path,const std::function<void (float)> & set_progress)104 std::unique_ptr<Package> Package::CreateMemoryPackage(
105     const std::string& path, const std::function<void(float)>& set_progress) {
106   std::unique_ptr<MemMapping> mmap = std::make_unique<MemMapping>();
107   if (!mmap->MapFile(path)) {
108     LOG(ERROR) << "failed to map file";
109     return nullptr;
110   }
111 
112   return std::make_unique<MemoryPackage>(path, std::move(mmap), set_progress);
113 }
114 
CreateFilePackage(const std::string & path,const std::function<void (float)> & set_progress)115 std::unique_ptr<Package> Package::CreateFilePackage(
116     const std::string& path, const std::function<void(float)>& set_progress) {
117   android::base::unique_fd fd(open(path.c_str(), O_RDONLY));
118   if (fd == -1) {
119     PLOG(ERROR) << "Failed to open " << path;
120     return nullptr;
121   }
122 
123   off64_t file_size = lseek64(fd.get(), 0, SEEK_END);
124   if (file_size == -1) {
125     PLOG(ERROR) << "Failed to get the package size";
126     return nullptr;
127   }
128 
129   return std::make_unique<FilePackage>(std::move(fd), file_size, path, set_progress);
130 }
131 
CreateMemoryPackage(std::vector<uint8_t> content,const std::function<void (float)> & set_progress)132 std::unique_ptr<Package> Package::CreateMemoryPackage(
133     std::vector<uint8_t> content, const std::function<void(float)>& set_progress) {
134   return std::make_unique<MemoryPackage>(std::move(content), set_progress);
135 }
136 
MemoryPackage(const std::string & path,std::unique_ptr<MemMapping> map,const std::function<void (float)> & set_progress)137 MemoryPackage::MemoryPackage(const std::string& path, std::unique_ptr<MemMapping> map,
138                              const std::function<void(float)>& set_progress)
139     : map_(std::move(map)), path_(path), zip_handle_(nullptr) {
140   addr_ = map_->addr;
141   package_size_ = map_->length;
142   set_progress_ = set_progress;
143 }
144 
MemoryPackage(std::vector<uint8_t> content,const std::function<void (float)> & set_progress)145 MemoryPackage::MemoryPackage(std::vector<uint8_t> content,
146                              const std::function<void(float)>& set_progress)
147     : package_content_(std::move(content)), zip_handle_(nullptr) {
148   CHECK(!package_content_.empty());
149   addr_ = package_content_.data();
150   package_size_ = package_content_.size();
151   set_progress_ = set_progress;
152 }
153 
~MemoryPackage()154 MemoryPackage::~MemoryPackage() {
155   if (zip_handle_) {
156     CloseArchive(zip_handle_);
157   }
158 }
159 
ReadFullyAtOffset(uint8_t * buffer,uint64_t byte_count,uint64_t offset)160 bool MemoryPackage::ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) {
161   if (byte_count > package_size_ || offset > package_size_ - byte_count) {
162     LOG(ERROR) << "Out of bound read, offset: " << offset << ", size: " << byte_count
163                << ", total package_size: " << package_size_;
164     return false;
165   }
166   memcpy(buffer, addr_ + offset, byte_count);
167   return true;
168 }
169 
UpdateHashAtOffset(const std::vector<HasherUpdateCallback> & hashers,uint64_t start,uint64_t length)170 bool MemoryPackage::UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers,
171                                        uint64_t start, uint64_t length) {
172   if (length > package_size_ || start > package_size_ - length) {
173     LOG(ERROR) << "Out of bound read, offset: " << start << ", size: " << length
174                << ", total package_size: " << package_size_;
175     return false;
176   }
177 
178   for (const auto& hasher : hashers) {
179     hasher(addr_ + start, length);
180   }
181   return true;
182 }
183 
GetZipArchiveHandle()184 ZipArchiveHandle MemoryPackage::GetZipArchiveHandle() {
185   if (zip_handle_) {
186     return zip_handle_;
187   }
188 
189   if (auto err = OpenArchiveFromMemory(const_cast<uint8_t*>(addr_), package_size_, path_.c_str(),
190                                        &zip_handle_);
191       err != 0) {
192     LOG(ERROR) << "Can't open package" << path_ << " : " << ErrorCodeString(err);
193     return nullptr;
194   }
195 
196   return zip_handle_;
197 }
198 
FilePackage(android::base::unique_fd && fd,uint64_t file_size,const std::string & path,const std::function<void (float)> & set_progress)199 FilePackage::FilePackage(android::base::unique_fd&& fd, uint64_t file_size, const std::string& path,
200                          const std::function<void(float)>& set_progress)
201     : fd_(std::move(fd)), package_size_(file_size), path_(path), zip_handle_(nullptr) {
202   set_progress_ = set_progress;
203 }
204 
~FilePackage()205 FilePackage::~FilePackage() {
206   if (zip_handle_) {
207     CloseArchive(zip_handle_);
208   }
209 }
210 
ReadFullyAtOffset(uint8_t * buffer,uint64_t byte_count,uint64_t offset)211 bool FilePackage::ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) {
212   if (byte_count > package_size_ || offset > package_size_ - byte_count) {
213     LOG(ERROR) << "Out of bound read, offset: " << offset << ", size: " << byte_count
214                << ", total package_size: " << package_size_;
215     return false;
216   }
217 
218   if (!android::base::ReadFullyAtOffset(fd_.get(), buffer, byte_count, offset)) {
219     PLOG(ERROR) << "Failed to read " << byte_count << " bytes data at offset " << offset;
220     return false;
221   }
222 
223   return true;
224 }
225 
UpdateHashAtOffset(const std::vector<HasherUpdateCallback> & hashers,uint64_t start,uint64_t length)226 bool FilePackage::UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers,
227                                      uint64_t start, uint64_t length) {
228   if (length > package_size_ || start > package_size_ - length) {
229     LOG(ERROR) << "Out of bound read, offset: " << start << ", size: " << length
230                << ", total package_size: " << package_size_;
231     return false;
232   }
233 
234   uint64_t so_far = 0;
235   while (so_far < length) {
236     uint64_t read_size = std::min<uint64_t>(length - so_far, 16 * MiB);
237     std::vector<uint8_t> buffer(read_size);
238     if (!ReadFullyAtOffset(buffer.data(), read_size, start + so_far)) {
239       return false;
240     }
241 
242     for (const auto& hasher : hashers) {
243       hasher(buffer.data(), read_size);
244     }
245     so_far += read_size;
246   }
247 
248   return true;
249 }
250 
GetZipArchiveHandle()251 ZipArchiveHandle FilePackage::GetZipArchiveHandle() {
252   if (zip_handle_) {
253     return zip_handle_;
254   }
255 
256   if (auto err = OpenArchiveFd(fd_.get(), path_.c_str(), &zip_handle_); err != 0) {
257     LOG(ERROR) << "Can't open package" << path_ << " : " << ErrorCodeString(err);
258     return nullptr;
259   }
260 
261   return zip_handle_;
262 }
263