Snap for 11219529 from 4281014b850669c2f46fcf54f45ae52e54cbc758 to mainline-tzdata4-release

Change-Id: I20715ec16b87329f105f87a6785a0785da61601f
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 019b64a..cd4c560 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -3166,7 +3166,8 @@
               << " writer.GetCowVersion(): " << writer.GetCowVersion();
 
     bool use_compression = IsCompressionEnabled() && dap_metadata.vabc_enabled() &&
-                           !device_->IsRecovery() && cow_format_support;
+                           !device_->IsRecovery() && cow_format_support &&
+                           KernelSupportsCompressedSnapshots();
 
     std::string compression_algorithm;
     if (use_compression) {
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index e7ffb16..bf630f5 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -315,7 +315,7 @@
     }
 
     AssertionResult DeleteDevice(const std::string& device) {
-        if (!dm_.DeleteDeviceIfExists(device)) {
+        if (!sm->DeleteDeviceIfExists(device, 1s)) {
             return AssertionFailure() << "Can't delete " << device;
         }
         return AssertionSuccess();
@@ -2760,7 +2760,7 @@
         return true;
     }
 
-    return IsUserspaceSnapshotsEnabled();
+    return IsUserspaceSnapshotsEnabled() && KernelSupportsCompressedSnapshots();
 }
 
 bool ShouldUseCompression() {
@@ -2770,7 +2770,7 @@
     if (FLAGS_force_config == "vabc") {
         return true;
     }
-    return IsCompressionEnabled();
+    return IsCompressionEnabled() && KernelSupportsCompressedSnapshots();
 }
 
 }  // namespace snapshot
diff --git a/fs_mgr/libsnapshot/utility.cpp b/fs_mgr/libsnapshot/utility.cpp
index f01bec9..841acf4 100644
--- a/fs_mgr/libsnapshot/utility.cpp
+++ b/fs_mgr/libsnapshot/utility.cpp
@@ -26,7 +26,9 @@
 #include <android-base/properties.h>
 #include <android-base/strings.h>
 #include <fs_mgr/roots.h>
+#include <libdm/dm.h>
 
+using android::dm::DeviceMapper;
 using android::dm::kSectorSize;
 using android::fiemap::FiemapStatus;
 using android::fs_mgr::EnsurePathMounted;
@@ -208,5 +210,10 @@
     return android::base::GetBoolProperty("snapuserd.test.dm.snapshots", false);
 }
 
+bool KernelSupportsCompressedSnapshots() {
+    auto& dm = DeviceMapper::Instance();
+    return dm.GetTargetByName("user", nullptr);
+}
+
 }  // namespace snapshot
 }  // namespace android
diff --git a/fs_mgr/libsnapshot/utility.h b/fs_mgr/libsnapshot/utility.h
index 0ef3234..0794154 100644
--- a/fs_mgr/libsnapshot/utility.h
+++ b/fs_mgr/libsnapshot/utility.h
@@ -129,6 +129,7 @@
 void AppendExtent(google::protobuf::RepeatedPtrField<chromeos_update_engine::Extent>* extents,
                   uint64_t start_block, uint64_t num_blocks);
 
+bool KernelSupportsCompressedSnapshots();
 bool IsCompressionEnabled();
 
 bool IsUserspaceSnapshotsEnabled();
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index c8bfb01..40c478a 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -303,11 +303,14 @@
     ],
 }
 
+always_static_test_libraries = [
+    "libjsoncpp",
+]
+
 test_libraries = [
     "libcutils",
     "liblog",
     "libbase",
-    "libjsoncpp",
     "libprocessgroup",
     "libcgrouprc",
 ]
@@ -318,6 +321,7 @@
     defaults: ["libcutils_test_default"],
     host_supported: true,
     shared_libs: test_libraries,
+    static_libs: always_static_test_libraries,
     require_root: true,
 }
 
@@ -327,7 +331,7 @@
     static_libs: [
         "libc",
         "libcgrouprc_format",
-    ] + test_libraries,
+    ] + test_libraries + always_static_test_libraries,
     stl: "libc++_static",
     require_root: true,
 
diff --git a/libcutils/ashmem-dev.cpp b/libcutils/ashmem-dev.cpp
index 6a27f9a..56d6875 100644
--- a/libcutils/ashmem-dev.cpp
+++ b/libcutils/ashmem-dev.cpp
@@ -349,6 +349,12 @@
         return -1;
     }
 
+    // forbid size changes to match ashmem behaviour
+    if (fcntl(fd, F_ADD_SEALS, F_SEAL_GROW | F_SEAL_SHRINK) == -1) {
+        ALOGE("memfd_create(%s, %zd) F_ADD_SEALS failed: %m", name, size);
+        return -1;
+    }
+
     if (debug_log) {
         ALOGE("memfd_create(%s, %zd) success. fd=%d\n", name, size, fd.get());
     }
@@ -400,14 +406,29 @@
 }
 
 static int memfd_set_prot_region(int fd, int prot) {
-    /* Only proceed if an fd needs to be write-protected */
+    int seals = fcntl(fd, F_GET_SEALS);
+    if (seals == -1) {
+        ALOGE("memfd_set_prot_region(%d, %d): F_GET_SEALS failed: %s\n", fd, prot, strerror(errno));
+        return -1;
+    }
+
     if (prot & PROT_WRITE) {
+        /* Now we want the buffer to be read-write, let's check if the buffer
+         * has been previously marked as read-only before, if so return error
+         */
+        if (seals & F_SEAL_FUTURE_WRITE) {
+            ALOGE("memfd_set_prot_region(%d, %d): region is write protected\n", fd, prot);
+            errno = EINVAL;  // inline with ashmem error code, if already in
+                             // read-only mode
+            return -1;
+        }
         return 0;
     }
 
-    if (fcntl(fd, F_ADD_SEALS, F_SEAL_FUTURE_WRITE) == -1) {
-        ALOGE("memfd_set_prot_region(%d, %d): F_SEAL_FUTURE_WRITE seal failed: %s\n", fd, prot,
-              strerror(errno));
+    /* We would only allow read-only for any future file operations */
+    if (fcntl(fd, F_ADD_SEALS, F_SEAL_FUTURE_WRITE | F_SEAL_SEAL) == -1) {
+        ALOGE("memfd_set_prot_region(%d, %d): F_SEAL_FUTURE_WRITE | F_SEAL_SEAL seal failed: %s\n",
+              fd, prot, strerror(errno));
         return -1;
     }