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 #ifndef FRAMEWORKS_BASE_CORE_JNI_FD_UTILS_H_
18 #define FRAMEWORKS_BASE_CORE_JNI_FD_UTILS_H_
19 
20 #include <set>
21 #include <string>
22 #include <unordered_map>
23 #include <vector>
24 
25 #include <dirent.h>
26 #include <inttypes.h>
27 #include <sys/stat.h>
28 
29 #include <android-base/macros.h>
30 
31 class FileDescriptorInfo;
32 
33 // This type is duplicated in com_android_internal_os_Zygote.cpp
34 typedef const std::function<void(std::string)>& fail_fn_t;
35 
36 // Whitelist of open paths that the zygote is allowed to keep open.
37 //
38 // In addition to the paths listed in kPathWhitelist in file_utils.cpp, and
39 // paths dynamically added with Allow(), all files ending with ".jar"
40 // under /system/framework" are whitelisted. See IsAllowed() for the canonical
41 // definition.
42 //
43 // If the whitelisted path is associated with a regular file or a
44 // character device, the file is reopened after a fork with the same
45 // offset and mode. If the whilelisted  path is associated with a
46 // AF_UNIX socket, the socket will refer to /dev/null after each
47 // fork, and all operations on it will fail.
48 class FileDescriptorWhitelist {
49  public:
50   // Lazily creates the global whitelist.
51   static FileDescriptorWhitelist* Get();
52 
53   // Adds a path to the whitelist.
Allow(const std::string & path)54   void Allow(const std::string& path) {
55     whitelist_.push_back(path);
56   }
57 
58   // Returns true iff. a given path is whitelisted. A path is whitelisted
59   // if it belongs to the whitelist (see kPathWhitelist) or if it's a path
60   // under /system/framework that ends with ".jar" or if it is a system
61   // framework overlay.
62   bool IsAllowed(const std::string& path) const;
63 
64  private:
65   FileDescriptorWhitelist();
66 
67   static FileDescriptorWhitelist* instance_;
68 
69   std::vector<std::string> whitelist_;
70 
71   DISALLOW_COPY_AND_ASSIGN(FileDescriptorWhitelist);
72 };
73 
74 // A FileDescriptorTable is a collection of FileDescriptorInfo objects
75 // keyed by their FDs.
76 class FileDescriptorTable {
77  public:
78   // Creates a new FileDescriptorTable. This function scans
79   // /proc/self/fd for the list of open file descriptors and collects
80   // information about them. Returns NULL if an error occurs.
81   static FileDescriptorTable* Create(const std::vector<int>& fds_to_ignore,
82                                      fail_fn_t fail_fn);
83 
84   void Restat(const std::vector<int>& fds_to_ignore, fail_fn_t fail_fn);
85 
86   // Reopens all file descriptors that are contained in the table. Returns true
87   // if all descriptors were successfully re-opened or detached, and false if an
88   // error occurred.
89   void ReopenOrDetach(fail_fn_t fail_fn);
90 
91  private:
92   explicit FileDescriptorTable(const std::unordered_map<int, FileDescriptorInfo*>& map);
93 
94   void RestatInternal(std::set<int>& open_fds, fail_fn_t fail_fn);
95 
96   static int ParseFd(dirent* e, int dir_fd);
97 
98   // Invariant: All values in this unordered_map are non-NULL.
99   std::unordered_map<int, FileDescriptorInfo*> open_fd_map_;
100 
101   DISALLOW_COPY_AND_ASSIGN(FileDescriptorTable);
102 };
103 
104 #endif  // FRAMEWORKS_BASE_CORE_JNI_FD_UTILS_H_
105