1 //
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
17 #include <errno.h>
18 #include <pwd.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21
22 #include <iostream>
23 #include <string>
24 #include <vector>
25
26 #include <android-base/file.h>
27 #include <android-base/logging.h>
28 #include <android-base/parseint.h>
29 #include <android-base/strings.h>
30
31 #include "action.h"
32 #include "action_manager.h"
33 #include "action_parser.h"
34 #include "host_import_parser.h"
35 #include "host_init_stubs.h"
36 #include "parser.h"
37 #include "result.h"
38 #include "service.h"
39
40 #define EXCLUDE_FS_CONFIG_STRUCTURES
41 #include "generated_android_ids.h"
42
43 using namespace std::literals;
44
45 using android::base::ParseInt;
46 using android::base::ReadFileToString;
47 using android::base::Split;
48
49 static std::string passwd_file;
50
GetVendorPasswd()51 static std::vector<std::pair<std::string, int>> GetVendorPasswd() {
52 std::string passwd;
53 if (!ReadFileToString(passwd_file, &passwd)) {
54 return {};
55 }
56
57 std::vector<std::pair<std::string, int>> result;
58 auto passwd_lines = Split(passwd, "\n");
59 for (const auto& line : passwd_lines) {
60 auto split_line = Split(line, ":");
61 if (split_line.size() < 3) {
62 continue;
63 }
64 int uid = 0;
65 if (!ParseInt(split_line[2], &uid)) {
66 continue;
67 }
68 result.emplace_back(split_line[0], uid);
69 }
70 return result;
71 }
72
getpwnam(const char * login)73 passwd* getpwnam(const char* login) { // NOLINT: implementing bad function.
74 // This isn't thread safe, but that's okay for our purposes.
75 static char static_name[32] = "";
76 static char static_dir[32] = "/";
77 static char static_shell[32] = "/system/bin/sh";
78 static passwd static_passwd = {
79 .pw_name = static_name,
80 .pw_dir = static_dir,
81 .pw_shell = static_shell,
82 .pw_uid = 0,
83 .pw_gid = 0,
84 };
85
86 for (size_t n = 0; n < android_id_count; ++n) {
87 if (!strcmp(android_ids[n].name, login)) {
88 snprintf(static_name, sizeof(static_name), "%s", android_ids[n].name);
89 static_passwd.pw_uid = android_ids[n].aid;
90 static_passwd.pw_gid = android_ids[n].aid;
91 return &static_passwd;
92 }
93 }
94
95 static const auto vendor_passwd = GetVendorPasswd();
96
97 for (const auto& [name, uid] : vendor_passwd) {
98 if (name == login) {
99 snprintf(static_name, sizeof(static_name), "%s", name.c_str());
100 static_passwd.pw_uid = uid;
101 static_passwd.pw_gid = uid;
102 return &static_passwd;
103 }
104 }
105
106 unsigned int oem_uid;
107 if (sscanf(login, "oem_%u", &oem_uid) == 1) {
108 snprintf(static_name, sizeof(static_name), "%s", login);
109 static_passwd.pw_uid = oem_uid;
110 static_passwd.pw_gid = oem_uid;
111 return &static_passwd;
112 }
113
114 errno = ENOENT;
115 return nullptr;
116 }
117
118 namespace android {
119 namespace init {
120
do_stub(const BuiltinArguments & args)121 static Result<Success> do_stub(const BuiltinArguments& args) {
122 return Success();
123 }
124
125 #include "generated_stub_builtin_function_map.h"
126
main(int argc,char ** argv)127 int main(int argc, char** argv) {
128 android::base::InitLogging(argv, &android::base::StdioLogger);
129 android::base::SetMinimumLogSeverity(android::base::ERROR);
130
131 if (argc != 2 && argc != 3) {
132 LOG(ERROR) << "Usage: " << argv[0] << " <init rc file> [passwd file]";
133 return EXIT_FAILURE;
134 }
135
136 if (argc == 3) {
137 passwd_file = argv[2];
138 }
139
140 const BuiltinFunctionMap function_map;
141 Action::set_function_map(&function_map);
142 ActionManager& am = ActionManager::GetInstance();
143 ServiceList& sl = ServiceList::GetInstance();
144 Parser parser;
145 parser.AddSectionParser("service", std::make_unique<ServiceParser>(&sl, nullptr));
146 parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
147 parser.AddSectionParser("import", std::make_unique<HostImportParser>());
148
149 if (!parser.ParseConfigFileInsecure(argv[1])) {
150 LOG(ERROR) << "Failed to open init rc script '" << argv[1] << "'";
151 return EXIT_FAILURE;
152 }
153 if (parser.parse_error_count() > 0) {
154 LOG(ERROR) << "Failed to parse init script '" << argv[1] << "' with "
155 << parser.parse_error_count() << " errors";
156 return EXIT_FAILURE;
157 }
158 return EXIT_SUCCESS;
159 }
160
161 } // namespace init
162 } // namespace android
163
main(int argc,char ** argv)164 int main(int argc, char** argv) {
165 return android::init::main(argc, argv);
166 }
167