blob: f2a2c264143060c93200a1f6f62aaa6210931f1f [file] [log] [blame]
Tom Cherryde6bd502018-02-13 16:50:08 -08001//
2// Copyright (C) 2018 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
Tom Cherry31525f52018-05-09 18:33:31 -070017#include <errno.h>
Tom Cherry3f1bce82019-06-05 09:13:11 -070018#include <getopt.h>
Tom Cherryde6bd502018-02-13 16:50:08 -080019#include <pwd.h>
Tom Cherry31525f52018-05-09 18:33:31 -070020#include <stdio.h>
Tom Cherry863d8082018-06-12 14:40:38 -070021#include <stdlib.h>
Tom Cherryde6bd502018-02-13 16:50:08 -080022
Daniel Norman3f42a762019-07-09 11:00:53 -070023#include <fstream>
Tom Cherry194b5d12018-05-09 17:38:30 -070024#include <iostream>
Tom Cherry3f1bce82019-06-05 09:13:11 -070025#include <iterator>
Tom Cherry194b5d12018-05-09 17:38:30 -070026#include <string>
Tom Cherry31525f52018-05-09 18:33:31 -070027#include <vector>
Tom Cherry194b5d12018-05-09 17:38:30 -070028
Tom Cherry31525f52018-05-09 18:33:31 -070029#include <android-base/file.h>
Tom Cherryde6bd502018-02-13 16:50:08 -080030#include <android-base/logging.h>
Tom Cherry31525f52018-05-09 18:33:31 -070031#include <android-base/parseint.h>
Tom Cherry194b5d12018-05-09 17:38:30 -070032#include <android-base/strings.h>
Tom Cherryde6bd502018-02-13 16:50:08 -080033
34#include "action.h"
35#include "action_manager.h"
36#include "action_parser.h"
Tom Cherry4772f1d2019-07-30 09:34:41 -070037#include "check_builtins.h"
Tom Cherry194b5d12018-05-09 17:38:30 -070038#include "host_import_parser.h"
39#include "host_init_stubs.h"
Daniel Normand2533c32019-08-02 15:13:50 -070040#include "interface_utils.h"
Tom Cherryde6bd502018-02-13 16:50:08 -080041#include "parser.h"
42#include "result.h"
43#include "service.h"
Tom Cherry2aeb1ad2019-06-26 10:46:20 -070044#include "service_list.h"
45#include "service_parser.h"
Tom Cherryde6bd502018-02-13 16:50:08 -080046
Tom Cherry31525f52018-05-09 18:33:31 -070047#define EXCLUDE_FS_CONFIG_STRUCTURES
48#include "generated_android_ids.h"
49
Tom Cherry194b5d12018-05-09 17:38:30 -070050using namespace std::literals;
51
Tom Cherry31525f52018-05-09 18:33:31 -070052using android::base::ParseInt;
53using android::base::ReadFileToString;
Tom Cherry194b5d12018-05-09 17:38:30 -070054using android::base::Split;
55
Tom Cherry3f1bce82019-06-05 09:13:11 -070056static std::vector<std::string> passwd_files;
Tom Cherry31525f52018-05-09 18:33:31 -070057
Tom Cherry3f1bce82019-06-05 09:13:11 -070058static std::vector<std::pair<std::string, int>> GetVendorPasswd(const std::string& passwd_file) {
Tom Cherry31525f52018-05-09 18:33:31 -070059 std::string passwd;
Tom Cherry863d8082018-06-12 14:40:38 -070060 if (!ReadFileToString(passwd_file, &passwd)) {
Tom Cherry31525f52018-05-09 18:33:31 -070061 return {};
62 }
63
64 std::vector<std::pair<std::string, int>> result;
65 auto passwd_lines = Split(passwd, "\n");
66 for (const auto& line : passwd_lines) {
67 auto split_line = Split(line, ":");
68 if (split_line.size() < 3) {
69 continue;
70 }
71 int uid = 0;
72 if (!ParseInt(split_line[2], &uid)) {
73 continue;
74 }
75 result.emplace_back(split_line[0], uid);
76 }
77 return result;
78}
79
Tom Cherry3f1bce82019-06-05 09:13:11 -070080static std::vector<std::pair<std::string, int>> GetVendorPasswd() {
81 std::vector<std::pair<std::string, int>> result;
82 for (const auto& passwd_file : passwd_files) {
83 auto individual_result = GetVendorPasswd(passwd_file);
84 std::move(individual_result.begin(), individual_result.end(),
85 std::back_insert_iterator(result));
86 }
87 return result;
88}
89
Tom Cherryde6bd502018-02-13 16:50:08 -080090passwd* getpwnam(const char* login) { // NOLINT: implementing bad function.
Tom Cherry31525f52018-05-09 18:33:31 -070091 // This isn't thread safe, but that's okay for our purposes.
92 static char static_name[32] = "";
93 static char static_dir[32] = "/";
94 static char static_shell[32] = "/system/bin/sh";
95 static passwd static_passwd = {
96 .pw_name = static_name,
97 .pw_dir = static_dir,
98 .pw_shell = static_shell,
99 .pw_uid = 0,
100 .pw_gid = 0,
Tom Cherryde6bd502018-02-13 16:50:08 -0800101 };
Tom Cherry31525f52018-05-09 18:33:31 -0700102
103 for (size_t n = 0; n < android_id_count; ++n) {
104 if (!strcmp(android_ids[n].name, login)) {
105 snprintf(static_name, sizeof(static_name), "%s", android_ids[n].name);
106 static_passwd.pw_uid = android_ids[n].aid;
107 static_passwd.pw_gid = android_ids[n].aid;
108 return &static_passwd;
109 }
110 }
111
112 static const auto vendor_passwd = GetVendorPasswd();
113
114 for (const auto& [name, uid] : vendor_passwd) {
115 if (name == login) {
116 snprintf(static_name, sizeof(static_name), "%s", name.c_str());
117 static_passwd.pw_uid = uid;
118 static_passwd.pw_gid = uid;
119 return &static_passwd;
120 }
121 }
122
Tom Cherry290427b2018-06-14 13:40:20 -0700123 unsigned int oem_uid;
124 if (sscanf(login, "oem_%u", &oem_uid) == 1) {
125 snprintf(static_name, sizeof(static_name), "%s", login);
126 static_passwd.pw_uid = oem_uid;
127 static_passwd.pw_gid = oem_uid;
128 return &static_passwd;
129 }
130
Tom Cherry31525f52018-05-09 18:33:31 -0700131 errno = ENOENT;
132 return nullptr;
Tom Cherryde6bd502018-02-13 16:50:08 -0800133}
134
135namespace android {
136namespace init {
137
Tom Cherry4772f1d2019-07-30 09:34:41 -0700138static Result<void> check_stub(const BuiltinArguments& args) {
Tom Cherrybbcbc2f2019-06-10 11:08:01 -0700139 return {};
Tom Cherryde6bd502018-02-13 16:50:08 -0800140}
141
142#include "generated_stub_builtin_function_map.h"
143
Tom Cherry3f1bce82019-06-05 09:13:11 -0700144void PrintUsage() {
Daniel Normane6586c42019-08-02 10:59:54 -0700145 std::cout << "usage: host_init_verifier [-p FILE] -i FILE <init rc file>\n"
Tom Cherry3f1bce82019-06-05 09:13:11 -0700146 "\n"
147 "Tests an init script for correctness\n"
148 "\n"
149 "-p FILE\tSearch this passwd file for users and groups\n"
Daniel Normane6586c42019-08-02 10:59:54 -0700150 "-i FILE\tParse this JSON file for the HIDL interface inheritance hierarchy\n"
Tom Cherry3f1bce82019-06-05 09:13:11 -0700151 << std::endl;
152}
153
Tom Cherryde6bd502018-02-13 16:50:08 -0800154int main(int argc, char** argv) {
Elliott Hughes1be0d142018-05-23 09:16:46 -0700155 android::base::InitLogging(argv, &android::base::StdioLogger);
Tom Cherry194b5d12018-05-09 17:38:30 -0700156 android::base::SetMinimumLogSeverity(android::base::ERROR);
Tom Cherry863d8082018-06-12 14:40:38 -0700157
Daniel Norman3f42a762019-07-09 11:00:53 -0700158 std::string interface_inheritance_hierarchy_file;
Daniel Norman3df8dc52019-06-27 12:18:08 -0700159
Tom Cherry3f1bce82019-06-05 09:13:11 -0700160 while (true) {
161 static const struct option long_options[] = {
162 {"help", no_argument, nullptr, 'h'},
163 {nullptr, 0, nullptr, 0},
164 };
165
Daniel Norman3f42a762019-07-09 11:00:53 -0700166 int arg = getopt_long(argc, argv, "p:i:", long_options, nullptr);
Tom Cherry3f1bce82019-06-05 09:13:11 -0700167
168 if (arg == -1) {
169 break;
170 }
171
172 switch (arg) {
173 case 'h':
174 PrintUsage();
175 return EXIT_FAILURE;
176 case 'p':
177 passwd_files.emplace_back(optarg);
178 break;
Daniel Norman3f42a762019-07-09 11:00:53 -0700179 case 'i':
180 interface_inheritance_hierarchy_file = optarg;
Daniel Norman3df8dc52019-06-27 12:18:08 -0700181 break;
Tom Cherry3f1bce82019-06-05 09:13:11 -0700182 default:
183 std::cerr << "getprop: getopt returned invalid result: " << arg << std::endl;
184 return EXIT_FAILURE;
185 }
Tom Cherryde6bd502018-02-13 16:50:08 -0800186 }
Tom Cherry194b5d12018-05-09 17:38:30 -0700187
Tom Cherry3f1bce82019-06-05 09:13:11 -0700188 argc -= optind;
189 argv += optind;
190
Daniel Normane6586c42019-08-02 10:59:54 -0700191 if (argc != 1 || interface_inheritance_hierarchy_file.empty()) {
Tom Cherry3f1bce82019-06-05 09:13:11 -0700192 PrintUsage();
193 return EXIT_FAILURE;
Tom Cherry194b5d12018-05-09 17:38:30 -0700194 }
195
Daniel Normand2533c32019-08-02 15:13:50 -0700196 auto interface_inheritance_hierarchy_map =
197 ReadInterfaceInheritanceHierarchy(interface_inheritance_hierarchy_file);
198 if (!interface_inheritance_hierarchy_map) {
199 LOG(ERROR) << interface_inheritance_hierarchy_map.error();
200 return EXIT_FAILURE;
201 }
202 SetKnownInterfaces(*interface_inheritance_hierarchy_map);
203
Tom Cherryd52a5b32019-07-22 16:05:36 -0700204 const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
Tom Cherryde6bd502018-02-13 16:50:08 -0800205 Action::set_function_map(&function_map);
206 ActionManager& am = ActionManager::GetInstance();
207 ServiceList& sl = ServiceList::GetInstance();
208 Parser parser;
Daniel Normand2533c32019-08-02 15:13:50 -0700209 parser.AddSectionParser("service", std::make_unique<ServiceParser>(
210 &sl, nullptr, *interface_inheritance_hierarchy_map));
Tom Cherryde6bd502018-02-13 16:50:08 -0800211 parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
Tom Cherry863d8082018-06-12 14:40:38 -0700212 parser.AddSectionParser("import", std::make_unique<HostImportParser>());
Tom Cherryde6bd502018-02-13 16:50:08 -0800213
Tom Cherry3f1bce82019-06-05 09:13:11 -0700214 if (!parser.ParseConfigFileInsecure(*argv)) {
215 LOG(ERROR) << "Failed to open init rc script '" << *argv << "'";
Tom Cherry863d8082018-06-12 14:40:38 -0700216 return EXIT_FAILURE;
Tom Cherryde6bd502018-02-13 16:50:08 -0800217 }
Tom Cherry4772f1d2019-07-30 09:34:41 -0700218 size_t failures = parser.parse_error_count() + am.CheckAllCommands();
219 if (failures > 0) {
220 LOG(ERROR) << "Failed to parse init script '" << *argv << "' with " << failures
221 << " errors";
Tom Cherry863d8082018-06-12 14:40:38 -0700222 return EXIT_FAILURE;
Tom Cherryde6bd502018-02-13 16:50:08 -0800223 }
Tom Cherry863d8082018-06-12 14:40:38 -0700224 return EXIT_SUCCESS;
Tom Cherryde6bd502018-02-13 16:50:08 -0800225}
226
227} // namespace init
228} // namespace android
229
230int main(int argc, char** argv) {
Tom Cherry863d8082018-06-12 14:40:38 -0700231 return android::init::main(argc, argv);
Tom Cherryde6bd502018-02-13 16:50:08 -0800232}