Merge "vold: Do not cache CE keys in vold"
diff --git a/Checkpoint.cpp b/Checkpoint.cpp
index 88f7cad..df5fc88 100644
--- a/Checkpoint.cpp
+++ b/Checkpoint.cpp
@@ -320,13 +320,13 @@
         uint64_t free_bytes = 0;
         if (is_fs_cp) {
             statvfs(mnt_pnt.c_str(), &data);
-            free_bytes = data.f_bavail * data.f_frsize;
+            free_bytes = ((uint64_t) data.f_bavail) * data.f_frsize;
         } else {
             std::string bow_device = fs_mgr_find_bow_device(blk_device);
             if (!bow_device.empty()) {
                 std::string content;
                 if (android::base::ReadFileToString(bow_device + "/bow/free", &content)) {
-                    free_bytes = std::strtoul(content.c_str(), NULL, 10);
+                    free_bytes = std::strtoull(content.c_str(), NULL, 10);
                 }
             }
         }
diff --git a/Utils.cpp b/Utils.cpp
index 67c48ad..a66e33c 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -1017,11 +1017,14 @@
     std::string pass_through_path(
             StringPrintf("%s/%s", pre_pass_through_path.c_str(), relative_upper_path.c_str()));
 
-    std::string sdcardfs_path(
-            StringPrintf("/mnt/runtime/full/%s", relative_upper_path.c_str()));
-
     // Create directories.
-    auto result = PrepareDir(pre_fuse_path, 0700, AID_ROOT, AID_ROOT);
+    // Shell is neither AID_ROOT nor AID_EVERYBODY. Since it equally needs 'execute' access to
+    // /mnt/user/0 to 'adb shell ls /sdcard' for instance, we set the uid bit of /mnt/user/0 to
+    // AID_SHELL. This gives shell access along with apps running as group everybody (user 0 apps)
+    // These bits should be consistent with what is set in zygote in
+    // com_android_internal_os_Zygote#MountEmulatedStorage on volume bind mount during app fork
+    auto result = PrepareDir(pre_fuse_path, 0710, user_id ? AID_ROOT : AID_SHELL,
+                             multiuser_get_uid(user_id, AID_EVERYBODY));
     if (result != android::OK) {
         PLOG(ERROR) << "Failed to prepare directory " << pre_fuse_path;
         return -1;
@@ -1053,8 +1056,16 @@
             return -1;
         }
         linkpath += "/primary";
+        Symlink("/storage/emulated/" + std::to_string(user_id), linkpath);
 
-        Symlink(fuse_path + "/" + std::to_string(user_id), linkpath);
+        std::string pass_through_linkpath(StringPrintf("/mnt/pass_through/%d/self", user_id));
+        result = PrepareDir(pass_through_linkpath, 0755, AID_ROOT, AID_ROOT);
+        if (result != android::OK) {
+            PLOG(ERROR) << "Failed to prepare directory " << pass_through_linkpath;
+            return -1;
+        }
+        pass_through_linkpath += "/primary";
+        Symlink("/storage/emulated/" + std::to_string(user_id), pass_through_linkpath);
     }
 
     // Open fuse fd.
@@ -1081,8 +1092,16 @@
         return -errno;
     }
 
-    LOG(INFO) << "Bind mounting " << sdcardfs_path << " to " << pass_through_path;
-    return BindMount(sdcardfs_path, pass_through_path);
+    if (IsFilesystemSupported("sdcardfs")) {
+        std::string sdcardfs_path(
+                StringPrintf("/mnt/runtime/full/%s", relative_upper_path.c_str()));
+
+        LOG(INFO) << "Bind mounting " << sdcardfs_path << " to " << pass_through_path;
+        return BindMount(sdcardfs_path, pass_through_path);
+    } else {
+        LOG(INFO) << "Bind mounting " << absolute_lower_path << " to " << pass_through_path;
+        return BindMount(absolute_lower_path, pass_through_path);
+    }
 }
 
 status_t UnmountUserFuse(userid_t user_id, const std::string& absolute_lower_path,
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index bc843b4..d8b1e32 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -264,10 +264,17 @@
 void VolumeManager::handleDiskAdded(const std::shared_ptr<android::vold::Disk>& disk) {
     // For security reasons, if secure keyguard is showing, wait
     // until the user unlocks the device to actually touch it
+    // Additionally, wait until user 0 is actually started, since we need
+    // the user to be up before we can mount a FUSE daemon to handle the disk.
+    bool userZeroStarted = mStartedUsers.find(0) != mStartedUsers.end();
     if (mSecureKeyguardShowing) {
         LOG(INFO) << "Found disk at " << disk->getEventPath()
                   << " but delaying scan due to secure keyguard";
         mPendingDisks.push_back(disk);
+    } else if (!userZeroStarted) {
+        LOG(INFO) << "Found disk at " << disk->getEventPath()
+                  << " but delaying scan due to user zero not having started";
+        mPendingDisks.push_back(disk);
     } else {
         disk->create();
         mDisks.push_back(disk);
@@ -482,6 +489,8 @@
     }
 
     mStartedUsers.insert(userId);
+
+    createPendingDisksIfNeeded();
     return 0;
 }
 
@@ -496,17 +505,22 @@
     return 0;
 }
 
