• 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 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 #include <android-base/logging.h>
20 
21 #include "RuntimeInfo.h"
22 
23 #include "CompatibilityMatrix.h"
24 #include "KernelConfigParser.h"
25 #include "parse_string.h"
26 
27 #include <dirent.h>
28 #include <errno.h>
29 #include <sys/utsname.h>
30 #include <unistd.h>
31 
32 #include <fstream>
33 #include <iostream>
34 #include <sstream>
35 
36 #include <android-base/properties.h>
37 #include <selinux/selinux.h>
38 #include <zlib.h>
39 
40 #define PROC_CONFIG "/proc/config.gz"
41 #define BUFFER_SIZE sysconf(_SC_PAGESIZE)
42 
43 namespace android {
44 namespace vintf {
45 
46 struct RuntimeInfoFetcher {
RuntimeInfoFetcherandroid::vintf::RuntimeInfoFetcher47     RuntimeInfoFetcher(RuntimeInfo *ki) : mRuntimeInfo(ki) { }
48     status_t fetchAllInformation(RuntimeInfo::FetchFlags flags);
49 
50    private:
51     status_t fetchVersion();
52     status_t fetchKernelConfigs();
53     status_t fetchCpuInfo();
54     status_t fetchKernelSepolicyVers();
55     status_t fetchAvb();
56     status_t parseKernelVersion();
57     RuntimeInfo *mRuntimeInfo;
58     KernelConfigParser mConfigParser;
59 };
60 
61 // decompress /proc/config.gz and read its contents.
fetchKernelConfigs()62 status_t RuntimeInfoFetcher::fetchKernelConfigs() {
63     gzFile f = gzopen(PROC_CONFIG, "rb");
64     if (f == NULL) {
65         LOG(ERROR) << "Could not open /proc/config.gz: " << errno;
66         return -errno;
67     }
68 
69     char buf[BUFFER_SIZE];
70     int len;
71     while ((len = gzread(f, buf, sizeof buf)) > 0) {
72         mConfigParser.process(buf, len);
73     }
74     status_t err = OK;
75     if (len < 0) {
76         int errnum;
77         const char *errmsg = gzerror(f, &errnum);
78         LOG(ERROR) << "Could not read /proc/config.gz: " << errmsg;
79         err = (errnum == Z_ERRNO ? -errno : errnum);
80     }
81     mConfigParser.finish();
82     gzclose(f);
83     mRuntimeInfo->mKernel.mConfigs = std::move(mConfigParser.configs());
84     return err;
85 }
86 
fetchCpuInfo()87 status_t RuntimeInfoFetcher::fetchCpuInfo() {
88     // TODO implement this; 32-bit and 64-bit has different format.
89     std::ifstream in{"/proc/cpuinfo"};
90     if (!in.is_open()) {
91         LOG(WARNING) << "Cannot read /proc/cpuinfo";
92         return UNKNOWN_ERROR;
93     }
94     std::stringstream sstream;
95     sstream << in.rdbuf();
96     mRuntimeInfo->mCpuInfo = sstream.str();
97     return OK;
98 }
99 
fetchKernelSepolicyVers()100 status_t RuntimeInfoFetcher::fetchKernelSepolicyVers() {
101     int pv;
102 #ifdef LIBVINTF_TARGET
103     pv = security_policyvers();
104 #else
105     pv = 0;
106 #endif
107     if (pv < 0) {
108         return pv;
109     }
110     mRuntimeInfo->mKernelSepolicyVersion = pv;
111     return OK;
112 }
113 
fetchVersion()114 status_t RuntimeInfoFetcher::fetchVersion() {
115     struct utsname buf;
116     if (uname(&buf)) {
117         return -errno;
118     }
119     mRuntimeInfo->mOsName = buf.sysname;
120     mRuntimeInfo->mNodeName = buf.nodename;
121     mRuntimeInfo->mOsRelease = buf.release;
122     mRuntimeInfo->mOsVersion = buf.version;
123     mRuntimeInfo->mHardwareId = buf.machine;
124 
125     status_t err = parseKernelVersion();
126     if (err != OK) {
127         LOG(ERROR) << "Could not parse kernel version from \""
128                    << mRuntimeInfo->mOsRelease << "\"";
129     }
130     return err;
131 }
132 
parseKernelVersion()133 status_t RuntimeInfoFetcher::parseKernelVersion() {
134     auto pos = mRuntimeInfo->mOsRelease.find('.');
135     if (pos == std::string::npos) {
136         return UNKNOWN_ERROR;
137     }
138     pos = mRuntimeInfo->mOsRelease.find('.', pos + 1);
139     if (pos == std::string::npos) {
140         return UNKNOWN_ERROR;
141     }
142     pos = mRuntimeInfo->mOsRelease.find_first_not_of("0123456789", pos + 1);
143     // no need to check pos == std::string::npos, because substr will handle this
144     if (!parse(mRuntimeInfo->mOsRelease.substr(0, pos), &mRuntimeInfo->mKernel.mVersion)) {
145         return UNKNOWN_ERROR;
146     }
147     return OK;
148 }
149 
fetchAvb()150 status_t RuntimeInfoFetcher::fetchAvb() {
151     std::string prop = android::base::GetProperty("ro.boot.vbmeta.avb_version", "0.0");
152     if (!parse(prop, &mRuntimeInfo->mBootVbmetaAvbVersion)) {
153         return UNKNOWN_ERROR;
154     }
155     prop = android::base::GetProperty("ro.boot.avb_version", "0.0");
156     if (!parse(prop, &mRuntimeInfo->mBootAvbVersion)) {
157         return UNKNOWN_ERROR;
158     }
159     return OK;
160 }
161 
fetchAllInformation(RuntimeInfo::FetchFlags flags)162 status_t RuntimeInfoFetcher::fetchAllInformation(RuntimeInfo::FetchFlags flags) {
163 
164     using F = RuntimeInfo::FetchFlag;
165     using RF = RuntimeInfoFetcher;
166     using FetchFunction = status_t(RF::*)();
167     const static std::vector<std::tuple<F, FetchFunction, std::string>> gFetchFunctions({
168         // flag          fetch function                 description
169         {F::CPU_VERSION, &RF::fetchVersion,             "/proc/version"},
170         {F::CONFIG_GZ,   &RF::fetchKernelConfigs,       "/proc/config.gz"},
171         {F::CPU_INFO,    &RF::fetchCpuInfo,             "/proc/cpuinfo"},
172         {F::POLICYVERS,  &RF::fetchKernelSepolicyVers,  "kernel sepolicy version"},
173         {F::AVB,         &RF::fetchAvb,                 "avb version"},
174     });
175 
176     status_t err;
177     for (const auto& tuple : gFetchFunctions)
178         if ((flags & std::get<0>(tuple)) && (err = (*this.*std::get<1>(tuple))()) != OK)
179             LOG(WARNING) << "Cannot fetch or parse " << std::get<2>(tuple) << ": "
180                          << strerror(-err);
181 
182     return OK;
183 }
184 
fetchAllInformation(RuntimeInfo::FetchFlags flags)185 status_t RuntimeInfo::fetchAllInformation(RuntimeInfo::FetchFlags flags) {
186     return RuntimeInfoFetcher(this).fetchAllInformation(flags);
187 }
188 
189 } // namespace vintf
190 } // namespace android
191