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