blob: 2ad176997109064c601997e2beaa0af42a737936 [file] [log] [blame]
shafikc3f62672019-08-30 11:15:48 +01001/*
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
Zimded1ab92021-01-15 10:36:17 +000020#include <android-base/logging.h>
shafikc3f62672019-08-30 11:15:48 +010021#include <jni.h>
22#include <sys/types.h>
23
Sahana Rao71693442019-11-13 13:48:07 +000024#include <dirent.h>
shafikcdb6b2b2019-09-30 12:49:26 +010025#include <atomic>
26#include <condition_variable>
27#include <functional>
28#include <mutex>
29#include <queue>
shafikc3f62672019-08-30 11:15:48 +010030#include <string>
shafikcdb6b2b2019-09-30 12:49:26 +010031#include <thread>
shafikc3f62672019-08-30 11:15:48 +010032
Sahana Raoa82bd6a2019-10-10 18:10:37 +010033#include "libfuse_jni/ReaddirHelper.h"
shafikc3f62672019-08-30 11:15:48 +010034#include "libfuse_jni/RedactionInfo.h"
35
36namespace mediaprovider {
37namespace fuse {
38
Zim73895ba2021-01-13 12:51:20 +000039/** Represents file open result from MediaProvider */
40struct FileOpenResult {
Manish Singh9a6ccce2021-02-05 23:50:08 +000041 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) {}
Zim73895ba2021-01-13 12:51:20 +000044
45 const int status;
46 const int uid;
Manish Singh9a6ccce2021-02-05 23:50:08 +000047 const uid_t transforms_uid;
Zim73895ba2021-01-13 12:51:20 +000048 std::unique_ptr<const RedactionInfo> redaction_info;
49};
50
shafikc3f62672019-08-30 11:15:48 +010051/**
Biswarup Pal63901f32021-01-07 14:57:23 +000052 * 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 */
55struct FileLookupResult {
Zim801d9852021-01-26 18:30:53 +000056 FileLookupResult(int transforms, int transforms_reason, uid_t uid, bool transforms_complete,
57 bool transforms_supported, const std::string& io_path)
Zimded1ab92021-01-15 10:36:17 +000058 : transforms(transforms),
Zim801d9852021-01-26 18:30:53 +000059 transforms_reason(transforms_reason),
Zimded1ab92021-01-15 10:36:17 +000060 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 }
Biswarup Pal63901f32021-01-07 14:57:23 +000068
69 /**
Manish Singh9a6ccce2021-02-05 23:50:08 +000070 * These fields are not to be interpreted, they are determined and populated from MediaProvider
Biswarup Pal63901f32021-01-07 14:57:23 +000071 * via a JNI call.
72 */
73 const int transforms;
Zim801d9852021-01-26 18:30:53 +000074 const int transforms_reason;
Zimded1ab92021-01-15 10:36:17 +000075 const uid_t uid;
Biswarup Pal63901f32021-01-07 14:57:23 +000076 const bool transforms_complete;
Zimded1ab92021-01-15 10:36:17 +000077 const bool transforms_supported;
Biswarup Pal63901f32021-01-07 14:57:23 +000078 const std::string io_path;
79};
80
81/**
shafikc3f62672019-08-30 11:15:48 +010082 * Class that wraps MediaProvider.java and all of the needed JNI calls to make
83 * interaction with MediaProvider easier.
84 */
85class MediaProviderWrapper final {
86 public:
shafikcdb6b2b2019-09-30 12:49:26 +010087 MediaProviderWrapper(JNIEnv* env, jobject media_provider);
shafikc3f62672019-08-30 11:15:48 +010088 ~MediaProviderWrapper();
89
90 /**
shafikc580b6d2019-12-10 18:45:17 +000091 * Computes and returns the RedactionInfo for a given file and UID.
shafikc3f62672019-08-30 11:15:48 +010092 *
93 * @param uid UID of the app requesting the read
Zime9ae6ee2020-11-26 15:38:13 +000094 * @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
shafikc3f62672019-08-30 11:15:48 +010096 * @return RedactionInfo on success, nullptr on failure to calculate
97 * redaction ranges (e.g. exception was thrown in Java world)
98 */
Zime9ae6ee2020-11-26 15:38:13 +000099 std::unique_ptr<RedactionInfo> GetRedactionInfo(const std::string& path,
100 const std::string& io_path, uid_t uid,
101 pid_t tid);
shafikc3f62672019-08-30 11:15:48 +0100102
shafika51f3ce2019-10-10 17:06:41 +0100103 /**
shafik9edfb142019-11-06 11:01:40 +0000104 * Inserts a new entry for the given path and UID.
shafika51f3ce2019-10-10 17:06:41 +0100105 *
106 * @param path the path of the file to be created
107 * @param uid UID of the calling app
shafik9edfb142019-11-06 11:01:40 +0000108 * @return 0 if the operation succeeded,
shafike4fb1462020-01-29 16:25:23 +0000109 * or errno error code if operation fails.
shafika51f3ce2019-10-10 17:06:41 +0100110 */
shafik9edfb142019-11-06 11:01:40 +0000111 int InsertFile(const std::string& path, uid_t uid);
shafika51f3ce2019-10-10 17:06:41 +0100112
shafik0c0e0d72019-10-16 17:34:17 +0100113 /**
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
shafike4fb1462020-01-29 16:25:23 +0000118 * @return 0 upon success, or errno error code if operation fails.
shafik0c0e0d72019-10-16 17:34:17 +0100119 */
120 int DeleteFile(const std::string& path, uid_t uid);
121
shafik15e2d612019-10-31 20:10:25 +0000122 /**
Sahana Rao8a588e72019-12-06 11:32:56 +0000123 * Gets directory entries for given path from MediaProvider database and lower file system
Sahana Raoa82bd6a2019-10-10 18:10:37 +0100124 *
125 * @param uid UID of the calling app.
126 * @param path Relative path of the directory.
Sahana Rao71693442019-11-13 13:48:07 +0000127 * @param dirp Pointer to directory stream, used to query lower file system.
Sahana Rao8a588e72019-12-06 11:32:56 +0000128 * @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.
Sahana Rao71693442019-11-13 13:48:07 +0000132 * 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.
Sahana Raoa82bd6a2019-10-10 18:10:37 +0100134 */
135 std::vector<std::shared_ptr<DirectoryEntry>> GetDirectoryEntries(uid_t uid,
136 const std::string& path,
137 DIR* dirp);
138
139 /**
shafik15e2d612019-10-31 20:10:25 +0000140 * Determines if the given UID is allowed to open the file denoted by the given path.
141 *
Zim73895ba2021-01-13 12:51:20 +0000142 * 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
shafik15e2d612019-10-31 20:10:25 +0000146 * @param uid UID of the calling app
Zim73895ba2021-01-13 12:51:20 +0000147 * @param tid UID of the calling app
shafik15e2d612019-10-31 20:10:25 +0000148 * @param for_write specifies if the file is to be opened for write
Zim73895ba2021-01-13 12:51:20 +0000149 * @param redact specifies whether to attempt redaction
150 * @return FileOpenResult containing status, uid and redaction_info
shafik15e2d612019-10-31 20:10:25 +0000151 */
Zim73895ba2021-01-13 12:51:20 +0000152 std::unique_ptr<FileOpenResult> OnFileOpen(const std::string& path, const std::string& io_path,
Zim801d9852021-01-26 18:30:53 +0000153 uid_t uid, pid_t tid, int transforms_reason,
154 bool for_write, bool redact,
155 bool log_transforms_metrics);
shafik15e2d612019-10-31 20:10:25 +0000156
157 /**
shafikbba5b672019-11-15 16:52:51 +0000158 * 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
shafike4fb1462020-01-29 16:25:23 +0000162 * @return 0 if it's allowed, or errno error code if operation isn't allowed.
shafikbba5b672019-11-15 16:52:51 +0000163 */
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
shafike4fb1462020-01-29 16:25:23 +0000171 * @return 0 if it's allowed, or errno error code if operation isn't allowed.
shafikbba5b672019-11-15 16:52:51 +0000172 */
173 int IsDeletingDirAllowed(const std::string& path, uid_t uid);
174
shafik824c1082019-11-22 12:00:52 +0000175 /**
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
Nandana Dutt5fc32012020-06-25 10:55:52 +0100180 * @param forWrite if it's a write access
shafike4fb1462020-01-29 16:25:23 +0000181 * @return 0 if it's allowed, or errno error code if operation isn't allowed.
shafik824c1082019-11-22 12:00:52 +0000182 */
Nandana Dutt5fc32012020-06-25 10:55:52 +0100183 int IsOpendirAllowed(const std::string& path, uid_t uid, bool forWrite);
shafik824c1082019-11-22 12:00:52 +0000184
Sahana Rao2c416032019-12-31 13:41:00 +0000185 /**
Abhijeet Kaurb3ac2802020-10-07 16:42:42 +0100186 * 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
Ricky Waif40c4022020-04-15 19:00:06 +0100193 *
Ricky Waif40c4022020-04-15 19:00:06 +0100194 * @param uid UID of the app
Abhijeet Kaurb3ac2802020-10-07 16:42:42 +0100195 * @param path the private path that the UID wants to access
Ricky Waif40c4022020-04-15 19:00:06 +0100196 * @return true if it matches, otherwise return false.
197 */
Abhijeet Kaurb3ac2802020-10-07 16:42:42 +0100198 bool isUidAllowedAccessToDataOrObbPath(uid_t uid, const std::string& path);
Ricky Waif40c4022020-04-15 19:00:06 +0100199
200 /**
Sahana Rao2c416032019-12-31 13:41:00 +0000201 * 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.
shafike4fb1462020-01-29 16:25:23 +0000206 * @return 0 if rename is successful, errno if one of the rename fails. If return
Sahana Rao2c416032019-12-31 13:41:00 +0000207 * 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
Narayan Kamathde3fe172020-02-18 12:14:51 +0000212 /**
Martijn Coenenaf2d34d2020-06-19 12:52:20 +0200213 * 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
Biswarup Pal63901f32021-01-07 14:57:23 +0000219 /**
220 * Returns FileLookupResult to determine transform info for a path and uid.
221 */
Zimded1ab92021-01-15 10:36:17 +0000222 std::unique_ptr<FileLookupResult> FileLookup(const std::string& path, uid_t uid, pid_t tid);
Zimbb91fef2020-09-23 14:32:27 +0100223
224 /** Transforms from src to dst file */
Zim801d9852021-01-26 18:30:53 +0000225 bool Transform(const std::string& src, const std::string& dst, int transforms,
Manish Singh9a6ccce2021-02-05 23:50:08 +0000226 int transforms_reason, uid_t read_uid, uid_t open_uid, uid_t transforms_uid);
Zimbb91fef2020-09-23 14:32:27 +0100227
Martijn Coenenaf2d34d2020-06-19 12:52:20 +0200228 /**
Zim5077a892020-09-08 12:55:12 +0100229 * 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 /**
Martijn Coenen87133092020-10-14 17:00:28 +0200237 * 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 /**
Narayan Kamathde3fe172020-02-18 12:14:51 +0000244 * Initializes per-process static variables associated with the lifetime of
245 * a managed runtime.
246 */
247 static void OneTimeInit(JavaVM* vm);
248
Zimc0e65bd2020-03-09 15:22:59 +0000249 /** TLS Key to map a given thread to its JNIEnv. */
250 static pthread_key_t gJniEnvKey;
251
shafikc3f62672019-08-30 11:15:48 +0100252 private:
Biswarup Pal63901f32021-01-07 14:57:23 +0000253 jclass file_lookup_result_class_;
Zim73895ba2021-01-13 12:51:20 +0000254 jclass file_open_result_class_;
shafikcdb6b2b2019-09-30 12:49:26 +0100255 jclass media_provider_class_;
256 jobject media_provider_object_;
shafik0c0e0d72019-10-16 17:34:17 +0100257 /** Cached MediaProvider method IDs **/
shafik9edfb142019-11-06 11:01:40 +0000258 jmethodID mid_insert_file_;
shafik0c0e0d72019-10-16 17:34:17 +0100259 jmethodID mid_delete_file_;
Zim73895ba2021-01-13 12:51:20 +0000260 jmethodID mid_on_file_open_;
shafik15e2d612019-10-31 20:10:25 +0000261 jmethodID mid_scan_file_;
shafikf0fea692020-02-14 15:49:17 +0000262 jmethodID mid_is_mkdir_or_rmdir_allowed_;
shafik824c1082019-11-22 12:00:52 +0000263 jmethodID mid_is_opendir_allowed_;
Sahana Rao8a588e72019-12-06 11:32:56 +0000264 jmethodID mid_get_files_in_dir_;
Sahana Rao2c416032019-12-31 13:41:00 +0000265 jmethodID mid_rename_;
Abhijeet Kaurb3ac2802020-10-07 16:42:42 +0100266 jmethodID mid_is_uid_allowed_access_to_data_or_obb_path_;
Martijn Coenenaf2d34d2020-06-19 12:52:20 +0200267 jmethodID mid_on_file_created_;
Zim5077a892020-09-08 12:55:12 +0100268 jmethodID mid_should_allow_lookup_;
Martijn Coenen87133092020-10-14 17:00:28 +0200269 jmethodID mid_is_app_clone_user_;
Zimbb91fef2020-09-23 14:32:27 +0100270 jmethodID mid_transform_;
Biswarup Pal63901f32021-01-07 14:57:23 +0000271 jmethodID mid_file_lookup_;
272 /** Cached FileLookupResult field IDs **/
273 jfieldID fid_file_lookup_transforms_;
Zim801d9852021-01-26 18:30:53 +0000274 jfieldID fid_file_lookup_transforms_reason_;
Zimded1ab92021-01-15 10:36:17 +0000275 jfieldID fid_file_lookup_uid_;
Biswarup Pal63901f32021-01-07 14:57:23 +0000276 jfieldID fid_file_lookup_transforms_complete_;
Zimded1ab92021-01-15 10:36:17 +0000277 jfieldID fid_file_lookup_transforms_supported_;
Biswarup Pal63901f32021-01-07 14:57:23 +0000278 jfieldID fid_file_lookup_io_path_;
Zim73895ba2021-01-13 12:51:20 +0000279 /** Cached FileOpenResult field IDs **/
280 jfieldID fid_file_open_status_;
281 jfieldID fid_file_open_uid_;
Manish Singh9a6ccce2021-02-05 23:50:08 +0000282 jfieldID fid_file_open_transforms_uid_;
Zim73895ba2021-01-13 12:51:20 +0000283 jfieldID fid_file_open_redaction_ranges_;
Sahana Rao2c416032019-12-31 13:41:00 +0000284
shafikcdb6b2b2019-09-30 12:49:26 +0100285 /**
shafik15e2d612019-10-31 20:10:25 +0000286 * Auxiliary for caching MediaProvider methods.
shafikcdb6b2b2019-09-30 12:49:26 +0100287 */
288 jmethodID CacheMethod(JNIEnv* env, const char method_name[], const char signature[],
289 bool is_static);
Narayan Kamathde3fe172020-02-18 12:14:51 +0000290
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;
shafikc3f62672019-08-30 11:15:48 +0100299};
300
301} // namespace fuse
302} // namespace mediaprovider
303
304#endif // MEDIAPROVIDER_FUSE_MEDIAPROVIDERWRAPPER_H_