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 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 
18 #define LOG_TAG "libvintf"
19 
20 #include "RuntimeInfo.h"
21 
22 #include <android-base/logging.h>
23 #include <android-base/strings.h>
24 #include <kver/kernel_release.h>
25 
26 #include "CompatibilityMatrix.h"
27 #include "parse_string.h"
28 
29 namespace android {
30 namespace vintf {
31 
osName() const32 const std::string &RuntimeInfo::osName() const {
33     return mOsName;
34 }
35 
nodeName() const36 const std::string &RuntimeInfo::nodeName() const {
37     return mNodeName;
38 }
39 
osRelease() const40 const std::string &RuntimeInfo::osRelease() const {
41     return mOsRelease;
42 }
43 
osVersion() const44 const std::string &RuntimeInfo::osVersion() const {
45     return mOsVersion;
46 }
47 
hardwareId() const48 const std::string &RuntimeInfo::hardwareId() const {
49     return mHardwareId;
50 }
51 
kernelVersion() const52 const KernelVersion &RuntimeInfo::kernelVersion() const {
53     return mKernel.version();
54 }
55 
kernelConfigs() const56 const std::map<std::string, std::string> &RuntimeInfo::kernelConfigs() const {
57     return mKernel.configs();
58 }
59 
kernelSepolicyVersion() const60 size_t RuntimeInfo::kernelSepolicyVersion() const {
61     return mKernelSepolicyVersion;
62 }
63 
cpuInfo() const64 const std::string &RuntimeInfo::cpuInfo() const {
65     return mCpuInfo;
66 }
67 
bootVbmetaAvbVersion() const68 const Version &RuntimeInfo::bootVbmetaAvbVersion() const {
69     return mBootVbmetaAvbVersion;
70 }
71 
bootAvbVersion() const72 const Version &RuntimeInfo::bootAvbVersion() const {
73     return mBootAvbVersion;
74 }
75 
isMainlineKernel() const76 bool RuntimeInfo::isMainlineKernel() const {
77     return mIsMainline;
78 }
79 
checkCompatibility(const CompatibilityMatrix & mat,std::string * error,CheckFlags::Type flags) const80 bool RuntimeInfo::checkCompatibility(const CompatibilityMatrix& mat, std::string* error,
81                                      CheckFlags::Type flags) const {
82     if (mat.mType != SchemaType::FRAMEWORK) {
83         if (error != nullptr) {
84             *error = "Should not check runtime info against " + to_string(mat.mType)
85                     + " compatibility matrix.";
86         }
87         return false;
88     }
89     if (kernelSepolicyVersion() < mat.framework.mSepolicy.kernelSepolicyVersion()) {
90         if (error != nullptr) {
91             *error =
92                 "kernelSepolicyVersion = " + to_string(kernelSepolicyVersion()) +
93                 " but required >= " + to_string(mat.framework.mSepolicy.kernelSepolicyVersion());
94         }
95         return false;
96     }
97 
98     // mat.mSepolicy.sepolicyVersion() is checked against static
99     // HalManifest.device.mSepolicyVersion in HalManifest::checkCompatibility.
100 
101     if (flags.isKernelEnabled()) {
102         if (!isMainlineKernel() &&
103             mKernel.getMatchedKernelRequirements(mat.framework.mKernels, kernelLevel(), error)
104                 .empty()) {
105             return false;
106         }
107     }
108 
109     if (flags.isAvbEnabled()) {
110         const Version& matAvb = mat.framework.mAvbMetaVersion;
111         if (mBootAvbVersion.majorVer != matAvb.majorVer ||
112             mBootAvbVersion.minorVer < matAvb.minorVer) {
113             if (error != nullptr) {
114                 std::stringstream ss;
115                 ss << "AVB version " << mBootAvbVersion << " does not match framework matrix "
116                    << matAvb;
117                 *error = ss.str();
118             }
119             return false;
120         }
121         if (mBootVbmetaAvbVersion.majorVer != matAvb.majorVer ||
122             mBootVbmetaAvbVersion.minorVer < matAvb.minorVer) {
123             if (error != nullptr) {
124                 std::stringstream ss;
125                 ss << "Vbmeta version " << mBootVbmetaAvbVersion
126                    << " does not match framework matrix " << matAvb;
127                 *error = ss.str();
128             }
129             return false;
130         }
131     }
132 
133     return true;
134 }
135 
setKernelLevel(Level level)136 void RuntimeInfo::setKernelLevel(Level level) {
137     mKernel.mLevel = level;
138 }
139 
kernelLevel() const140 Level RuntimeInfo::kernelLevel() const {
141     return mKernel.mLevel;
142 }
143 
parseGkiKernelRelease(RuntimeInfo::FetchFlags flags,const std::string & kernelReleaseString,KernelVersion * outVersion,Level * outLevel)144 status_t RuntimeInfo::parseGkiKernelRelease(RuntimeInfo::FetchFlags flags,
145                                             const std::string& kernelReleaseString,
146                                             KernelVersion* outVersion, Level* outLevel) {
147     auto kernelRelease =
148         android::kver::KernelRelease::Parse(kernelReleaseString, true /* allow suffix */);
149     if (kernelRelease == std::nullopt) {
150         return UNKNOWN_ERROR;
151     }
152 
153     if (flags & RuntimeInfo::FetchFlag::CPU_VERSION) {
154         if (kernelRelease->version() > std::numeric_limits<size_t>::max() ||
155             kernelRelease->patch_level() > std::numeric_limits<size_t>::max() ||
156             kernelRelease->sub_level() > std::numeric_limits<size_t>::max()) {
157             LOG(ERROR) << "Overflow : " << kernelRelease->string();
158             return UNKNOWN_ERROR;
159         }
160         *outVersion = {static_cast<size_t>(kernelRelease->version()),
161                        static_cast<size_t>(kernelRelease->patch_level()),
162                        static_cast<size_t>(kernelRelease->sub_level())};
163     }
164 
165     if (flags & RuntimeInfo::FetchFlag::KERNEL_FCM) {
166         Level kernelLevel = gkiAndroidReleaseToLevel(kernelRelease->android_release());
167         if (kernelLevel == Level::UNSPECIFIED) {
168             LOG(ERROR) << "Cannot infer level corresponding to Android "
169                        << kernelRelease->android_release()
170                        << "; update libvintf to recognize this value.";
171             return UNKNOWN_ERROR;
172         }
173         // VintfObject may previously set mRuntimeInfo->mKernel.mLevel to the kernel level
174         // from device manifest. Check consistency.
175         if (*outLevel != Level::UNSPECIFIED && *outLevel != kernelLevel) {
176             LOG(ERROR) << "Kernel level in device manifest (" << *outLevel
177                        << ") does not match kernel level in kernel release (" << kernelLevel
178                        << " for Android " << kernelRelease->android_release() << ")";
179             return UNKNOWN_ERROR;
180         }
181         *outLevel = kernelLevel;
182     }
183     return OK;
184 }
185 
gkiAndroidReleaseToLevel(uint64_t androidRelease)186 Level RuntimeInfo::gkiAndroidReleaseToLevel(uint64_t androidRelease) {
187     constexpr size_t ANDROID_S = 12;
188     constexpr size_t ANDROID_V = 15;
189 
190     // Values prior to Android 12 is ignored because GKI kernel release format starts
191     // at Android 12.
192     if (androidRelease < ANDROID_S) return Level::UNSPECIFIED;
193 
194     Level ret = Level::UNSPECIFIED;
195     if (androidRelease < ANDROID_V) {
196         ret = static_cast<Level>(androidRelease - ANDROID_S + static_cast<size_t>(Level::S));
197     } else {
198         switch (androidRelease) {
199             case 15: {
200                 ret = Level::V;
201             } break;
202             // Add more levels above this line.
203             default: {
204                 LOG(FATAL) << "Convert Android " << androidRelease << " to level '" << ret
205                            << "' goes out of bounds. Fix by editing "
206                            << "RuntimeInfo::gkiAndroidReleaseToLevel";
207             } break;
208         }
209     }
210 
211     CHECK(IsValid(ret) && ret != Level::UNSPECIFIED)
212         << "Convert Android " << androidRelease << " to level '" << ret
213         << "' goes out of bounds. Fix by adding a new Level enum.";
214     return ret;
215 }
216 
kernelReleaseIsMainline(std::string_view kernelRelease)217 bool RuntimeInfo::kernelReleaseIsMainline(std::string_view kernelRelease) {
218     static constexpr char kMainline[] = "-mainline-";
219     static constexpr char kMainlineSuffix[] = "-mainline";
220 
221     return kernelRelease.find(kMainline) != std::string::npos ||
222            android::base::EndsWith(kernelRelease, kMainlineSuffix);
223 }
224 
225 } // namespace vintf
226 } // namespace android
227