/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "fd_utils.h"

#include <algorithm>

#include <fcntl.h>
#include <grp.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>

// Static whitelist of open paths that the zygote is allowed to keep open.
static const char* kPathWhitelist[] = {
  "/apex/com.android.conscrypt/javalib/conscrypt.jar",
  "/apex/com.android.media/javalib/updatable-media.jar",
  "/dev/null",
  "/dev/socket/zygote",
  "/dev/socket/zygote_secondary",
  "/dev/socket/usap_pool_primary",
  "/dev/socket/usap_pool_secondary",
  "/dev/socket/webview_zygote",
  "/dev/socket/heapprofd",
  "/sys/kernel/debug/tracing/trace_marker",
  "/system/framework/framework-res.apk",
  "/dev/urandom",
  "/dev/ion",
  "/dev/dri/renderD129", // Fixes b/31172436
};

static const char kFdPath[] = "/proc/self/fd";

// static
FileDescriptorWhitelist* FileDescriptorWhitelist::Get() {
  if (instance_ == nullptr) {
    instance_ = new FileDescriptorWhitelist();
  }
  return instance_;
}

bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const {
  // Check the static whitelist path.
  for (const auto& whitelist_path : kPathWhitelist) {
    if (path == whitelist_path)
      return true;
  }

  // Check any paths added to the dynamic whitelist.
  for (const auto& whitelist_path : whitelist_) {
    if (path == whitelist_path)
      return true;
  }

  // Framework jars are allowed.
  static const char* kFrameworksPrefix = "/system/framework/";
  static const char* kJarSuffix = ".jar";
  if (android::base::StartsWith(path, kFrameworksPrefix)
      && android::base::EndsWith(path, kJarSuffix)) {
    return true;
  }

  // Jars from the runtime apex are allowed.
  static const char* kRuntimeApexPrefix = "/apex/com.android.runtime/javalib/";
  if (android::base::StartsWith(path, kRuntimeApexPrefix)
      && android::base::EndsWith(path, kJarSuffix)) {
    return true;
  }

  // Whitelist files needed for Runtime Resource Overlay, like these:
  // /system/vendor/overlay/framework-res.apk
  // /system/vendor/overlay-subdir/pg/framework-res.apk
  // /vendor/overlay/framework-res.apk
  // /vendor/overlay/PG/android-framework-runtime-resource-overlay.apk
  // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap
  // /data/resource-cache/system@vendor@overlay-subdir@pg@framework-res.apk@idmap
  // See AssetManager.cpp for more details on overlay-subdir.
  static const char* kOverlayDir = "/system/vendor/overlay/";
  static const char* kVendorOverlayDir = "/vendor/overlay";
  static const char* kVendorOverlaySubdir = "/system/vendor/overlay-subdir/";
  static const char* kSystemProductOverlayDir = "/system/product/overlay/";
  static const char* kProductOverlayDir = "/product/overlay";
  static const char* kSystemProductServicesOverlayDir = "/system/product_services/overlay/";
  static const char* kProductServicesOverlayDir = "/product_services/overlay";
  static const char* kSystemOdmOverlayDir = "/system/odm/overlay";
  static const char* kOdmOverlayDir = "/odm/overlay";
  static const char* kSystemOemOverlayDir = "/system/oem/overlay";
  static const char* kOemOverlayDir = "/oem/overlay";
  static const char* kApkSuffix = ".apk";

  if ((android::base::StartsWith(path, kOverlayDir)
       || android::base::StartsWith(path, kVendorOverlaySubdir)
       || android::base::StartsWith(path, kVendorOverlayDir)
       || android::base::StartsWith(path, kSystemProductOverlayDir)
       || android::base::StartsWith(path, kProductOverlayDir)
       || android::base::StartsWith(path, kSystemProductServicesOverlayDir)
       || android::base::StartsWith(path, kProductServicesOverlayDir)
       || android::base::StartsWith(path, kSystemOdmOverlayDir)
       || android::base::StartsWith(path, kOdmOverlayDir)
       || android::base::StartsWith(path, kSystemOemOverlayDir)
       || android::base::StartsWith(path, kOemOverlayDir))
      && android::base::EndsWith(path, kApkSuffix)
      && path.find("/../") == std::string::npos) {
    return true;
  }

  static const char* kOverlayIdmapPrefix = "/data/resource-cache/";
  static const char* kOverlayIdmapSuffix = ".apk@idmap";
  if (android::base::StartsWith(path, kOverlayIdmapPrefix)
      && android::base::EndsWith(path, kOverlayIdmapSuffix)
      && path.find("/../") == std::string::npos) {
    return true;
  }

  // All regular files that are placed under this path are whitelisted automatically.
  static const char* kZygoteWhitelistPath = "/vendor/zygote_whitelist/";
  if (android::base::StartsWith(path, kZygoteWhitelistPath)
      && path.find("/../") == std::string::npos) {
    return true;
  }

  return false;
}

