blob: c7f5cf3632c5ef6440226cdce8e03b0dde7c0f45 [file] [log] [blame]
felkachang1039d612022-06-21 15:09:47 +08001/*
2 * Copyright (C) 2022 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 <sys/stat.h>
18
19#include <fstream>
20#include <optional>
21
22#define LOG_TAG "SelfTargeting"
23
24#include "androidfw/ResourceTypes.h"
25#include "idmap2/BinaryStreamVisitor.h"
26#include "idmap2/FabricatedOverlay.h"
27#include "idmap2/Idmap.h"
28#include "idmap2/Result.h"
29
30using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask;
31using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
32using android::idmap2::BinaryStreamVisitor;
33using android::idmap2::Idmap;
34using android::idmap2::OverlayResourceContainer;
35
36namespace android::self_targeting {
37
38constexpr const mode_t kIdmapFilePermission = S_IRUSR | S_IWUSR; // u=rw-, g=---, o=---
39
40extern "C" bool
felkachanga8fc0152022-09-22 20:00:34 +080041CreateFrroFile(std::string& out_err_result, const std::string& packageName,
42 const std::string& overlayName, const std::string& targetPackageName,
43 const std::optional<std::string>& targetOverlayable,
44 const std::vector<FabricatedOverlayEntryParameters>& entries_params,
felkachang1039d612022-06-21 15:09:47 +080045 const std::string& frro_file_path) {
46 android::idmap2::FabricatedOverlay::Builder builder(packageName, overlayName,
47 targetPackageName);
48 if (targetOverlayable.has_value()) {
49 builder.SetOverlayable(targetOverlayable.value_or(std::string()));
50 }
51 for (const auto& entry_params : entries_params) {
52 const auto dataType = entry_params.data_type;
53 if (entry_params.data_binary_value.has_value()) {
54 builder.SetResourceValue(entry_params.resource_name, *entry_params.data_binary_value,
Jeremy Meyerc04bcb32023-07-27 22:49:14 +000055 entry_params.binary_data_offset, entry_params.binary_data_size,
felkachang1039d612022-06-21 15:09:47 +080056 entry_params.configuration);
57 } else if (dataType >= Res_value::TYPE_FIRST_INT && dataType <= Res_value::TYPE_LAST_INT) {
58 builder.SetResourceValue(entry_params.resource_name, dataType,
59 entry_params.data_value, entry_params.configuration);
60 } else if (dataType == Res_value::TYPE_STRING) {
61 builder.SetResourceValue(entry_params.resource_name, dataType,
62 entry_params.data_string_value , entry_params.configuration);
63 } else {
64 out_err_result = base::StringPrintf("Unsupported data type %d", dataType);
65 return false;
66 }
67 }
68
69 const auto frro = builder.Build();
70 std::ofstream fout(frro_file_path);
71 if (fout.fail()) {
72 out_err_result = base::StringPrintf("open output stream fail %s", std::strerror(errno));
73 return false;
74 }
75 auto result = frro->ToBinaryStream(fout);
76 if (!result) {
77 unlink(frro_file_path.c_str());
78 out_err_result = base::StringPrintf("to stream fail %s", result.GetErrorMessage().c_str());
79 return false;
80 }
81 fout.close();
82 if (fout.fail()) {
83 unlink(frro_file_path.c_str());
84 out_err_result = base::StringPrintf("output stream fail %s", std::strerror(errno));
85 return false;
86 }
87 if (chmod(frro_file_path.c_str(), kIdmapFilePermission) == -1) {
88 out_err_result = base::StringPrintf("Failed to change the file permission %s",
89 frro_file_path.c_str());
90 return false;
91 }
92 return true;
93}
94
felkachanga8fc0152022-09-22 20:00:34 +080095static PolicyBitmask GetFulfilledPolicy(const bool isSystem, const bool isVendor,
96 const bool isProduct, const bool isTargetSignature,
97 const bool isOdm, const bool isOem) {
98 auto fulfilled_policy = static_cast<PolicyBitmask>(PolicyFlags::PUBLIC);
99
100 if (isSystem) {
101 fulfilled_policy |= PolicyFlags::SYSTEM_PARTITION;
102 }
103 if (isVendor) {
104 fulfilled_policy |= PolicyFlags::VENDOR_PARTITION;
105 }
106 if (isProduct) {
107 fulfilled_policy |= PolicyFlags::PRODUCT_PARTITION;
108 }
109 if (isOdm) {
110 fulfilled_policy |= PolicyFlags::ODM_PARTITION;
111 }
112 if (isOem) {
113 fulfilled_policy |= PolicyFlags::OEM_PARTITION;
114 }
115 if (isTargetSignature) {
116 fulfilled_policy |= PolicyFlags::SIGNATURE;
117 }
118
119 // Not support actor_signature and config_overlay_signature
120 fulfilled_policy &=
121 ~(PolicyFlags::ACTOR_SIGNATURE | PolicyFlags::CONFIG_SIGNATURE);
122
123 ALOGV(
124 "fulfilled_policy = 0x%08x, isSystem = %d, isVendor = %d, isProduct = %d,"
125 " isTargetSignature = %d, isOdm = %d, isOem = %d,",
126 fulfilled_policy, isSystem, isVendor, isProduct, isTargetSignature, isOdm, isOem);
127 return fulfilled_policy;
128}
129
felkachang1039d612022-06-21 15:09:47 +0800130extern "C" bool
131CreateIdmapFile(std::string& out_err, const std::string& targetPath, const std::string& overlayPath,
felkachanga8fc0152022-09-22 20:00:34 +0800132 const std::string& idmapPath, const std::string& overlayName,
133 const bool isSystem, const bool isVendor, const bool isProduct,
134 const bool isTargetSignature, const bool isOdm, const bool isOem) {
felkachang1039d612022-06-21 15:09:47 +0800135 // idmap files are mapped with mmap in libandroidfw. Deleting and recreating the idmap
136 // guarantees that existing memory maps will continue to be valid and unaffected. The file must
137 // be deleted before attempting to create the idmap, so that if idmap creation fails, the
138 // overlay will no longer be usable.
139 unlink(idmapPath.c_str());
140
141 const auto target = idmap2::TargetResourceContainer::FromPath(targetPath);
142 if (!target) {
143 out_err = base::StringPrintf("Failed to load target %s because of %s", targetPath.c_str(),
144 target.GetErrorMessage().c_str());
145 return false;
146 }
147
148 const auto overlay = OverlayResourceContainer::FromPath(overlayPath);
149 if (!overlay) {
150 out_err = base::StringPrintf("Failed to load overlay %s because of %s", overlayPath.c_str(),
151 overlay.GetErrorMessage().c_str());
152 return false;
153 }
154
155 // Overlay self target process. Only allow self-targeting types.
felkachanga8fc0152022-09-22 20:00:34 +0800156 const auto fulfilled_policies = GetFulfilledPolicy(isSystem, isVendor, isProduct,
157 isTargetSignature, isOdm, isOem);
felkachang1039d612022-06-21 15:09:47 +0800158
159 const auto idmap = Idmap::FromContainers(**target, **overlay, overlayName,
felkachanga8fc0152022-09-22 20:00:34 +0800160 fulfilled_policies, true /* enforce_overlayable */);
felkachang1039d612022-06-21 15:09:47 +0800161 if (!idmap) {
162 out_err = base::StringPrintf("Failed to create idmap because of %s",
163 idmap.GetErrorMessage().c_str());
164 return false;
165 }
166
167 std::ofstream fout(idmapPath.c_str());
168 if (fout.fail()) {
169 out_err = base::StringPrintf("Failed to create idmap %s because of %s", idmapPath.c_str(),
170 strerror(errno));
171 return false;
172 }
173
174 BinaryStreamVisitor visitor(fout);
175 (*idmap)->accept(&visitor);
176 fout.close();
177 if (fout.fail()) {
178 unlink(idmapPath.c_str());
179 out_err = base::StringPrintf("Failed to write idmap %s because of %s", idmapPath.c_str(),
180 strerror(errno));
181 return false;
182 }
183 if (chmod(idmapPath.c_str(), kIdmapFilePermission) == -1) {
184 out_err = base::StringPrintf("Failed to change the file permission %s", idmapPath.c_str());
185 return false;
186 }
187 return true;
188}
189
190extern "C" bool
191GetFabricatedOverlayInfo(std::string& out_err, const std::string& overlay_path,
192 OverlayManifestInfo& out_info) {
193 const auto overlay = idmap2::FabricatedOverlayContainer::FromPath(overlay_path);
194 if (!overlay) {
195 out_err = base::StringPrintf("Failed to write idmap %s because of %s",
196 overlay_path.c_str(), strerror(errno));
197 return false;
198 }
199
200 out_info = (*overlay)->GetManifestInfo();
201
202 return true;
203}
204
205} // namespace android::self_targeting
206