• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "fd_utils.h"
18 
19 #include <algorithm>
20 
21 #include <fcntl.h>
22 #include <grp.h>
23 #include <stdlib.h>
24 #include <sys/socket.h>
25 #include <sys/types.h>
26 #include <sys/un.h>
27 #include <unistd.h>
28 
29 #include <android-base/file.h>
30 #include <android-base/logging.h>
31 #include <android-base/stringprintf.h>
32 #include <android-base/strings.h>
33 
34 // Static allowlist of open paths that the zygote is allowed to keep open.
35 static const char* kPathAllowlist[] = {
36         "/dev/null",
37         "/dev/socket/zygote",
38         "/dev/socket/zygote_secondary",
39         "/dev/socket/usap_pool_primary",
40         "/dev/socket/usap_pool_secondary",
41         "/dev/socket/webview_zygote",
42         "/dev/socket/heapprofd",
43         "/sys/kernel/debug/tracing/trace_marker",
44         "/sys/kernel/tracing/trace_marker",
45         "/system/framework/framework-res.apk",
46         "/dev/urandom",
47         "/dev/ion",
48         "/dev/dri/renderD129", // Fixes b/31172436
49         "/dev/stune/foreground/tasks",
50         "/dev/blkio/tasks",
51 };
52 
53 static const char kFdPath[] = "/proc/self/fd";
54 
Get()55 FileDescriptorAllowlist* FileDescriptorAllowlist::Get() {
56     if (instance_ == nullptr) {
57         instance_ = new FileDescriptorAllowlist();
58     }
59     return instance_;
60 }
61 
IsArtMemfd(const std::string & path)62 static bool IsArtMemfd(const std::string& path) {
63   return android::base::StartsWith(path, "/memfd:/boot-image-methods.art");
64 }
65 
IsAllowed(const std::string & path) const66 bool FileDescriptorAllowlist::IsAllowed(const std::string& path) const {
67     // Check the static allowlist path.
68     for (const auto& allowlist_path : kPathAllowlist) {
69         if (path == allowlist_path) return true;
70     }
71 
72     // Check any paths added to the dynamic allowlist.
73     for (const auto& allowlist_path : allowlist_) {
74         if (path == allowlist_path) return true;
75     }
76 
77     // Framework jars are allowed.
78     static const char* kFrameworksPrefix[] = {
79             "/system/framework/",
80             "/system_ext/framework/",
81     };
82 
83     static const char* kJarSuffix = ".jar";
84 
85     for (const auto& frameworks_prefix : kFrameworksPrefix) {
86         if (android::base::StartsWith(path, frameworks_prefix) &&
87             android::base::EndsWith(path, kJarSuffix)) {
88             return true;
89         }
90     }
91 
92     // Jars from APEXes are allowed. This matches /apex/**/javalib/*.jar.
93     static const char* kApexPrefix = "/apex/";
94     static const char* kApexJavalibPathSuffix = "/javalib";
95     if (android::base::StartsWith(path, kApexPrefix) && android::base::EndsWith(path, kJarSuffix) &&
96         android::base::EndsWith(android::base::Dirname(path), kApexJavalibPathSuffix)) {
97         return true;
98     }
99 
100     // the in-memory file created by ART through memfd_create is allowed.
101     if (IsArtMemfd(path)) {
102         return true;
103     }
104 
105     // Allowlist files needed for Runtime Resource Overlay, like these:
106     // /system/vendor/overlay/framework-res.apk
107     // /system/vendor/overlay-subdir/pg/framework-res.apk
108     // /vendor/overlay/framework-res.apk
109     // /vendor/overlay/PG/android-framework-runtime-resource-overlay.apk
110     // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap
111     // /data/resource-cache/system@vendor@overlay-subdir@pg@framework-res.apk@idmap
112     // See AssetManager.cpp for more details on overlay-subdir.
113     static const char* kOverlayDir = "/system/vendor/overlay/";
114     static const char* kVendorOverlayDir = "/vendor/overlay";
115     static const char* kVendorOverlaySubdir = "/system/vendor/overlay-subdir/";
116     static const char* kSystemProductOverlayDir = "/system/product/overlay/";
117     static const char* kProductOverlayDir = "/product/overlay";
118     static const char* kSystemSystemExtOverlayDir = "/system/system_ext/overlay/";
119     static const char* kSystemExtOverlayDir = "/system_ext/overlay";
120     static const char* kSystemOdmOverlayDir = "/system/odm/overlay";
121     static const char* kOdmOverlayDir = "/odm/overlay";
122     static const char* kSystemOemOverlayDir = "/system/oem/overlay";
123     static const char* kOemOverlayDir = "/oem/overlay";
124     static const char* kApkSuffix = ".apk";
125 
126     if ((android::base::StartsWith(path, kOverlayDir) ||
127          android::base::StartsWith(path, kVendorOverlaySubdir) ||
128          android::base::StartsWith(path, kVendorOverlayDir) ||
129          android::base::StartsWith(path, kSystemProductOverlayDir) ||
130          android::base::StartsWith(path, kProductOverlayDir) ||
131          android::base::StartsWith(path, kSystemSystemExtOverlayDir) ||
132          android::base::StartsWith(path, kSystemExtOverlayDir) ||
133          android::base::StartsWith(path, kSystemOdmOverlayDir) ||
134          android::base::StartsWith(path, kOdmOverlayDir) ||
135          android::base::StartsWith(path, kSystemOemOverlayDir) ||
136          android::base::StartsWith(path, kOemOverlayDir)) &&
137         android::base::EndsWith(path, kApkSuffix) && path.find("/../") == std::string::npos) {
138         return true;
139     }
140 
141     static const char* kOverlayIdmapPrefix = "/data/resource-cache/";
142     static const char* kOverlayIdmapSuffix = ".apk@idmap";
143     if (android::base::StartsWith(path, kOverlayIdmapPrefix) &&
144         android::base::EndsWith(path, kOverlayIdmapSuffix) &&
145         path.find("/../") == std::string::npos) {
146         return true;
147     }
148 
149     // All regular files that are placed under this path are allowlisted
150     // automatically.  The directory name is maintained for compatibility.
151     static const char* kZygoteAllowlistPath = "/vendor/zygote_whitelist/";
152     if (android::base::StartsWith(path, kZygoteAllowlistPath) &&
153         path.find("/../") == std::string::npos) {
154         return true;
155     }
156 
157     return false;
158 }
159 
FileDescriptorAllowlist()160 FileDescriptorAllowlist::FileDescriptorAllowlist() : allowlist_() {}
161 
162 FileDescriptorAllowlist* FileDescriptorAllowlist::instance_ = nullptr;
163 
164 // Keeps track of all relevant information (flags, offset etc.) of an
165 // open zygote file descriptor.
166 class FileDescriptorInfo {
167  public:
168   // Create a FileDescriptorInfo for a given file descriptor.
169   static FileDescriptorInfo* CreateFromFd(int fd, fail_fn_t fail_fn);
170 
171   // Checks whether the file descriptor associated with this object refers to
172   // the same description.
173   bool RefersToSameFile() const;
174 
175   void ReopenOrDetach(fail_fn_t fail_fn) const;
176 
177   const int fd;
178   const struct stat stat;
179   const std::string file_path;
180   const int open_flags;
181   const int fd_flags;
182   const int fs_flags;
183   const off_t offset;
184   const bool is_sock;
185 
186  private:
187   // Constructs for sockets.
188   explicit FileDescriptorInfo(int fd);
189 
190   // Constructs for non-socket file descriptors.
191   FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
192                      int fd_flags, int fs_flags, off_t offset);
193 
194   // Returns the locally-bound name of the socket |fd|. Returns true
195   // iff. all of the following hold :
196   //
197   // - the socket's sa_family is AF_UNIX.
198   // - the length of the path is greater than zero (i.e, not an unnamed socket).
199   // - the first byte of the path isn't zero (i.e, not a socket with an abstract
200   //   address).
201   static bool GetSocketName(const int fd, std::string* result);
202 
203   void DetachSocket(fail_fn_t fail_fn) const;
204 
205   DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo);
206 };
207 
CreateFromFd(int fd,fail_fn_t fail_fn)208 FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd, fail_fn_t fail_fn) {
209   struct stat f_stat;
210   // This should never happen; the zygote should always have the right set
211   // of permissions required to stat all its open files.
212   if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
213     fail_fn(android::base::StringPrintf("Unable to stat %d", fd));
214   }
215 
216   const FileDescriptorAllowlist* allowlist = FileDescriptorAllowlist::Get();
217 
218   if (S_ISSOCK(f_stat.st_mode)) {
219     std::string socket_name;
220     if (!GetSocketName(fd, &socket_name)) {
221       fail_fn("Unable to get socket name");
222     }
223 
224     if (!allowlist->IsAllowed(socket_name)) {
225         fail_fn(android::base::StringPrintf("Socket name not allowlisted : %s (fd=%d)",
226                                             socket_name.c_str(), fd));
227     }
228 
229     return new FileDescriptorInfo(fd);
230   }
231 
232   // We only handle allowlisted regular files and character devices. Allowlisted
233   // character devices must provide a guarantee of sensible behaviour when
234   // reopened.
235   //
236   // S_ISDIR : Not supported. (We could if we wanted to, but it's unused).
237   // S_ISLINK : Not supported.
238   // S_ISBLK : Not supported.
239   // S_ISFIFO : Not supported. Note that the Zygote and USAPs use pipes to
240   // communicate with the child processes across forks but those should have been
241   // added to the redirection exemption list.
242   if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) {
243     std::string mode = "Unknown";
244 
245     if (S_ISDIR(f_stat.st_mode)) {
246       mode = "DIR";
247     } else if (S_ISLNK(f_stat.st_mode)) {
248       mode = "LINK";
249     } else if (S_ISBLK(f_stat.st_mode)) {
250       mode = "BLOCK";
251     } else if (S_ISFIFO(f_stat.st_mode)) {
252       mode = "FIFO";
253     }
254 
255     fail_fn(android::base::StringPrintf("Unsupported st_mode for FD %d:  %s", fd, mode.c_str()));
256   }
257 
258   std::string file_path;
259   const std::string fd_path = android::base::StringPrintf("/proc/self/fd/%d", fd);
260   if (!android::base::Readlink(fd_path, &file_path)) {
261     fail_fn(android::base::StringPrintf("Could not read fd link %s: %s",
262                                         fd_path.c_str(),
263                                         strerror(errno)));
264   }
265 
266   if (!allowlist->IsAllowed(file_path)) {
267       fail_fn(android::base::StringPrintf("Not allowlisted (%d): %s", fd, file_path.c_str()));
268   }
269 
270   // File descriptor flags : currently on FD_CLOEXEC. We can set these
271   // using F_SETFD - we're single threaded at this point of execution so
272   // there won't be any races.
273   const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD));
274   if (fd_flags == -1) {
275     fail_fn(android::base::StringPrintf("Failed fcntl(%d, F_GETFD) (%s): %s",
276                                         fd,
277                                         file_path.c_str(),
278                                         strerror(errno)));
279   }
280 
281   // File status flags :
282   // - File access mode : (O_RDONLY, O_WRONLY...) we'll pass these through
283   //   to the open() call.
284   //
285   // - File creation flags : (O_CREAT, O_EXCL...) - there's not much we can
286   //   do about these, since the file has already been created. We shall ignore
287   //   them here.
288   //
289   // - Other flags : We'll have to set these via F_SETFL. On linux, F_SETFL
290   //   can only set O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK.
291   //   In particular, it can't set O_SYNC and O_DSYNC. We'll have to test for
292   //   their presence and pass them in to open().
293   int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
294   if (fs_flags == -1) {
295     fail_fn(android::base::StringPrintf("Failed fcntl(%d, F_GETFL) (%s): %s",
296                                         fd,
297                                         file_path.c_str(),
298                                         strerror(errno)));
299   }
300 
301   // File offset : Ignore the offset for non seekable files.
302   const off_t offset = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR));
303 
304   // We pass the flags that open accepts to open, and use F_SETFL for
305   // the rest of them.
306   static const int kOpenFlags = (O_RDONLY | O_WRONLY | O_RDWR | O_DSYNC | O_SYNC);
307   int open_flags = fs_flags & (kOpenFlags);
308   fs_flags = fs_flags & (~(kOpenFlags));
309 
310   return new FileDescriptorInfo(f_stat, file_path, fd, open_flags, fd_flags, fs_flags, offset);
311 }
312 
RefersToSameFile() const313 bool FileDescriptorInfo::RefersToSameFile() const {
314   struct stat f_stat;
315   if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
316     PLOG(ERROR) << "Unable to restat fd " << fd;
317     return false;
318   }
319 
320   return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev;
321 }
322 
ReopenOrDetach(fail_fn_t fail_fn) const323 void FileDescriptorInfo::ReopenOrDetach(fail_fn_t fail_fn) const {
324   if (is_sock) {
325     return DetachSocket(fail_fn);
326   }
327 
328   // Children can directly use the in-memory file created by ART through memfd_create.
329   if (IsArtMemfd(file_path)) {
330     return;
331   }
332 
333   // NOTE: This might happen if the file was unlinked after being opened.
334   // It's a common pattern in the case of temporary files and the like but
335   // we should not allow such usage from the zygote.
336   const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags));
337 
338   if (new_fd == -1) {
339     fail_fn(android::base::StringPrintf("Failed open(%s, %i): %s",
340                                         file_path.c_str(),
341                                         open_flags,
342                                         strerror(errno)));
343   }
344 
345   if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) {
346     close(new_fd);
347     fail_fn(android::base::StringPrintf("Failed fcntl(%d, F_SETFD, %d) (%s): %s",
348                                         new_fd,
349                                         fd_flags,
350                                         file_path.c_str(),
351                                         strerror(errno)));
352   }
353 
354   if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) {
355     close(new_fd);
356     fail_fn(android::base::StringPrintf("Failed fcntl(%d, F_SETFL, %d) (%s): %s",
357                                         new_fd,
358                                         fs_flags,
359                                         file_path.c_str(),
360                                         strerror(errno)));
361   }
362 
363   if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) {
364     close(new_fd);
365     fail_fn(android::base::StringPrintf("Failed lseek64(%d, SEEK_SET) (%s): %s",
366                                         new_fd,
367                                         file_path.c_str(),
368                                         strerror(errno)));
369   }
370 
371   int dup_flags = (fd_flags & FD_CLOEXEC) ? O_CLOEXEC : 0;
372   if (TEMP_FAILURE_RETRY(dup3(new_fd, fd, dup_flags)) == -1) {
373     close(new_fd);
374     fail_fn(android::base::StringPrintf("Failed dup3(%d, %d, %d) (%s): %s",
375                                         fd,
376                                         new_fd,
377                                         dup_flags,
378                                         file_path.c_str(),
379                                         strerror(errno)));
380   }
381 
382   close(new_fd);
383 }
384 
FileDescriptorInfo(int fd)385 FileDescriptorInfo::FileDescriptorInfo(int fd) :
386   fd(fd),
387   stat(),
388   open_flags(0),
389   fd_flags(0),
390   fs_flags(0),
391   offset(0),
392   is_sock(true) {
393 }
394 
FileDescriptorInfo(struct stat stat,const std::string & file_path,int fd,int open_flags,int fd_flags,int fs_flags,off_t offset)395 FileDescriptorInfo::FileDescriptorInfo(struct stat stat, const std::string& file_path,
396                                        int fd, int open_flags, int fd_flags, int fs_flags,
397                                        off_t offset) :
398   fd(fd),
399   stat(stat),
400   file_path(file_path),
401   open_flags(open_flags),
402   fd_flags(fd_flags),
403   fs_flags(fs_flags),
404   offset(offset),
405   is_sock(false) {
406 }
407 
GetSocketName(const int fd,std::string * result)408 bool FileDescriptorInfo::GetSocketName(const int fd, std::string* result) {
409   sockaddr_storage ss;
410   sockaddr* addr = reinterpret_cast<sockaddr*>(&ss);
411   socklen_t addr_len = sizeof(ss);
412 
413   if (TEMP_FAILURE_RETRY(getsockname(fd, addr, &addr_len)) == -1) {
414     PLOG(ERROR) << "Failed getsockname(" << fd << ")";
415     return false;
416   }
417 
418   if (addr->sa_family != AF_UNIX) {
419     LOG(ERROR) << "Unsupported socket (fd=" << fd << ") with family " << addr->sa_family;
420     return false;
421   }
422 
423   const sockaddr_un* unix_addr = reinterpret_cast<const sockaddr_un*>(&ss);
424 
425   size_t path_len = addr_len - offsetof(struct sockaddr_un, sun_path);
426   // This is an unnamed local socket, we do not accept it.
427   if (path_len == 0) {
428     LOG(ERROR) << "Unsupported AF_UNIX socket (fd=" << fd << ") with empty path.";
429     return false;
430   }
431 
432   // This is a local socket with an abstract address. Remove the leading NUL byte and
433   // add a human-readable "ABSTRACT/" prefix.
434   if (unix_addr->sun_path[0] == '\0') {
435     *result = "ABSTRACT/";
436     result->append(&unix_addr->sun_path[1], path_len - 1);
437     return true;
438   }
439 
440   // If we're here, sun_path must refer to a null terminated filesystem
441   // pathname (man 7 unix). Remove the terminator before assigning it to an
442   // std::string.
443   if (unix_addr->sun_path[path_len - 1] ==  '\0') {
444     --path_len;
445   }
446 
447   result->assign(unix_addr->sun_path, path_len);
448   return true;
449 }
450 
DetachSocket(fail_fn_t fail_fn) const451 void FileDescriptorInfo::DetachSocket(fail_fn_t fail_fn) const {
452   const int dev_null_fd = open("/dev/null", O_RDWR | O_CLOEXEC);
453   if (dev_null_fd < 0) {
454     fail_fn(std::string("Failed to open /dev/null: ").append(strerror(errno)));
455   }
456 
457   if (dup3(dev_null_fd, fd, O_CLOEXEC) == -1) {
458     fail_fn(android::base::StringPrintf("Failed dup3 on socket descriptor %d: %s",
459                                         fd,
460                                         strerror(errno)));
461   }
462 
463   if (close(dev_null_fd) == -1) {
464     fail_fn(android::base::StringPrintf("Failed close(%d): %s", dev_null_fd, strerror(errno)));
465   }
466 }
467 
468 // TODO: Move the definitions here and eliminate the forward declarations. They
469 // temporarily help making code reviews easier.
470 static int ParseFd(dirent* dir_entry, int dir_fd);
471 static std::unique_ptr<std::set<int>> GetOpenFdsIgnoring(const std::vector<int>& fds_to_ignore,
472                                                          fail_fn_t fail_fn);
473 
Create(const std::vector<int> & fds_to_ignore,fail_fn_t fail_fn)474 FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore,
475                                                  fail_fn_t fail_fn) {
476   std::unique_ptr<std::set<int>> open_fds = GetOpenFdsIgnoring(fds_to_ignore, fail_fn);
477   std::unordered_map<int, FileDescriptorInfo*> open_fd_map;
478   for (auto fd : *open_fds) {
479     open_fd_map[fd] = FileDescriptorInfo::CreateFromFd(fd, fail_fn);
480   }
481   return new FileDescriptorTable(open_fd_map);
482 }
483 
GetOpenFdsIgnoring(const std::vector<int> & fds_to_ignore,fail_fn_t fail_fn)484 static std::unique_ptr<std::set<int>> GetOpenFdsIgnoring(const std::vector<int>& fds_to_ignore,
485                                                          fail_fn_t fail_fn) {
486   DIR* proc_fd_dir = opendir(kFdPath);
487   if (proc_fd_dir == nullptr) {
488     fail_fn(android::base::StringPrintf("Unable to open directory %s: %s",
489                                         kFdPath,
490                                         strerror(errno)));
491   }
492 
493   auto result = std::make_unique<std::set<int>>();
494   int dir_fd = dirfd(proc_fd_dir);
495   dirent* dir_entry;
496   while ((dir_entry = readdir(proc_fd_dir)) != nullptr) {
497     const int fd = ParseFd(dir_entry, dir_fd);
498     if (fd == -1) {
499       continue;
500     }
501 
502     if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
503       continue;
504     }
505 
506     result->insert(fd);
507   }
508 
509   if (closedir(proc_fd_dir) == -1) {
510     fail_fn(android::base::StringPrintf("Unable to close directory: %s", strerror(errno)));
511   }
512   return result;
513 }
514 
GetOpenFds(fail_fn_t fail_fn)515 std::unique_ptr<std::set<int>> GetOpenFds(fail_fn_t fail_fn) {
516   const std::vector<int> nothing_to_ignore;
517   return GetOpenFdsIgnoring(nothing_to_ignore, fail_fn);
518 }
519 
Restat(const std::vector<int> & fds_to_ignore,fail_fn_t fail_fn)520 void FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore, fail_fn_t fail_fn) {
521   std::unique_ptr<std::set<int>> open_fds = GetOpenFdsIgnoring(fds_to_ignore, fail_fn);
522 
523   // Check that the files did not change, and leave only newly opened FDs in
524   // |open_fds|.
525   RestatInternal(*open_fds, fail_fn);
526 }
527 
528 // Reopens all file descriptors that are contained in the table.
ReopenOrDetach(fail_fn_t fail_fn)529 void FileDescriptorTable::ReopenOrDetach(fail_fn_t fail_fn) {
530   std::unordered_map<int, FileDescriptorInfo*>::const_iterator it;
531   for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) {
532     const FileDescriptorInfo* info = it->second;
533     if (info == nullptr) {
534       return;
535     } else {
536       info->ReopenOrDetach(fail_fn);
537     }
538   }
539 }
540 
FileDescriptorTable(const std::unordered_map<int,FileDescriptorInfo * > & map)541 FileDescriptorTable::FileDescriptorTable(
542     const std::unordered_map<int, FileDescriptorInfo*>& map)
543     : open_fd_map_(map) {
544 }
545 
~FileDescriptorTable()546 FileDescriptorTable::~FileDescriptorTable() {
547     for (auto& it : open_fd_map_) {
548         delete it.second;
549     }
550 }
551 
RestatInternal(std::set<int> & open_fds,fail_fn_t fail_fn)552 void FileDescriptorTable::RestatInternal(std::set<int>& open_fds, fail_fn_t fail_fn) {
553   // ART creates a file through memfd for optimization purposes. We make sure
554   // there is at most one being created.
555   bool art_memfd_seen = false;
556 
557   // Iterate through the list of file descriptors we've already recorded
558   // and check whether :
559   //
560   // (a) they continue to be open.
561   // (b) they refer to the same file.
562   //
563   // We'll only store the last error message.
564   std::unordered_map<int, FileDescriptorInfo*>::iterator it = open_fd_map_.begin();
565   while (it != open_fd_map_.end()) {
566     std::set<int>::const_iterator element = open_fds.find(it->first);
567     if (element == open_fds.end()) {
568       // The entry from the file descriptor table is no longer in the list
569       // of open files. We warn about this condition and remove it from
570       // the list of FDs under consideration.
571       //
572       // TODO(narayan): This will be an error in a future android release.
573       // error = true;
574       // ALOGW("Zygote closed file descriptor %d.", it->first);
575       it = open_fd_map_.erase(it);
576     } else {
577       // The entry from the file descriptor table is still open. Restat
578       // it and check whether it refers to the same file.
579       if (!it->second->RefersToSameFile()) {
580         // The file descriptor refers to a different description. We must
581         // update our entry in the table.
582         delete it->second;
583         it->second = FileDescriptorInfo::CreateFromFd(*element, fail_fn);
584       } else {
585         // It's the same file. Nothing to do here. Move on to the next open
586         // FD.
587       }
588 
589       if (IsArtMemfd(it->second->file_path)) {
590         if (art_memfd_seen) {
591           fail_fn("ART fd already seen: " + it->second->file_path);
592         } else {
593           art_memfd_seen = true;
594         }
595       }
596 
597       ++it;
598 
599       // Finally, remove the FD from the set of open_fds. We do this last because
600       // |element| will not remain valid after a call to erase.
601       open_fds.erase(element);
602     }
603   }
604 
605   if (open_fds.size() > 0) {
606     // The zygote has opened new file descriptors since our last inspection.
607     // We warn about this condition and add them to our table.
608     //
609     // TODO(narayan): This will be an error in a future android release.
610     // error = true;
611     // ALOGW("Zygote opened %zd new file descriptor(s).", open_fds.size());
612 
613     // TODO(narayan): This code will be removed in a future android release.
614     std::set<int>::const_iterator it;
615     for (it = open_fds.begin(); it != open_fds.end(); ++it) {
616       const int fd = (*it);
617       open_fd_map_[fd] = FileDescriptorInfo::CreateFromFd(fd, fail_fn);
618     }
619   }
620 }
621 
ParseFd(dirent * dir_entry,int dir_fd)622 static int ParseFd(dirent* dir_entry, int dir_fd) {
623   char* end;
624   const int fd = strtol(dir_entry->d_name, &end, 10);
625   if ((*end) != '\0') {
626     return -1;
627   }
628 
629   // Don't bother with the standard input/output/error, they're handled
630   // specially post-fork anyway.
631   if (fd <= STDERR_FILENO || fd == dir_fd) {
632     return -1;
633   }
634 
635   return fd;
636 }
637