FileDescriptorWhitelist::FileDescriptorWhitelist()
    : whitelist_() {
}

FileDescriptorWhitelist* FileDescriptorWhitelist::instance_ = nullptr;

// Keeps track of all relevant information (flags, offset etc.) of an
// open zygote file descriptor.
class FileDescriptorInfo {
 public:
  // Create a FileDescriptorInfo for a given file descriptor.
  static FileDescriptorInfo* CreateFromFd(int fd, fail_fn_t fail_fn);

  // Checks whether the file descriptor associated with this object
  // refers to the same description.
  bool RefersToSameFile() const;

  void ReopenOrDetach(fail_fn_t fail_fn) const;

  const int fd;
  const struct stat stat;
  const std::string file_path;
  const int open_flags;
  const int fd_flags;
  const int fs_flags;
  const off_t offset;
  const bool is_sock;

 private:
  explicit FileDescriptorInfo(int fd);

  FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
                     int fd_flags, int fs_flags, off_t offset);

  // Returns the locally-bound name of the socket |fd|. Returns true
  // iff. all of the following hold :
  //
  // - the socket's sa_family is AF_UNIX.
  // - the length of the path is greater than zero (i.e, not an unnamed socket).
  // - the first byte of the path isn't zero (i.e, not a socket with an abstract
  //   address).
  static bool GetSocketName(const int fd, std::string* result);

  void DetachSocket(fail_fn_t fail_fn) const;

  DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo);
};

