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