18225b7c95185dfbfe67da105df4402430784393cRobert Sesek/*
28225b7c95185dfbfe67da105df4402430784393cRobert Sesek * Copyright (C) 2016 The Android Open Source Project
38225b7c95185dfbfe67da105df4402430784393cRobert Sesek *
48225b7c95185dfbfe67da105df4402430784393cRobert Sesek * Licensed under the Apache License, Version 2.0 (the "License");
58225b7c95185dfbfe67da105df4402430784393cRobert Sesek * you may not use this file except in compliance with the License.
68225b7c95185dfbfe67da105df4402430784393cRobert Sesek * You may obtain a copy of the License at
78225b7c95185dfbfe67da105df4402430784393cRobert Sesek *
88225b7c95185dfbfe67da105df4402430784393cRobert Sesek *      http://www.apache.org/licenses/LICENSE-2.0
98225b7c95185dfbfe67da105df4402430784393cRobert Sesek *
108225b7c95185dfbfe67da105df4402430784393cRobert Sesek * Unless required by applicable law or agreed to in writing, software
118225b7c95185dfbfe67da105df4402430784393cRobert Sesek * distributed under the License is distributed on an "AS IS" BASIS,
128225b7c95185dfbfe67da105df4402430784393cRobert Sesek * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138225b7c95185dfbfe67da105df4402430784393cRobert Sesek * See the License for the specific language governing permissions and
148225b7c95185dfbfe67da105df4402430784393cRobert Sesek * limitations under the License.
158225b7c95185dfbfe67da105df4402430784393cRobert Sesek */
168225b7c95185dfbfe67da105df4402430784393cRobert Sesek
178225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include "fd_utils.h"
188225b7c95185dfbfe67da105df4402430784393cRobert Sesek
198225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <algorithm>
208225b7c95185dfbfe67da105df4402430784393cRobert Sesek
218225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <fcntl.h>
228225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <grp.h>
238225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <stdlib.h>
248225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <sys/socket.h>
258225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <sys/types.h>
268225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <sys/un.h>
278225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <unistd.h>
288225b7c95185dfbfe67da105df4402430784393cRobert Sesek
293879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath#include <android-base/file.h>
30a352d2473a8bf5d5cb711ea5ef1591604e2bef94Narayan Kamath#include <android-base/logging.h>
313879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath#include <android-base/stringprintf.h>
328225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <android-base/strings.h>
338225b7c95185dfbfe67da105df4402430784393cRobert Sesek
3454e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek// Static whitelist of open paths that the zygote is allowed to keep open.
358225b7c95185dfbfe67da105df4402430784393cRobert Sesekstatic const char* kPathWhitelist[] = {
368225b7c95185dfbfe67da105df4402430784393cRobert Sesek  "/dev/null",
378225b7c95185dfbfe67da105df4402430784393cRobert Sesek  "/dev/socket/zygote",
388225b7c95185dfbfe67da105df4402430784393cRobert Sesek  "/dev/socket/zygote_secondary",
398225b7c95185dfbfe67da105df4402430784393cRobert Sesek  "/dev/socket/webview_zygote",
408225b7c95185dfbfe67da105df4402430784393cRobert Sesek  "/sys/kernel/debug/tracing/trace_marker",
418225b7c95185dfbfe67da105df4402430784393cRobert Sesek  "/system/framework/framework-res.apk",
428225b7c95185dfbfe67da105df4402430784393cRobert Sesek  "/dev/urandom",
438225b7c95185dfbfe67da105df4402430784393cRobert Sesek  "/dev/ion",
448225b7c95185dfbfe67da105df4402430784393cRobert Sesek  "/dev/dri/renderD129", // Fixes b/31172436
458225b7c95185dfbfe67da105df4402430784393cRobert Sesek};
468225b7c95185dfbfe67da105df4402430784393cRobert Sesek
478225b7c95185dfbfe67da105df4402430784393cRobert Sesekstatic const char kFdPath[] = "/proc/self/fd";
488225b7c95185dfbfe67da105df4402430784393cRobert Sesek
498225b7c95185dfbfe67da105df4402430784393cRobert Sesek// static
5054e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert SesekFileDescriptorWhitelist* FileDescriptorWhitelist::Get() {
5154e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  if (instance_ == nullptr) {
5254e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek    instance_ = new FileDescriptorWhitelist();
5354e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  }
5454e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  return instance_;
5554e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek}
5654e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek
5754e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesekbool FileDescriptorWhitelist::IsAllowed(const std::string& path) const {
5854e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  // Check the static whitelist path.
5954e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  for (const auto& whitelist_path : kPathWhitelist) {
6054e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek    if (path == whitelist_path)
6154e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek      return true;
6254e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  }
6354e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek
6454e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  // Check any paths added to the dynamic whitelist.
6554e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  for (const auto& whitelist_path : whitelist_) {
6654e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek    if (path == whitelist_path)
6754e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek      return true;
6854e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  }
6954e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek
703879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath  static const char* kFrameworksPrefix = "/system/framework/";
713879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath  static const char* kJarSuffix = ".jar";
723879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath  if (android::base::StartsWith(path, kFrameworksPrefix)
733879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath      && android::base::EndsWith(path, kJarSuffix)) {
7454e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek    return true;
7554e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  }
7654e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek
7754e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  // Whitelist files needed for Runtime Resource Overlay, like these:
7854e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  // /system/vendor/overlay/framework-res.apk
7954e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  // /system/vendor/overlay-subdir/pg/framework-res.apk
8054e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  // /vendor/overlay/framework-res.apk
8154e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  // /vendor/overlay/PG/android-framework-runtime-resource-overlay.apk
8254e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap
8354e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  // /data/resource-cache/system@vendor@overlay-subdir@pg@framework-res.apk@idmap
8454e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  // See AssetManager.cpp for more details on overlay-subdir.
853879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath  static const char* kOverlayDir = "/system/vendor/overlay/";
863879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath  static const char* kVendorOverlayDir = "/vendor/overlay";
873879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath  static const char* kOverlaySubdir = "/system/vendor/overlay-subdir/";
883879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath  static const char* kApkSuffix = ".apk";
893879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath
903879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath  if ((android::base::StartsWith(path, kOverlayDir)
913879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath       || android::base::StartsWith(path, kOverlaySubdir)
923879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath       || android::base::StartsWith(path, kVendorOverlayDir))
933879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath      && android::base::EndsWith(path, kApkSuffix)
9454e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek      && path.find("/../") == std::string::npos) {
9554e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek    return true;
9654e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  }
9754e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek
983879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath  static const char* kOverlayIdmapPrefix = "/data/resource-cache/";
993879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath  static const char* kOverlayIdmapSuffix = ".apk@idmap";
1003879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath  if (android::base::StartsWith(path, kOverlayIdmapPrefix)
1013879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath      && android::base::EndsWith(path, kOverlayIdmapSuffix)
10254e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek      && path.find("/../") == std::string::npos) {
10354e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek    return true;
10454e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  }
10554e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek
10654e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  // All regular files that are placed under this path are whitelisted automatically.
1073879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath  static const char* kZygoteWhitelistPath = "/vendor/zygote_whitelist/";
1083879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath  if (android::base::StartsWith(path, kZygoteWhitelistPath)
1093879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath      && path.find("/../") == std::string::npos) {
11054e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek    return true;
11154e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  }
11254e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek
11354e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  return false;
11454e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek}
11554e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek
11654e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert SesekFileDescriptorWhitelist::FileDescriptorWhitelist()
11754e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek    : whitelist_() {
11854e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek}
11954e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek
12054e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert SesekFileDescriptorWhitelist* FileDescriptorWhitelist::instance_ = nullptr;
12154e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek
12254e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek// static
1238225b7c95185dfbfe67da105df4402430784393cRobert SesekFileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) {
1248225b7c95185dfbfe67da105df4402430784393cRobert Sesek  struct stat f_stat;
1258225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // This should never happen; the zygote should always have the right set
1268225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // of permissions required to stat all its open files.
1278225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
12884b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    PLOG(ERROR) << "Unable to stat fd " << fd;
1298225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return NULL;
1308225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
1318225b7c95185dfbfe67da105df4402430784393cRobert Sesek
13254e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  const FileDescriptorWhitelist* whitelist = FileDescriptorWhitelist::Get();
13354e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek
1348225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (S_ISSOCK(f_stat.st_mode)) {
1358225b7c95185dfbfe67da105df4402430784393cRobert Sesek    std::string socket_name;
1368225b7c95185dfbfe67da105df4402430784393cRobert Sesek    if (!GetSocketName(fd, &socket_name)) {
1378225b7c95185dfbfe67da105df4402430784393cRobert Sesek      return NULL;
1388225b7c95185dfbfe67da105df4402430784393cRobert Sesek    }
1398225b7c95185dfbfe67da105df4402430784393cRobert Sesek
14054e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek    if (!whitelist->IsAllowed(socket_name)) {
14184b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath      LOG(ERROR) << "Socket name not whitelisted : " << socket_name
14284b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath                 << " (fd=" << fd << ")";
1438225b7c95185dfbfe67da105df4402430784393cRobert Sesek      return NULL;
1448225b7c95185dfbfe67da105df4402430784393cRobert Sesek    }
1458225b7c95185dfbfe67da105df4402430784393cRobert Sesek
1468225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return new FileDescriptorInfo(fd);
1478225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
1488225b7c95185dfbfe67da105df4402430784393cRobert Sesek
1498225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // We only handle whitelisted regular files and character devices. Whitelisted
1508225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // character devices must provide a guarantee of sensible behaviour when
1518225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // reopened.
1528225b7c95185dfbfe67da105df4402430784393cRobert Sesek  //
1538225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // S_ISDIR : Not supported. (We could if we wanted to, but it's unused).
1548225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // S_ISLINK : Not supported.
1558225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // S_ISBLK : Not supported.
1568225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // S_ISFIFO : Not supported. Note that the zygote uses pipes to communicate
1578225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // with the child process across forks but those should have been closed
1588225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // before we got to this point.
1598225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) {
16084b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    LOG(ERROR) << "Unsupported st_mode " << f_stat.st_mode;
1618225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return NULL;
1628225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
1638225b7c95185dfbfe67da105df4402430784393cRobert Sesek
1648225b7c95185dfbfe67da105df4402430784393cRobert Sesek  std::string file_path;
1653879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath  const std::string fd_path = android::base::StringPrintf("/proc/self/fd/%d", fd);
1663879ecc891bcfce91662db6d0823c96770058df5Narayan Kamath  if (!android::base::Readlink(fd_path, &file_path)) {
1678225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return NULL;
1688225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
1698225b7c95185dfbfe67da105df4402430784393cRobert Sesek
17054e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek  if (!whitelist->IsAllowed(file_path)) {
17184b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    LOG(ERROR) << "Not whitelisted : " << file_path;
1728225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return NULL;
1738225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
1748225b7c95185dfbfe67da105df4402430784393cRobert Sesek
1758225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // File descriptor flags : currently on FD_CLOEXEC. We can set these
1768225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // using F_SETFD - we're single threaded at this point of execution so
1778225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // there won't be any races.
1788225b7c95185dfbfe67da105df4402430784393cRobert Sesek  const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD));
1798225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (fd_flags == -1) {
18084b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    PLOG(ERROR) << "Failed fcntl(" << fd << ", F_GETFD)";
1818225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return NULL;
1828225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
1838225b7c95185dfbfe67da105df4402430784393cRobert Sesek
1848225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // File status flags :
1858225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // - File access mode : (O_RDONLY, O_WRONLY...) we'll pass these through
1868225b7c95185dfbfe67da105df4402430784393cRobert Sesek  //   to the open() call.
1878225b7c95185dfbfe67da105df4402430784393cRobert Sesek  //
1888225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // - File creation flags : (O_CREAT, O_EXCL...) - there's not much we can
1898225b7c95185dfbfe67da105df4402430784393cRobert Sesek  //   do about these, since the file has already been created. We shall ignore
1908225b7c95185dfbfe67da105df4402430784393cRobert Sesek  //   them here.
1918225b7c95185dfbfe67da105df4402430784393cRobert Sesek  //
1928225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // - Other flags : We'll have to set these via F_SETFL. On linux, F_SETFL
1938225b7c95185dfbfe67da105df4402430784393cRobert Sesek  //   can only set O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK.
1948225b7c95185dfbfe67da105df4402430784393cRobert Sesek  //   In particular, it can't set O_SYNC and O_DSYNC. We'll have to test for
1958225b7c95185dfbfe67da105df4402430784393cRobert Sesek  //   their presence and pass them in to open().
1968225b7c95185dfbfe67da105df4402430784393cRobert Sesek  int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
1978225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (fs_flags == -1) {
19884b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    PLOG(ERROR) << "Failed fcntl(" << fd << ", F_GETFL)";
1998225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return NULL;
2008225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
2018225b7c95185dfbfe67da105df4402430784393cRobert Sesek
2028225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // File offset : Ignore the offset for non seekable files.
2038225b7c95185dfbfe67da105df4402430784393cRobert Sesek  const off_t offset = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR));
2048225b7c95185dfbfe67da105df4402430784393cRobert Sesek
2058225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // We pass the flags that open accepts to open, and use F_SETFL for
2068225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // the rest of them.
2078225b7c95185dfbfe67da105df4402430784393cRobert Sesek  static const int kOpenFlags = (O_RDONLY | O_WRONLY | O_RDWR | O_DSYNC | O_SYNC);
2088225b7c95185dfbfe67da105df4402430784393cRobert Sesek  int open_flags = fs_flags & (kOpenFlags);
2098225b7c95185dfbfe67da105df4402430784393cRobert Sesek  fs_flags = fs_flags & (~(kOpenFlags));
2108225b7c95185dfbfe67da105df4402430784393cRobert Sesek
2118225b7c95185dfbfe67da105df4402430784393cRobert Sesek  return new FileDescriptorInfo(f_stat, file_path, fd, open_flags, fd_flags, fs_flags, offset);
2128225b7c95185dfbfe67da105df4402430784393cRobert Sesek}
2138225b7c95185dfbfe67da105df4402430784393cRobert Sesek
2148225b7c95185dfbfe67da105df4402430784393cRobert Sesekbool FileDescriptorInfo::Restat() const {
2158225b7c95185dfbfe67da105df4402430784393cRobert Sesek  struct stat f_stat;
2168225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
217a352d2473a8bf5d5cb711ea5ef1591604e2bef94Narayan Kamath    PLOG(ERROR) << "Unable to restat fd " << fd;
2188225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return false;
2198225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
2208225b7c95185dfbfe67da105df4402430784393cRobert Sesek
2218225b7c95185dfbfe67da105df4402430784393cRobert Sesek  return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev;
2228225b7c95185dfbfe67da105df4402430784393cRobert Sesek}
2238225b7c95185dfbfe67da105df4402430784393cRobert Sesek
2248225b7c95185dfbfe67da105df4402430784393cRobert Sesekbool FileDescriptorInfo::ReopenOrDetach() const {
2258225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (is_sock) {
2268225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return DetachSocket();
2278225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
2288225b7c95185dfbfe67da105df4402430784393cRobert Sesek
2298225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // NOTE: This might happen if the file was unlinked after being opened.
2308225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // It's a common pattern in the case of temporary files and the like but
2318225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // we should not allow such usage from the zygote.
2328225b7c95185dfbfe67da105df4402430784393cRobert Sesek  const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags));
2338225b7c95185dfbfe67da105df4402430784393cRobert Sesek
2348225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (new_fd == -1) {
23584b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    PLOG(ERROR) << "Failed open(" << file_path << ", " << open_flags << ")";
2368225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return false;
2378225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
2388225b7c95185dfbfe67da105df4402430784393cRobert Sesek
2398225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) {
2408225b7c95185dfbfe67da105df4402430784393cRobert Sesek    close(new_fd);
24184b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    PLOG(ERROR) << "Failed fcntl(" << new_fd << ", F_SETFD, " << fd_flags << ")";
2428225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return false;
2438225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
2448225b7c95185dfbfe67da105df4402430784393cRobert Sesek
2458225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) {
2468225b7c95185dfbfe67da105df4402430784393cRobert Sesek    close(new_fd);
24784b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    PLOG(ERROR) << "Failed fcntl(" << new_fd << ", F_SETFL, " << fs_flags << ")";
2488225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return false;
2498225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
2508225b7c95185dfbfe67da105df4402430784393cRobert Sesek
2518225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) {
2528225b7c95185dfbfe67da105df4402430784393cRobert Sesek    close(new_fd);
25384b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    PLOG(ERROR) << "Failed lseek64(" << new_fd << ", SEEK_SET)";
2548225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return false;
2558225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
2568225b7c95185dfbfe67da105df4402430784393cRobert Sesek
2578225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) {
2588225b7c95185dfbfe67da105df4402430784393cRobert Sesek    close(new_fd);
25984b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    PLOG(ERROR) << "Failed dup2(" << fd << ", " << new_fd << ")";
2608225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return false;
2618225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
2628225b7c95185dfbfe67da105df4402430784393cRobert Sesek
2638225b7c95185dfbfe67da105df4402430784393cRobert Sesek  close(new_fd);
2648225b7c95185dfbfe67da105df4402430784393cRobert Sesek
2658225b7c95185dfbfe67da105df4402430784393cRobert Sesek  return true;
2668225b7c95185dfbfe67da105df4402430784393cRobert Sesek}
2678225b7c95185dfbfe67da105df4402430784393cRobert Sesek
2688225b7c95185dfbfe67da105df4402430784393cRobert SesekFileDescriptorInfo::FileDescriptorInfo(int fd) :
2698225b7c95185dfbfe67da105df4402430784393cRobert Sesek  fd(fd),
2708225b7c95185dfbfe67da105df4402430784393cRobert Sesek  stat(),
2718225b7c95185dfbfe67da105df4402430784393cRobert Sesek  open_flags(0),
2728225b7c95185dfbfe67da105df4402430784393cRobert Sesek  fd_flags(0),
2738225b7c95185dfbfe67da105df4402430784393cRobert Sesek  fs_flags(0),
2748225b7c95185dfbfe67da105df4402430784393cRobert Sesek  offset(0),
2758225b7c95185dfbfe67da105df4402430784393cRobert Sesek  is_sock(true) {
2768225b7c95185dfbfe67da105df4402430784393cRobert Sesek}
2778225b7c95185dfbfe67da105df4402430784393cRobert Sesek
2788225b7c95185dfbfe67da105df4402430784393cRobert SesekFileDescriptorInfo::FileDescriptorInfo(struct stat stat, const std::string& file_path,
2798225b7c95185dfbfe67da105df4402430784393cRobert Sesek                                       int fd, int open_flags, int fd_flags, int fs_flags,
2808225b7c95185dfbfe67da105df4402430784393cRobert Sesek                                       off_t offset) :
2818225b7c95185dfbfe67da105df4402430784393cRobert Sesek  fd(fd),
2828225b7c95185dfbfe67da105df4402430784393cRobert Sesek  stat(stat),
2838225b7c95185dfbfe67da105df4402430784393cRobert Sesek  file_path(file_path),
2848225b7c95185dfbfe67da105df4402430784393cRobert Sesek  open_flags(open_flags),
2858225b7c95185dfbfe67da105df4402430784393cRobert Sesek  fd_flags(fd_flags),
2868225b7c95185dfbfe67da105df4402430784393cRobert Sesek  fs_flags(fs_flags),
2878225b7c95185dfbfe67da105df4402430784393cRobert Sesek  offset(offset),
2888225b7c95185dfbfe67da105df4402430784393cRobert Sesek  is_sock(false) {
2898225b7c95185dfbfe67da105df4402430784393cRobert Sesek}
2908225b7c95185dfbfe67da105df4402430784393cRobert Sesek
2918225b7c95185dfbfe67da105df4402430784393cRobert Sesek// static
2928225b7c95185dfbfe67da105df4402430784393cRobert Sesekbool FileDescriptorInfo::GetSocketName(const int fd, std::string* result) {
2938225b7c95185dfbfe67da105df4402430784393cRobert Sesek  sockaddr_storage ss;
2948225b7c95185dfbfe67da105df4402430784393cRobert Sesek  sockaddr* addr = reinterpret_cast<sockaddr*>(&ss);
2958225b7c95185dfbfe67da105df4402430784393cRobert Sesek  socklen_t addr_len = sizeof(ss);
2968225b7c95185dfbfe67da105df4402430784393cRobert Sesek
2978225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (TEMP_FAILURE_RETRY(getsockname(fd, addr, &addr_len)) == -1) {
29884b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    PLOG(ERROR) << "Failed getsockname(" << fd << ")";
2998225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return false;
3008225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
3018225b7c95185dfbfe67da105df4402430784393cRobert Sesek
3028225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (addr->sa_family != AF_UNIX) {
30384b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    LOG(ERROR) << "Unsupported socket (fd=" << fd << ") with family " << addr->sa_family;
3048225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return false;
3058225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
3068225b7c95185dfbfe67da105df4402430784393cRobert Sesek
3078225b7c95185dfbfe67da105df4402430784393cRobert Sesek  const sockaddr_un* unix_addr = reinterpret_cast<const sockaddr_un*>(&ss);
3088225b7c95185dfbfe67da105df4402430784393cRobert Sesek
3098225b7c95185dfbfe67da105df4402430784393cRobert Sesek  size_t path_len = addr_len - offsetof(struct sockaddr_un, sun_path);
3108225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // This is an unnamed local socket, we do not accept it.
3118225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (path_len == 0) {
31284b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    LOG(ERROR) << "Unsupported AF_UNIX socket (fd=" << fd << ") with empty path.";
3138225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return false;
3148225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
3158225b7c95185dfbfe67da105df4402430784393cRobert Sesek
3168225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // This is a local socket with an abstract address, we do not accept it.
3178225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (unix_addr->sun_path[0] == '\0') {
31884b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    LOG(ERROR) << "Unsupported AF_UNIX socket (fd=" << fd << ") with abstract address.";
3198225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return false;
3208225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
3218225b7c95185dfbfe67da105df4402430784393cRobert Sesek
3228225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // If we're here, sun_path must refer to a null terminated filesystem
3238225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // pathname (man 7 unix). Remove the terminator before assigning it to an
3248225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // std::string.
3258225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (unix_addr->sun_path[path_len - 1] ==  '\0') {
3268225b7c95185dfbfe67da105df4402430784393cRobert Sesek    --path_len;
3278225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
3288225b7c95185dfbfe67da105df4402430784393cRobert Sesek
3298225b7c95185dfbfe67da105df4402430784393cRobert Sesek  result->assign(unix_addr->sun_path, path_len);
3308225b7c95185dfbfe67da105df4402430784393cRobert Sesek  return true;
3318225b7c95185dfbfe67da105df4402430784393cRobert Sesek}
3328225b7c95185dfbfe67da105df4402430784393cRobert Sesek
3338225b7c95185dfbfe67da105df4402430784393cRobert Sesekbool FileDescriptorInfo::DetachSocket() const {
3348225b7c95185dfbfe67da105df4402430784393cRobert Sesek  const int dev_null_fd = open("/dev/null", O_RDWR);
3358225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (dev_null_fd < 0) {
33684b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    PLOG(ERROR) << "Failed to open /dev/null";
3378225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return false;
3388225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
3398225b7c95185dfbfe67da105df4402430784393cRobert Sesek
3408225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (dup2(dev_null_fd, fd) == -1) {
34184b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    PLOG(ERROR) << "Failed dup2 on socket descriptor " << fd;
3428225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return false;
3438225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
3448225b7c95185dfbfe67da105df4402430784393cRobert Sesek
3458225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (close(dev_null_fd) == -1) {
34684b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    PLOG(ERROR) << "Failed close(" << dev_null_fd << ")";
3478225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return false;
3488225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
3498225b7c95185dfbfe67da105df4402430784393cRobert Sesek
3508225b7c95185dfbfe67da105df4402430784393cRobert Sesek  return true;
3518225b7c95185dfbfe67da105df4402430784393cRobert Sesek}
3528225b7c95185dfbfe67da105df4402430784393cRobert Sesek
3538225b7c95185dfbfe67da105df4402430784393cRobert Sesek// static
3548dfa178efbbb155657639bd526e9a8579fce3886Andreas GampeFileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore) {
3558225b7c95185dfbfe67da105df4402430784393cRobert Sesek  DIR* d = opendir(kFdPath);
3568225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (d == NULL) {
35784b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    PLOG(ERROR) << "Unable to open directory " << std::string(kFdPath);
3588225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return NULL;
3598225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
3608225b7c95185dfbfe67da105df4402430784393cRobert Sesek  int dir_fd = dirfd(d);
3618225b7c95185dfbfe67da105df4402430784393cRobert Sesek  dirent* e;
3628225b7c95185dfbfe67da105df4402430784393cRobert Sesek
3638225b7c95185dfbfe67da105df4402430784393cRobert Sesek  std::unordered_map<int, FileDescriptorInfo*> open_fd_map;
3648225b7c95185dfbfe67da105df4402430784393cRobert Sesek  while ((e = readdir(d)) != NULL) {
3658225b7c95185dfbfe67da105df4402430784393cRobert Sesek    const int fd = ParseFd(e, dir_fd);
3668225b7c95185dfbfe67da105df4402430784393cRobert Sesek    if (fd == -1) {
3678225b7c95185dfbfe67da105df4402430784393cRobert Sesek      continue;
3688225b7c95185dfbfe67da105df4402430784393cRobert Sesek    }
3698dfa178efbbb155657639bd526e9a8579fce3886Andreas Gampe    if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
37084b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath      LOG(INFO) << "Ignoring open file descriptor " << fd;
3718dfa178efbbb155657639bd526e9a8579fce3886Andreas Gampe      continue;
3728dfa178efbbb155657639bd526e9a8579fce3886Andreas Gampe    }
3738225b7c95185dfbfe67da105df4402430784393cRobert Sesek
3748225b7c95185dfbfe67da105df4402430784393cRobert Sesek    FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd);
3758225b7c95185dfbfe67da105df4402430784393cRobert Sesek    if (info == NULL) {
3768225b7c95185dfbfe67da105df4402430784393cRobert Sesek      if (closedir(d) == -1) {
37784b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath        PLOG(ERROR) << "Unable to close directory";
3788225b7c95185dfbfe67da105df4402430784393cRobert Sesek      }
3798225b7c95185dfbfe67da105df4402430784393cRobert Sesek      return NULL;
3808225b7c95185dfbfe67da105df4402430784393cRobert Sesek    }
3818225b7c95185dfbfe67da105df4402430784393cRobert Sesek    open_fd_map[fd] = info;
3828225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
3838225b7c95185dfbfe67da105df4402430784393cRobert Sesek
3848225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (closedir(d) == -1) {
38584b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    PLOG(ERROR) << "Unable to close directory";
3868225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return NULL;
3878225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
3888225b7c95185dfbfe67da105df4402430784393cRobert Sesek  return new FileDescriptorTable(open_fd_map);
3898225b7c95185dfbfe67da105df4402430784393cRobert Sesek}
3908225b7c95185dfbfe67da105df4402430784393cRobert Sesek
3918dfa178efbbb155657639bd526e9a8579fce3886Andreas Gampebool FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore) {
3928225b7c95185dfbfe67da105df4402430784393cRobert Sesek  std::set<int> open_fds;
3938225b7c95185dfbfe67da105df4402430784393cRobert Sesek
3948225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // First get the list of open descriptors.
3958225b7c95185dfbfe67da105df4402430784393cRobert Sesek  DIR* d = opendir(kFdPath);
3968225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (d == NULL) {
39784b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    PLOG(ERROR) << "Unable to open directory " << std::string(kFdPath);
3988225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return false;
3998225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
4008225b7c95185dfbfe67da105df4402430784393cRobert Sesek
4018225b7c95185dfbfe67da105df4402430784393cRobert Sesek  int dir_fd = dirfd(d);
4028225b7c95185dfbfe67da105df4402430784393cRobert Sesek  dirent* e;
4038225b7c95185dfbfe67da105df4402430784393cRobert Sesek  while ((e = readdir(d)) != NULL) {
4048225b7c95185dfbfe67da105df4402430784393cRobert Sesek    const int fd = ParseFd(e, dir_fd);
4058225b7c95185dfbfe67da105df4402430784393cRobert Sesek    if (fd == -1) {
4068225b7c95185dfbfe67da105df4402430784393cRobert Sesek      continue;
4078225b7c95185dfbfe67da105df4402430784393cRobert Sesek    }
4088dfa178efbbb155657639bd526e9a8579fce3886Andreas Gampe    if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
40984b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath      LOG(INFO) << "Ignoring open file descriptor " << fd;
4108dfa178efbbb155657639bd526e9a8579fce3886Andreas Gampe      continue;
4118dfa178efbbb155657639bd526e9a8579fce3886Andreas Gampe    }
4128225b7c95185dfbfe67da105df4402430784393cRobert Sesek
4138225b7c95185dfbfe67da105df4402430784393cRobert Sesek    open_fds.insert(fd);
4148225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
4158225b7c95185dfbfe67da105df4402430784393cRobert Sesek
4168225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (closedir(d) == -1) {
41784b55115354f3c2c9531f251f9d126bb7a06988dNarayan Kamath    PLOG(ERROR) << "Unable to close directory";
4188225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return false;
4198225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
4208225b7c95185dfbfe67da105df4402430784393cRobert Sesek
4218225b7c95185dfbfe67da105df4402430784393cRobert Sesek  return RestatInternal(open_fds);
4228225b7c95185dfbfe67da105df4402430784393cRobert Sesek}
4238225b7c95185dfbfe67da105df4402430784393cRobert Sesek
4248225b7c95185dfbfe67da105df4402430784393cRobert Sesek// Reopens all file descriptors that are contained in the table. Returns true
4258225b7c95185dfbfe67da105df4402430784393cRobert Sesek// if all descriptors were successfully re-opened or detached, and false if an
4268225b7c95185dfbfe67da105df4402430784393cRobert Sesek// error occurred.
4278225b7c95185dfbfe67da105df4402430784393cRobert Sesekbool FileDescriptorTable::ReopenOrDetach() {
4288225b7c95185dfbfe67da105df4402430784393cRobert Sesek  std::unordered_map<int, FileDescriptorInfo*>::const_iterator it;
4298225b7c95185dfbfe67da105df4402430784393cRobert Sesek  for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) {
4308225b7c95185dfbfe67da105df4402430784393cRobert Sesek    const FileDescriptorInfo* info = it->second;
4318225b7c95185dfbfe67da105df4402430784393cRobert Sesek    if (info == NULL || !info->ReopenOrDetach()) {
4328225b7c95185dfbfe67da105df4402430784393cRobert Sesek      return false;
4338225b7c95185dfbfe67da105df4402430784393cRobert Sesek    }
4348225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
4358225b7c95185dfbfe67da105df4402430784393cRobert Sesek
4368225b7c95185dfbfe67da105df4402430784393cRobert Sesek  return true;
4378225b7c95185dfbfe67da105df4402430784393cRobert Sesek}
4388225b7c95185dfbfe67da105df4402430784393cRobert Sesek
4398225b7c95185dfbfe67da105df4402430784393cRobert SesekFileDescriptorTable::FileDescriptorTable(
4408225b7c95185dfbfe67da105df4402430784393cRobert Sesek    const std::unordered_map<int, FileDescriptorInfo*>& map)
4418225b7c95185dfbfe67da105df4402430784393cRobert Sesek    : open_fd_map_(map) {
4428225b7c95185dfbfe67da105df4402430784393cRobert Sesek}
4438225b7c95185dfbfe67da105df4402430784393cRobert Sesek
4448225b7c95185dfbfe67da105df4402430784393cRobert Sesekbool FileDescriptorTable::RestatInternal(std::set<int>& open_fds) {
4458225b7c95185dfbfe67da105df4402430784393cRobert Sesek  bool error = false;
4468225b7c95185dfbfe67da105df4402430784393cRobert Sesek
4478225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // Iterate through the list of file descriptors we've already recorded
4488225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // and check whether :
4498225b7c95185dfbfe67da105df4402430784393cRobert Sesek  //
4508225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // (a) they continue to be open.
4518225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // (b) they refer to the same file.
4528225b7c95185dfbfe67da105df4402430784393cRobert Sesek  std::unordered_map<int, FileDescriptorInfo*>::iterator it = open_fd_map_.begin();
4538225b7c95185dfbfe67da105df4402430784393cRobert Sesek  while (it != open_fd_map_.end()) {
4548225b7c95185dfbfe67da105df4402430784393cRobert Sesek    std::set<int>::const_iterator element = open_fds.find(it->first);
4558225b7c95185dfbfe67da105df4402430784393cRobert Sesek    if (element == open_fds.end()) {
4568225b7c95185dfbfe67da105df4402430784393cRobert Sesek      // The entry from the file descriptor table is no longer in the list
4578225b7c95185dfbfe67da105df4402430784393cRobert Sesek      // of open files. We warn about this condition and remove it from
4588225b7c95185dfbfe67da105df4402430784393cRobert Sesek      // the list of FDs under consideration.
4598225b7c95185dfbfe67da105df4402430784393cRobert Sesek      //
4608225b7c95185dfbfe67da105df4402430784393cRobert Sesek      // TODO(narayan): This will be an error in a future android release.
4618225b7c95185dfbfe67da105df4402430784393cRobert Sesek      // error = true;
4628225b7c95185dfbfe67da105df4402430784393cRobert Sesek      // ALOGW("Zygote closed file descriptor %d.", it->first);
4638225b7c95185dfbfe67da105df4402430784393cRobert Sesek      it = open_fd_map_.erase(it);
4648225b7c95185dfbfe67da105df4402430784393cRobert Sesek    } else {
4658225b7c95185dfbfe67da105df4402430784393cRobert Sesek      // The entry from the file descriptor table is still open. Restat
4668225b7c95185dfbfe67da105df4402430784393cRobert Sesek      // it and check whether it refers to the same file.
4678225b7c95185dfbfe67da105df4402430784393cRobert Sesek      const bool same_file = it->second->Restat();
4688225b7c95185dfbfe67da105df4402430784393cRobert Sesek      if (!same_file) {
4698225b7c95185dfbfe67da105df4402430784393cRobert Sesek        // The file descriptor refers to a different description. We must
4708225b7c95185dfbfe67da105df4402430784393cRobert Sesek        // update our entry in the table.
4718225b7c95185dfbfe67da105df4402430784393cRobert Sesek        delete it->second;
4728225b7c95185dfbfe67da105df4402430784393cRobert Sesek        it->second = FileDescriptorInfo::CreateFromFd(*element);
4738225b7c95185dfbfe67da105df4402430784393cRobert Sesek        if (it->second == NULL) {
4748225b7c95185dfbfe67da105df4402430784393cRobert Sesek          // The descriptor no longer no longer refers to a whitelisted file.
4758225b7c95185dfbfe67da105df4402430784393cRobert Sesek          // We flag an error and remove it from the list of files we're
4768225b7c95185dfbfe67da105df4402430784393cRobert Sesek          // tracking.
4778225b7c95185dfbfe67da105df4402430784393cRobert Sesek          error = true;
4788225b7c95185dfbfe67da105df4402430784393cRobert Sesek          it = open_fd_map_.erase(it);
4798225b7c95185dfbfe67da105df4402430784393cRobert Sesek        } else {
4808225b7c95185dfbfe67da105df4402430784393cRobert Sesek          // Successfully restatted the file, move on to the next open FD.
4818225b7c95185dfbfe67da105df4402430784393cRobert Sesek          ++it;
4828225b7c95185dfbfe67da105df4402430784393cRobert Sesek        }
4838225b7c95185dfbfe67da105df4402430784393cRobert Sesek      } else {
4848225b7c95185dfbfe67da105df4402430784393cRobert Sesek        // It's the same file. Nothing to do here. Move on to the next open
4858225b7c95185dfbfe67da105df4402430784393cRobert Sesek        // FD.
4868225b7c95185dfbfe67da105df4402430784393cRobert Sesek        ++it;
4878225b7c95185dfbfe67da105df4402430784393cRobert Sesek      }
4888225b7c95185dfbfe67da105df4402430784393cRobert Sesek
4898225b7c95185dfbfe67da105df4402430784393cRobert Sesek      // Finally, remove the FD from the set of open_fds. We do this last because
4908225b7c95185dfbfe67da105df4402430784393cRobert Sesek      // |element| will not remain valid after a call to erase.
4918225b7c95185dfbfe67da105df4402430784393cRobert Sesek      open_fds.erase(element);
4928225b7c95185dfbfe67da105df4402430784393cRobert Sesek    }
4938225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
4948225b7c95185dfbfe67da105df4402430784393cRobert Sesek
4958225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (open_fds.size() > 0) {
4968225b7c95185dfbfe67da105df4402430784393cRobert Sesek    // The zygote has opened new file descriptors since our last inspection.
4978225b7c95185dfbfe67da105df4402430784393cRobert Sesek    // We warn about this condition and add them to our table.
4988225b7c95185dfbfe67da105df4402430784393cRobert Sesek    //
4998225b7c95185dfbfe67da105df4402430784393cRobert Sesek    // TODO(narayan): This will be an error in a future android release.
5008225b7c95185dfbfe67da105df4402430784393cRobert Sesek    // error = true;
5018225b7c95185dfbfe67da105df4402430784393cRobert Sesek    // ALOGW("Zygote opened %zd new file descriptor(s).", open_fds.size());
5028225b7c95185dfbfe67da105df4402430784393cRobert Sesek
5038225b7c95185dfbfe67da105df4402430784393cRobert Sesek    // TODO(narayan): This code will be removed in a future android release.
5048225b7c95185dfbfe67da105df4402430784393cRobert Sesek    std::set<int>::const_iterator it;
5058225b7c95185dfbfe67da105df4402430784393cRobert Sesek    for (it = open_fds.begin(); it != open_fds.end(); ++it) {
5068225b7c95185dfbfe67da105df4402430784393cRobert Sesek      const int fd = (*it);
5078225b7c95185dfbfe67da105df4402430784393cRobert Sesek      FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd);
5088225b7c95185dfbfe67da105df4402430784393cRobert Sesek      if (info == NULL) {
5098225b7c95185dfbfe67da105df4402430784393cRobert Sesek        // A newly opened file is not on the whitelist. Flag an error and
5108225b7c95185dfbfe67da105df4402430784393cRobert Sesek        // continue.
5118225b7c95185dfbfe67da105df4402430784393cRobert Sesek        error = true;
5128225b7c95185dfbfe67da105df4402430784393cRobert Sesek      } else {
5138225b7c95185dfbfe67da105df4402430784393cRobert Sesek        // Track the newly opened file.
5148225b7c95185dfbfe67da105df4402430784393cRobert Sesek        open_fd_map_[fd] = info;
5158225b7c95185dfbfe67da105df4402430784393cRobert Sesek      }
5168225b7c95185dfbfe67da105df4402430784393cRobert Sesek    }
5178225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
5188225b7c95185dfbfe67da105df4402430784393cRobert Sesek
5198225b7c95185dfbfe67da105df4402430784393cRobert Sesek  return !error;
5208225b7c95185dfbfe67da105df4402430784393cRobert Sesek}
5218225b7c95185dfbfe67da105df4402430784393cRobert Sesek
5228225b7c95185dfbfe67da105df4402430784393cRobert Sesek// static
5238225b7c95185dfbfe67da105df4402430784393cRobert Sesekint FileDescriptorTable::ParseFd(dirent* e, int dir_fd) {
5248225b7c95185dfbfe67da105df4402430784393cRobert Sesek  char* end;
5258225b7c95185dfbfe67da105df4402430784393cRobert Sesek  const int fd = strtol(e->d_name, &end, 10);
5268225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if ((*end) != '\0') {
5278225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return -1;
5288225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
5298225b7c95185dfbfe67da105df4402430784393cRobert Sesek
5308225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // Don't bother with the standard input/output/error, they're handled
5318225b7c95185dfbfe67da105df4402430784393cRobert Sesek  // specially post-fork anyway.
5328225b7c95185dfbfe67da105df4402430784393cRobert Sesek  if (fd <= STDERR_FILENO || fd == dir_fd) {
5338225b7c95185dfbfe67da105df4402430784393cRobert Sesek    return -1;
5348225b7c95185dfbfe67da105df4402430784393cRobert Sesek  }
5358225b7c95185dfbfe67da105df4402430784393cRobert Sesek
5368225b7c95185dfbfe67da105df4402430784393cRobert Sesek  return fd;
5378225b7c95185dfbfe67da105df4402430784393cRobert Sesek}
538