• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 agree 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 <stdio.h>
18 #include <sys/stat.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21 
22 #include <algorithm>
23 #include <string>
24 #include <vector>
25 
26 #include <android-base/file.h>
27 #include <android-base/properties.h>
28 #include <android-base/strings.h>
29 #include <android-base/test_utils.h>
30 #include <gtest/gtest.h>
31 #include <vintf/VintfObjectRecovery.h>
32 #include <ziparchive/zip_archive.h>
33 #include <ziparchive/zip_writer.h>
34 
35 #include "install.h"
36 #include "private/install.h"
37 
TEST(InstallTest,verify_package_compatibility_no_entry)38 TEST(InstallTest, verify_package_compatibility_no_entry) {
39   TemporaryFile temp_file;
40   FILE* zip_file = fdopen(temp_file.release(), "w");
41   ZipWriter writer(zip_file);
42   // The archive must have something to be opened correctly.
43   ASSERT_EQ(0, writer.StartEntry("dummy_entry", 0));
44   ASSERT_EQ(0, writer.FinishEntry());
45   ASSERT_EQ(0, writer.Finish());
46   ASSERT_EQ(0, fclose(zip_file));
47 
48   // Doesn't contain compatibility zip entry.
49   ZipArchiveHandle zip;
50   ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
51   ASSERT_TRUE(verify_package_compatibility(zip));
52   CloseArchive(zip);
53 }
54 
TEST(InstallTest,verify_package_compatibility_invalid_entry)55 TEST(InstallTest, verify_package_compatibility_invalid_entry) {
56   TemporaryFile temp_file;
57   FILE* zip_file = fdopen(temp_file.release(), "w");
58   ZipWriter writer(zip_file);
59   ASSERT_EQ(0, writer.StartEntry("compatibility.zip", 0));
60   ASSERT_EQ(0, writer.FinishEntry());
61   ASSERT_EQ(0, writer.Finish());
62   ASSERT_EQ(0, fclose(zip_file));
63 
64   // Empty compatibility zip entry.
65   ZipArchiveHandle zip;
66   ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
67   ASSERT_FALSE(verify_package_compatibility(zip));
68   CloseArchive(zip);
69 }
70 
TEST(InstallTest,read_metadata_from_package_smoke)71 TEST(InstallTest, read_metadata_from_package_smoke) {
72   TemporaryFile temp_file;
73   FILE* zip_file = fdopen(temp_file.release(), "w");
74   ZipWriter writer(zip_file);
75   ASSERT_EQ(0, writer.StartEntry("META-INF/com/android/metadata", kCompressStored));
76   const std::string content("abcdefg");
77   ASSERT_EQ(0, writer.WriteBytes(content.data(), content.size()));
78   ASSERT_EQ(0, writer.FinishEntry());
79   ASSERT_EQ(0, writer.Finish());
80   ASSERT_EQ(0, fclose(zip_file));
81 
82   ZipArchiveHandle zip;
83   ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
84   std::string metadata;
85   ASSERT_TRUE(read_metadata_from_package(zip, &metadata));
86   ASSERT_EQ(content, metadata);
87   CloseArchive(zip);
88 
89   TemporaryFile temp_file2;
90   FILE* zip_file2 = fdopen(temp_file2.release(), "w");
91   ZipWriter writer2(zip_file2);
92   ASSERT_EQ(0, writer2.StartEntry("META-INF/com/android/metadata", kCompressDeflated));
93   ASSERT_EQ(0, writer2.WriteBytes(content.data(), content.size()));
94   ASSERT_EQ(0, writer2.FinishEntry());
95   ASSERT_EQ(0, writer2.Finish());
96   ASSERT_EQ(0, fclose(zip_file2));
97 
98   ASSERT_EQ(0, OpenArchive(temp_file2.path, &zip));
99   metadata.clear();
100   ASSERT_TRUE(read_metadata_from_package(zip, &metadata));
101   ASSERT_EQ(content, metadata);
102   CloseArchive(zip);
103 }
104 
TEST(InstallTest,read_metadata_from_package_no_entry)105 TEST(InstallTest, read_metadata_from_package_no_entry) {
106   TemporaryFile temp_file;
107   FILE* zip_file = fdopen(temp_file.release(), "w");
108   ZipWriter writer(zip_file);
109   ASSERT_EQ(0, writer.StartEntry("dummy_entry", kCompressStored));
110   ASSERT_EQ(0, writer.FinishEntry());
111   ASSERT_EQ(0, writer.Finish());
112   ASSERT_EQ(0, fclose(zip_file));
113 
114   ZipArchiveHandle zip;
115   ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
116   std::string metadata;
117   ASSERT_FALSE(read_metadata_from_package(zip, &metadata));
118   CloseArchive(zip);
119 }
120 
TEST(InstallTest,verify_package_compatibility_with_libvintf_malformed_xml)121 TEST(InstallTest, verify_package_compatibility_with_libvintf_malformed_xml) {
122   TemporaryFile compatibility_zip_file;
123   FILE* compatibility_zip = fdopen(compatibility_zip_file.release(), "w");
124   ZipWriter compatibility_zip_writer(compatibility_zip);
125   ASSERT_EQ(0, compatibility_zip_writer.StartEntry("system_manifest.xml", kCompressDeflated));
126   std::string malformed_xml = "malformed";
127   ASSERT_EQ(0, compatibility_zip_writer.WriteBytes(malformed_xml.data(), malformed_xml.size()));
128   ASSERT_EQ(0, compatibility_zip_writer.FinishEntry());
129   ASSERT_EQ(0, compatibility_zip_writer.Finish());
130   ASSERT_EQ(0, fclose(compatibility_zip));
131 
132   TemporaryFile temp_file;
133   FILE* zip_file = fdopen(temp_file.release(), "w");
134   ZipWriter writer(zip_file);
135   ASSERT_EQ(0, writer.StartEntry("compatibility.zip", kCompressStored));
136   std::string compatibility_zip_content;
137   ASSERT_TRUE(
138       android::base::ReadFileToString(compatibility_zip_file.path, &compatibility_zip_content));
139   ASSERT_EQ(0,
140             writer.WriteBytes(compatibility_zip_content.data(), compatibility_zip_content.size()));
141   ASSERT_EQ(0, writer.FinishEntry());
142   ASSERT_EQ(0, writer.Finish());
143   ASSERT_EQ(0, fclose(zip_file));
144 
145   ZipArchiveHandle zip;
146   ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
147   std::vector<std::string> compatibility_info;
148   compatibility_info.push_back(malformed_xml);
149   // Malformed compatibility zip is expected to be rejected by libvintf. But we defer that to
150   // libvintf.
151   std::string err;
152   bool result =
153       android::vintf::VintfObjectRecovery::CheckCompatibility(compatibility_info, &err) == 0;
154   ASSERT_EQ(result, verify_package_compatibility(zip));
155   CloseArchive(zip);
156 }
157 
TEST(InstallTest,verify_package_compatibility_with_libvintf_system_manifest_xml)158 TEST(InstallTest, verify_package_compatibility_with_libvintf_system_manifest_xml) {
159   static constexpr const char* system_manifest_xml_path = "/system/manifest.xml";
160   if (access(system_manifest_xml_path, R_OK) == -1) {
161     GTEST_LOG_(INFO) << "Test skipped on devices w/o /system/manifest.xml.";
162     return;
163   }
164   std::string system_manifest_xml_content;
165   ASSERT_TRUE(
166       android::base::ReadFileToString(system_manifest_xml_path, &system_manifest_xml_content));
167   TemporaryFile compatibility_zip_file;
168   FILE* compatibility_zip = fdopen(compatibility_zip_file.release(), "w");
169   ZipWriter compatibility_zip_writer(compatibility_zip);
170   ASSERT_EQ(0, compatibility_zip_writer.StartEntry("system_manifest.xml", kCompressDeflated));
171   ASSERT_EQ(0, compatibility_zip_writer.WriteBytes(system_manifest_xml_content.data(),
172                                                    system_manifest_xml_content.size()));
173   ASSERT_EQ(0, compatibility_zip_writer.FinishEntry());
174   ASSERT_EQ(0, compatibility_zip_writer.Finish());
175   ASSERT_EQ(0, fclose(compatibility_zip));
176 
177   TemporaryFile temp_file;
178   FILE* zip_file = fdopen(temp_file.release(), "w");
179   ZipWriter writer(zip_file);
180   ASSERT_EQ(0, writer.StartEntry("compatibility.zip", kCompressStored));
181   std::string compatibility_zip_content;
182   ASSERT_TRUE(
183       android::base::ReadFileToString(compatibility_zip_file.path, &compatibility_zip_content));
184   ASSERT_EQ(0,
185             writer.WriteBytes(compatibility_zip_content.data(), compatibility_zip_content.size()));
186   ASSERT_EQ(0, writer.FinishEntry());
187   ASSERT_EQ(0, writer.Finish());
188   ASSERT_EQ(0, fclose(zip_file));
189 
190   ZipArchiveHandle zip;
191   ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
192   std::vector<std::string> compatibility_info;
193   compatibility_info.push_back(system_manifest_xml_content);
194   std::string err;
195   bool result =
196       android::vintf::VintfObjectRecovery::CheckCompatibility(compatibility_info, &err) == 0;
197   // Make sure the result is consistent with libvintf library.
198   ASSERT_EQ(result, verify_package_compatibility(zip));
199   CloseArchive(zip);
200 }
201 
202 #ifdef AB_OTA_UPDATER
VerifyAbUpdateBinaryCommand(const std::string & serialno,bool success=true)203 static void VerifyAbUpdateBinaryCommand(const std::string& serialno, bool success = true) {
204   TemporaryFile temp_file;
205   FILE* zip_file = fdopen(temp_file.release(), "w");
206   ZipWriter writer(zip_file);
207   ASSERT_EQ(0, writer.StartEntry("payload.bin", kCompressStored));
208   ASSERT_EQ(0, writer.FinishEntry());
209   ASSERT_EQ(0, writer.StartEntry("payload_properties.txt", kCompressStored));
210   const std::string properties = "some_properties";
211   ASSERT_EQ(0, writer.WriteBytes(properties.data(), properties.size()));
212   ASSERT_EQ(0, writer.FinishEntry());
213   // A metadata entry is mandatory.
214   ASSERT_EQ(0, writer.StartEntry("META-INF/com/android/metadata", kCompressStored));
215   std::string device = android::base::GetProperty("ro.product.device", "");
216   ASSERT_NE("", device);
217   std::string timestamp = android::base::GetProperty("ro.build.date.utc", "");
218   ASSERT_NE("", timestamp);
219 
220   std::vector<std::string> meta{ "ota-type=AB", "pre-device=" + device,
221                                  "post-timestamp=" + timestamp };
222   if (!serialno.empty()) {
223     meta.push_back("serialno=" + serialno);
224   }
225   std::string metadata = android::base::Join(meta, "\n");
226   ASSERT_EQ(0, writer.WriteBytes(metadata.data(), metadata.size()));
227   ASSERT_EQ(0, writer.FinishEntry());
228   ASSERT_EQ(0, writer.Finish());
229   ASSERT_EQ(0, fclose(zip_file));
230 
231   ZipArchiveHandle zip;
232   ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
233   ZipString payload_name("payload.bin");
234   ZipEntry payload_entry;
235   ASSERT_EQ(0, FindEntry(zip, payload_name, &payload_entry));
236   int status_fd = 10;
237   std::string package = "/path/to/update.zip";
238   std::string binary_path = "/sbin/update_engine_sideload";
239   std::vector<std::string> cmd;
240   if (success) {
241     ASSERT_EQ(0, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd));
242     ASSERT_EQ(5U, cmd.size());
243     ASSERT_EQ(binary_path, cmd[0]);
244     ASSERT_EQ("--payload=file://" + package, cmd[1]);
245     ASSERT_EQ("--offset=" + std::to_string(payload_entry.offset), cmd[2]);
246     ASSERT_EQ("--headers=" + properties, cmd[3]);
247     ASSERT_EQ("--status_fd=" + std::to_string(status_fd), cmd[4]);
248   } else {
249     ASSERT_EQ(INSTALL_ERROR, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd));
250   }
251   CloseArchive(zip);
252 }
253 #endif  // AB_OTA_UPDATER
254 
TEST(InstallTest,update_binary_command_smoke)255 TEST(InstallTest, update_binary_command_smoke) {
256 #ifdef AB_OTA_UPDATER
257   // Empty serialno will pass the verification.
258   VerifyAbUpdateBinaryCommand({});
259 #else
260   TemporaryFile temp_file;
261   FILE* zip_file = fdopen(temp_file.release(), "w");
262   ZipWriter writer(zip_file);
263   static constexpr const char* UPDATE_BINARY_NAME = "META-INF/com/google/android/update-binary";
264   ASSERT_EQ(0, writer.StartEntry(UPDATE_BINARY_NAME, kCompressStored));
265   ASSERT_EQ(0, writer.FinishEntry());
266   ASSERT_EQ(0, writer.Finish());
267   ASSERT_EQ(0, fclose(zip_file));
268 
269   ZipArchiveHandle zip;
270   ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
271   int status_fd = 10;
272   std::string package = "/path/to/update.zip";
273   TemporaryDir td;
274   std::string binary_path = std::string(td.path) + "/update_binary";
275   std::vector<std::string> cmd;
276   ASSERT_EQ(0, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd));
277   ASSERT_EQ(4U, cmd.size());
278   ASSERT_EQ(binary_path, cmd[0]);
279   ASSERT_EQ("3", cmd[1]);  // RECOVERY_API_VERSION
280   ASSERT_EQ(std::to_string(status_fd), cmd[2]);
281   ASSERT_EQ(package, cmd[3]);
282   struct stat sb;
283   ASSERT_EQ(0, stat(binary_path.c_str(), &sb));
284   ASSERT_EQ(static_cast<mode_t>(0755), sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
285 
286   // With non-zero retry count. update_binary will be removed automatically.
287   cmd.clear();
288   ASSERT_EQ(0, update_binary_command(package, zip, binary_path, 2, status_fd, &cmd));
289   ASSERT_EQ(5U, cmd.size());
290   ASSERT_EQ(binary_path, cmd[0]);
291   ASSERT_EQ("3", cmd[1]);  // RECOVERY_API_VERSION
292   ASSERT_EQ(std::to_string(status_fd), cmd[2]);
293   ASSERT_EQ(package, cmd[3]);
294   ASSERT_EQ("retry", cmd[4]);
295   sb = {};
296   ASSERT_EQ(0, stat(binary_path.c_str(), &sb));
297   ASSERT_EQ(static_cast<mode_t>(0755), sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
298 
299   CloseArchive(zip);
300 #endif  // AB_OTA_UPDATER
301 }
302 
TEST(InstallTest,update_binary_command_invalid)303 TEST(InstallTest, update_binary_command_invalid) {
304 #ifdef AB_OTA_UPDATER
305   TemporaryFile temp_file;
306   FILE* zip_file = fdopen(temp_file.release(), "w");
307   ZipWriter writer(zip_file);
308   // Missing payload_properties.txt.
309   ASSERT_EQ(0, writer.StartEntry("payload.bin", kCompressStored));
310   ASSERT_EQ(0, writer.FinishEntry());
311   // A metadata entry is mandatory.
312   ASSERT_EQ(0, writer.StartEntry("META-INF/com/android/metadata", kCompressStored));
313   std::string device = android::base::GetProperty("ro.product.device", "");
314   ASSERT_NE("", device);
315   std::string timestamp = android::base::GetProperty("ro.build.date.utc", "");
316   ASSERT_NE("", timestamp);
317   std::string metadata = android::base::Join(
318       std::vector<std::string>{
319           "ota-type=AB", "pre-device=" + device, "post-timestamp=" + timestamp,
320       },
321       "\n");
322   ASSERT_EQ(0, writer.WriteBytes(metadata.data(), metadata.size()));
323   ASSERT_EQ(0, writer.FinishEntry());
324   ASSERT_EQ(0, writer.Finish());
325   ASSERT_EQ(0, fclose(zip_file));
326 
327   ZipArchiveHandle zip;
328   ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
329   int status_fd = 10;
330   std::string package = "/path/to/update.zip";
331   std::string binary_path = "/sbin/update_engine_sideload";
332   std::vector<std::string> cmd;
333   ASSERT_EQ(INSTALL_CORRUPT, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd));
334   CloseArchive(zip);
335 #else
336   TemporaryFile temp_file;
337   FILE* zip_file = fdopen(temp_file.release(), "w");
338   ZipWriter writer(zip_file);
339   // The archive must have something to be opened correctly.
340   ASSERT_EQ(0, writer.StartEntry("dummy_entry", 0));
341   ASSERT_EQ(0, writer.FinishEntry());
342   ASSERT_EQ(0, writer.Finish());
343   ASSERT_EQ(0, fclose(zip_file));
344 
345   // Missing update binary.
346   ZipArchiveHandle zip;
347   ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
348   int status_fd = 10;
349   std::string package = "/path/to/update.zip";
350   TemporaryDir td;
351   std::string binary_path = std::string(td.path) + "/update_binary";
352   std::vector<std::string> cmd;
353   ASSERT_EQ(INSTALL_CORRUPT, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd));
354   CloseArchive(zip);
355 #endif  // AB_OTA_UPDATER
356 }
357 
358 #ifdef AB_OTA_UPDATER
TEST(InstallTest,update_binary_command_multiple_serialno)359 TEST(InstallTest, update_binary_command_multiple_serialno) {
360   std::string serialno = android::base::GetProperty("ro.serialno", "");
361   ASSERT_NE("", serialno);
362 
363   // Single matching serialno will pass the verification.
364   VerifyAbUpdateBinaryCommand(serialno);
365 
366   static constexpr char alphabet[] =
367       "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
368   auto generator = []() { return alphabet[rand() % (sizeof(alphabet) - 1)]; };
369 
370   // Generate 900 random serial numbers.
371   std::string random_serial;
372   for (size_t i = 0; i < 900; i++) {
373     generate_n(back_inserter(random_serial), serialno.size(), generator);
374     random_serial.append("|");
375   }
376   // Random serialnos should fail the verification.
377   VerifyAbUpdateBinaryCommand(random_serial, false);
378 
379   std::string long_serial = random_serial + serialno + "|";
380   for (size_t i = 0; i < 99; i++) {
381     generate_n(back_inserter(long_serial), serialno.size(), generator);
382     long_serial.append("|");
383   }
384   // String with the matching serialno should pass the verification.
385   VerifyAbUpdateBinaryCommand(long_serial);
386 }
387 #endif  // AB_OTA_UPDATER
388