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