1 /*
2  * Copyright (C) 2019 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 specic language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef MEDIAPROVIDER_FUSE_MEDIAPROVIDERWRAPPER_H_
18 #define MEDIAPROVIDER_FUSE_MEDIAPROVIDERWRAPPER_H_
19 
20 #include <jni.h>
21 #include <sys/types.h>
22 
23 #include <dirent.h>
24 #include <atomic>
25 #include <condition_variable>
26 #include <functional>
27 #include <mutex>
28 #include <queue>
29 #include <string>
30 #include <thread>
31 
32 #include "libfuse_jni/ReaddirHelper.h"
33 #include "libfuse_jni/RedactionInfo.h"
34 
35 namespace mediaprovider {
36 namespace fuse {
37 
38 /**
39  * Class that wraps MediaProvider.java and all of the needed JNI calls to make
40  * interaction with MediaProvider easier.
41  */
42 class MediaProviderWrapper final {
43   public:
44     MediaProviderWrapper(JNIEnv* env, jobject media_provider);
45     ~MediaProviderWrapper();
46 
47     /**
48      * Computes and returns the RedactionInfo for a given file and UID.
49      *
50      * @param uid UID of the app requesting the read
51      * @param path path of the requested file
52      * @return RedactionInfo on success, nullptr on failure to calculate
53      * redaction ranges (e.g. exception was thrown in Java world)
54      */
55     std::unique_ptr<RedactionInfo> GetRedactionInfo(const std::string& path, uid_t uid, pid_t tid);
56 
57     /**
58      * Inserts a new entry for the given path and UID.
59      *
60      * @param path the path of the file to be created
61      * @param uid UID of the calling app
62      * @return 0 if the operation succeeded,
63      * or errno error code if operation fails.
64      */
65     int InsertFile(const std::string& path, uid_t uid);
66 
67     /**
68      * Delete the file denoted by the given path on behalf of the given UID.
69      *
70      * @param path the path of the file to be deleted
71      * @param uid UID of the calling app
72      * @return 0 upon success, or errno error code if operation fails.
73      */
74     int DeleteFile(const std::string& path, uid_t uid);
75 
76     /**
77      * Gets directory entries for given path from MediaProvider database and lower file system
78      *
79      * @param uid UID of the calling app.
80      * @param path Relative path of the directory.
81      * @param dirp Pointer to directory stream, used to query lower file system.
82      * @return DirectoryEntries with list of directory entries on success.
83      * File names in a directory are obtained from MediaProvider. If a path is unknown to
84      * MediaProvider, file names are obtained from lower file system. All directory names in the
85      * given directory are obtained from lower file system.
86      * An empty string in first directory entry name indicates the error occurred while obtaining
87      * directory entries, directory entry type will hold the corresponding errno information.
88      */
89     std::vector<std::shared_ptr<DirectoryEntry>> GetDirectoryEntries(uid_t uid,
90                                                                      const std::string& path,
91                                                                      DIR* dirp);
92 
93     /**
94      * Determines if the given UID is allowed to open the file denoted by the given path.
95      *
96      * @param path the path of the file to be opened
97      * @param uid UID of the calling app
98      * @param for_write specifies if the file is to be opened for write
99      * @return 0 upon success or errno value upon failure.
100      */
101     int IsOpenAllowed(const std::string& path, uid_t uid, bool for_write);
102 
103     /**
104      * Potentially triggers a scan of the file before closing it and reconciles it with the
105      * MediaProvider database.
106      *
107      * @param path the path of the file to be scanned
108      */
109     void ScanFile(const std::string& path);
110 
111     /**
112      * Determines if the given UID is allowed to create a directory with the given path.
113      *
114      * @param path the path of the directory to be created
115      * @param uid UID of the calling app
116      * @return 0 if it's allowed, or errno error code if operation isn't allowed.
117      */
118     int IsCreatingDirAllowed(const std::string& path, uid_t uid);
119 
120     /**
121      * Determines if the given UID is allowed to delete the directory with the given path.
122      *
123      * @param path the path of the directory to be deleted
124      * @param uid UID of the calling app
125      * @return 0 if it's allowed, or errno error code if operation isn't allowed.
126      */
127     int IsDeletingDirAllowed(const std::string& path, uid_t uid);
128 
129     /**
130      * Determines if the given UID is allowed to open the directory with the given path.
131      *
132      * @param path the path of the directory to be opened
133      * @param uid UID of the calling app
134      * @param forWrite if it's a write access
135      * @return 0 if it's allowed, or errno error code if operation isn't allowed.
136      */
137     int IsOpendirAllowed(const std::string& path, uid_t uid, bool forWrite);
138 
139     /**
140      * Determines if the given package name matches its uid.
141      *
142      * @param pkg the package name of the app
143      * @param uid UID of the app
144      * @return true if it matches, otherwise return false.
145      */
146     bool IsUidForPackage(const std::string& pkg, uid_t uid);
147 
148     /**
149      * Renames a file or directory to new path.
150      *
151      * @param old_path path of the file or directory to be renamed.
152      * @param new_path new path of the file or directory to be renamed.
153      * @param uid UID of the calling app.
154      * @return 0 if rename is successful, errno if one of the rename fails. If return
155      * value is 0, it's guaranteed that file/directory is moved to new_path. For any other errno
156      * except EFAULT/EIO, it's guaranteed that file/directory is not renamed.
157      */
158     int Rename(const std::string& old_path, const std::string& new_path, uid_t uid);
159 
160     /**
161      * Called whenever a file has been created through FUSE.
162      *
163      * @param path path of the file that has been created.
164      */
165     void OnFileCreated(const std::string& path);
166 
167     /**
168      * Initializes per-process static variables associated with the lifetime of
169      * a managed runtime.
170      */
171     static void OneTimeInit(JavaVM* vm);
172 
173     /** TLS Key to map a given thread to its JNIEnv. */
174     static pthread_key_t gJniEnvKey;
175 
176   private:
177     jclass media_provider_class_;
178     jobject media_provider_object_;
179     /** Cached MediaProvider method IDs **/
180     jmethodID mid_get_redaction_ranges_;
181     jmethodID mid_insert_file_;
182     jmethodID mid_delete_file_;
183     jmethodID mid_is_open_allowed_;
184     jmethodID mid_scan_file_;
185     jmethodID mid_is_mkdir_or_rmdir_allowed_;
186     jmethodID mid_is_opendir_allowed_;
187     jmethodID mid_get_files_in_dir_;
188     jmethodID mid_rename_;
189     jmethodID mid_is_uid_for_package_;
190     jmethodID mid_on_file_created_;
191 
192     /**
193      * Auxiliary for caching MediaProvider methods.
194      */
195     jmethodID CacheMethod(JNIEnv* env, const char method_name[], const char signature[],
196                           bool is_static);
197 
198     // Attaches the current thread (if necessary) and returns the JNIEnv
199     // associated with it.
200     static JNIEnv* MaybeAttachCurrentThread();
201     // Destructor function for a given native thread. Called precisely once
202     // by the pthreads library.
203     static void DetachThreadFunction(void* unused);
204 
205     static JavaVM* gJavaVm;
206 };
207 
208 }  // namespace fuse
209 }  // namespace mediaprovider
210 
211 #endif  // MEDIAPROVIDER_FUSE_MEDIAPROVIDERWRAPPER_H_
212