-int VolumeManager::onSecureKeyguardStateChanged(bool isShowing) {
-    mSecureKeyguardShowing = isShowing;
-    if (!mSecureKeyguardShowing) {
-        // Now that secure keyguard has been dismissed, process
-        // any pending disks
+void VolumeManager::createPendingDisksIfNeeded() {
+    bool userZeroStarted = mStartedUsers.find(0) != mStartedUsers.end();
+    if (!mSecureKeyguardShowing && userZeroStarted) {
+        // Now that secure keyguard has been dismissed and user 0 has
+        // started, process any pending disks
         for (const auto& disk : mPendingDisks) {
             disk->create();
             mDisks.push_back(disk);
         }
         mPendingDisks.clear();
     }
+}
+
+int VolumeManager::onSecureKeyguardStateChanged(bool isShowing) {
+    mSecureKeyguardShowing = isShowing;
+    createPendingDisksIfNeeded();
     return 0;
 }
 
@@ -792,7 +806,8 @@
 #ifdef __ANDROID_DEBUGGABLE__
              !StartsWith(test, "/mnt/scratch") &&
 #endif
-             !StartsWith(test, "/mnt/vendor") && !StartsWith(test, "/mnt/product")) ||
+             !StartsWith(test, "/mnt/vendor") && !StartsWith(test, "/mnt/product") &&
+             !StartsWith(test, "/mnt/installer")) ||
             StartsWith(test, "/storage/")) {
             toUnmount.push_front(test);
         }
@@ -815,13 +830,21 @@
         return -EINVAL;
     }
 
+    // Convert paths to lower filesystem paths to avoid making FUSE requests for these reasons:
+    // 1. A FUSE request from vold puts vold at risk of hanging if the FUSE daemon is down
+    // 2. The FUSE daemon prevents requests on /mnt/user/0/emulated/<userid != 0> and a request
+    // on /storage/emulated/10 means /mnt/user/0/emulated/10
+    // TODO(b/146419093): Use lower filesystem paths that don't depend on sdcardfs
+    const std::string lowerPath = "/mnt/runtime/default/" + path.substr(9);
+    const std::string lowerAppDirRoot = "/mnt/runtime/default/" + appDirRoot.substr(9);
+
     // First create the root which holds app dirs, if needed.
-    int ret = PrepareDirsFromRoot(appDirRoot, "/storage/", 0771, AID_MEDIA_RW, AID_MEDIA_RW);
+    int ret = PrepareDirsFromRoot(lowerAppDirRoot, "/mnt/runtime/default/", 0771, AID_MEDIA_RW, AID_MEDIA_RW);
     if (ret != 0) {
         return ret;
     }
     // Then, create app-specific dirs with the correct UID/GID
-    return PrepareDirsFromRoot(path, appDirRoot, 0770, appUid, AID_MEDIA_RW);
+    return PrepareDirsFromRoot(lowerPath, lowerAppDirRoot, 0770, appUid, AID_MEDIA_RW);
 }
 
 int VolumeManager::createObb(const std::string& sourcePath, const std::string& sourceKey,
diff --git a/VolumeManager.h b/VolumeManager.h
index db32ecd..cacab85 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -94,6 +94,7 @@
     int onUserStarted(userid_t userId);
     int onUserStopped(userid_t userId);
 
+    void createPendingDisksIfNeeded();
     int onSecureKeyguardStateChanged(bool isShowing);
 
     int setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol);
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index e7a44bc..1819e09 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -169,6 +169,7 @@
     const int REMOUNT_MODE_INSTALLER = 5;
     const int REMOUNT_MODE_FULL = 6;
     const int REMOUNT_MODE_PASS_THROUGH = 7;
