blob: 31d9d1bc1a5c0abe241d4ee03fdd48678dadac34 [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
20#include <jni.h>
21#include <sys/types.h>
22
Sahana Rao71693442019-11-13 13:48:07 +000023#include <dirent.h>
shafikcdb6b2b2019-09-30 12:49:26 +010024#include <atomic>
25#include <condition_variable>
26#include <functional>
27#include <mutex>
28#include <queue>
shafikc3f62672019-08-30 11:15:48 +010029#include <string>
shafikcdb6b2b2019-09-30 12:49:26 +010030#include <thread>
shafikc3f62672019-08-30 11:15:48 +010031
Sahana Raoa82bd6a2019-10-10 18:10:37 +010032#include "libfuse_jni/ReaddirHelper.h"
shafikc3f62672019-08-30 11:15:48 +010033#include "libfuse_jni/RedactionInfo.h"
34
35namespace mediaprovider {
36namespace fuse {
37
38/**
Biswarup Pal63901f32021-01-07 14:57:23 +000039 * Represents transform info for a file, containing the transforms, the transforms completion
40 * status and the ioPath. Provided by MediaProvider.java via a JNI call.
41 */
42struct FileLookupResult {
43 FileLookupResult(int transforms, bool transforms_complete, const std::string& io_path)
44 : transforms(transforms), transforms_complete(transforms_complete), io_path(io_path) {}
45
46 /**
47 * This field is not to be interpreted, it is determined and populated from MediaProvider
48 * via a JNI call.
49 */
50 const int transforms;
51 const bool transforms_complete;
52 const std::string io_path;
53};
54
55/**
shafikc3f62672019-08-30 11:15:48 +010056 * Class that wraps MediaProvider.java and all of the needed JNI calls to make
57 * interaction with MediaProvider easier.
58 */
59class MediaProviderWrapper final {
60 public:
shafikcdb6b2b2019-09-30 12:49:26 +010061 MediaProviderWrapper(JNIEnv* env, jobject media_provider);
shafikc3f62672019-08-30 11:15:48 +010062 ~MediaProviderWrapper();
63
64 /**
shafikc580b6d2019-12-10 18:45:17 +000065 * Computes and returns the RedactionInfo for a given file and UID.
shafikc3f62672019-08-30 11:15:48 +010066 *
67 * @param uid UID of the app requesting the read
Zime9ae6ee2020-11-26 15:38:13 +000068 * @param path path of the requested file that will be used for database operations
69 * @param io_path path of the requested file that will be used for IO
shafikc3f62672019-08-30 11:15:48 +010070 * @return RedactionInfo on success, nullptr on failure to calculate
71 * redaction ranges (e.g. exception was thrown in Java world)
72 */
Zime9ae6ee2020-11-26 15:38:13 +000073 std::unique_ptr<RedactionInfo> GetRedactionInfo(const std::string& path,
74 const std::string& io_path, uid_t uid,
75 pid_t tid);
shafikc3f62672019-08-30 11:15:48 +010076
shafika51f3ce2019-10-10 17:06:41 +010077 /**
shafik9edfb142019-11-06 11:01:40 +000078 * Inserts a new entry for the given path and UID.
shafika51f3ce2019-10-10 17:06:41 +010079 *
80 * @param path the path of the file to be created
81 * @param uid UID of the calling app
shafik9edfb142019-11-06 11:01:40 +000082 * @return 0 if the operation succeeded,
shafike4fb1462020-01-29 16:25:23 +000083 * or errno error code if operation fails.
shafika51f3ce2019-10-10 17:06:41 +010084 */
shafik9edfb142019-11-06 11:01:40 +000085 int InsertFile(const std::string& path, uid_t uid);
shafika51f3ce2019-10-10 17:06:41 +010086
shafik0c0e0d72019-10-16 17:34:17 +010087 /**
88 * Delete the file denoted by the given path on behalf of the given UID.
89 *
90 * @param path the path of the file to be deleted
91 * @param uid UID of the calling app
shafike4fb1462020-01-29 16:25:23 +000092 * @return 0 upon success, or errno error code if operation fails.
shafik0c0e0d72019-10-16 17:34:17 +010093 */
94 int DeleteFile(const std::string& path, uid_t uid);
95
shafik15e2d612019-10-31 20:10:25 +000096 /**
Sahana Rao8a588e72019-12-06 11:32:56 +000097 * Gets directory entries for given path from MediaProvider database and lower file system
Sahana Raoa82bd6a2019-10-10 18:10:37 +010098 *
99 * @param uid UID of the calling app.
100 * @param path Relative path of the directory.
Sahana Rao71693442019-11-13 13:48:07 +0000101 * @param dirp Pointer to directory stream, used to query lower file system.
Sahana Rao8a588e72019-12-06 11:32:56 +0000102 * @return DirectoryEntries with list of directory entries on success.
103 * File names in a directory are obtained from MediaProvider. If a path is unknown to
104 * MediaProvider, file names are obtained from lower file system. All directory names in the
105 * given directory are obtained from lower file system.
Sahana Rao71693442019-11-13 13:48:07 +0000106 * An empty string in first directory entry name indicates the error occurred while obtaining
107 * directory entries, directory entry type will hold the corresponding errno information.
Sahana Raoa82bd6a2019-10-10 18:10:37 +0100108 */
109 std::vector<std::shared_ptr<DirectoryEntry>> GetDirectoryEntries(uid_t uid,
110 const std::string& path,
111 DIR* dirp);
112
113 /**
shafik15e2d612019-10-31 20:10:25 +0000114 * Determines if the given UID is allowed to open the file denoted by the given path.
115 *
116 * @param path the path of the file to be opened
117 * @param uid UID of the calling app
118 * @param for_write specifies if the file is to be opened for write
shafike4fb1462020-01-29 16:25:23 +0000119 * @return 0 upon success or errno value upon failure.
shafik15e2d612019-10-31 20:10:25 +0000120 */
121 int IsOpenAllowed(const std::string& path, uid_t uid, bool for_write);
122
123 /**
124 * Potentially triggers a scan of the file before closing it and reconciles it with the
125 * MediaProvider database.
126 *
127 * @param path the path of the file to be scanned
128 */
Sahana Raoee321362020-03-05 19:27:37 +0000129 void ScanFile(const std::string& path);
shafik15e2d612019-10-31 20:10:25 +0000130
shafikbba5b672019-11-15 16:52:51 +0000131 /**
132 * Determines if the given UID is allowed to create a directory with the given path.
133 *
134 * @param path the path of the directory to be created
135 * @param uid UID of the calling app
shafike4fb1462020-01-29 16:25:23 +0000136 * @return 0 if it's allowed, or errno error code if operation isn't allowed.
shafikbba5b672019-11-15 16:52:51 +0000137 */
138 int IsCreatingDirAllowed(const std::string& path, uid_t uid);
139
140 /**
141 * Determines if the given UID is allowed to delete the directory with the given path.
142 *
143 * @param path the path of the directory to be deleted
144 * @param uid UID of the calling app
shafike4fb1462020-01-29 16:25:23 +0000145 * @return 0 if it's allowed, or errno error code if operation isn't allowed.
shafikbba5b672019-11-15 16:52:51 +0000146 */
147 int IsDeletingDirAllowed(const std::string& path, uid_t uid);
148
shafik824c1082019-11-22 12:00:52 +0000149 /**
150 * Determines if the given UID is allowed to open the directory with the given path.
151 *
152 * @param path the path of the directory to be opened
153 * @param uid UID of the calling app
Nandana Dutt5fc32012020-06-25 10:55:52 +0100154 * @param forWrite if it's a write access
shafike4fb1462020-01-29 16:25:23 +0000155 * @return 0 if it's allowed, or errno error code if operation isn't allowed.
shafik824c1082019-11-22 12:00:52 +0000156 */
Nandana Dutt5fc32012020-06-25 10:55:52 +0100157 int IsOpendirAllowed(const std::string& path, uid_t uid, bool forWrite);
shafik824c1082019-11-22 12:00:52 +0000158
Sahana Rao2c416032019-12-31 13:41:00 +0000159 /**
Abhijeet Kaurb3ac2802020-10-07 16:42:42 +0100160 * Determines if one of the follows is true:
161 * 1. The package name of the given private path matches the given uid,
162 then this uid has access to private-app directories for this package.
163 * 2. The calling uid has special access to private-app directories:
164 * * DownloadProvider and ExternalStorageProvider has access to private
165 * app directories.
166 * * Installer apps have access to Android/obb directories
Ricky Waif40c4022020-04-15 19:00:06 +0100167 *
Ricky Waif40c4022020-04-15 19:00:06 +0100168 * @param uid UID of the app
Abhijeet Kaurb3ac2802020-10-07 16:42:42 +0100169 * @param path the private path that the UID wants to access
Ricky Waif40c4022020-04-15 19:00:06 +0100170 * @return true if it matches, otherwise return false.
171 */
Abhijeet Kaurb3ac2802020-10-07 16:42:42 +0100172 bool isUidAllowedAccessToDataOrObbPath(uid_t uid, const std::string& path);
Ricky Waif40c4022020-04-15 19:00:06 +0100173
174 /**
Sahana Rao2c416032019-12-31 13:41:00 +0000175 * Renames a file or directory to new path.
176 *
177 * @param old_path path of the file or directory to be renamed.
178 * @param new_path new path of the file or directory to be renamed.
179 * @param uid UID of the calling app.
shafike4fb1462020-01-29 16:25:23 +0000180 * @return 0 if rename is successful, errno if one of the rename fails. If return
Sahana Rao2c416032019-12-31 13:41:00 +0000181 * value is 0, it's guaranteed that file/directory is moved to new_path. For any other errno
182 * except EFAULT/EIO, it's guaranteed that file/directory is not renamed.
183 */
184 int Rename(const std::string& old_path, const std::string& new_path, uid_t uid);
185
Narayan Kamathde3fe172020-02-18 12:14:51 +0000186 /**
Martijn Coenenaf2d34d2020-06-19 12:52:20 +0200187 * Called whenever a file has been created through FUSE.
188 *
189 * @param path path of the file that has been created.
190 */
191 void OnFileCreated(const std::string& path);
192
Biswarup Pal63901f32021-01-07 14:57:23 +0000193 /**
194 * Returns FileLookupResult to determine transform info for a path and uid.
195 */
196 std::unique_ptr<FileLookupResult> FileLookup(const std::string& path, uid_t uid);
Zimbb91fef2020-09-23 14:32:27 +0100197
198 /** Transforms from src to dst file */
199 bool Transform(const std::string& src, const std::string& dst, int transforms, uid_t uid);
200
Martijn Coenenaf2d34d2020-06-19 12:52:20 +0200201 /**
Zim5077a892020-09-08 12:55:12 +0100202 * Determines if to allow FUSE_LOOKUP for uid. Might allow uids that don't belong to the
203 * MediaProvider user, depending on OEM configuration.
204 *
205 * @param uid linux uid to check
206 */
207 bool ShouldAllowLookup(uid_t uid, int path_user_id);
208
209 /**
Martijn Coenen87133092020-10-14 17:00:28 +0200210 * Determines if the passed in user ID is an app clone user (paired with user 0)
211 *
212 * @param userId the user ID to check
213 */
214 bool IsAppCloneUser(uid_t userId);
215
216 /**
Narayan Kamathde3fe172020-02-18 12:14:51 +0000217 * Initializes per-process static variables associated with the lifetime of
218 * a managed runtime.
219 */
220 static void OneTimeInit(JavaVM* vm);
221
Zimc0e65bd2020-03-09 15:22:59 +0000222 /** TLS Key to map a given thread to its JNIEnv. */
223 static pthread_key_t gJniEnvKey;
224
shafikc3f62672019-08-30 11:15:48 +0100225 private:
Biswarup Pal63901f32021-01-07 14:57:23 +0000226 jclass file_lookup_result_class_;
shafikcdb6b2b2019-09-30 12:49:26 +0100227 jclass media_provider_class_;
228 jobject media_provider_object_;
shafik0c0e0d72019-10-16 17:34:17 +0100229 /** Cached MediaProvider method IDs **/
shafikcdb6b2b2019-09-30 12:49:26 +0100230 jmethodID mid_get_redaction_ranges_;
shafik9edfb142019-11-06 11:01:40 +0000231 jmethodID mid_insert_file_;
shafik0c0e0d72019-10-16 17:34:17 +0100232 jmethodID mid_delete_file_;
shafik15e2d612019-10-31 20:10:25 +0000233 jmethodID mid_is_open_allowed_;
234 jmethodID mid_scan_file_;
shafikf0fea692020-02-14 15:49:17 +0000235 jmethodID mid_is_mkdir_or_rmdir_allowed_;
shafik824c1082019-11-22 12:00:52 +0000236 jmethodID mid_is_opendir_allowed_;
Sahana Rao8a588e72019-12-06 11:32:56 +0000237 jmethodID mid_get_files_in_dir_;
Sahana Rao2c416032019-12-31 13:41:00 +0000238 jmethodID mid_rename_;
Abhijeet Kaurb3ac2802020-10-07 16:42:42 +0100239 jmethodID mid_is_uid_allowed_access_to_data_or_obb_path_;
Martijn Coenenaf2d34d2020-06-19 12:52:20 +0200240 jmethodID mid_on_file_created_;
Zim5077a892020-09-08 12:55:12 +0100241 jmethodID mid_should_allow_lookup_;
Martijn Coenen87133092020-10-14 17:00:28 +0200242 jmethodID mid_is_app_clone_user_;
Zimbb91fef2020-09-23 14:32:27 +0100243 jmethodID mid_transform_;
Biswarup Pal63901f32021-01-07 14:57:23 +0000244 jmethodID mid_file_lookup_;
245 /** Cached FileLookupResult field IDs **/
246 jfieldID fid_file_lookup_transforms_;
247 jfieldID fid_file_lookup_transforms_complete_;
248 jfieldID fid_file_lookup_io_path_;
Sahana Rao2c416032019-12-31 13:41:00 +0000249
shafikcdb6b2b2019-09-30 12:49:26 +0100250 /**
shafik15e2d612019-10-31 20:10:25 +0000251 * Auxiliary for caching MediaProvider methods.
shafikcdb6b2b2019-09-30 12:49:26 +0100252 */
253 jmethodID CacheMethod(JNIEnv* env, const char method_name[], const char signature[],
254 bool is_static);
Narayan Kamathde3fe172020-02-18 12:14:51 +0000255
Biswarup Pal63901f32021-01-07 14:57:23 +0000256 /**
257 * Auxiliary for caching FileLookupResult fields.
258 */
259 jfieldID CacheFileLookupField(JNIEnv* env, const char field_name[], const char type[]);
260
Narayan Kamathde3fe172020-02-18 12:14:51 +0000261 // Attaches the current thread (if necessary) and returns the JNIEnv
262 // associated with it.
263 static JNIEnv* MaybeAttachCurrentThread();
264 // Destructor function for a given native thread. Called precisely once
265 // by the pthreads library.
266 static void DetachThreadFunction(void* unused);
267
268 static JavaVM* gJavaVm;
shafikc3f62672019-08-30 11:15:48 +0100269};
270
271} // namespace fuse
272} // namespace mediaprovider
273
274#endif // MEDIAPROVIDER_FUSE_MEDIAPROVIDERWRAPPER_H_