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