Merge "Adding corpus for vold fuzzer" into main
diff --git a/Android.bp b/Android.bp
index 7e41f22..6d70d4d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -165,7 +165,6 @@
         },
     },
     whole_static_libs: [
-        "libcom.android.sysprop.apex",
         "libc++fs",
     ],
 }
diff --git a/IdleMaint.cpp b/IdleMaint.cpp
index 1a6c0a6..7d3eaf4 100644
--- a/IdleMaint.cpp
+++ b/IdleMaint.cpp
@@ -551,9 +551,9 @@
 
     int32_t freeSegments = std::stoi(freeSegmentsStr);
     int32_t dirtySegments = std::stoi(dirtySegmentsStr);
-    int32_t reservedBlocks = std::stoi(ovpSegmentsStr) + std::stoi(reservedBlocksStr);
+    int32_t reservedSegments = std::stoi(ovpSegmentsStr) + std::stoi(reservedBlocksStr) / 512;
 
-    freeSegments = freeSegments > reservedBlocks ? freeSegments - reservedBlocks : 0;
+    freeSegments = freeSegments > reservedSegments ? freeSegments - reservedSegments : 0;
     int32_t totalSegments = freeSegments + dirtySegments;
     int32_t finalTargetSegments = 0;
 
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index dc6fae9..db356db 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -35,7 +35,6 @@
 
 #include <linux/kdev_t.h>
 
-#include <ApexProperties.sysprop.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/parseint.h>
@@ -70,6 +69,7 @@
 #include "model/EmulatedVolume.h"
 #include "model/ObbVolume.h"
 #include "model/PrivateVolume.h"
+#include "model/PublicVolume.h"
 #include "model/StubVolume.h"
 
 using android::OK;
@@ -90,6 +90,7 @@
 using android::vold::PrepareAndroidDirs;
 using android::vold::PrepareAppDirFromRoot;
 using android::vold::PrivateVolume;
+using android::vold::PublicVolume;
 using android::vold::Symlink;
 using android::vold::Unlink;
 using android::vold::UnmountTree;
@@ -459,6 +460,31 @@
 
     if (mStartedUsers.find(userId) == mStartedUsers.end()) {
         createEmulatedVolumesForUser(userId);
+        std::list<std::string> public_vols;
+        listVolumes(VolumeBase::Type::kPublic, public_vols);
+        for (const std::string& id : public_vols) {
+            PublicVolume* pvol = static_cast<PublicVolume*>(findVolume(id).get());
+            if (pvol->getState() != VolumeBase::State::kMounted) {
+                continue;
+            }
+            if (pvol->isVisible() == 0) {
+                continue;
+            }
+            userid_t mountUserId = pvol->getMountUserId();
+            if (userId == mountUserId) {
+                // No need to bind mount for the user that owns the mount
+                continue;
+            }
+            if (mountUserId != VolumeManager::Instance()->getSharedStorageUser(userId)) {
+                // No need to bind if the user does not share storage with the mount owner
+                continue;
+            }
+            auto bindMountStatus = pvol->bindMountForUser(userId);
+            if (bindMountStatus != OK) {
+                LOG(ERROR) << "Bind Mounting Public Volume: " << pvol << " for user: " << userId
+                           << "Failed. Error: " << bindMountStatus;
+            }
+        }
     }
 
     mStartedUsers.insert(userId);
@@ -595,12 +621,11 @@
     struct dirent* de;
     std::string rootName;
     std::string pidName;
+    std::string exeName;
     int pidFd;
     int nsFd;
     struct stat sb;
 
-    static bool apexUpdatable = android::sysprop::ApexProperties::updatable().value_or(false);
-
     if (!(dir = opendir("/proc"))) {
         async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to opendir");
         return false;
@@ -648,22 +673,18 @@
             goto next;
         }
 
