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