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