• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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