summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'init/util.cpp')
-rw-r--r--init/util.cpp191
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
55static 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
50using android::base::boot_clock;
51using 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.
56bool 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 */
81unsigned 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 */
95int create_socket(const char *name, int type, mode_t perm, uid_t uid, 86int 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
164bool read_file(const std::string& path, std::string* content) { 162bool 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
188bool write_file(const std::string& path, const std::string& content) { 192bool 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
202boot_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
209int mkdir_recursive(const char *pathname, mode_t mode) 208int 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 */
247void 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
264int wait_for_file(const char* filename, std::chrono::nanoseconds timeout) { 223int 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
288int make_dir(const char *path, mode_t mode) 247int 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
311int 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 */