-        if (apexUpdatable) {
-            std::string exeName;
-            // When ro.apex.bionic_updatable is set to true,
-            // some early native processes have mount namespaces that are different
-            // from that of the init. Therefore, above check can't filter them out.
-            // Since the propagation type of / is 'shared', unmounting /storage
-            // for the early native processes affects other processes including
-            // init. Filter out such processes by skipping if a process is a
-            // non-Java process whose UID is < AID_APP_START. (The UID condition
-            // is required to not filter out child processes spawned by apps.)
-            if (!android::vold::Readlinkat(pidFd, "exe", &exeName)) {
-                goto next;
-            }
-            if (!StartsWith(exeName, "/system/bin/app_process") && sb.st_uid < AID_APP_START) {
-                goto next;
-            }
+        // Some early native processes have mount namespaces that are different
+        // from that of the init. Therefore, above check can't filter them out.
+        // Since the propagation type of / is 'shared', unmounting /storage
+        // for the early native processes affects other processes including
+        // init. Filter out such processes by skipping if a process is a
+        // non-Java process whose UID is < AID_APP_START. (The UID condition
+        // is required to not filter out child processes spawned by apps.)
+        if (!android::vold::Readlinkat(pidFd, "exe", &exeName)) {
+            goto next;
+        }
+        if (!StartsWith(exeName, "/system/bin/app_process") && sb.st_uid < AID_APP_START) {
+            goto next;
         }
 
         // We purposefully leave the namespace open across the fork
diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp
index 034fb23..e86d002 100644
--- a/model/PublicVolume.cpp
+++ b/model/PublicVolume.cpp
@@ -257,9 +257,45 @@
     // See comment in model/EmulatedVolume.cpp
     ConfigureMaxDirtyRatioForFuse(GetFuseMountPathForUser(user_id, stableName), 40u);
 
+    auto vol_manager = VolumeManager::Instance();
+    // Create bind mounts for all running users
+    for (userid_t started_user : vol_manager->getStartedUsers()) {
+        userid_t mountUserId = getMountUserId();
+        if (started_user == mountUserId) {
+            // No need to bind mount for the user that owns the mount
+            continue;
+        }
+        if (mountUserId != VolumeManager::Instance()->getSharedStorageUser(started_user)) {
+            // No need to bind if the user does not share storage with the mount owner
+            continue;
+        }
+        auto bindMountStatus = bindMountForUser(started_user);
+        if (bindMountStatus != OK) {
+            LOG(ERROR) << "Bind Mounting Public Volume: " << stableName
+                       << " for user: " << started_user << "Failed. Error: " << bindMountStatus;
+        }
+    }
     return OK;
 }
 
+status_t PublicVolume::bindMountForUser(userid_t user_id) {
+    userid_t mountUserId = getMountUserId();
+    std::string stableName = getId();
+    if (!mFsUuid.empty()) {
+        stableName = mFsUuid;
+    }
+
+    LOG(INFO) << "Bind Mounting Public Volume for user: " << user_id
+              << ".Mount owner: " << mountUserId;
+    auto sourcePath = GetFuseMountPathForUser(mountUserId, stableName);
+    auto destPath = GetFuseMountPathForUser(user_id, stableName);
+    PrepareDir(destPath, 0770, AID_ROOT, AID_MEDIA_RW);
+    auto mountRes = BindMount(sourcePath, destPath);
+    LOG(INFO) << "Mount status: " << mountRes;
+
+    return mountRes;
+}
+
 status_t PublicVolume::doUnmount() {
     // Unmount the storage before we kill the FUSE process. If we kill
     // the FUSE process first, most file system operations will return
@@ -274,6 +310,20 @@
             stableName = mFsUuid;
         }
 
+        // Unmount bind mounts for running users
+        auto vol_manager = VolumeManager::Instance();
+        int user_id = getMountUserId();
+        for (int started_user : vol_manager->getStartedUsers()) {
+            if (started_user == user_id) {
+                // No need to remove bind mount for the user that owns the mount
+                continue;
+            }
+            LOG(INFO) << "Removing Public Volume Bind Mount for: " << started_user;
+            auto mountPath = GetFuseMountPathForUser(started_user, stableName);
+            ForceUnmount(mountPath);
+            rmdir(mountPath.c_str());
+        }
+
         if (UnmountUserFuse(getMountUserId(), getInternalPath(), stableName) != OK) {
             PLOG(INFO) << "UnmountUserFuse failed on public fuse volume";
             return -errno;
diff --git a/model/PublicVolume.h b/model/PublicVolume.h
index 3156b53..ca553b0 100644
--- a/model/PublicVolume.h
+++ b/model/PublicVolume.h
@@ -42,6 +42,8 @@
     explicit PublicVolume(dev_t device);
     virtual ~PublicVolume();
 
+    status_t bindMountForUser(userid_t user_id);
+
   protected:
     status_t doCreate() override;
     status_t doDestroy() override;