1 /* 2 * Copyright (C) 2008 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 <stdarg.h> 18 #include <stdlib.h> 19 #include <stdio.h> 20 #include <string.h> 21 #include <fcntl.h> 22 #include <ctype.h> 23 #include <errno.h> 24 #include <time.h> 25 #include <ftw.h> 26 27 #include <selinux/label.h> 28 #include <selinux/android.h> 29 30 #include <sys/stat.h> 31 #include <sys/types.h> 32 #include <sys/socket.h> 33 #include <sys/un.h> 34 35 /* for ANDROID_SOCKET_* */ 36 #include <cutils/sockets.h> 37 38 #include <private/android_filesystem_config.h> 39 40 #include "init.h" 41 #include "log.h" 42 #include "util.h" 43 44 /* 45 * android_name_to_id - returns the integer uid/gid associated with the given 46 * name, or -1U on error. 47 */ 48 static unsigned int android_name_to_id(const char *name) 49 { 50 const struct android_id_info *info = android_ids; 51 unsigned int n; 52 53 for (n = 0; n < android_id_count; n++) { 54 if (!strcmp(info[n].name, name)) 55 return info[n].aid; 56 } 57 58 return -1U; 59 } 60 61 /* 62 * decode_uid - decodes and returns the given string, which can be either the 63 * numeric or name representation, into the integer uid or gid. Returns -1U on 64 * error. 65 */ 66 unsigned int decode_uid(const char *s) 67 { 68 unsigned int v; 69 70 if (!s || *s == '\0') 71 return -1U; 72 if (isalpha(s[0])) 73 return android_name_to_id(s); 74 75 errno = 0; 76 v = (unsigned int) strtoul(s, 0, 0); 77 if (errno) 78 return -1U; 79 return v; 80 } 81 82 /* 83 * create_socket - creates a Unix domain socket in ANDROID_SOCKET_DIR 84 * ("/dev/socket") as dictated in init.rc. This socket is inherited by the 85 * daemon. We communicate the file descriptor's value via the environment 86 * variable ANDROID_SOCKET_ENV_PREFIX<name> ("ANDROID_SOCKET_foo"). 87 */ 88 int create_socket(const char *name, int type, mode_t perm, uid_t uid, 89 gid_t gid, const char *socketcon) 90 { 91 struct sockaddr_un addr; 92 int fd, ret; 93 char *filecon; 94 95 if (socketcon) 96 setsockcreatecon(socketcon); 97 98 fd = socket(PF_UNIX, type, 0); 99 if (fd < 0) { 100 ERROR("Failed to open socket '%s': %s\n", name, strerror(errno)); 101 return -1; 102 } 103 104 if (socketcon) 105 setsockcreatecon(NULL); 106 107 memset(&addr, 0 , sizeof(addr)); 108 addr.sun_family = AF_UNIX; 109 snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s", 110 name); 111 112 ret = unlink(addr.sun_path); 113 if (ret != 0 && errno != ENOENT) { 114 ERROR("Failed to unlink old socket '%s': %s\n", name, strerror(errno)); 115 goto out_close; 116 } 117 118 filecon = NULL; 119 if (sehandle) { 120 ret = selabel_lookup(sehandle, &filecon, addr.sun_path, S_IFSOCK); 121 if (ret == 0) 122 setfscreatecon(filecon); 123 } 124 125 ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr)); 126 if (ret) { 127 ERROR("Failed to bind socket '%s': %s\n", name, strerror(errno)); 128 goto out_unlink; 129 } 130 131 setfscreatecon(NULL); 132 freecon(filecon); 133 134 chown(addr.sun_path, uid, gid); 135 chmod(addr.sun_path, perm); 136 137 INFO("Created socket '%s' with mode '%o', user '%d', group '%d'\n", 138 addr.sun_path, perm, uid, gid); 139 140 return fd; 141 142 out_unlink: 143 unlink(addr.sun_path); 144 out_close: 145 close(fd); 146 return -1; 147 } 148 149 /* reads a file, making sure it is terminated with \n \0 */ 150 void *read_file(const char *fn, unsigned *_sz) 151 { 152 char *data; 153 int sz; 154 int fd; 155 struct stat sb; 156 157 data = 0; 158 fd = open(fn, O_RDONLY); 159 if(fd < 0) return 0; 160 161 // for security reasons, disallow world-writable 162 // or group-writable files 163 if (fstat(fd, &sb) < 0) { 164 ERROR("fstat failed for '%s'\n", fn); 165 goto oops; 166 } 167 if ((sb.st_mode & (S_IWGRP | S_IWOTH)) != 0) { 168 ERROR("skipping insecure file '%s'\n", fn); 169 goto oops; 170 } 171 172 sz = lseek(fd, 0, SEEK_END); 173 if(sz < 0) goto oops; 174 175 if(lseek(fd, 0, SEEK_SET) != 0) goto oops; 176 177 data = (char*) malloc(sz + 2); 178 if(data == 0) goto oops; 179 180 if(read(fd, data, sz) != sz) goto oops; 181 close(fd); 182 data[sz] = '\n'; 183 data[sz+1] = 0; 184 if(_sz) *_sz = sz; 185 return data; 186 187 oops: 188 close(fd); 189 if(data != 0) free(data); 190 return 0; 191 } 192 193 #define MAX_MTD_PARTITIONS 16 194 195 static struct { 196 char name[16]; 197 int number; 198 } mtd_part_map[MAX_MTD_PARTITIONS]; 199 200 static int mtd_part_count = -1; 201 202 static void find_mtd_partitions(void) 203 { 204 int fd; 205 char buf[1024]; 206 char *pmtdbufp; 207 ssize_t pmtdsize; 208 int r; 209 210 fd = open("/proc/mtd", O_RDONLY); 211 if (fd < 0) 212 return; 213 214 buf[sizeof(buf) - 1] = '\0'; 215 pmtdsize = read(fd, buf, sizeof(buf) - 1); 216 pmtdbufp = buf; 217 while (pmtdsize > 0) { 218 int mtdnum, mtdsize, mtderasesize; 219 char mtdname[16]; 220 mtdname[0] = '\0'; 221 mtdnum = -1; 222 r = sscanf(pmtdbufp, "mtd%d: %x %x %15s", 223 &mtdnum, &mtdsize, &mtderasesize, mtdname); 224 if ((r == 4) && (mtdname[0] == '"')) { 225 char *x = strchr(mtdname + 1, '"'); 226 if (x) { 227 *x = 0; 228 } 229 INFO("mtd partition %d, %s\n", mtdnum, mtdname + 1); 230 if (mtd_part_count < MAX_MTD_PARTITIONS) { 231 strcpy(mtd_part_map[mtd_part_count].name, mtdname + 1); 232 mtd_part_map[mtd_part_count].number = mtdnum; 233 mtd_part_count++; 234 } else { 235 ERROR("too many mtd partitions\n"); 236 } 237 } 238 while (pmtdsize > 0 && *pmtdbufp != '\n') { 239 pmtdbufp++; 240 pmtdsize--; 241 } 242 if (pmtdsize > 0) { 243 pmtdbufp++; 244 pmtdsize--; 245 } 246 } 247 close(fd); 248 } 249 250 int mtd_name_to_number(const char *name) 251 { 252 int n; 253 if (mtd_part_count < 0) { 254 mtd_part_count = 0; 255 find_mtd_partitions(); 256 } 257 for (n = 0; n < mtd_part_count; n++) { 258 if (!strcmp(name, mtd_part_map[n].name)) { 259 return mtd_part_map[n].number; 260 } 261 } 262 return -1; 263 } 264 265 /* 266 * gettime() - returns the time in seconds of the system's monotonic clock or 267 * zero on error. 268 */ 269 time_t gettime(void) 270 { 271 struct timespec ts; 272 int ret; 273 274 ret = clock_gettime(CLOCK_MONOTONIC, &ts); 275 if (ret < 0) { 276 ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno)); 277 return 0; 278 } 279 280 return ts.tv_sec; 281 } 282 283 int mkdir_recursive(const char *pathname, mode_t mode) 284 { 285 char buf[128]; 286 const char *slash; 287 const char *p = pathname; 288 int width; 289 int ret; 290 struct stat info; 291 292 while ((slash = strchr(p, '/')) != NULL) { 293 width = slash - pathname; 294 p = slash + 1; 295 if (width < 0) 296 break; 297 if (width == 0) 298 continue; 299 if ((unsigned int)width > sizeof(buf) - 1) { 300 ERROR("path too long for mkdir_recursive\n"); 301 return -1; 302 } 303 memcpy(buf, pathname, width); 304 buf[width] = 0; 305 if (stat(buf, &info) != 0) { 306 ret = make_dir(buf, mode); 307 if (ret && errno != EEXIST) 308 return ret; 309 } 310 } 311 ret = make_dir(pathname, mode); 312 if (ret && errno != EEXIST) 313 return ret; 314 return 0; 315 } 316 317 /* 318 * replaces any unacceptable characters with '_', the 319 * length of the resulting string is equal to the input string 320 */ 321 void sanitize(char *s) 322 { 323 const char* accept = 324 "abcdefghijklmnopqrstuvwxyz" 325 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 326 "0123456789" 327 "_-."; 328 329 if (!s) 330 return; 331 332 while (*s) { 333 s += strspn(s, accept); 334 if (*s) *s++ = '_'; 335 } 336 } 337 338 void make_link(const char *oldpath, const char *newpath) 339 { 340 int ret; 341 char buf[256]; 342 char *slash; 343 int width; 344 345 slash = strrchr(newpath, '/'); 346 if (!slash) 347 return; 348 width = slash - newpath; 349 if (width <= 0 || width > (int)sizeof(buf) - 1) 350 return; 351 memcpy(buf, newpath, width); 352 buf[width] = 0; 353 ret = mkdir_recursive(buf, 0755); 354 if (ret) 355 ERROR("Failed to create directory %s: %s (%d)\n", buf, strerror(errno), errno); 356 357 ret = symlink(oldpath, newpath); 358 if (ret && errno != EEXIST) 359 ERROR("Failed to symlink %s to %s: %s (%d)\n", oldpath, newpath, strerror(errno), errno); 360 } 361 362 void remove_link(const char *oldpath, const char *newpath) 363 { 364 char path[256]; 365 ssize_t ret; 366 ret = readlink(newpath, path, sizeof(path) - 1); 367 if (ret <= 0) 368 return; 369 path[ret] = 0; 370 if (!strcmp(path, oldpath)) 371 unlink(newpath); 372 } 373 374 int wait_for_file(const char *filename, int timeout) 375 { 376 struct stat info; 377 time_t timeout_time = gettime() + timeout; 378 int ret = -1; 379 380 while (gettime() < timeout_time && ((ret = stat(filename, &info)) < 0)) 381 usleep(10000); 382 383 return ret; 384 } 385 386 void open_devnull_stdio(void) 387 { 388 int fd; 389 static const char *name = "/dev/__null__"; 390 if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) { 391 fd = open(name, O_RDWR); 392 unlink(name); 393 if (fd >= 0) { 394 dup2(fd, 0); 395 dup2(fd, 1); 396 dup2(fd, 2); 397 if (fd > 2) { 398 close(fd); 399 } 400 return; 401 } 402 } 403 404 exit(1); 405 } 406 407 void get_hardware_name(char *hardware, unsigned int *revision) 408 { 409 const char *cpuinfo = "/proc/cpuinfo"; 410 char *data = NULL; 411 size_t len = 0, limit = 1024; 412 int fd, n; 413 char *x, *hw, *rev; 414 415 /* Hardware string was provided on kernel command line */ 416 if (hardware[0]) 417 return; 418 419 fd = open(cpuinfo, O_RDONLY); 420 if (fd < 0) return; 421 422 for (;;) { 423 x = realloc(data, limit); 424 if (!x) { 425 ERROR("Failed to allocate memory to read %s\n", cpuinfo); 426 goto done; 427 } 428 data = x; 429 430 n = read(fd, data + len, limit - len); 431 if (n < 0) { 432 ERROR("Failed reading %s: %s (%d)\n", cpuinfo, strerror(errno), errno); 433 goto done; 434 } 435 len += n; 436 437 if (len < limit) 438 break; 439 440 /* We filled the buffer, so increase size and loop to read more */ 441 limit *= 2; 442 } 443 444 data[len] = 0; 445 hw = strstr(data, "\nHardware"); 446 rev = strstr(data, "\nRevision"); 447 448 if (hw) { 449 x = strstr(hw, ": "); 450 if (x) { 451 x += 2; 452 n = 0; 453 while (*x && *x != '\n') { 454 if (!isspace(*x)) 455 hardware[n++] = tolower(*x); 456 x++; 457 if (n == 31) break; 458 } 459 hardware[n] = 0; 460 } 461 } 462 463 if (rev) { 464 x = strstr(rev, ": "); 465 if (x) { 466 *revision = strtoul(x + 2, 0, 16); 467 } 468 } 469 470 done: 471 close(fd); 472 free(data); 473 } 474 475 void import_kernel_cmdline(int in_qemu, 476 void (*import_kernel_nv)(char *name, int in_qemu)) 477 { 478 char cmdline[2048]; 479 char *ptr; 480 int fd; 481 482 fd = open("/proc/cmdline", O_RDONLY); 483 if (fd >= 0) { 484 int n = read(fd, cmdline, sizeof(cmdline) - 1); 485 if (n < 0) n = 0; 486 487 /* get rid of trailing newline, it happens */ 488 if (n > 0 && cmdline[n-1] == '\n') n--; 489 490 cmdline[n] = 0; 491 close(fd); 492 } else { 493 cmdline[0] = 0; 494 } 495 496 ptr = cmdline; 497 while (ptr && *ptr) { 498 char *x = strchr(ptr, ' '); 499 if (x != 0) *x++ = 0; 500 import_kernel_nv(ptr, in_qemu); 501 ptr = x; 502 } 503 } 504 505 int make_dir(const char *path, mode_t mode) 506 { 507 int rc; 508 509 char *secontext = NULL; 510 511 if (sehandle) { 512 selabel_lookup(sehandle, &secontext, path, mode); 513 setfscreatecon(secontext); 514 } 515 516 rc = mkdir(path, mode); 517 518 if (secontext) { 519 int save_errno = errno; 520 freecon(secontext); 521 setfscreatecon(NULL); 522 errno = save_errno; 523 } 524 525 return rc; 526 } 527 528 int restorecon(const char* pathname) 529 { 530 return selinux_android_restorecon(pathname, 0); 531 } 532 533 int restorecon_recursive(const char* pathname) 534 { 535 return selinux_android_restorecon(pathname, SELINUX_ANDROID_RESTORECON_RECURSE); 536 } 537