OSDN Git Service

Set a default ACL on /data/media/userId.
authorMartijn Coenen <maco@google.com>
Mon, 1 Feb 2021 07:57:02 +0000 (07:57 +0000)
committerMartijn Coenen <maco@google.com>
Wed, 24 Feb 2021 11:45:09 +0000 (12:45 +0100)
This directory is used as a root for external storage on adopted storage
devices. It needs to be writable by processes holding the AID_MEDIA_RW
GID permission; in particular, it should be writable by the FUSE daemon.

On devices with sdcardfs, this was ensured automatically, because
sdcardfs presented a view of this directory that was writable, that we
could use for the FUSE daemon. But on devices without sdcardfs, the FUSE
daemon sees the raw filesystem and its permissions. This also means that
files created by the FUSE daemon will have their uid/gid set to the uid
of the FUSE daemon; to ensure these files stay writable to other system
applications that have AID_MEDIA_RW, use a default ACL to make sure the
gid stays AID_MEDIA_RW.

In particular, this fixes an issue with app cloning, where we want the
FUSE daemon of user 0 to be able to access the files of the app clone
user, and vice versa.

Bug: 154057120
Test: inspect uid/gid of /data/media/0 and contents
Change-Id: Ic5d63457ec917ea407b900dbb7773d89311780c6

FsCrypt.cpp
Utils.cpp
Utils.h

index 988d2a7..c62eb25 100644 (file)
@@ -74,6 +74,7 @@ using android::vold::KeyBuffer;
 using android::vold::KeyGeneration;
 using android::vold::retrieveKey;
 using android::vold::retrieveOrGenerateKey;
+using android::vold::SetDefaultAcl;
 using android::vold::SetQuotaInherit;
 using android::vold::SetQuotaProjectId;
 using android::vold::writeStringToFile;
@@ -862,7 +863,15 @@ bool fscrypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_
             if (!prepare_dir(misc_ce_path, 01771, AID_SYSTEM, AID_MISC)) return false;
             if (!prepare_dir(vendor_ce_path, 0771, AID_ROOT, AID_ROOT)) return false;
         }
-        if (!prepare_dir(media_ce_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return false;
+        if (!prepare_dir(media_ce_path, 02770, AID_MEDIA_RW, AID_MEDIA_RW)) return false;
+        // On devices without sdcardfs (kernel 5.4+), the path permissions aren't fixed
+        // up automatically; therefore, use a default ACL, to ensure apps with MEDIA_RW
+        // can keep reading external storage; in particular, this allows app cloning
+        // scenarios to work correctly on such devices.
+        int ret = SetDefaultAcl(media_ce_path, 02770, AID_MEDIA_RW, AID_MEDIA_RW, {AID_MEDIA_RW});
+        if (ret != android::OK) {
+            return false;
+        }
 
         if (!prepare_dir(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
 
index d5648f7..98797b2 100644 (file)
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -136,8 +136,8 @@ status_t DestroyDeviceNode(const std::string& path) {
 }
 
 // Sets a default ACL on the directory.
-int SetDefaultAcl(const std::string& path, mode_t mode, uid_t uid, gid_t gid,
-                  std::vector<gid_t> additionalGids) {
+status_t SetDefaultAcl(const std::string& path, mode_t mode, uid_t uid, gid_t gid,
+                       std::vector<gid_t> additionalGids) {
     if (IsSdcardfsUsed()) {
         // sdcardfs magically takes care of this
         return OK;
diff --git a/Utils.h b/Utils.h
index 49901c8..a727e63 100644 (file)
--- a/Utils.h
+++ b/Utils.h
@@ -51,6 +51,9 @@ std::string GetFuseMountPathForUser(userid_t user_id, const std::string& relativ
 status_t CreateDeviceNode(const std::string& path, dev_t dev);
 status_t DestroyDeviceNode(const std::string& path);
 
+status_t SetDefaultAcl(const std::string& path, mode_t mode, uid_t uid, gid_t gid,
+                       std::vector<gid_t> additionalGids);
+
 status_t AbortFuseConnections();
 
 int SetQuotaInherit(const std::string& path);