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