From 8688eb4f47bd589feb2e885836b34c5991158845 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Wed, 16 Dec 2020 09:40:33 +0100 Subject: [PATCH] Set a default ACL on /data/media/userId. 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: I6dfae41f9cb6a8283978b2667b02708a000f07c0 --- FsCrypt.cpp | 9 +++++++++ Utils.cpp | 4 ++-- Utils.h | 3 +++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/FsCrypt.cpp b/FsCrypt.cpp index 8f6ba9c..6471231 100644 --- a/FsCrypt.cpp +++ b/FsCrypt.cpp @@ -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; @@ -868,6 +869,14 @@ bool fscrypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_ 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; + // 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, 0770, 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; diff --git a/Utils.cpp b/Utils.cpp index d5648f7..98797b2 100644 --- 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 additionalGids) { +status_t SetDefaultAcl(const std::string& path, mode_t mode, uid_t uid, gid_t gid, + std::vector additionalGids) { if (IsSdcardfsUsed()) { // sdcardfs magically takes care of this return OK; diff --git a/Utils.h b/Utils.h index cf3fd9b..8975adc 100644 --- a/Utils.h +++ b/Utils.h @@ -52,6 +52,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 additionalGids); + status_t AbortFuseConnections(); int SetQuotaInherit(const std::string& path);