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