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