// static
FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd, fail_fn_t fail_fn) {
  struct stat f_stat;
  // This should never happen; the zygote should always have the right set
  // of permissions required to stat all its open files.
  if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
    fail_fn(android::base::StringPrintf("Unable to stat %d", fd));
  }

  const FileDescriptorWhitelist* whitelist = FileDescriptorWhitelist::Get();

  if (S_ISSOCK(f_stat.st_mode)) {
    std::string socket_name;
    if (!GetSocketName(fd, &socket_name)) {
      fail_fn("Unable to get socket name");
    }

    if (!whitelist->IsAllowed(socket_name)) {
      fail_fn(android::base::StringPrintf("Socket name not whitelisted : %s (fd=%d)",
                                          socket_name.c_str(),
                                          fd));
    }

    return new FileDescriptorInfo(fd);
  }

  // We only handle whitelisted regular files and character devices. Whitelisted
  // character devices must provide a guarantee of sensible behaviour when
  // reopened.
  //
  // S_ISDIR : Not supported. (We could if we wanted to, but it's unused).
  // S_ISLINK : Not supported.
  // S_ISBLK : Not supported.
  // S_ISFIFO : Not supported. Note that the Zygote and USAPs use pipes to
  // communicate with the child processes across forks but those should have been
  // added to the redirection exemption list.
  if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) {
    std::string mode = "Unknown";

    if (S_ISDIR(f_stat.st_mode)) {
      mode = "DIR";
    } else if (S_ISLNK(f_stat.st_mode)) {
      mode = "LINK";
    } else if (S_ISBLK(f_stat.st_mode)) {
      mode = "BLOCK";
    } else if (S_ISFIFO(f_stat.st_mode)) {
      mode = "FIFO";
    }

    fail_fn(android::base::StringPrintf("Unsupported st_mode for FD %d:  %s", fd, mode.c_str()));
  }

  std::string file_path;
  const std::string fd_path = android::base::StringPrintf("/proc/self/fd/%d", fd);
  if (!android::base::Readlink(fd_path, &file_path)) {
    fail_fn(android::base::StringPrintf("Could not read fd link %s: %s",
                                        fd_path.c_str(),
                                        strerror(errno)));
  }

  if (!whitelist->IsAllowed(file_path)) {
    fail_fn(std::string("Not whitelisted : ").append(file_path));
  }

  // File descriptor flags : currently on FD_CLOEXEC. We can set these
  // using F_SETFD - we're single threaded at this point of execution so
  // there won't be any races.
  const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD));
  if (fd_flags == -1) {
    fail_fn(android::base::StringPrintf("Failed fcntl(%d, F_GETFD) (%s): %s",
                                        fd,
                                        file_path.c_str(),
                                        strerror(errno)));
  }

  // File status flags :
  // - File access mode : (O_RDONLY, O_WRONLY...) we'll pass these through
  //   to the open() call.
  //
  // - File creation flags : (O_CREAT, O_EXCL...) - there's not much we can
  //   do about these, since the file has already been created. We shall ignore
  //   them here.
  //
  // - Other flags : We'll have to set these via F_SETFL. On linux, F_SETFL
  //   can only set O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK.
  //   In particular, it can't set O_SYNC and O_DSYNC. We'll have to test for
  //   their presence and pass them in to open().
  int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
  if (fs_flags == -1) {
    fail_fn(android::base::StringPrintf("Failed fcntl(%d, F_GETFL) (%s): %s",
                                        fd,
                                        file_path.c_str(),
                                        strerror(errno)));
  }

  // File offset : Ignore the offset for non seekable files.
  const off_t offset = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR));

  // We pass the flags that open accepts to open, and use F_SETFL for
  // the rest of them.
  static const int kOpenFlags = (O_RDONLY | O_WRONLY | O_RDWR | O_DSYNC | O_SYNC);
  int open_flags = fs_flags & (kOpenFlags);
  fs_flags = fs_flags & (~(kOpenFlags));

  return new FileDescriptorInfo(f_stat, file_path, fd, open_flags, fd_flags, fs_flags, offset);
}

bool FileDescriptorInfo::RefersToSameFile() const {
  struct stat f_stat;
  if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
    PLOG(ERROR) << "Unable to restat fd " << fd;
    return false;
  }

  return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev;
}

void FileDescriptorInfo::ReopenOrDetach(fail_fn_t fail_fn) const {
  if (is_sock) {
    return DetachSocket(fail_fn);
  }

  // NOTE: This might happen if the file was unlinked after being opened.
  // It's a common pattern in the case of temporary files and the like but
  // we should not allow such usage from the zygote.
  const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags));

  if (new_fd == -1) {
    fail_fn(android::base::StringPrintf("Failed open(%s, %i): %s",
                                        file_path.c_str(),
                                        open_flags,
                                        strerror(errno)));
  }

  if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) {
    close(new_fd);
    fail_fn(android::base::StringPrintf("Failed fcntl(%d, F_SETFD, %d) (%s): %s",
                                        new_fd,
                                        fd_flags,
                                        file_path.c_str(),
                                        strerror(errno)));
  }

  if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) {
    close(new_fd);
    fail_fn(android::base::StringPrintf("Failed fcntl(%d, F_SETFL, %d) (%s): %s",
                                        new_fd,
                                        fs_flags,
                                        file_path.c_str(),
                                        strerror(errno)));
  }

  if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) {
    close(new_fd);
    fail_fn(android::base::StringPrintf("Failed lseek64(%d, SEEK_SET) (%s): %s",
                                        new_fd,
                                        file_path.c_str(),
                                        strerror(errno)));
  }

  int dup_flags = (fd_flags & FD_CLOEXEC) ? O_CLOEXEC : 0;
  if (TEMP_FAILURE_RETRY(dup3(new_fd, fd, dup_flags)) == -1) {
    close(new_fd);
    fail_fn(android::base::StringPrintf("Failed dup3(%d, %d, %d) (%s): %s",
                                        fd,
                                        new_fd,
                                        dup_flags,
                                        file_path.c_str(),
                                        strerror(errno)));
  }

  close(new_fd);
}

