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>
283764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath#include <sys/socket.h>
29c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include <sys/stat.h>
30c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include <sys/types.h>
313764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath#include <sys/un.h>
32c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include <unistd.h>
33c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
34c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include <cutils/log.h>
35c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include "JNIHelp.h"
36c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath#include "ScopedPrimitiveArray.h"
37c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
383764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath// Whitelist of open paths that the zygote is allowed to keep open.
393764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath//
403764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath// In addition to the paths listed here, all files ending with
413764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath// ".jar" under /system/framework" are whitelisted. See
423764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath// FileDescriptorInfo::IsWhitelisted for the canonical definition.
433764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath//
443764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath// If the whitelisted path is associated with a regular file or a
453764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath// character device, the file is reopened after a fork with the same
463764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath// offset and mode. If the whilelisted  path is associated with a
473764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath// AF_UNIX socket, the socket will refer to /dev/null after each
483764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath// fork, and all operations on it will fail.
49c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamathstatic const char* kPathWhitelist[] = {
50c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  "/dev/null",
513764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath  "/dev/socket/zygote",
523764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath  "/dev/socket/zygote_secondary",
53c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  "/sys/kernel/debug/tracing/trace_marker",
54c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  "/system/framework/framework-res.apk",
55c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  "/dev/urandom",
568977e424ee2d6d85fec419532ae510131aa88c45Adrian Salido  "/dev/ion",
578977e424ee2d6d85fec419532ae510131aa88c45Adrian Salido  "/dev/dri/renderD129", // Fixes b/31172436
58c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath};
59c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
60c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamathstatic const char* kFdPath = "/proc/self/fd";
61c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
62c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath// Keeps track of all relevant information (flags, offset etc.) of an
63c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath// open zygote file descriptor.
64c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamathclass FileDescriptorInfo {
65c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath public:
66c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  // Create a FileDescriptorInfo for a given file descriptor. Returns
67c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  // |NULL| if an error occurred.
68c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  static FileDescriptorInfo* createFromFd(int fd) {
69c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    struct stat f_stat;
70c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // This should never happen; the zygote should always have the right set
71c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // of permissions required to stat all its open files.
72c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
73c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      ALOGE("Unable to stat fd %d : %s", fd, strerror(errno));
74c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return NULL;
75c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
76c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
77c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (S_ISSOCK(f_stat.st_mode)) {
783764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      std::string socket_name;
793764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      if (!GetSocketName(fd, &socket_name)) {
803764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath        return NULL;
813764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      }
823764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath
833764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      if (!IsWhitelisted(socket_name)) {
843764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath        ALOGE("Socket name not whitelisted : %s (fd=%d)", socket_name.c_str(), fd);
853764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath        return NULL;
863764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      }
873764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath
88c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return new FileDescriptorInfo(fd);
89c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
90c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
91c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // We only handle whitelisted regular files and character devices. Whitelisted
92c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // character devices must provide a guarantee of sensible behaviour when
93c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // reopened.
94c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    //
95c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // S_ISDIR : Not supported. (We could if we wanted to, but it's unused).
96c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // S_ISLINK : Not supported.
97c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // S_ISBLK : Not supported.
98c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // S_ISFIFO : Not supported. Note that the zygote uses pipes to communicate
99c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // with the child process across forks but those should have been closed
100c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // before we got to this point.
101c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) {
102c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      ALOGE("Unsupported st_mode %d", f_stat.st_mode);
103c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return NULL;
104c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
105c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
106c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    std::string file_path;
107c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (!Readlink(fd, &file_path)) {
108c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return NULL;
109c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
110c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
111c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (!IsWhitelisted(file_path)) {
112c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      ALOGE("Not whitelisted : %s", file_path.c_str());
113c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return NULL;
114c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
115c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
116c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // File descriptor flags : currently on FD_CLOEXEC. We can set these
117c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // using F_SETFD - we're single threaded at this point of execution so
118c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // there won't be any races.
119c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD));
120c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (fd_flags == -1) {
121c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      ALOGE("Failed fcntl(%d, F_GETFD) : %s", fd, strerror(errno));
122c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return NULL;
123c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
124c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
125c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // File status flags :
126c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // - File access mode : (O_RDONLY, O_WRONLY...) we'll pass these through
127c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    //   to the open() call.
128c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    //
129c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // - File creation flags : (O_CREAT, O_EXCL...) - there's not much we can
130c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    //   do about these, since the file has already been created. We shall ignore
131c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    //   them here.
132c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    //
133c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // - Other flags : We'll have to set these via F_SETFL. On linux, F_SETFL
134c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    //   can only set O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK.
135c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    //   In particular, it can't set O_SYNC and O_DSYNC. We'll have to test for
136c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    //   their presence and pass them in to open().
137c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
138c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (fs_flags == -1) {
139c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      ALOGE("Failed fcntl(%d, F_GETFL) : %s", fd, strerror(errno));
140c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return NULL;
141c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
142c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
143c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // File offset : Ignore the offset for non seekable files.
144c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    const off_t offset = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR));
145c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
146c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // We pass the flags that open accepts to open, and use F_SETFL for
147c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // the rest of them.
148c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    static const int kOpenFlags = (O_RDONLY | O_WRONLY | O_RDWR | O_DSYNC | O_SYNC);
149c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    int open_flags = fs_flags & (kOpenFlags);
150c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    fs_flags = fs_flags & (~(kOpenFlags));
151c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
152c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    return new FileDescriptorInfo(f_stat, file_path, fd, open_flags, fd_flags, fs_flags, offset);
153c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  }
154c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
155c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  // Checks whether the file descriptor associated with this object
156c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  // refers to the same description.
157c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  bool Restat() const {
158c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    struct stat f_stat;
159c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
160c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return false;
161c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
162c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
163c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev;
164c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  }
165c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
1663764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath  bool ReopenOrDetach() const {
167c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (is_sock) {
1683764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      return DetachSocket();
169c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
170c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
171c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // NOTE: This might happen if the file was unlinked after being opened.
172c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // It's a common pattern in the case of temporary files and the like but
173c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // we should not allow such usage from the zygote.
174c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags));
175c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
176c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (new_fd == -1) {
177c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      ALOGE("Failed open(%s, %d) : %s", file_path.c_str(), open_flags, strerror(errno));
178c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return false;
179c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
180c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
181c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) {
182c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      close(new_fd);
183c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      ALOGE("Failed fcntl(%d, F_SETFD, %x) : %s", new_fd, fd_flags, strerror(errno));
184c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return false;
185c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
186c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
187c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) {
188c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      close(new_fd);
189c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      ALOGE("Failed fcntl(%d, F_SETFL, %x) : %s", new_fd, fs_flags, strerror(errno));
190c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return false;
191c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
192c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
193c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) {
194c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      close(new_fd);
195c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      ALOGE("Failed lseek64(%d, SEEK_SET) : %s", new_fd, strerror(errno));
196c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return false;
197c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
198c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
199c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) {
200c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      close(new_fd);
201c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      ALOGE("Failed dup2(%d, %d) : %s", fd, new_fd, strerror(errno));
202c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return false;
203c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
204c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
2053764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    close(new_fd);
206c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
207c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    return true;
208c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  }
209c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
210c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  const int fd;
211c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  const struct stat stat;
212c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  const std::string file_path;
213c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  const int open_flags;
214c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  const int fd_flags;
215c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  const int fs_flags;
216c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  const off_t offset;
217c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  const bool is_sock;
218c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
219c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath private:
220c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  FileDescriptorInfo(int fd) :
221c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    fd(fd),
222c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    stat(),
223c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    open_flags(0),
224c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    fd_flags(0),
225c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    fs_flags(0),
226c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    offset(0),
227c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    is_sock(true) {
228c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  }
229c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
230c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
231c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath                     int fd_flags, int fs_flags, off_t offset) :
232c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    fd(fd),
233c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    stat(stat),
234c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    file_path(file_path),
235c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    open_flags(open_flags),
236c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    fd_flags(fd_flags),
237c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    fs_flags(fs_flags),
238c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    offset(offset),
239c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    is_sock(false) {
240c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  }
241c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
242c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  // Returns true iff. a given path is whitelisted. A path is whitelisted
243c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  // if it belongs to the whitelist (see kPathWhitelist) or if it's a path
244c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  // under /system/framework that ends with ".jar".
245c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  static bool IsWhitelisted(const std::string& path) {
246c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    for (size_t i = 0; i < (sizeof(kPathWhitelist) / sizeof(kPathWhitelist[0])); ++i) {
247c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      if (kPathWhitelist[i] == path) {
248c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        return true;
249c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      }
250c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
251c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
252c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    static const std::string kFrameworksPrefix = "/system/framework/";
253c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    static const std::string kJarSuffix = ".jar";
254c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (path.compare(0, kFrameworksPrefix.size(), kFrameworksPrefix) == 0 &&
255c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        path.compare(path.size() - kJarSuffix.size(), kJarSuffix.size(), kJarSuffix) == 0) {
256c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return true;
257c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
258c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    return false;
259c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  }
260c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
261c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  // TODO: Call android::base::Readlink instead of copying the code here.
262c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  static bool Readlink(const int fd, std::string* result) {
263c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    char path[64];
264c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
265c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
266c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // Code copied from android::base::Readlink starts here :
267c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
268c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // Annoyingly, the readlink system call returns EINVAL for a zero-sized buffer,
269c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // and truncates to whatever size you do supply, so it can't be used to query.
270c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // We could call lstat first, but that would introduce a race condition that
271c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // we couldn't detect.
272c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // ext2 and ext4 both have PAGE_SIZE limitations, so we assume that here.
273c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    char buf[4096];
274c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    ssize_t len = readlink(path, buf, sizeof(buf));
275c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (len == -1) return false;
276c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
277c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    result->assign(buf, len);
278c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    return true;
279c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  }
280c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
2813764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath  // Returns the locally-bound name of the socket |fd|. Returns true
2823764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath  // iff. all of the following hold :
2833764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath  //
2843764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath  // - the socket's sa_family is AF_UNIX.
2853764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath  // - the length of the path is greater than zero (i.e, not an unnamed socket).
2863764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath  // - the first byte of the path isn't zero (i.e, not a socket with an abstract
2873764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath  //   address).
2883764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath  static bool GetSocketName(const int fd, std::string* result) {
2893764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    sockaddr_storage ss;
2903764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    sockaddr* addr = reinterpret_cast<sockaddr*>(&ss);
2913764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    socklen_t addr_len = sizeof(ss);
2923764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath
2933764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    if (TEMP_FAILURE_RETRY(getsockname(fd, addr, &addr_len)) == -1) {
2943764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      ALOGE("Failed getsockname(%d) : %s", fd, strerror(errno));
2953764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      return false;
2963764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    }
2973764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath
2983764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    if (addr->sa_family != AF_UNIX) {
2993764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      ALOGE("Unsupported socket (fd=%d) with family %d", fd, addr->sa_family);
3003764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      return false;
3013764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    }
3023764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath
3033764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    const sockaddr_un* unix_addr = reinterpret_cast<const sockaddr_un*>(&ss);
3043764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath
3053764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    size_t path_len = addr_len - offsetof(struct sockaddr_un, sun_path);
3063764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    // This is an unnamed local socket, we do not accept it.
3073764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    if (path_len == 0) {
3083764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      ALOGE("Unsupported AF_UNIX socket (fd=%d) with empty path.", fd);
3093764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      return false;
3103764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    }
3113764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath
3123764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    // This is a local socket with an abstract address, we do not accept it.
3133764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    if (unix_addr->sun_path[0] == '\0') {
3143764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      ALOGE("Unsupported AF_UNIX socket (fd=%d) with abstract address.", fd);
3153764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      return false;
3163764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    }
3173764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath
3183764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    // If we're here, sun_path must refer to a null terminated filesystem
3193764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    // pathname (man 7 unix). Remove the terminator before assigning it to an
3203764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    // std::string.
3213764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    if (unix_addr->sun_path[path_len - 1] ==  '\0') {
3223764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      --path_len;
3233764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    }
3243764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath
3253764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    result->assign(unix_addr->sun_path, path_len);
3263764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    return true;
3273764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath  }
3283764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath
3293764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath  bool DetachSocket() const {
3303764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    const int dev_null_fd = open("/dev/null", O_RDWR);
3313764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    if (dev_null_fd < 0) {
3323764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      ALOGE("Failed to open /dev/null : %s", strerror(errno));
3333764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      return false;
3343764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    }
3353764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath
3363764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    if (dup2(dev_null_fd, fd) == -1) {
3373764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      ALOGE("Failed dup2 on socket descriptor %d : %s", fd, strerror(errno));
3383764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      return false;
3393764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    }
3403764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath
3413764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    if (close(dev_null_fd) == -1) {
3423764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      ALOGE("Failed close(%d) : %s", dev_null_fd, strerror(errno));
3433764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      return false;
3443764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    }
3453764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath
3463764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath    return true;
3473764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath  }
3483764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath
349c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo);
350c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath};
351c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
352c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath// A FileDescriptorTable is a collection of FileDescriptorInfo objects
353c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath// keyed by their FDs.
354c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamathclass FileDescriptorTable {
355c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath public:
356c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  // Creates a new FileDescriptorTable. This function scans
357c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  // /proc/self/fd for the list of open file descriptors and collects
358c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  // information about them. Returns NULL if an error occurs.
359c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  static FileDescriptorTable* Create() {
360c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    DIR* d = opendir(kFdPath);
361c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (d == NULL) {
362c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno));
363c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return NULL;
364c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
365c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    int dir_fd = dirfd(d);
366c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    dirent* e;
367c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
368c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    std::unordered_map<int, FileDescriptorInfo*> open_fd_map;
369c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    while ((e = readdir(d)) != NULL) {
370c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      const int fd = ParseFd(e, dir_fd);
371c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      if (fd == -1) {
372c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        continue;
373c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      }
374c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
375c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      FileDescriptorInfo* info = FileDescriptorInfo::createFromFd(fd);
376c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      if (info == NULL) {
377c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        if (closedir(d) == -1) {
378c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath          ALOGE("Unable to close directory : %s", strerror(errno));
379c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        }
380c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        return NULL;
381c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      }
382c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      open_fd_map[fd] = info;
383c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
384c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
385c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (closedir(d) == -1) {
386c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      ALOGE("Unable to close directory : %s", strerror(errno));
387c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return NULL;
388c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
389c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    return new FileDescriptorTable(open_fd_map);
390c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  }
391c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
392c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  bool Restat() {
393c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    std::set<int> open_fds;
394c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
395c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // First get the list of open descriptors.
396c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    DIR* d = opendir(kFdPath);
397c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (d == NULL) {
398c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno));
399c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return false;
400c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
401c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
402c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    int dir_fd = dirfd(d);
403c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    dirent* e;
404c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    while ((e = readdir(d)) != NULL) {
405c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      const int fd = ParseFd(e, dir_fd);
406c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      if (fd == -1) {
407c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        continue;
408c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      }
409c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
410c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      open_fds.insert(fd);
411c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
412c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
413c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (closedir(d) == -1) {
414c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      ALOGE("Unable to close directory : %s", strerror(errno));
415c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return false;
416c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
417c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
418c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    return RestatInternal(open_fds);
419c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  }
420c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
421c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  // Reopens all file descriptors that are contained in the table. Returns true
4223764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath  // if all descriptors were successfully re-opened or detached, and false if an
4233764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath  // error occurred.
4243764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath  bool ReopenOrDetach() {
425c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    std::unordered_map<int, FileDescriptorInfo*>::const_iterator it;
426c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) {
427c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      const FileDescriptorInfo* info = it->second;
4283764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      if (info == NULL || !info->ReopenOrDetach()) {
429c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        return false;
430c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      }
431c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
432c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
433c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    return true;
434c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  }
435c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
436c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath private:
437c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  FileDescriptorTable(const std::unordered_map<int, FileDescriptorInfo*>& map)
438c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      : open_fd_map_(map) {
439c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  }
440c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
441c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  bool RestatInternal(std::set<int>& open_fds) {
442c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    bool error = false;
443c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
444c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // Iterate through the list of file descriptors we've already recorded
445c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // and check whether :
446c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    //
447c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // (a) they continue to be open.
448c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // (b) they refer to the same file.
4490b76d6a28e6978151bf245a775329cdae5e574d5Narayan Kamath    std::unordered_map<int, FileDescriptorInfo*>::iterator it = open_fd_map_.begin();
4500b76d6a28e6978151bf245a775329cdae5e574d5Narayan Kamath    while (it != open_fd_map_.end()) {
451c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      std::set<int>::const_iterator element = open_fds.find(it->first);
452c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      if (element == open_fds.end()) {
453c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        // The entry from the file descriptor table is no longer in the list
454c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        // of open files. We warn about this condition and remove it from
455c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        // the list of FDs under consideration.
456c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        //
457c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        // TODO(narayan): This will be an error in a future android release.
458c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        // error = true;
4593764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath        // ALOGW("Zygote closed file descriptor %d.", it->first);
4600b76d6a28e6978151bf245a775329cdae5e574d5Narayan Kamath        it = open_fd_map_.erase(it);
461c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      } else {
462c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        // The entry from the file descriptor table is still open. Restat
463c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        // it and check whether it refers to the same file.
464c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        const bool same_file = it->second->Restat();
465c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        if (!same_file) {
466c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath          // The file descriptor refers to a different description. We must
467c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath          // update our entry in the table.
468c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath          delete it->second;
469c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath          it->second = FileDescriptorInfo::createFromFd(*element);
470c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath          if (it->second == NULL) {
471c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath            // The descriptor no longer no longer refers to a whitelisted file.
472c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath            // We flag an error and remove it from the list of files we're
473c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath            // tracking.
474c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath            error = true;
4750b76d6a28e6978151bf245a775329cdae5e574d5Narayan Kamath            it = open_fd_map_.erase(it);
4760b76d6a28e6978151bf245a775329cdae5e574d5Narayan Kamath          } else {
4770b76d6a28e6978151bf245a775329cdae5e574d5Narayan Kamath            // Successfully restatted the file, move on to the next open FD.
4780b76d6a28e6978151bf245a775329cdae5e574d5Narayan Kamath            ++it;
479c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath          }
480c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        } else {
4810b76d6a28e6978151bf245a775329cdae5e574d5Narayan Kamath          // It's the same file. Nothing to do here. Move on to the next open
4820b76d6a28e6978151bf245a775329cdae5e574d5Narayan Kamath          // FD.
4830b76d6a28e6978151bf245a775329cdae5e574d5Narayan Kamath          ++it;
484c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        }
4850b76d6a28e6978151bf245a775329cdae5e574d5Narayan Kamath
4860b76d6a28e6978151bf245a775329cdae5e574d5Narayan Kamath        // Finally, remove the FD from the set of open_fds. We do this last because
4870b76d6a28e6978151bf245a775329cdae5e574d5Narayan Kamath        // |element| will not remain valid after a call to erase.
4880b76d6a28e6978151bf245a775329cdae5e574d5Narayan Kamath        open_fds.erase(element);
489c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      }
490c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
491c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
492c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (open_fds.size() > 0) {
493c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      // The zygote has opened new file descriptors since our last inspection.
494c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      // We warn about this condition and add them to our table.
495c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      //
496c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      // TODO(narayan): This will be an error in a future android release.
497c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      // error = true;
4983764a260f0c90dcb323caeda14baf903cc108759Narayan Kamath      // ALOGW("Zygote opened %zd new file descriptor(s).", open_fds.size());
499c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
500c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      // TODO(narayan): This code will be removed in a future android release.
501c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      std::set<int>::const_iterator it;
502c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      for (it = open_fds.begin(); it != open_fds.end(); ++it) {
503c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        const int fd = (*it);
504c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        FileDescriptorInfo* info = FileDescriptorInfo::createFromFd(fd);
505c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        if (info == NULL) {
506c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath          // A newly opened file is not on the whitelist. Flag an error and
507c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath          // continue.
508c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath          error = true;
509c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        } else {
510c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath          // Track the newly opened file.
511c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath          open_fd_map_[fd] = info;
512c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath        }
513c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      }
514c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
515c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
516c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    return !error;
517c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  }
518c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
519c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  static int ParseFd(dirent* e, int dir_fd) {
520c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    char* end;
521c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    const int fd = strtol(e->d_name, &end, 10);
522c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if ((*end) != '\0') {
523c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return -1;
524c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
525c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
526c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // Don't bother with the standard input/output/error, they're handled
527c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    // specially post-fork anyway.
528c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    if (fd <= STDERR_FILENO || fd == dir_fd) {
529c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath      return -1;
530c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    }
531c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
532c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath    return fd;
533c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  }
534c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
535c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  // Invariant: All values in this unordered_map are non-NULL.
536c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  std::unordered_map<int, FileDescriptorInfo*> open_fd_map_;
537c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath
538c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath  DISALLOW_COPY_AND_ASSIGN(FileDescriptorTable);
539c5f27a7cb2ec816f483a65255034a1b57a8aa221Narayan Kamath};
540