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