FileDescriptorInfo::FileDescriptorInfo(int fd) :
  fd(fd),
  stat(),
  open_flags(0),
  fd_flags(0),
  fs_flags(0),
  offset(0),
  is_sock(true) {
}

FileDescriptorInfo::FileDescriptorInfo(struct stat stat, const std::string& file_path,
                                       int fd, int open_flags, int fd_flags, int fs_flags,
                                       off_t offset) :
  fd(fd),
  stat(stat),
  file_path(file_path),
  open_flags(open_flags),
  fd_flags(fd_flags),
  fs_flags(fs_flags),
  offset(offset),
  is_sock(false) {
}

bool FileDescriptorInfo::GetSocketName(const int fd, std::string* result) {
  sockaddr_storage ss;
  sockaddr* addr = reinterpret_cast<sockaddr*>(&ss);
  socklen_t addr_len = sizeof(ss);

  if (TEMP_FAILURE_RETRY(getsockname(fd, addr, &addr_len)) == -1) {
    PLOG(ERROR) << "Failed getsockname(" << fd << ")";
    return false;
  }

  if (addr->sa_family != AF_UNIX) {
    LOG(ERROR) << "Unsupported socket (fd=" << fd << ") with family " << addr->sa_family;
    return false;
  }

  const sockaddr_un* unix_addr = reinterpret_cast<const sockaddr_un*>(&ss);

  size_t path_len = addr_len - offsetof(struct sockaddr_un, sun_path);
  // This is an unnamed local socket, we do not accept it.
  if (path_len == 0) {
    LOG(ERROR) << "Unsupported AF_UNIX socket (fd=" << fd << ") with empty path.";
    return false;
  }

  // This is a local socket with an abstract address. Remove the leading NUL byte and
  // add a human-readable "ABSTRACT/" prefix.
  if (unix_addr->sun_path[0] == '\0') {
    *result = "ABSTRACT/";
    result->append(&unix_addr->sun_path[1], path_len - 1);
    return true;
  }

  // If we're here, sun_path must refer to a null terminated filesystem
  // pathname (man 7 unix). Remove the terminator before assigning it to an
  // std::string.
  if (unix_addr->sun_path[path_len - 1] ==  '\0') {
    --path_len;
  }

  result->assign(unix_addr->sun_path, path_len);
  return true;
}

void FileDescriptorInfo::DetachSocket(fail_fn_t fail_fn) const {
  const int dev_null_fd = open("/dev/null", O_RDWR | O_CLOEXEC);
  if (dev_null_fd < 0) {
    fail_fn(std::string("Failed to open /dev/null: ").append(strerror(errno)));
  }

  if (dup3(dev_null_fd, fd, O_CLOEXEC) == -1) {
    fail_fn(android::base::StringPrintf("Failed dup3 on socket descriptor %d: %s",
                                        fd,
                                        strerror(errno)));
  }

  if (close(dev_null_fd) == -1) {
    fail_fn(android::base::StringPrintf("Failed close(%d): %s", dev_null_fd, strerror(errno)));
  }
}

// static
FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore,
                                                 fail_fn_t fail_fn) {
  DIR* proc_fd_dir = opendir(kFdPath);
  if (proc_fd_dir == nullptr) {
    fail_fn(std::string("Unable to open directory ").append(kFdPath));
  }

  int dir_fd = dirfd(proc_fd_dir);
  dirent* dir_entry;

  std::unordered_map<int, FileDescriptorInfo*> open_fd_map;
  while ((dir_entry = readdir(proc_fd_dir)) != nullptr) {
    const int fd = ParseFd(dir_entry, dir_fd);
    if (fd == -1) {
      continue;
    }

    if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
      continue;
    }

    open_fd_map[fd] = FileDescriptorInfo::CreateFromFd(fd, fail_fn);
  }

  if (closedir(proc_fd_dir) == -1) {
    fail_fn("Unable to close directory");
  }

  return new FileDescriptorTable(open_fd_map);
}

void FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore, fail_fn_t fail_fn) {
  std::set<int> open_fds;

  // First get the list of open descriptors.
  DIR* proc_fd_dir = opendir(kFdPath);
  if (proc_fd_dir == nullptr) {
    fail_fn(android::base::StringPrintf("Unable to open directory %s: %s",
                                        kFdPath,
                                        strerror(errno)));
  }

  int dir_fd = dirfd(proc_fd_dir);
  dirent* dir_entry;
  while ((dir_entry = readdir(proc_fd_dir)) != nullptr) {
    const int fd = ParseFd(dir_entry, dir_fd);
    if (fd == -1) {
      continue;
    }

    if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
      continue;
    }

    open_fds.insert(fd);
  }

  if (closedir(proc_fd_dir) == -1) {
    fail_fn(android::base::StringPrintf("Unable to close directory: %s", strerror(errno)));
  }

  RestatInternal(open_fds, fail_fn);
}

// Reopens all file descriptors that are contained in the table.
void FileDescriptorTable::ReopenOrDetach(fail_fn_t fail_fn) {
  std::unordered_map<int, FileDescriptorInfo*>::const_iterator it;
  for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) {
    const FileDescriptorInfo* info = it->second;
    if (info == nullptr) {
      return;
    } else {
      info->ReopenOrDetach(fail_fn);
    }
  }
}

FileDescriptorTable::FileDescriptorTable(
    const std::unordered_map<int, FileDescriptorInfo*>& map)
    : open_fd_map_(map) {
}

void FileDescriptorTable::RestatInternal(std::set<int>& open_fds, fail_fn_t fail_fn) {
  // Iterate through the list of file descriptors we've already recorded
  // and check whether :
  //
  // (a) they continue to be open.
  // (b) they refer to the same file.
  //
  // We'll only store the last error message.
  std::unordered_map<int, FileDescriptorInfo*>::iterator it = open_fd_map_.begin();
  while (it != open_fd_map_.end()) {
    std::set<int>::const_iterator element = open_fds.find(it->first);
    if (element == open_fds.end()) {
      // The entry from the file descriptor table is no longer in the list
      // of open files. We warn about this condition and remove it from
      // the list of FDs under consideration.
      //
      // TODO(narayan): This will be an error in a future android release.
      // error = true;
      // ALOGW("Zygote closed file descriptor %d.", it->first);
      it = open_fd_map_.erase(it);
    } else {
      // The entry from the file descriptor table is still open. Restat
      // it and check whether it refers to the same file.
      if (!it->second->RefersToSameFile()) {
        // The file descriptor refers to a different description. We must
        // update our entry in the table.
        delete it->second;
        it->second = FileDescriptorInfo::CreateFromFd(*element, fail_fn);
      } else {
        // It's the same file. Nothing to do here. Move on to the next open
        // FD.
      }

      ++it;

      // Finally, remove the FD from the set of open_fds. We do this last because
      // |element| will not remain valid after a call to erase.
      open_fds.erase(element);
    }
  }

  if (open_fds.size() > 0) {
    // The zygote has opened new file descriptors since our last inspection.
    // We warn about this condition and add them to our table.
    //
    // TODO(narayan): This will be an error in a future android release.
    // error = true;
    // ALOGW("Zygote opened %zd new file descriptor(s).", open_fds.size());

    // TODO(narayan): This code will be removed in a future android release.
    std::set<int>::const_iterator it;
    for (it = open_fds.begin(); it != open_fds.end(); ++it) {
      const int fd = (*it);
      open_fd_map_[fd] = FileDescriptorInfo::CreateFromFd(fd, fail_fn);
    }
  }
}

// static
int FileDescriptorTable::ParseFd(dirent* dir_entry, int dir_fd) {
  char* end;
  const int fd = strtol(dir_entry->d_name, &end, 10);
  if ((*end) != '\0') {
    return -1;
  }

  // Don't bother with the standard input/output/error, they're handled
  // specially post-fork anyway.
  if (fd <= STDERR_FILENO || fd == dir_fd) {
    return -1;
  }

  return fd;
}
