fd_utils-inl.h revision c5f27a7cb2ec816f483a65255034a1b57a8aa221
1c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath/* 2c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath * Copyright (C) 2016 The Android Open Source Project 3c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath * 4c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath * Licensed under the Apache License, Version 2.0 (the "License"); 5c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath * you may not use this file except in compliance with the License. 6c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath * You may obtain a copy of the License at 7c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath * 8c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath * http://www.apache.org/licenses/LICENSE-2.0 9c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath * 10c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath * Unless required by applicable law or agreed to in writing, software 11c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath * distributed under the License is distributed on an "AS IS" BASIS, 12c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath * See the License for the specific language governing permissions and 14c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath * limitations under the License. 15c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath */ 16c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 17c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include <string> 18c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include <unordered_map> 19c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include <set> 20c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include <vector> 21c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include <algorithm> 22c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 23c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include <dirent.h> 24c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include <fcntl.h> 25c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include <grp.h> 26c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include <inttypes.h> 27c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include <stdlib.h> 28c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include <sys/stat.h> 29c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include <sys/types.h> 30c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include <unistd.h> 31c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 32c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include <cutils/log.h> 33c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include "JNIHelp.h" 34c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include "ScopedPrimitiveArray.h" 35c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 36c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath// Whitelist of open paths that the zygote is allowed to keep open 37c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath// that will be recreated across forks. In addition to files here, 38c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath// all files ending with ".jar" under /system/framework" are 39c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath// whitelisted. See FileDescriptorInfo::IsWhitelisted for the 40c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath// canonical definition. 41c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamathstatic const char* kPathWhitelist[] = { 42c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath "/dev/null", 43c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath "/dev/pmsg0", 44c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath "/system/etc/event-log-tags", 45c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath "/sys/kernel/debug/tracing/trace_marker", 46c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath "/system/framework/framework-res.apk", 47c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath "/dev/urandom", 48c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath "/dev/ion" 49c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath}; 50c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 51c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamathstatic const char* kFdPath = "/proc/self/fd"; 52c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 53c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath// Keeps track of all relevant information (flags, offset etc.) of an 54c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath// open zygote file descriptor. 55c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamathclass FileDescriptorInfo { 56c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath public: 57c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // Create a FileDescriptorInfo for a given file descriptor. Returns 58c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // |NULL| if an error occurred. 59c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath static FileDescriptorInfo* createFromFd(int fd) { 60c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath struct stat f_stat; 61c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // This should never happen; the zygote should always have the right set 62c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // of permissions required to stat all its open files. 63c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) { 64c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGE("Unable to stat fd %d : %s", fd, strerror(errno)); 65c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return NULL; 66c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 67c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 68c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // Ignore (don't reopen or fail on) socket fds for now. 69c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (S_ISSOCK(f_stat.st_mode)) { 70c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGW("Unsupported socket FD: %d, ignoring.", fd); 71c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return new FileDescriptorInfo(fd); 72c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 73c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 74c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // We only handle whitelisted regular files and character devices. Whitelisted 75c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // character devices must provide a guarantee of sensible behaviour when 76c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // reopened. 77c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // 78c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // S_ISDIR : Not supported. (We could if we wanted to, but it's unused). 79c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // S_ISLINK : Not supported. 80c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // S_ISBLK : Not supported. 81c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // S_ISFIFO : Not supported. Note that the zygote uses pipes to communicate 82c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // with the child process across forks but those should have been closed 83c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // before we got to this point. 84c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) { 85c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGE("Unsupported st_mode %d", f_stat.st_mode); 86c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return NULL; 87c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 88c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 89c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath std::string file_path; 90c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (!Readlink(fd, &file_path)) { 91c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return NULL; 92c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 93c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 94c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (!IsWhitelisted(file_path)) { 95c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGE("Not whitelisted : %s", file_path.c_str()); 96c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return NULL; 97c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 98c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 99c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // File descriptor flags : currently on FD_CLOEXEC. We can set these 100c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // using F_SETFD - we're single threaded at this point of execution so 101c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // there won't be any races. 102c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD)); 103c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (fd_flags == -1) { 104c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGE("Failed fcntl(%d, F_GETFD) : %s", fd, strerror(errno)); 105c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return NULL; 106c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 107c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 108c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // File status flags : 109c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // - File access mode : (O_RDONLY, O_WRONLY...) we'll pass these through 110c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // to the open() call. 111c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // 112c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // - File creation flags : (O_CREAT, O_EXCL...) - there's not much we can 113c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // do about these, since the file has already been created. We shall ignore 114c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // them here. 115c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // 116c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // - Other flags : We'll have to set these via F_SETFL. On linux, F_SETFL 117c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // can only set O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK. 118c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // In particular, it can't set O_SYNC and O_DSYNC. We'll have to test for 119c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // their presence and pass them in to open(). 120c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL)); 121c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (fs_flags == -1) { 122c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGE("Failed fcntl(%d, F_GETFL) : %s", fd, strerror(errno)); 123c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return NULL; 124c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 125c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 126c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // File offset : Ignore the offset for non seekable files. 127c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath const off_t offset = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR)); 128c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 129c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // We pass the flags that open accepts to open, and use F_SETFL for 130c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // the rest of them. 131c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath static const int kOpenFlags = (O_RDONLY | O_WRONLY | O_RDWR | O_DSYNC | O_SYNC); 132c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath int open_flags = fs_flags & (kOpenFlags); 133c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath fs_flags = fs_flags & (~(kOpenFlags)); 134c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 135c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return new FileDescriptorInfo(f_stat, file_path, fd, open_flags, fd_flags, fs_flags, offset); 136c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 137c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 138c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // Checks whether the file descriptor associated with this object 139c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // refers to the same description. 140c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath bool Restat() const { 141c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath struct stat f_stat; 142c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) { 143c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return false; 144c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 145c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 146c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev; 147c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 148c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 149c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath bool Reopen() const { 150c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // Always skip over socket FDs for now. 151c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (is_sock) { 152c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return true; 153c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 154c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 155c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // NOTE: This might happen if the file was unlinked after being opened. 156c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // It's a common pattern in the case of temporary files and the like but 157c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // we should not allow such usage from the zygote. 158c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags)); 159c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 160c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (new_fd == -1) { 161c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGE("Failed open(%s, %d) : %s", file_path.c_str(), open_flags, strerror(errno)); 162c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return false; 163c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 164c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 165c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) { 166c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath close(new_fd); 167c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGE("Failed fcntl(%d, F_SETFD, %x) : %s", new_fd, fd_flags, strerror(errno)); 168c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return false; 169c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 170c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 171c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) { 172c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath close(new_fd); 173c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGE("Failed fcntl(%d, F_SETFL, %x) : %s", new_fd, fs_flags, strerror(errno)); 174c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return false; 175c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 176c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 177c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) { 178c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath close(new_fd); 179c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGE("Failed lseek64(%d, SEEK_SET) : %s", new_fd, strerror(errno)); 180c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return false; 181c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 182c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 183c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) { 184c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath close(new_fd); 185c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGE("Failed dup2(%d, %d) : %s", fd, new_fd, strerror(errno)); 186c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return false; 187c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 188c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 189c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (close(new_fd) == -1) { 190c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGW("Failed close(%d) : %s", new_fd, strerror(errno)); 191c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 192c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 193c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return true; 194c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 195c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 196c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath const int fd; 197c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath const struct stat stat; 198c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath const std::string file_path; 199c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath const int open_flags; 200c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath const int fd_flags; 201c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath const int fs_flags; 202c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath const off_t offset; 203c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath const bool is_sock; 204c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 205c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath private: 206c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath FileDescriptorInfo(int fd) : 207c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath fd(fd), 208c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath stat(), 209c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath open_flags(0), 210c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath fd_flags(0), 211c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath fs_flags(0), 212c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath offset(0), 213c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath is_sock(true) { 214c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 215c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 216c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags, 217c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath int fd_flags, int fs_flags, off_t offset) : 218c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath fd(fd), 219c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath stat(stat), 220c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath file_path(file_path), 221c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath open_flags(open_flags), 222c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath fd_flags(fd_flags), 223c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath fs_flags(fs_flags), 224c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath offset(offset), 225c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath is_sock(false) { 226c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 227c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 228c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // Returns true iff. a given path is whitelisted. A path is whitelisted 229c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // if it belongs to the whitelist (see kPathWhitelist) or if it's a path 230c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // under /system/framework that ends with ".jar". 231c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath static bool IsWhitelisted(const std::string& path) { 232c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath for (size_t i = 0; i < (sizeof(kPathWhitelist) / sizeof(kPathWhitelist[0])); ++i) { 233c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (kPathWhitelist[i] == path) { 234c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return true; 235c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 236c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 237c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 238c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath static const std::string kFrameworksPrefix = "/system/framework/"; 239c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath static const std::string kJarSuffix = ".jar"; 240c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (path.compare(0, kFrameworksPrefix.size(), kFrameworksPrefix) == 0 && 241c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath path.compare(path.size() - kJarSuffix.size(), kJarSuffix.size(), kJarSuffix) == 0) { 242c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return true; 243c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 244c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return false; 245c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 246c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 247c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // TODO: Call android::base::Readlink instead of copying the code here. 248c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath static bool Readlink(const int fd, std::string* result) { 249c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath char path[64]; 250c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath snprintf(path, sizeof(path), "/proc/self/fd/%d", fd); 251c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 252c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // Code copied from android::base::Readlink starts here : 253c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 254c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // Annoyingly, the readlink system call returns EINVAL for a zero-sized buffer, 255c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // and truncates to whatever size you do supply, so it can't be used to query. 256c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // We could call lstat first, but that would introduce a race condition that 257c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // we couldn't detect. 258c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // ext2 and ext4 both have PAGE_SIZE limitations, so we assume that here. 259c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath char buf[4096]; 260c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ssize_t len = readlink(path, buf, sizeof(buf)); 261c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (len == -1) return false; 262c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 263c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath result->assign(buf, len); 264c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return true; 265c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 266c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 267c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo); 268c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath}; 269c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 270c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath// A FileDescriptorTable is a collection of FileDescriptorInfo objects 271c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath// keyed by their FDs. 272c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamathclass FileDescriptorTable { 273c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath public: 274c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // Creates a new FileDescriptorTable. This function scans 275c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // /proc/self/fd for the list of open file descriptors and collects 276c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // information about them. Returns NULL if an error occurs. 277c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath static FileDescriptorTable* Create() { 278c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath DIR* d = opendir(kFdPath); 279c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (d == NULL) { 280c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno)); 281c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return NULL; 282c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 283c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath int dir_fd = dirfd(d); 284c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath dirent* e; 285c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 286c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath std::unordered_map<int, FileDescriptorInfo*> open_fd_map; 287c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath while ((e = readdir(d)) != NULL) { 288c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath const int fd = ParseFd(e, dir_fd); 289c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (fd == -1) { 290c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath continue; 291c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 292c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 293c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath FileDescriptorInfo* info = FileDescriptorInfo::createFromFd(fd); 294c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (info == NULL) { 295c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (closedir(d) == -1) { 296c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGE("Unable to close directory : %s", strerror(errno)); 297c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 298c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return NULL; 299c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 300c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath open_fd_map[fd] = info; 301c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 302c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 303c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (closedir(d) == -1) { 304c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGE("Unable to close directory : %s", strerror(errno)); 305c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return NULL; 306c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 307c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return new FileDescriptorTable(open_fd_map); 308c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 309c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 310c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath bool Restat() { 311c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath std::set<int> open_fds; 312c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 313c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // First get the list of open descriptors. 314c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath DIR* d = opendir(kFdPath); 315c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (d == NULL) { 316c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno)); 317c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return false; 318c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 319c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 320c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath int dir_fd = dirfd(d); 321c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath dirent* e; 322c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath while ((e = readdir(d)) != NULL) { 323c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath const int fd = ParseFd(e, dir_fd); 324c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (fd == -1) { 325c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath continue; 326c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 327c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 328c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath open_fds.insert(fd); 329c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 330c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 331c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (closedir(d) == -1) { 332c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGE("Unable to close directory : %s", strerror(errno)); 333c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return false; 334c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 335c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 336c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return RestatInternal(open_fds); 337c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 338c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 339c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // Reopens all file descriptors that are contained in the table. Returns true 340c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // if all descriptors were re-opened, and false if an error occurred. 341c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath bool Reopen() { 342c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath std::unordered_map<int, FileDescriptorInfo*>::const_iterator it; 343c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) { 344c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath const FileDescriptorInfo* info = it->second; 345c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (info == NULL || !info->Reopen()) { 346c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return false; 347c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 348c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 349c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 350c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return true; 351c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 352c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 353c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath private: 354c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath FileDescriptorTable(const std::unordered_map<int, FileDescriptorInfo*>& map) 355c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath : open_fd_map_(map) { 356c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 357c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 358c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath bool RestatInternal(std::set<int>& open_fds) { 359c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath bool error = false; 360c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 361c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // Iterate through the list of file descriptors we've already recorded 362c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // and check whether : 363c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // 364c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // (a) they continue to be open. 365c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // (b) they refer to the same file. 366c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath std::unordered_map<int, FileDescriptorInfo*>::iterator it; 367c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) { 368c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath std::set<int>::const_iterator element = open_fds.find(it->first); 369c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (element == open_fds.end()) { 370c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // The entry from the file descriptor table is no longer in the list 371c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // of open files. We warn about this condition and remove it from 372c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // the list of FDs under consideration. 373c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // 374c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // TODO(narayan): This will be an error in a future android release. 375c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // error = true; 376c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGW("Zygote closed file descriptor %d.", it->first); 377c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath open_fd_map_.erase(it); 378c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } else { 379c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // The entry from the file descriptor table is still open. Restat 380c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // it and check whether it refers to the same file. 381c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath open_fds.erase(element); 382c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath const bool same_file = it->second->Restat(); 383c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (!same_file) { 384c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // The file descriptor refers to a different description. We must 385c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // update our entry in the table. 386c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath delete it->second; 387c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath it->second = FileDescriptorInfo::createFromFd(*element); 388c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (it->second == NULL) { 389c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // The descriptor no longer no longer refers to a whitelisted file. 390c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // We flag an error and remove it from the list of files we're 391c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // tracking. 392c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath error = true; 393c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath open_fd_map_.erase(it); 394c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 395c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } else { 396c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // It's the same file. Nothing to do here. 397c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 398c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 399c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 400c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 401c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (open_fds.size() > 0) { 402c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // The zygote has opened new file descriptors since our last inspection. 403c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // We warn about this condition and add them to our table. 404c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // 405c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // TODO(narayan): This will be an error in a future android release. 406c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // error = true; 407c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath ALOGW("Zygote opened %d new file descriptor(s).", open_fds.size()); 408c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 409c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // TODO(narayan): This code will be removed in a future android release. 410c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath std::set<int>::const_iterator it; 411c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath for (it = open_fds.begin(); it != open_fds.end(); ++it) { 412c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath const int fd = (*it); 413c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath FileDescriptorInfo* info = FileDescriptorInfo::createFromFd(fd); 414c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (info == NULL) { 415c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // A newly opened file is not on the whitelist. Flag an error and 416c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // continue. 417c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath error = true; 418c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } else { 419c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // Track the newly opened file. 420c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath open_fd_map_[fd] = info; 421c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 422c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 423c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 424c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 425c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return !error; 426c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 427c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 428c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath static int ParseFd(dirent* e, int dir_fd) { 429c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath char* end; 430c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath const int fd = strtol(e->d_name, &end, 10); 431c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if ((*end) != '\0') { 432c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return -1; 433c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 434c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 435c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // Don't bother with the standard input/output/error, they're handled 436c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // specially post-fork anyway. 437c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath if (fd <= STDERR_FILENO || fd == dir_fd) { 438c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return -1; 439c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 440c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 441c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath return fd; 442c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath } 443c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 444c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath // Invariant: All values in this unordered_map are non-NULL. 445c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath std::unordered_map<int, FileDescriptorInfo*> open_fd_map_; 446c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath 447c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath DISALLOW_COPY_AND_ASSIGN(FileDescriptorTable); 448c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath}; 449