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     // Allow Runtime Resource Overlays inside APEXes.
142     static const char* kOverlayPathSuffix = "/overlay";
143     if (android::base::StartsWith(path, kApexPrefix) &&
144         android::base::EndsWith(android::base::Dirname(path), kOverlayPathSuffix) &&
145         android::base::EndsWith(path, kApkSuffix) && path.find("/../") == std::string::npos) {
146         return true;
147     }
148 
149     static const char* kOverlayIdmapPrefix = "/data/resource-cache/";
150     static const char* kOverlayIdmapSuffix = ".apk@idmap";
151     if (android::base::StartsWith(path, kOverlayIdmapPrefix) &&
152         android::base::EndsWith(path, kOverlayIdmapSuffix) &&
153         path.find("/../") == std::string::npos) {
154         return true;
155     }
156 
157     // All regular files that are placed under this path are allowlisted
158     // automatically.  The directory name is maintained for compatibility.
159     static const char* kZygoteAllowlistPath = "/vendor/zygote_whitelist/";
160     if (android::base::StartsWith(path, kZygoteAllowlistPath) &&
161         path.find("/../") == std::string::npos) {
162         return true;
163     }
164 
165     return false;
166 }
167 
FileDescriptorAllowlist()168 FileDescriptorAllowlist::FileDescriptorAllowlist() : allowlist_() {}
169 
170 FileDescriptorAllowlist* FileDescriptorAllowlist::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 refers to
180   // 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   // Constructs for sockets.
196   explicit FileDescriptorInfo(int fd);
197 
198   // Constructs for non-socket file descriptors.
199   FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
200                      int fd_flags, int fs_flags, off_t offset);
201 
202   // Returns the locally-bound name of the socket |fd|. Returns true
203   // iff. all of the following hold :
204   //
205   // - the socket's sa_family is AF_UNIX.
206   // - the length of the path is greater than zero (i.e, not an unnamed socket).
207   // - the first byte of the path isn't zero (i.e, not a socket with an abstract
208   //   address).
209   static bool GetSocketName(const int fd, std::string* result);
210 
211   void DetachSocket(fail_fn_t fail_fn) const;
212 
213   DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo);
214 };
215 
CreateFromFd(int fd,fail_fn_t fail_fn)216 FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd, fail_fn_t fail_fn) {
217   struct stat f_stat;
218   // This should never happen; the zygote should always have the right set
219   // of permissions required to stat all its open files.
220   if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
221     fail_fn(android::base::StringPrintf("Unable to stat %d", fd));
222   }
223 
224   const FileDescriptorAllowlist* allowlist = FileDescriptorAllowlist::Get();
225 
226   if (S_ISSOCK(f_stat.st_mode)) {
227     std::string socket_name;
228     if (!GetSocketName(fd, &socket_name)) {
229       fail_fn("Unable to get socket name");
230     }
231 
232     if (!allowlist->IsAllowed(socket_name)) {
233         fail_fn(android::base::StringPrintf("Socket name not allowlisted : %s (fd=%d)",
234                                             socket_name.c_str(), fd));
235     }
236 
237     return new FileDescriptorInfo(fd);
238   }
239 
240   // We only handle allowlisted regular files and character devices. Allowlisted
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 (!allowlist->IsAllowed(file_path)) {
275       fail_fn(android::base::StringPrintf("Not allowlisted (%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 // TODO: Move the definitions here and eliminate the forward declarations. They
477 // temporarily help making code reviews easier.
478 static int ParseFd(dirent* dir_entry, int dir_fd);
479 static std::unique_ptr<std::set<int>> GetOpenFdsIgnoring(const std::vector<int>& fds_to_ignore,
480                                                          fail_fn_t fail_fn);
481 
Create(const std::vector<int> & fds_to_ignore,fail_fn_t fail_fn)482 FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore,
483                                                  fail_fn_t fail_fn) {
484   std::unique_ptr<std::set<int>> open_fds = GetOpenFdsIgnoring(fds_to_ignore, fail_fn);
485   std::unordered_map<int, FileDescriptorInfo*> open_fd_map;
486   for (auto fd : *open_fds) {
487     open_fd_map[fd] = FileDescriptorInfo::CreateFromFd(fd, fail_fn);
488   }
489   return new FileDescriptorTable(open_fd_map);
490 }
491 
GetOpenFdsIgnoring(const std::vector<int> & fds_to_ignore,fail_fn_t fail_fn)492 static std::unique_ptr<std::set<int>> GetOpenFdsIgnoring(const std::vector<int>& fds_to_ignore,
493                                                          fail_fn_t fail_fn) {
494   DIR* proc_fd_dir = opendir(kFdPath);
495   if (proc_fd_dir == nullptr) {
496     fail_fn(android::base::StringPrintf("Unable to open directory %s: %s",
497                                         kFdPath,
498                                         strerror(errno)));
499   }
500 
501   auto result = std::make_unique<std::set<int>>();
502   int dir_fd = dirfd(proc_fd_dir);
503   dirent* dir_entry;
504   while ((dir_entry = readdir(proc_fd_dir)) != nullptr) {
505     const int fd = ParseFd(dir_entry, dir_fd);
506     if (fd == -1) {
507       continue;
508     }
509 
510     if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
511       continue;
512     }
513 
514     result->insert(fd);
515   }
516 
517   if (closedir(proc_fd_dir) == -1) {
518     fail_fn(android::base::StringPrintf("Unable to close directory: %s", strerror(errno)));
519   }
520   return result;
521 }
522 
GetOpenFds(fail_fn_t fail_fn)523 std::unique_ptr<std::set<int>> GetOpenFds(fail_fn_t fail_fn) {
524   const std::vector<int> nothing_to_ignore;
525   return GetOpenFdsIgnoring(nothing_to_ignore, fail_fn);
526 }
527 
Restat(const std::vector<int> & fds_to_ignore,fail_fn_t fail_fn)528 void FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore, fail_fn_t fail_fn) {
529   std::unique_ptr<std::set<int>> open_fds = GetOpenFdsIgnoring(fds_to_ignore, fail_fn);
530 
531   // Check that the files did not change, and leave only newly opened FDs in
532   // |open_fds|.
533   RestatInternal(*open_fds, fail_fn);
534 }
535 
536 // Reopens all file descriptors that are contained in the table.
ReopenOrDetach(fail_fn_t fail_fn)537 void FileDescriptorTable::ReopenOrDetach(fail_fn_t fail_fn) {
538   std::unordered_map<int, FileDescriptorInfo*>::const_iterator it;
539   for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) {
540     const FileDescriptorInfo* info = it->second;
541     if (info == nullptr) {
542       return;
543     } else {
544       info->ReopenOrDetach(fail_fn);
545     }
546   }
547 }
548 
FileDescriptorTable(const std::unordered_map<int,FileDescriptorInfo * > & map)549 FileDescriptorTable::FileDescriptorTable(
550     const std::unordered_map<int, FileDescriptorInfo*>& map)
551     : open_fd_map_(map) {
552 }
553 
~FileDescriptorTable()554 FileDescriptorTable::~FileDescriptorTable() {
555     for (auto& it : open_fd_map_) {
556         delete it.second;
557     }
558 }
559 
RestatInternal(std::set<int> & open_fds,fail_fn_t fail_fn)560 void FileDescriptorTable::RestatInternal(std::set<int>& open_fds, fail_fn_t fail_fn) {
561   // ART creates a file through memfd for optimization purposes. We make sure
562   // there is at most one being created.
563   bool art_memfd_seen = false;
564 
565   // Iterate through the list of file descriptors we've already recorded
566   // and check whether :
567   //
568   // (a) they continue to be open.
569   // (b) they refer to the same file.
570   //
571   // We'll only store the last error message.
572   std::unordered_map<int, FileDescriptorInfo*>::iterator it = open_fd_map_.begin();
573   while (it != open_fd_map_.end()) {
574     std::set<int>::const_iterator element = open_fds.find(it->first);
575     if (element == open_fds.end()) {
576       // The entry from the file descriptor table is no longer in the list
577       // of open files. We warn about this condition and remove it from
578       // the list of FDs under consideration.
579       //
580       // TODO(narayan): This will be an error in a future android release.
581       // error = true;
582       // ALOGW("Zygote closed file descriptor %d.", it->first);
583       delete it->second;
584       it = open_fd_map_.erase(it);
585     } else {
586       // The entry from the file descriptor table is still open. Restat
587       // it and check whether it refers to the same file.
588       if (!it->second->RefersToSameFile()) {
589         // The file descriptor refers to a different description. We must
590         // update our entry in the table.
591         delete it->second;
592         it->second = FileDescriptorInfo::CreateFromFd(*element, fail_fn);
593       } else {
594         // It's the same file. Nothing to do here. Move on to the next open
595         // FD.
596       }
597 
598       if (IsArtMemfd(it->second->file_path)) {
599         if (art_memfd_seen) {
600           fail_fn("ART fd already seen: " + it->second->file_path);
601         } else {
602           art_memfd_seen = true;
603         }
604       }
605 
606       ++it;
607 
608       // Finally, remove the FD from the set of open_fds. We do this last because
609       // |element| will not remain valid after a call to erase.
610       open_fds.erase(element);
611     }
612   }
613 
614   if (open_fds.size() > 0) {
615     // The zygote has opened new file descriptors since our last inspection.
616     // We warn about this condition and add them to our table.
617     //
618     // TODO(narayan): This will be an error in a future android release.
619     // error = true;
620     // ALOGW("Zygote opened %zd new file descriptor(s).", open_fds.size());
621 
622     // TODO(narayan): This code will be removed in a future android release.
623     std::set<int>::const_iterator it;
624     for (it = open_fds.begin(); it != open_fds.end(); ++it) {
625       const int fd = (*it);
626       open_fd_map_[fd] = FileDescriptorInfo::CreateFromFd(fd, fail_fn);
627     }
628   }
629 }
630 
ParseFd(dirent * dir_entry,int dir_fd)631 static int ParseFd(dirent* dir_entry, int dir_fd) {
632   char* end;
633   const int fd = strtol(dir_entry->d_name, &end, 10);
634   if ((*end) != '\0') {
635     return -1;
636   }
637 
638   // Don't bother with the standard input/output/error, they're handled
639   // specially post-fork anyway.
640   if (fd <= STDERR_FILENO || fd == dir_fd) {
641     return -1;
642   }
643 
644   return fd;
645 }
646