1 /* 2 * Copyright (C) 2016 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 "fd_utils.h" 18 19 #include <algorithm> 20 21 #include <fcntl.h> 22 #include <grp.h> 23 #include <stdlib.h> 24 #include <sys/socket.h> 25 #include <sys/types.h> 26 #include <sys/un.h> 27 #include <unistd.h> 28 29 #include <android-base/file.h> 30 #include <android-base/logging.h> 31 #include <android-base/stringprintf.h> 32 #include <android-base/strings.h> 33 34 // Static whitelist of open paths that the zygote is allowed to keep open. 35 static const char* kPathWhitelist[] = { 36 "/dev/null", 37 "/dev/socket/zygote", 38 "/dev/socket/zygote_secondary", 39 "/dev/socket/webview_zygote", 40 "/sys/kernel/debug/tracing/trace_marker", 41 "/system/framework/framework-res.apk", 42 "/dev/urandom", 43 "/dev/ion", 44 "/dev/dri/renderD129", // Fixes b/31172436 45 }; 46 47 static const char kFdPath[] = "/proc/self/fd"; 48 49 // static 50 FileDescriptorWhitelist* FileDescriptorWhitelist::Get() { 51 if (instance_ == nullptr) { 52 instance_ = new FileDescriptorWhitelist(); 53 } 54 return instance_; 55 } 56 57 bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const { 58 // Check the static whitelist path. 59 for (const auto& whitelist_path : kPathWhitelist) { 60 if (path == whitelist_path) 61 return true; 62 } 63 64 // Check any paths added to the dynamic whitelist. 65 for (const auto& whitelist_path : whitelist_) { 66 if (path == whitelist_path) 67 return true; 68 } 69 70 static const char* kFrameworksPrefix = "/system/framework/"; 71 static const char* kJarSuffix = ".jar"; 72 if (android::base::StartsWith(path, kFrameworksPrefix) 73 && android::base::EndsWith(path, kJarSuffix)) { 74 return true; 75 } 76 77 // Whitelist files needed for Runtime Resource Overlay, like these: 78 // /system/vendor/overlay/framework-res.apk 79 // /system/vendor/overlay-subdir/pg/framework-res.apk 80 // /vendor/overlay/framework-res.apk 81 // /vendor/overlay/PG/android-framework-runtime-resource-overlay.apk 82 // /data/resource-cache/system@vendor@overlay (at) framework-res.apk@idmap 83 // /data/resource-cache/system@vendor@overlay-subdir@pg (at) framework-res.apk@idmap 84 // See AssetManager.cpp for more details on overlay-subdir. 85 static const char* kOverlayDir = "/system/vendor/overlay/"; 86 static const char* kVendorOverlayDir = "/vendor/overlay"; 87 static const char* kOverlaySubdir = "/system/vendor/overlay-subdir/"; 88 static const char* kSystemProductOverlayDir = "/system/product/overlay/"; 89 static const char* kProductOverlayDir = "/product/overlay"; 90 static const char* kApkSuffix = ".apk"; 91 92 if ((android::base::StartsWith(path, kOverlayDir) 93 || android::base::StartsWith(path, kOverlaySubdir) 94 || android::base::StartsWith(path, kVendorOverlayDir) 95 || android::base::StartsWith(path, kSystemProductOverlayDir) 96 || android::base::StartsWith(path, kProductOverlayDir)) 97 && android::base::EndsWith(path, kApkSuffix) 98 && path.find("/../") == std::string::npos) { 99 return true; 100 } 101 102 static const char* kOverlayIdmapPrefix = "/data/resource-cache/"; 103 static const char* kOverlayIdmapSuffix = ".apk@idmap"; 104 if (android::base::StartsWith(path, kOverlayIdmapPrefix) 105 && android::base::EndsWith(path, kOverlayIdmapSuffix) 106 && path.find("/../") == std::string::npos) { 107 return true; 108 } 109 110 // All regular files that are placed under this path are whitelisted automatically. 111 static const char* kZygoteWhitelistPath = "/vendor/zygote_whitelist/"; 112 if (android::base::StartsWith(path, kZygoteWhitelistPath) 113 && path.find("/../") == std::string::npos) { 114 return true; 115 } 116 117 return false; 118 } 119 120 FileDescriptorWhitelist::FileDescriptorWhitelist() 121 : whitelist_() { 122 } 123 124 FileDescriptorWhitelist* FileDescriptorWhitelist::instance_ = nullptr; 125 126 // Keeps track of all relevant information (flags, offset etc.) of an 127 // open zygote file descriptor. 128 class FileDescriptorInfo { 129 public: 130 // Create a FileDescriptorInfo for a given file descriptor. Returns 131 // |NULL| if an error occurred. 132 static FileDescriptorInfo* CreateFromFd(int fd, std::string* error_msg); 133 134 // Checks whether the file descriptor associated with this object 135 // refers to the same description. 136 bool Restat() const; 137 138 bool ReopenOrDetach(std::string* error_msg) const; 139 140 const int fd; 141 const struct stat stat; 142 const std::string file_path; 143 const int open_flags; 144 const int fd_flags; 145 const int fs_flags; 146 const off_t offset; 147 const bool is_sock; 148 149 private: 150 FileDescriptorInfo(int fd); 151 152 FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags, 153 int fd_flags, int fs_flags, off_t offset); 154 155 // Returns the locally-bound name of the socket |fd|. Returns true 156 // iff. all of the following hold : 157 // 158 // - the socket's sa_family is AF_UNIX. 159 // - the length of the path is greater than zero (i.e, not an unnamed socket). 160 // - the first byte of the path isn't zero (i.e, not a socket with an abstract 161 // address). 162 static bool GetSocketName(const int fd, std::string* result); 163 164 bool DetachSocket(std::string* error_msg) const; 165 166 DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo); 167 }; 168 169 // static 170 FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd, std::string* error_msg) { 171 struct stat f_stat; 172 // This should never happen; the zygote should always have the right set 173 // of permissions required to stat all its open files. 174 if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) { 175 *error_msg = android::base::StringPrintf("Unable to stat %d", fd); 176 return nullptr; 177 } 178 179 const FileDescriptorWhitelist* whitelist = FileDescriptorWhitelist::Get(); 180 181 if (S_ISSOCK(f_stat.st_mode)) { 182 std::string socket_name; 183 if (!GetSocketName(fd, &socket_name)) { 184 *error_msg = "Unable to get socket name"; 185 return nullptr; 186 } 187 188 if (!whitelist->IsAllowed(socket_name)) { 189 *error_msg = android::base::StringPrintf("Socket name not whitelisted : %s (fd=%d)", 190 socket_name.c_str(), 191 fd); 192 return nullptr; 193 } 194 195 return new FileDescriptorInfo(fd); 196 } 197 198 // We only handle whitelisted regular files and character devices. Whitelisted 199 // character devices must provide a guarantee of sensible behaviour when 200 // reopened. 201 // 202 // S_ISDIR : Not supported. (We could if we wanted to, but it's unused). 203 // S_ISLINK : Not supported. 204 // S_ISBLK : Not supported. 205 // S_ISFIFO : Not supported. Note that the zygote uses pipes to communicate 206 // with the child process across forks but those should have been closed 207 // before we got to this point. 208 if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) { 209 *error_msg = android::base::StringPrintf("Unsupported st_mode %u", f_stat.st_mode); 210 return nullptr; 211 } 212 213 std::string file_path; 214 const std::string fd_path = android::base::StringPrintf("/proc/self/fd/%d", fd); 215 if (!android::base::Readlink(fd_path, &file_path)) { 216 *error_msg = android::base::StringPrintf("Could not read fd link %s: %s", 217 fd_path.c_str(), 218 strerror(errno)); 219 return nullptr; 220 } 221 222 if (!whitelist->IsAllowed(file_path)) { 223 *error_msg = std::string("Not whitelisted : ").append(file_path); 224 return nullptr; 225 } 226 227 // File descriptor flags : currently on FD_CLOEXEC. We can set these 228 // using F_SETFD - we're single threaded at this point of execution so 229 // there won't be any races. 230 const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD)); 231 if (fd_flags == -1) { 232 *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_GETFD) (%s): %s", 233 fd, 234 file_path.c_str(), 235 strerror(errno)); 236 return nullptr; 237 } 238 239 // File status flags : 240 // - File access mode : (O_RDONLY, O_WRONLY...) we'll pass these through 241 // to the open() call. 242 // 243 // - File creation flags : (O_CREAT, O_EXCL...) - there's not much we can 244 // do about these, since the file has already been created. We shall ignore 245 // them here. 246 // 247 // - Other flags : We'll have to set these via F_SETFL. On linux, F_SETFL 248 // can only set O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK. 249 // In particular, it can't set O_SYNC and O_DSYNC. We'll have to test for 250 // their presence and pass them in to open(). 251 int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL)); 252 if (fs_flags == -1) { 253 *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_GETFL) (%s): %s", 254 fd, 255 file_path.c_str(), 256 strerror(errno)); 257 return nullptr; 258 } 259 260 // File offset : Ignore the offset for non seekable files. 261 const off_t offset = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR)); 262 263 // We pass the flags that open accepts to open, and use F_SETFL for 264 // the rest of them. 265 static const int kOpenFlags = (O_RDONLY | O_WRONLY | O_RDWR | O_DSYNC | O_SYNC); 266 int open_flags = fs_flags & (kOpenFlags); 267 fs_flags = fs_flags & (~(kOpenFlags)); 268 269 return new FileDescriptorInfo(f_stat, file_path, fd, open_flags, fd_flags, fs_flags, offset); 270 } 271 272 bool FileDescriptorInfo::Restat() const { 273 struct stat f_stat; 274 if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) { 275 PLOG(ERROR) << "Unable to restat fd " << fd; 276 return false; 277 } 278 279 return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev; 280 } 281 282 bool FileDescriptorInfo::ReopenOrDetach(std::string* error_msg) const { 283 if (is_sock) { 284 return DetachSocket(error_msg); 285 } 286 287 // NOTE: This might happen if the file was unlinked after being opened. 288 // It's a common pattern in the case of temporary files and the like but 289 // we should not allow such usage from the zygote. 290 const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags)); 291 292 if (new_fd == -1) { 293 *error_msg = android::base::StringPrintf("Failed open(%s, %i): %s", 294 file_path.c_str(), 295 open_flags, 296 strerror(errno)); 297 return false; 298 } 299 300 if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) { 301 close(new_fd); 302 *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_SETFD, %d) (%s): %s", 303 new_fd, 304 fd_flags, 305 file_path.c_str(), 306 strerror(errno)); 307 return false; 308 } 309 310 if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) { 311 close(new_fd); 312 *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_SETFL, %d) (%s): %s", 313 new_fd, 314 fs_flags, 315 file_path.c_str(), 316 strerror(errno)); 317 return false; 318 } 319 320 if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) { 321 close(new_fd); 322 *error_msg = android::base::StringPrintf("Failed lseek64(%d, SEEK_SET) (%s): %s", 323 new_fd, 324 file_path.c_str(), 325 strerror(errno)); 326 return false; 327 } 328 329 if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) { 330 close(new_fd); 331 *error_msg = android::base::StringPrintf("Failed dup2(%d, %d) (%s): %s", 332 fd, 333 new_fd, 334 file_path.c_str(), 335 strerror(errno)); 336 return false; 337 } 338 339 close(new_fd); 340 341 return true; 342 } 343 344 FileDescriptorInfo::FileDescriptorInfo(int fd) : 345 fd(fd), 346 stat(), 347 open_flags(0), 348 fd_flags(0), 349 fs_flags(0), 350 offset(0), 351 is_sock(true) { 352 } 353 354 FileDescriptorInfo::FileDescriptorInfo(struct stat stat, const std::string& file_path, 355 int fd, int open_flags, int fd_flags, int fs_flags, 356 off_t offset) : 357 fd(fd), 358 stat(stat), 359 file_path(file_path), 360 open_flags(open_flags), 361 fd_flags(fd_flags), 362 fs_flags(fs_flags), 363 offset(offset), 364 is_sock(false) { 365 } 366 367 // static 368 bool FileDescriptorInfo::GetSocketName(const int fd, std::string* result) { 369 sockaddr_storage ss; 370 sockaddr* addr = reinterpret_cast<sockaddr*>(&ss); 371 socklen_t addr_len = sizeof(ss); 372 373 if (TEMP_FAILURE_RETRY(getsockname(fd, addr, &addr_len)) == -1) { 374 PLOG(ERROR) << "Failed getsockname(" << fd << ")"; 375 return false; 376 } 377 378 if (addr->sa_family != AF_UNIX) { 379 LOG(ERROR) << "Unsupported socket (fd=" << fd << ") with family " << addr->sa_family; 380 return false; 381 } 382 383 const sockaddr_un* unix_addr = reinterpret_cast<const sockaddr_un*>(&ss); 384 385 size_t path_len = addr_len - offsetof(struct sockaddr_un, sun_path); 386 // This is an unnamed local socket, we do not accept it. 387 if (path_len == 0) { 388 LOG(ERROR) << "Unsupported AF_UNIX socket (fd=" << fd << ") with empty path."; 389 return false; 390 } 391 392 // This is a local socket with an abstract address. Remove the leading NUL byte and 393 // add a human-readable "ABSTRACT/" prefix. 394 if (unix_addr->sun_path[0] == '\0') { 395 *result = "ABSTRACT/"; 396 result->append(&unix_addr->sun_path[1], path_len - 1); 397 return true; 398 } 399 400 // If we're here, sun_path must refer to a null terminated filesystem 401 // pathname (man 7 unix). Remove the terminator before assigning it to an 402 // std::string. 403 if (unix_addr->sun_path[path_len - 1] == '\0') { 404 --path_len; 405 } 406 407 result->assign(unix_addr->sun_path, path_len); 408 return true; 409 } 410 411 bool FileDescriptorInfo::DetachSocket(std::string* error_msg) const { 412 const int dev_null_fd = open("/dev/null", O_RDWR); 413 if (dev_null_fd < 0) { 414 *error_msg = std::string("Failed to open /dev/null: ").append(strerror(errno)); 415 return false; 416 } 417 418 if (dup2(dev_null_fd, fd) == -1) { 419 *error_msg = android::base::StringPrintf("Failed dup2 on socket descriptor %d: %s", 420 fd, 421 strerror(errno)); 422 return false; 423 } 424 425 if (close(dev_null_fd) == -1) { 426 *error_msg = android::base::StringPrintf("Failed close(%d): %s", dev_null_fd, strerror(errno)); 427 return false; 428 } 429 430 return true; 431 } 432 433 // static 434 FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore, 435 std::string* error_msg) { 436 DIR* d = opendir(kFdPath); 437 if (d == nullptr) { 438 *error_msg = std::string("Unable to open directory ").append(kFdPath); 439 return nullptr; 440 } 441 int dir_fd = dirfd(d); 442 dirent* e; 443 444 std::unordered_map<int, FileDescriptorInfo*> open_fd_map; 445 while ((e = readdir(d)) != NULL) { 446 const int fd = ParseFd(e, dir_fd); 447 if (fd == -1) { 448 continue; 449 } 450 if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) { 451 LOG(INFO) << "Ignoring open file descriptor " << fd; 452 continue; 453 } 454 455 FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd, error_msg); 456 if (info == NULL) { 457 if (closedir(d) == -1) { 458 PLOG(ERROR) << "Unable to close directory"; 459 } 460 return NULL; 461 } 462 open_fd_map[fd] = info; 463 } 464 465 if (closedir(d) == -1) { 466 *error_msg = "Unable to close directory"; 467 return nullptr; 468 } 469 return new FileDescriptorTable(open_fd_map); 470 } 471 472 bool FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore, std::string* error_msg) { 473 std::set<int> open_fds; 474 475 // First get the list of open descriptors. 476 DIR* d = opendir(kFdPath); 477 if (d == NULL) { 478 *error_msg = android::base::StringPrintf("Unable to open directory %s: %s", 479 kFdPath, 480 strerror(errno)); 481 return false; 482 } 483 484 int dir_fd = dirfd(d); 485 dirent* e; 486 while ((e = readdir(d)) != NULL) { 487 const int fd = ParseFd(e, dir_fd); 488 if (fd == -1) { 489 continue; 490 } 491 if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) { 492 LOG(INFO) << "Ignoring open file descriptor " << fd; 493 continue; 494 } 495 496 open_fds.insert(fd); 497 } 498 499 if (closedir(d) == -1) { 500 *error_msg = android::base::StringPrintf("Unable to close directory: %s", strerror(errno)); 501 return false; 502 } 503 504 return RestatInternal(open_fds, error_msg); 505 } 506 507 // Reopens all file descriptors that are contained in the table. Returns true 508 // if all descriptors were successfully re-opened or detached, and false if an 509 // error occurred. 510 bool FileDescriptorTable::ReopenOrDetach(std::string* error_msg) { 511 std::unordered_map<int, FileDescriptorInfo*>::const_iterator it; 512 for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) { 513 const FileDescriptorInfo* info = it->second; 514 if (info == NULL || !info->ReopenOrDetach(error_msg)) { 515 return false; 516 } 517 } 518 519 return true; 520 } 521 522 FileDescriptorTable::FileDescriptorTable( 523 const std::unordered_map<int, FileDescriptorInfo*>& map) 524 : open_fd_map_(map) { 525 } 526 527 bool FileDescriptorTable::RestatInternal(std::set<int>& open_fds, std::string* error_msg) { 528 bool error = false; 529 530 // Iterate through the list of file descriptors we've already recorded 531 // and check whether : 532 // 533 // (a) they continue to be open. 534 // (b) they refer to the same file. 535 // 536 // We'll only store the last error message. 537 std::unordered_map<int, FileDescriptorInfo*>::iterator it = open_fd_map_.begin(); 538 while (it != open_fd_map_.end()) { 539 std::set<int>::const_iterator element = open_fds.find(it->first); 540 if (element == open_fds.end()) { 541 // The entry from the file descriptor table is no longer in the list 542 // of open files. We warn about this condition and remove it from 543 // the list of FDs under consideration. 544 // 545 // TODO(narayan): This will be an error in a future android release. 546 // error = true; 547 // ALOGW("Zygote closed file descriptor %d.", it->first); 548 it = open_fd_map_.erase(it); 549 } else { 550 // The entry from the file descriptor table is still open. Restat 551 // it and check whether it refers to the same file. 552 const bool same_file = it->second->Restat(); 553 if (!same_file) { 554 // The file descriptor refers to a different description. We must 555 // update our entry in the table. 556 delete it->second; 557 it->second = FileDescriptorInfo::CreateFromFd(*element, error_msg); 558 if (it->second == NULL) { 559 // The descriptor no longer no longer refers to a whitelisted file. 560 // We flag an error and remove it from the list of files we're 561 // tracking. 562 error = true; 563 it = open_fd_map_.erase(it); 564 } else { 565 // Successfully restatted the file, move on to the next open FD. 566 ++it; 567 } 568 } else { 569 // It's the same file. Nothing to do here. Move on to the next open 570 // FD. 571 ++it; 572 } 573 574 // Finally, remove the FD from the set of open_fds. We do this last because 575 // |element| will not remain valid after a call to erase. 576 open_fds.erase(element); 577 } 578 } 579 580 if (open_fds.size() > 0) { 581 // The zygote has opened new file descriptors since our last inspection. 582 // We warn about this condition and add them to our table. 583 // 584 // TODO(narayan): This will be an error in a future android release. 585 // error = true; 586 // ALOGW("Zygote opened %zd new file descriptor(s).", open_fds.size()); 587 588 // TODO(narayan): This code will be removed in a future android release. 589 std::set<int>::const_iterator it; 590 for (it = open_fds.begin(); it != open_fds.end(); ++it) { 591 const int fd = (*it); 592 FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd, error_msg); 593 if (info == NULL) { 594 // A newly opened file is not on the whitelist. Flag an error and 595 // continue. 596 error = true; 597 } else { 598 // Track the newly opened file. 599 open_fd_map_[fd] = info; 600 } 601 } 602 } 603 604 return !error; 605 } 606 607 // static 608 int FileDescriptorTable::ParseFd(dirent* e, int dir_fd) { 609 char* end; 610 const int fd = strtol(e->d_name, &end, 10); 611 if ((*end) != '\0') { 612 return -1; 613 } 614 615 // Don't bother with the standard input/output/error, they're handled 616 // specially post-fork anyway. 617 if (fd <= STDERR_FILENO || fd == dir_fd) { 618 return -1; 619 } 620 621 return fd; 622 } 623