+    const int REMOUNT_MODE_ANDROID_WRITABLE = 8;
 
     const int VOLUME_STATE_UNMOUNTED = 0;
     const int VOLUME_STATE_CHECKING = 1;
diff --git a/model/EmulatedVolume.cpp b/model/EmulatedVolume.cpp
index aef7b77..082dea5 100644
--- a/model/EmulatedVolume.cpp
+++ b/model/EmulatedVolume.cpp
@@ -48,6 +48,7 @@
     mRawPath = rawPath;
     mLabel = "emulated";
     mFuseMounted = false;
+    mUseSdcardFs = IsFilesystemSupported("sdcardfs");
 }
 
 EmulatedVolume::EmulatedVolume(const std::string& rawPath, dev_t device, const std::string& fsUuid,
@@ -57,6 +58,7 @@
     mRawPath = rawPath;
     mLabel = fsUuid;
     mFuseMounted = false;
+    mUseSdcardFs = IsFilesystemSupported("sdcardfs");
 }
 
 EmulatedVolume::~EmulatedVolume() {}
@@ -71,33 +73,78 @@
     }
 }
 
-static status_t mountFuseBindMounts(int userId, const std::string& label) {
-    // TODO(b/134706060) we don't actually want to mount the "write" view by
-    // default, since it gives write access to all OBB dirs.
-    std::string androidSource(
-            StringPrintf("/mnt/runtime/default/%s/%d/Android", label.c_str(), userId));
-    std::string androidTarget(
-            StringPrintf("/mnt/user/%d/%s/%d/Android", userId, label.c_str(), userId));
-
-    if (access(androidSource.c_str(), F_OK) != 0) {
+// Creates a bind mount from source to target, creating the source (!) directory
+// if not yet present.
+static status_t doFuseBindMount(const std::string& source, const std::string& target) {
+    if (access(source.c_str(), F_OK) != 0) {
         // Android path may not exist yet if users has just been created; create it on
         // the lower fs.
-        if (fs_prepare_dir(androidSource.c_str(), 0771, AID_ROOT, AID_ROOT) != 0) {
-            PLOG(ERROR) << "Failed to create " << androidSource;
+        if (fs_prepare_dir(source.c_str(), 0771, AID_MEDIA_RW, AID_MEDIA_RW) != 0) {
+            PLOG(ERROR) << "Failed to create " << source;
             return -errno;
         }
     }
-    LOG(INFO) << "Bind mounting " << androidSource << " on " << androidTarget;
-    auto status = BindMount(androidSource, androidTarget);
+    LOG(INFO) << "Bind mounting " << source << " on " << target;
+    auto status = BindMount(source, target);
     if (status != OK) {
         return status;
     }
-    LOG(INFO) << "Bind mounted " << androidSource << " on " << androidTarget;
-
+    LOG(INFO) << "Bind mounted " << source << " on " << target;
     return OK;
 }
 
-static status_t unmountFuseBindMounts(int userId, const std::string& label) {
+status_t EmulatedVolume::mountFuseBindMounts() {
+    std::string androidSource;
+    std::string label = getLabel();
+    int userId = getMountUserId();
+
+    if (mUseSdcardFs) {
+        androidSource = StringPrintf("/mnt/runtime/default/%s/%d/Android", label.c_str(), userId);
+    } else {
+        androidSource = StringPrintf("/%s/%d/Android", mRawPath.c_str(), userId);
+    }
+    std::string androidTarget(
+            StringPrintf("/mnt/user/%d/%s/%d/Android", userId, label.c_str(), userId));
+
+    auto status = doFuseBindMount(androidSource, androidTarget);
+    if (status != OK) {
+        return status;
+    }
+
+    // Installers get the same view as all other apps, with the sole exception that the
+    // OBB dirs (Android/obb) are writable to them. On sdcardfs devices, this requires
+    // a special bind mount, since app-private and OBB dirs share the same GID, but we
+    // only want to give access to the latter.
+    if (!mUseSdcardFs) {
+        return OK;
+    }
+    std::string installerSource(
+            StringPrintf("/mnt/runtime/write/%s/%d/Android/obb", label.c_str(), userId));
+    std::string installerTarget(
+            StringPrintf("/mnt/installer/%d/%s/%d/Android/obb", userId, label.c_str(), userId));
+
+    status = doFuseBindMount(installerSource, installerTarget);
+    if (status != OK) {
+        return status;
+    }
+    return OK;
+}
+
+status_t EmulatedVolume::unmountFuseBindMounts() {
+    std::string label = getLabel();
+    int userId = getMountUserId();
+
+    if (mUseSdcardFs) {
+        std::string installerTarget(
+                StringPrintf("/mnt/installer/%d/%s/%d/Android/obb", userId, label.c_str(), userId));
+        LOG(INFO) << "Unmounting " << installerTarget;
+        auto status = UnmountTree(installerTarget);
+        if (status != OK) {
+            LOG(ERROR) << "Failed to unmount " << installerTarget;
+            // Intentional continue to try to unmount the other bind mount
+        }
+    }
+
     std::string androidTarget(
             StringPrintf("/mnt/user/%d/%s/%d/Android", userId, label.c_str(), userId));
 
@@ -137,7 +184,7 @@
 
     // Mount sdcardfs regardless of FUSE, since we need it to bind-mount on top of the
     // FUSE volume for various reasons.
-    if (getMountUserId() == 0) {
+    if (mUseSdcardFs && getMountUserId() == 0) {
         LOG(INFO) << "Executing sdcardfs";
         int sdcardFsPid;
         if (!(sdcardFsPid = fork())) {
@@ -198,12 +245,19 @@
             bool is_ready = false;
             callback->onVolumeChecking(std::move(fd), getPath(), getInternalPath(), &is_ready);
             if (!is_ready) {
+                fd.reset();
+                doUnmount();
                 return -EIO;
             }
         }
 
         // Only do the bind-mounts when we know for sure the FUSE daemon can resolve the path.
-        return mountFuseBindMounts(user_id, label);
+        status_t res = mountFuseBindMounts();
+        if (res != OK) {
+            fd.reset();
+            doUnmount();
+        }
+        return res;
     }
 
     return OK;
@@ -231,7 +285,7 @@
         // Ignoring unmount return status because we do want to try to unmount
         // the rest cleanly.
 
-        unmountFuseBindMounts(userId, label);
+        unmountFuseBindMounts();
         if (UnmountUserFuse(userId, getInternalPath(), label) != OK) {
             PLOG(INFO) << "UnmountUserFuse failed on emulated fuse volume";
             return -errno;
@@ -239,7 +293,7 @@
 
         mFuseMounted = false;
     }
-    if (getMountUserId() != 0) {
+    if (getMountUserId() != 0 || !mUseSdcardFs) {
         // For sdcardfs, only unmount for user 0, since user 0 will always be running
         // and the paths don't change for different users.
         return OK;
diff --git a/model/EmulatedVolume.h b/model/EmulatedVolume.h
index 131761c..4f76a60 100644
--- a/model/EmulatedVolume.h
+++ b/model/EmulatedVolume.h
@@ -46,6 +46,9 @@
     status_t doUnmount() override;
 
   private:
+    status_t mountFuseBindMounts();
+    status_t unmountFuseBindMounts();
+
     std::string getLabel();
     std::string mRawPath;
     std::string mLabel;
@@ -58,6 +61,9 @@
     /* Whether we mounted FUSE for this volume */
     bool mFuseMounted;
 
+    /* Whether to use sdcardfs for this volume */
+    bool mUseSdcardFs;
+
     DISALLOW_COPY_AND_ASSIGN(EmulatedVolume);
 };
 
diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp
index 78f150d..b246c95 100644
--- a/model/PublicVolume.cpp
+++ b/model/PublicVolume.cpp
@@ -51,6 +51,7 @@
     setId(StringPrintf("public:%u,%u", major(device), minor(device)));
     mDevPath = StringPrintf("/dev/block/vold/%s", getId().c_str());
     mFuseMounted = false;
+    mUseSdcardFs = IsFilesystemSupported("sdcardfs");
 }
 
 PublicVolume::~PublicVolume() {}
@@ -161,67 +162,69 @@
         return OK;
     }
 
-    if (fs_prepare_dir(mSdcardFsDefault.c_str(), 0700, AID_ROOT, AID_ROOT) ||
-        fs_prepare_dir(mSdcardFsRead.c_str(), 0700, AID_ROOT, AID_ROOT) ||
-        fs_prepare_dir(mSdcardFsWrite.c_str(), 0700, AID_ROOT, AID_ROOT) ||
-        fs_prepare_dir(mSdcardFsFull.c_str(), 0700, AID_ROOT, AID_ROOT)) {
-        PLOG(ERROR) << getId() << " failed to create sdcardfs mount points";
-        return -errno;
-    }
-
-    dev_t before = GetDevice(mSdcardFsFull);
-
-    int sdcardFsPid;
-    if (!(sdcardFsPid = fork())) {
-        if (getMountFlags() & MountFlags::kPrimary) {
-            // clang-format off
-            if (execl(kSdcardFsPath, kSdcardFsPath,
-                    "-u", "1023", // AID_MEDIA_RW
-                    "-g", "1023", // AID_MEDIA_RW
-                    "-U", std::to_string(getMountUserId()).c_str(),
-                    "-w",
-                    mRawPath.c_str(),
-                    stableName.c_str(),
-                    NULL)) {
-                // clang-format on
-                PLOG(ERROR) << "Failed to exec";
-            }
-        } else {
-            // clang-format off
-            if (execl(kSdcardFsPath, kSdcardFsPath,
-                    "-u", "1023", // AID_MEDIA_RW
-                    "-g", "1023", // AID_MEDIA_RW
-                    "-U", std::to_string(getMountUserId()).c_str(),
-                    mRawPath.c_str(),
-                    stableName.c_str(),
-                    NULL)) {
-                // clang-format on
-                PLOG(ERROR) << "Failed to exec";
-            }
+    if (mUseSdcardFs) {
+        if (fs_prepare_dir(mSdcardFsDefault.c_str(), 0700, AID_ROOT, AID_ROOT) ||
+            fs_prepare_dir(mSdcardFsRead.c_str(), 0700, AID_ROOT, AID_ROOT) ||
+            fs_prepare_dir(mSdcardFsWrite.c_str(), 0700, AID_ROOT, AID_ROOT) ||
+            fs_prepare_dir(mSdcardFsFull.c_str(), 0700, AID_ROOT, AID_ROOT)) {
+            PLOG(ERROR) << getId() << " failed to create sdcardfs mount points";
+            return -errno;
         }
 
-        LOG(ERROR) << "sdcardfs exiting";
-        _exit(1);
-    }
+        dev_t before = GetDevice(mSdcardFsFull);
 
-    if (sdcardFsPid == -1) {
-        PLOG(ERROR) << getId() << " failed to fork";
-        return -errno;
-    }
+        int sdcardFsPid;
+        if (!(sdcardFsPid = fork())) {
+            if (getMountFlags() & MountFlags::kPrimary) {
+                // clang-format off
+                if (execl(kSdcardFsPath, kSdcardFsPath,
+                        "-u", "1023", // AID_MEDIA_RW
+                        "-g", "1023", // AID_MEDIA_RW
+                        "-U", std::to_string(getMountUserId()).c_str(),
+                        "-w",
+                        mRawPath.c_str(),
+                        stableName.c_str(),
+                        NULL)) {
+                    // clang-format on
+                    PLOG(ERROR) << "Failed to exec";
+                }
+            } else {
+                // clang-format off
+                if (execl(kSdcardFsPath, kSdcardFsPath,
+                        "-u", "1023", // AID_MEDIA_RW
+                        "-g", "1023", // AID_MEDIA_RW
+                        "-U", std::to_string(getMountUserId()).c_str(),
+                        mRawPath.c_str(),
+                        stableName.c_str(),
+                        NULL)) {
+                    // clang-format on
+                    PLOG(ERROR) << "Failed to exec";
+                }
+            }
 
-    nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
-    while (before == GetDevice(mSdcardFsFull)) {
-        LOG(DEBUG) << "Waiting for sdcardfs to spin up...";
-        usleep(50000);  // 50ms
-
-        nsecs_t now = systemTime(SYSTEM_TIME_BOOTTIME);
-        if (nanoseconds_to_milliseconds(now - start) > 5000) {
-            LOG(WARNING) << "Timed out while waiting for sdcardfs to spin up";
-            return -ETIMEDOUT;
+            LOG(ERROR) << "sdcardfs exiting";
+            _exit(1);
         }
+
+        if (sdcardFsPid == -1) {
+            PLOG(ERROR) << getId() << " failed to fork";
+            return -errno;
+        }
+
+        nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
+        while (before == GetDevice(mSdcardFsFull)) {
+            LOG(DEBUG) << "Waiting for sdcardfs to spin up...";
+            usleep(50000);  // 50ms
+
+            nsecs_t now = systemTime(SYSTEM_TIME_BOOTTIME);
+            if (nanoseconds_to_milliseconds(now - start) > 5000) {
+                LOG(WARNING) << "Timed out while waiting for sdcardfs to spin up";
+                return -ETIMEDOUT;
+            }
+        }
+        /* sdcardfs will have exited already. The filesystem will still be running */
+        TEMP_FAILURE_RETRY(waitpid(sdcardFsPid, nullptr, 0));
     }
-    /* sdcardfs will have exited already. The filesystem will still be running */
-    TEMP_FAILURE_RETRY(waitpid(sdcardFsPid, nullptr, 0));
 
     bool isFuse = base::GetBoolProperty(kPropFuse, false);
     if (isFuse) {
@@ -275,22 +278,24 @@
 
     ForceUnmount(kAsecPath);
 
-    ForceUnmount(mSdcardFsDefault);
-    ForceUnmount(mSdcardFsRead);
-    ForceUnmount(mSdcardFsWrite);
-    ForceUnmount(mSdcardFsFull);
+    if (mUseSdcardFs) {
+        ForceUnmount(mSdcardFsDefault);
+        ForceUnmount(mSdcardFsRead);
+        ForceUnmount(mSdcardFsWrite);
+        ForceUnmount(mSdcardFsFull);
+
+        rmdir(mSdcardFsDefault.c_str());
+        rmdir(mSdcardFsRead.c_str());
+        rmdir(mSdcardFsWrite.c_str());
+        rmdir(mSdcardFsFull.c_str());
+
+        mSdcardFsDefault.clear();
+        mSdcardFsRead.clear();
+        mSdcardFsWrite.clear();
+        mSdcardFsFull.clear();
+    }
     ForceUnmount(mRawPath);
-
-    rmdir(mSdcardFsDefault.c_str());
-    rmdir(mSdcardFsRead.c_str());
-    rmdir(mSdcardFsWrite.c_str());
-    rmdir(mSdcardFsFull.c_str());
     rmdir(mRawPath.c_str());
-
-    mSdcardFsDefault.clear();
-    mSdcardFsRead.clear();
-    mSdcardFsWrite.clear();
-    mSdcardFsFull.clear();
     mRawPath.clear();
 
     return OK;
diff --git a/model/PublicVolume.h b/model/PublicVolume.h
index dd76373..3156b53 100644
--- a/model/PublicVolume.h
+++ b/model/PublicVolume.h
@@ -68,6 +68,9 @@
     /* Whether we mounted FUSE for this volume */
     bool mFuseMounted;
 
+    /* Whether to use sdcardfs for this volume */
+    bool mUseSdcardFs;
+
     /* Filesystem type */
     std::string mFsType;
     /* Filesystem UUID */
diff --git a/vold_prepare_subdirs.cpp b/vold_prepare_subdirs.cpp
index 3a58b2e..d624d73 100644
--- a/vold_prepare_subdirs.cpp
+++ b/vold_prepare_subdirs.cpp
@@ -121,7 +121,7 @@
 }
 
 static bool prepare_apex_subdirs(struct selabel_handle* sehandle, const std::string& path) {
-    if (!prepare_dir(sehandle, 0700, 0, 0, path + "/apexdata")) return false;
+    if (!prepare_dir(sehandle, 0711, 0, 0, path + "/apexdata")) return false;
 
     auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir("/apex"), closedir);
     if (!dirp) {
@@ -138,7 +138,7 @@
 
         if (strchr(name, '@') != NULL) continue;
 
-        if (!prepare_dir(sehandle, 0700, AID_SYSTEM, AID_SYSTEM, path + "/apexdata/" + name)) {
+        if (!prepare_dir(sehandle, 0771, AID_ROOT, AID_SYSTEM, path + "/apexdata/" + name)) {
             return false;
         }
     }