• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <android-base/logging.h>
21 #include <jni.h>
22 #include <sys/types.h>
23 
24 #include <dirent.h>
25 #include <atomic>
26 #include <condition_variable>
27 #include <functional>
28 #include <mutex>
29 #include <queue>
30 #include <string>
31 #include <thread>
32 
33 #include "libfuse_jni/ReaddirHelper.h"
34 #include "libfuse_jni/RedactionInfo.h"
35 
36 namespace mediaprovider {
37 namespace fuse {
38 
39 /** Represents file open result from MediaProvider */
40 struct FileOpenResult {
FileOpenResultFileOpenResult41     FileOpenResult(const int status, const int uid, uid_t transforms_uid,
42                    const RedactionInfo* redaction_info)
43         : status(status), uid(uid), transforms_uid(transforms_uid), redaction_info(redaction_info) {}
44 
45     const int status;
46     const int uid;
47     const uid_t transforms_uid;
48     std::unique_ptr<const RedactionInfo> redaction_info;
49 };
50 
51 /**
52  * Represents transform info for a file, containing the transforms, the transforms completion
53  * status and the ioPath. Provided by MediaProvider.java via a JNI call.
54  */
55 struct FileLookupResult {
FileLookupResultFileLookupResult56     FileLookupResult(int transforms, int transforms_reason, uid_t uid, bool transforms_complete,
57                      bool transforms_supported, const std::string& io_path)
58         : transforms(transforms),
59           transforms_reason(transforms_reason),
60           uid(uid),
61           transforms_complete(transforms_complete),
62           transforms_supported(transforms_supported),
63           io_path(io_path) {
64         if (transforms != 0) {
65             CHECK(transforms_supported);
66         }
67     }
68 
69     /**
70      * These fields are not to be interpreted, they are determined and populated from MediaProvider
71      * via a JNI call.
72      */
73     const int transforms;
74     const int transforms_reason;
75     const uid_t uid;
76     const bool transforms_complete;
77     const bool transforms_supported;
78     const std::string io_path;
79 };
80 
81 /**
82  * Class that wraps MediaProvider.java and all of the needed JNI calls to make
83  * interaction with MediaProvider easier.
84  */
85 class MediaProviderWrapper final {
86   public:
87     MediaProviderWrapper(JNIEnv* env, jobject media_provider);
88     ~MediaProviderWrapper();
89 
90     /**
91      * Computes and returns the RedactionInfo for a given file and UID.
92      *
93      * @param uid UID of the app requesting the read
94      * @param path path of the requested file that will be used for database operations
95      * @param io_path path of the requested file that will be used for IO
96      * @return RedactionInfo on success, nullptr on failure to calculate
97      * redaction ranges (e.g. exception was thrown in Java world)
98      */
99     std::unique_ptr<RedactionInfo> GetRedactionInfo(const std::string& path,
100                                                     const std::string& io_path, uid_t uid,
101                                                     pid_t tid);
102 
103     /**
104      * Inserts a new entry for the given path and UID.
105      *
106      * @param path the path of the file to be created
107      * @param uid UID of the calling app
108      * @return 0 if the operation succeeded,
109      * or errno error code if operation fails.
110      */
111     int InsertFile(const std::string& path, uid_t uid);
112 
113     /**
114      * Delete the file denoted by the given path on behalf of the given UID.
115      *
116      * @param path the path of the file to be deleted
117      * @param uid UID of the calling app
118      * @return 0 upon success, or errno error code if operation fails.
119      */
120     int DeleteFile(const std::string& path, uid_t uid);
121 
122     /**
123      * Gets directory entries for given path from MediaProvider database and lower file system
124      *
125      * @param uid UID of the calling app.
126      * @param path Relative path of the directory.
127      * @param dirp Pointer to directory stream, used to query lower file system.
128      * @return DirectoryEntries with list of directory entries on success.
129      * File names in a directory are obtained from MediaProvider. If a path is unknown to
130      * MediaProvider, file names are obtained from lower file system. All directory names in the
131      * given directory are obtained from lower file system.
132      * An empty string in first directory entry name indicates the error occurred while obtaining
133      * directory entries, directory entry type will hold the corresponding errno information.
134      */
135     std::vector<std::shared_ptr<DirectoryEntry>> GetDirectoryEntries(uid_t uid,
136                                                                      const std::string& path,
137                                                                      DIR* dirp);
138 
139     /**
140      * Determines if the given UID is allowed to open the file denoted by the given path.
141      *
142      * Also computes and returns the RedactionInfo for a given file and |uid|
143      *
144      * @param path path of the requested file that will be used for database operations
145      * @param io_path path of the requested file that will be used for IO
146      * @param uid UID of the calling app
147      * @param tid UID of the calling app
148      * @param for_write specifies if the file is to be opened for write
149      * @param redact specifies whether to attempt redaction
150      * @return FileOpenResult containing status, uid and redaction_info
151      */
152     std::unique_ptr<FileOpenResult> OnFileOpen(const std::string& path, const std::string& io_path,
153                                                uid_t uid, pid_t tid, int transforms_reason,
154                                                bool for_write, bool redact,
155                                                bool log_transforms_metrics);
156 
157     /**
158      * Determines if the given UID is allowed to create a directory with the given path.
159      *
160      * @param path the path of the directory to be created
161      * @param uid UID of the calling app
162      * @return 0 if it's allowed, or errno error code if operation isn't allowed.
163      */
164     int IsCreatingDirAllowed(const std::string& path, uid_t uid);
165 
166     /**
167      * Determines if the given UID is allowed to delete the directory with the given path.
168      *
169      * @param path the path of the directory to be deleted
170      * @param uid UID of the calling app
171      * @return 0 if it's allowed, or errno error code if operation isn't allowed.
172      */
173     int IsDeletingDirAllowed(const std::string& path, uid_t uid);
174 
175     /**
176      * Determines if the given UID is allowed to open the directory with the given path.
177      *
178      * @param path the path of the directory to be opened
179      * @param uid UID of the calling app
180      * @param forWrite if it's a write access
181      * @return 0 if it's allowed, or errno error code if operation isn't allowed.
182      */
183     int IsOpendirAllowed(const std::string& path, uid_t uid, bool forWrite);
184 
185     /**
186      * Determines if one of the follows is true:
187      * 1. The package name of the given private path matches the given uid,
188           then this uid has access to private-app directories for this package.
189      * 2. The calling uid has special access to private-app directories:
190      *    * DownloadProvider and ExternalStorageProvider has access to private
191      *      app directories.
192      *    * Installer apps have access to Android/obb directories
193      *
194      * @param uid UID of the app
195      * @param path the private path that the UID wants to access
196      * @return true if it matches, otherwise return false.
197      */
198     bool isUidAllowedAccessToDataOrObbPath(uid_t uid, const std::string& path);
199 
200     /**
201      * Renames a file or directory to new path.
202      *
203      * @param old_path path of the file or directory to be renamed.
204      * @param new_path new path of the file or directory to be renamed.
205      * @param uid UID of the calling app.
206      * @return 0 if rename is successful, errno if one of the rename fails. If return
207      * value is 0, it's guaranteed that file/directory is moved to new_path. For any other errno
208      * except EFAULT/EIO, it's guaranteed that file/directory is not renamed.
209      */
210     int Rename(const std::string& old_path, const std::string& new_path, uid_t uid);
211 
212     /**
213      * Called whenever a file has been created through FUSE.
214      *
215      * @param path path of the file that has been created.
216      */
217     void OnFileCreated(const std::string& path);
218 
219     /**
220      * Returns FileLookupResult to determine transform info for a path and uid.
221      */
222     std::unique_ptr<FileLookupResult> FileLookup(const std::string& path, uid_t uid, pid_t tid);
223 
224     /** Transforms from src to dst file */
225     bool Transform(const std::string& src, const std::string& dst, int transforms,
226                    int transforms_reason, uid_t read_uid, uid_t open_uid, uid_t transforms_uid);
227 
228     /**
229      * Determines if to allow FUSE_LOOKUP for uid. Might allow uids that don't belong to the
230      * MediaProvider user, depending on OEM configuration.
231      *
232      * @param uid linux uid to check
233      */
234     bool ShouldAllowLookup(uid_t uid, int path_user_id);
235 
236     /**
237      * Determines if the passed in user ID is an app clone user (paired with user 0)
238      *
239      * @param userId the user ID to check
240      */
241     bool IsAppCloneUser(uid_t userId);
242 
243     /**
244      * Initializes per-process static variables associated with the lifetime of
245      * a managed runtime.
246      */
247     static void OneTimeInit(JavaVM* vm);
248 
249     /** TLS Key to map a given thread to its JNIEnv. */
250     static pthread_key_t gJniEnvKey;
251 
252   private:
253     jclass file_lookup_result_class_;
254     jclass file_open_result_class_;
255     jclass media_provider_class_;
256     jobject media_provider_object_;
257     /** Cached MediaProvider method IDs **/
258     jmethodID mid_insert_file_;
259     jmethodID mid_delete_file_;
260     jmethodID mid_on_file_open_;
261     jmethodID mid_scan_file_;
262     jmethodID mid_is_mkdir_or_rmdir_allowed_;
263     jmethodID mid_is_opendir_allowed_;
264     jmethodID mid_get_files_in_dir_;
265     jmethodID mid_rename_;
266     jmethodID mid_is_uid_allowed_access_to_data_or_obb_path_;
267     jmethodID mid_on_file_created_;
268     jmethodID mid_should_allow_lookup_;
269     jmethodID mid_is_app_clone_user_;
270     jmethodID mid_transform_;
271     jmethodID mid_file_lookup_;
272     /** Cached FileLookupResult field IDs **/
273     jfieldID fid_file_lookup_transforms_;
274     jfieldID fid_file_lookup_transforms_reason_;
275     jfieldID fid_file_lookup_uid_;
276     jfieldID fid_file_lookup_transforms_complete_;
277     jfieldID fid_file_lookup_transforms_supported_;
278     jfieldID fid_file_lookup_io_path_;
279     /** Cached FileOpenResult field IDs **/
280     jfieldID fid_file_open_status_;
281     jfieldID fid_file_open_uid_;
282     jfieldID fid_file_open_transforms_uid_;
283     jfieldID fid_file_open_redaction_ranges_;
284 
285     /**
286      * Auxiliary for caching MediaProvider methods.
287      */
288     jmethodID CacheMethod(JNIEnv* env, const char method_name[], const char signature[],
289                           bool is_static);
290 
291     // Attaches the current thread (if necessary) and returns the JNIEnv
292     // associated with it.
293     static JNIEnv* MaybeAttachCurrentThread();
294     // Destructor function for a given native thread. Called precisely once
295     // by the pthreads library.
296     static void DetachThreadFunction(void* unused);
297 
298     static JavaVM* gJavaVm;
299 };
300 
301 }  // namespace fuse
302 }  // namespace mediaprovider
303 
304 #endif  // MEDIAPROVIDER_FUSE_MEDIAPROVIDERWRAPPER_H_
305