diff options
Diffstat (limited to 'init/util.cpp')
-rw-r--r-- | init/util.cpp | 191 |
1 files changed, 72 insertions, 119 deletions
diff --git a/init/util.cpp b/init/util.cpp index 4e3537b76..75f81b946 100644 --- a/init/util.cpp +++ b/init/util.cpp | |||
@@ -14,25 +14,20 @@ | |||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "util.h" | ||
18 | |||
17 | #include <ctype.h> | 19 | #include <ctype.h> |
18 | #include <errno.h> | 20 | #include <errno.h> |
19 | #include <fcntl.h> | 21 | #include <fcntl.h> |
20 | #include <ftw.h> | ||
21 | #include <pwd.h> | 22 | #include <pwd.h> |
22 | #include <stdarg.h> | 23 | #include <stdarg.h> |
23 | #include <stdlib.h> | ||
24 | #include <stdio.h> | 24 | #include <stdio.h> |
25 | #include <stdlib.h> | ||
25 | #include <string.h> | 26 | #include <string.h> |
26 | #include <time.h> | ||
27 | #include <unistd.h> | ||
28 | |||
29 | #include <selinux/android.h> | ||
30 | #include <selinux/label.h> | ||
31 | |||
32 | #include <sys/socket.h> | 27 | #include <sys/socket.h> |
33 | #include <sys/stat.h> | ||
34 | #include <sys/types.h> | ||
35 | #include <sys/un.h> | 28 | #include <sys/un.h> |
29 | #include <time.h> | ||
30 | #include <unistd.h> | ||
36 | 31 | ||
37 | #include <thread> | 32 | #include <thread> |
38 | 33 | ||
@@ -42,59 +37,54 @@ | |||
42 | #include <android-base/stringprintf.h> | 37 | #include <android-base/stringprintf.h> |
43 | #include <android-base/strings.h> | 38 | #include <android-base/strings.h> |
44 | #include <android-base/unique_fd.h> | 39 | #include <android-base/unique_fd.h> |
45 | |||
46 | #include <cutils/android_reboot.h> | 40 | #include <cutils/android_reboot.h> |
47 | /* for ANDROID_SOCKET_* */ | ||
48 | #include <cutils/sockets.h> | 41 | #include <cutils/sockets.h> |
42 | #include <selinux/android.h> | ||
49 | 43 | ||
50 | #include "init.h" | ||
51 | #include "log.h" | ||
52 | #include "reboot.h" | 44 | #include "reboot.h" |
53 | #include "util.h" | ||
54 | 45 | ||
55 | static unsigned int do_decode_uid(const char *s) | 46 | #ifdef _INIT_INIT_H |
56 | { | 47 | #error "Do not include init.h in files used by ueventd or watchdogd; it will expose init's globals" |
57 | unsigned int v; | 48 | #endif |
49 | |||
50 | using android::base::boot_clock; | ||
51 | using namespace std::literals::string_literals; | ||
58 | 52 | ||
59 | if (!s || *s == '\0') | 53 | // DecodeUid() - decodes and returns the given string, which can be either the |
60 | return UINT_MAX; | 54 | // numeric or name representation, into the integer uid or gid. Returns |
55 | // UINT_MAX on error. | ||
56 | bool DecodeUid(const std::string& name, uid_t* uid, std::string* err) { | ||
57 | *uid = UINT_MAX; | ||
58 | *err = ""; | ||
61 | 59 | ||
62 | if (isalpha(s[0])) { | 60 | if (isalpha(name[0])) { |
63 | struct passwd* pwd = getpwnam(s); | 61 | passwd* pwd = getpwnam(name.c_str()); |
64 | if (!pwd) | 62 | if (!pwd) { |
65 | return UINT_MAX; | 63 | *err = "getpwnam failed: "s + strerror(errno); |
66 | return pwd->pw_uid; | 64 | return false; |
65 | } | ||
66 | *uid = pwd->pw_uid; | ||
67 | return true; | ||
67 | } | 68 | } |
68 | 69 | ||
69 | errno = 0; | 70 | errno = 0; |
70 | v = (unsigned int) strtoul(s, 0, 0); | 71 | uid_t result = static_cast<uid_t>(strtoul(name.c_str(), 0, 0)); |
71 | if (errno) | 72 | if (errno) { |
72 | return UINT_MAX; | 73 | *err = "strtoul failed: "s + strerror(errno); |
73 | return v; | 74 | return false; |
74 | } | ||
75 | |||
76 | /* | ||
77 | * decode_uid - decodes and returns the given string, which can be either the | ||
78 | * numeric or name representation, into the integer uid or gid. Returns | ||
79 | * UINT_MAX on error. | ||
80 | */ | ||
81 | unsigned int decode_uid(const char *s) { | ||
82 | unsigned int v = do_decode_uid(s); | ||
83 | if (v == UINT_MAX) { | ||
84 | LOG(ERROR) << "decode_uid: Unable to find UID for '" << s << "'; returning UINT_MAX"; | ||
85 | } | 75 | } |
86 | return v; | 76 | *uid = result; |
77 | return true; | ||
87 | } | 78 | } |
88 | 79 | ||
89 | /* | 80 | /* |
90 | * create_socket - creates a Unix domain socket in ANDROID_SOCKET_DIR | 81 | * CreateSocket - creates a Unix domain socket in ANDROID_SOCKET_DIR |
91 | * ("/dev/socket") as dictated in init.rc. This socket is inherited by the | 82 | * ("/dev/socket") as dictated in init.rc. This socket is inherited by the |
92 | * daemon. We communicate the file descriptor's value via the environment | 83 | * daemon. We communicate the file descriptor's value via the environment |
93 | * variable ANDROID_SOCKET_ENV_PREFIX<name> ("ANDROID_SOCKET_foo"). | 84 | * variable ANDROID_SOCKET_ENV_PREFIX<name> ("ANDROID_SOCKET_foo"). |
94 | */ | 85 | */ |
95 | int create_socket(const char *name, int type, mode_t perm, uid_t uid, | 86 | int CreateSocket(const char* name, int type, bool passcred, mode_t perm, uid_t uid, gid_t gid, |
96 | gid_t gid, const char *socketcon) | 87 | const char* socketcon, selabel_handle* sehandle) { |
97 | { | ||
98 | if (socketcon) { | 88 | if (socketcon) { |
99 | if (setsockcreatecon(socketcon) == -1) { | 89 | if (setsockcreatecon(socketcon) == -1) { |
100 | PLOG(ERROR) << "setsockcreatecon(\"" << socketcon << "\") failed"; | 90 | PLOG(ERROR) << "setsockcreatecon(\"" << socketcon << "\") failed"; |
@@ -128,6 +118,14 @@ int create_socket(const char *name, int type, mode_t perm, uid_t uid, | |||
128 | } | 118 | } |
129 | } | 119 | } |
130 | 120 | ||
121 | if (passcred) { | ||
122 | int on = 1; | ||
123 | if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) { | ||
124 | PLOG(ERROR) << "Failed to set SO_PASSCRED '" << name << "'"; | ||
125 | return -1; | ||
126 | } | ||
127 | } | ||
128 | |||
131 | int ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr)); | 129 | int ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr)); |
132 | int savederrno = errno; | 130 | int savederrno = errno; |
133 | 131 | ||
@@ -161,12 +159,14 @@ out_unlink: | |||
161 | return -1; | 159 | return -1; |
162 | } | 160 | } |
163 | 161 | ||
164 | bool read_file(const std::string& path, std::string* content) { | 162 | bool ReadFile(const std::string& path, std::string* content, std::string* err) { |
165 | content->clear(); | 163 | content->clear(); |
164 | *err = ""; | ||
166 | 165 | ||
167 | android::base::unique_fd fd( | 166 | android::base::unique_fd fd( |
168 | TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC))); | 167 | TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC))); |
169 | if (fd == -1) { | 168 | if (fd == -1) { |
169 | *err = "Unable to open '" + path + "': " + strerror(errno); | ||
170 | return false; | 170 | return false; |
171 | } | 171 | } |
172 | 172 | ||
@@ -174,93 +174,52 @@ bool read_file(const std::string& path, std::string* content) { | |||
174 | // or group-writable files. | 174 | // or group-writable files. |
175 | struct stat sb; | 175 | struct stat sb; |
176 | if (fstat(fd, &sb) == -1) { | 176 | if (fstat(fd, &sb) == -1) { |
177 | PLOG(ERROR) << "fstat failed for '" << path << "'"; | 177 | *err = "fstat failed for '" + path + "': " + strerror(errno); |
178 | return false; | 178 | return false; |
179 | } | 179 | } |
180 | if ((sb.st_mode & (S_IWGRP | S_IWOTH)) != 0) { | 180 | if ((sb.st_mode & (S_IWGRP | S_IWOTH)) != 0) { |
181 | LOG(ERROR) << "skipping insecure file '" << path << "'"; | 181 | *err = "Skipping insecure file '" + path + "'"; |
182 | return false; | 182 | return false; |
183 | } | 183 | } |
184 | 184 | ||
185 | return android::base::ReadFdToString(fd, content); | 185 | if (!android::base::ReadFdToString(fd, content)) { |
186 | *err = "Unable to read '" + path + "': " + strerror(errno); | ||
187 | return false; | ||
188 | } | ||
189 | return true; | ||
186 | } | 190 | } |
187 | 191 | ||
188 | bool write_file(const std::string& path, const std::string& content) { | 192 | bool WriteFile(const std::string& path, const std::string& content, std::string* err) { |
193 | *err = ""; | ||
194 | |||
189 | android::base::unique_fd fd(TEMP_FAILURE_RETRY( | 195 | android::base::unique_fd fd(TEMP_FAILURE_RETRY( |
190 | open(path.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0600))); | 196 | open(path.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0600))); |
191 | if (fd == -1) { | 197 | if (fd == -1) { |
192 | PLOG(ERROR) << "write_file: Unable to open '" << path << "'"; | 198 | *err = "Unable to open '" + path + "': " + strerror(errno); |
193 | return false; | 199 | return false; |
194 | } | 200 | } |
195 | bool success = android::base::WriteStringToFd(content, fd); | 201 | if (!android::base::WriteStringToFd(content, fd)) { |
196 | if (!success) { | 202 | *err = "Unable to write to '" + path + "': " + strerror(errno); |
197 | PLOG(ERROR) << "write_file: Unable to write to '" << path << "'"; | 203 | return false; |
198 | } | 204 | } |
199 | return success; | 205 | return true; |
200 | } | ||
201 | |||
202 | boot_clock::time_point boot_clock::now() { | ||
203 | timespec ts; | ||
204 | clock_gettime(CLOCK_BOOTTIME, &ts); | ||
205 | return boot_clock::time_point(std::chrono::seconds(ts.tv_sec) + | ||
206 | std::chrono::nanoseconds(ts.tv_nsec)); | ||
207 | } | 206 | } |
208 | 207 | ||
209 | int mkdir_recursive(const char *pathname, mode_t mode) | 208 | int mkdir_recursive(const std::string& path, mode_t mode, selabel_handle* sehandle) { |
210 | { | 209 | std::string::size_type slash = 0; |
211 | char buf[128]; | 210 | while ((slash = path.find('/', slash + 1)) != std::string::npos) { |
212 | const char *slash; | 211 | auto directory = path.substr(0, slash); |
213 | const char *p = pathname; | 212 | struct stat info; |
214 | int width; | 213 | if (stat(directory.c_str(), &info) != 0) { |
215 | int ret; | 214 | auto ret = make_dir(directory.c_str(), mode, sehandle); |
216 | struct stat info; | 215 | if (ret && errno != EEXIST) return ret; |
217 | |||
218 | while ((slash = strchr(p, '/')) != NULL) { | ||
219 | width = slash - pathname; | ||
220 | p = slash + 1; | ||
221 | if (width < 0) | ||
222 | break; | ||
223 | if (width == 0) | ||
224 | continue; | ||
225 | if ((unsigned int)width > sizeof(buf) - 1) { | ||
226 | LOG(ERROR) << "path too long for mkdir_recursive"; | ||
227 | return -1; | ||
228 | } | ||
229 | memcpy(buf, pathname, width); | ||
230 | buf[width] = 0; | ||
231 | if (stat(buf, &info) != 0) { | ||
232 | ret = make_dir(buf, mode); | ||
233 | if (ret && errno != EEXIST) | ||
234 | return ret; | ||
235 | } | 216 | } |
236 | } | 217 | } |
237 | ret = make_dir(pathname, mode); | 218 | auto ret = make_dir(path.c_str(), mode, sehandle); |
238 | if (ret && errno != EEXIST) | 219 | if (ret && errno != EEXIST) return ret; |
239 | return ret; | ||
240 | return 0; | 220 | return 0; |
241 | } | 221 | } |
242 | 222 | ||
243 | /* | ||
244 | * replaces any unacceptable characters with '_', the | ||
245 | * length of the resulting string is equal to the input string | ||
246 | */ | ||
247 | void sanitize(char *s) | ||
248 | { | ||
249 | const char* accept = | ||
250 | "abcdefghijklmnopqrstuvwxyz" | ||
251 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | ||
252 | "0123456789" | ||
253 | "_-."; | ||
254 | |||
255 | if (!s) | ||
256 | return; | ||
257 | |||
258 | while (*s) { | ||
259 | s += strspn(s, accept); | ||
260 | if (*s) *s++ = '_'; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | int wait_for_file(const char* filename, std::chrono::nanoseconds timeout) { | 223 | int wait_for_file(const char* filename, std::chrono::nanoseconds timeout) { |
265 | boot_clock::time_point timeout_time = boot_clock::now() + timeout; | 224 | boot_clock::time_point timeout_time = boot_clock::now() + timeout; |
266 | while (boot_clock::now() < timeout_time) { | 225 | while (boot_clock::now() < timeout_time) { |
@@ -285,8 +244,7 @@ void import_kernel_cmdline(bool in_qemu, | |||
285 | } | 244 | } |
286 | } | 245 | } |
287 | 246 | ||
288 | int make_dir(const char *path, mode_t mode) | 247 | int make_dir(const char* path, mode_t mode, selabel_handle* sehandle) { |
289 | { | ||
290 | int rc; | 248 | int rc; |
291 | 249 | ||
292 | char *secontext = NULL; | 250 | char *secontext = NULL; |
@@ -308,11 +266,6 @@ int make_dir(const char *path, mode_t mode) | |||
308 | return rc; | 266 | return rc; |
309 | } | 267 | } |
310 | 268 | ||
311 | int restorecon(const char* pathname, int flags) | ||
312 | { | ||
313 | return selinux_android_restorecon(pathname, flags); | ||
314 | } | ||
315 | |||
316 | /* | 269 | /* |
317 | * Writes hex_len hex characters (1/2 byte) to hex from bytes. | 270 | * Writes hex_len hex characters (1/2 byte) to hex from bytes. |
318 | */ | 271 | */ |