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