Merge changes I49495684,I0db2e0f4,I07bb811b am: 67665a4571 am: f6016177f2 am: 44cb302f6e am: 601c99bae5

Original change: https://android-review.googlesource.com/c/platform/system/core/+/1358187

Change-Id: I3375f950a8b24b65ec2c922a24b36740ff7466ee
diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp
index 58241b3..e425284 100644
--- a/fs_mgr/libdm/Android.bp
+++ b/fs_mgr/libdm/Android.bp
@@ -42,6 +42,7 @@
             enabled: false,
         },
     },
+    ramdisk_available: true,
 }
 
 filegroup {
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index 95301ff..eaef180 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -310,3 +310,36 @@
     auto_gen_config: true,
     require_root: true,
 }
+
+cc_defaults {
+    name: "snapuserd_defaults",
+    srcs: [
+        "snapuserd.cpp",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror"
+    ],
+
+    static_libs: [
+        "libbase",
+        "liblog",
+        "libdm",
+    ],
+}
+
+cc_binary {
+    name: "snapuserd",
+    defaults: ["snapuserd_defaults"],
+}
+
+cc_binary {
+    name: "snapuserd_ramdisk",
+    stem: "snapuserd",
+    defaults: ["snapuserd_defaults"],
+
+    ramdisk: true,
+    static_executable: true,
+    system_shared_libs: [],
+}
diff --git a/fs_mgr/libsnapshot/snapuserd.cpp b/fs_mgr/libsnapshot/snapuserd.cpp
new file mode 100644
index 0000000..a6ff4fd
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapuserd.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <linux/types.h>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <libdm/dm.h>
+
+using android::base::unique_fd;
+
+#define DM_USER_MAP_READ 0
+#define DM_USER_MAP_WRITE 1
+
+struct dm_user_message {
+    __u64 seq;
+    __u64 type;
+    __u64 flags;
+    __u64 sector;
+    __u64 len;
+    __u8 buf[];
+};
+
+using namespace android::dm;
+
+static int daemon_main(const std::string& device) {
+    unique_fd block_fd(open(device.c_str(), O_RDWR));
+    if (block_fd < 0) {
+        PLOG(ERROR) << "Unable to open " << device;
+        return 1;
+    }
+
+    unique_fd ctrl_fd(open("/dev/dm-user", O_RDWR));
+    if (ctrl_fd < 0) {
+        PLOG(ERROR) << "Unable to open /dev/dm-user";
+        return 1;
+    }
+
+    size_t buf_size = 1UL << 16;
+    auto buf = std::make_unique<char>(buf_size);
+
+    /* Just keeps pumping messages between userspace and the kernel.  We won't
+     * actually be doing anything, but the sequence numbers line up so it'll at
+     * least make forward progress. */
+    while (true) {
+        struct dm_user_message* msg = (struct dm_user_message*)buf.get();
+
+        memset(buf.get(), 0, buf_size);
+
+        ssize_t readed = read(ctrl_fd.get(), buf.get(), buf_size);
+        if (readed < 0) {
+            PLOG(ERROR) << "Control read failed, trying with more space";
+            buf_size *= 2;
+            buf = std::make_unique<char>(buf_size);
+            continue;
+        }
+
+        LOG(DEBUG) << android::base::StringPrintf("read() from dm-user returned %d bytes:",
+                                                  (int)readed);
+        LOG(DEBUG) << android::base::StringPrintf("    msg->seq:    0x%016llx", msg->seq);
+        LOG(DEBUG) << android::base::StringPrintf("    msg->type:   0x%016llx", msg->type);
+        LOG(DEBUG) << android::base::StringPrintf("    msg->flags:  0x%016llx", msg->flags);
+        LOG(DEBUG) << android::base::StringPrintf("    msg->sector: 0x%016llx", msg->sector);
+        LOG(DEBUG) << android::base::StringPrintf("    msg->len:    0x%016llx", msg->len);
+
+        switch (msg->type) {
+            case DM_USER_MAP_READ: {
+                LOG(DEBUG) << android::base::StringPrintf(
+                        "Responding to read of sector %lld with %lld bytes data", msg->sector,
+                        msg->len);
+
+                if ((sizeof(*msg) + msg->len) > buf_size) {
+                    auto old_buf = std::move(buf);
+                    buf_size = sizeof(*msg) + msg->len;
+                    buf = std::make_unique<char>(buf_size);
+                    memcpy(buf.get(), old_buf.get(), sizeof(*msg));
+                    msg = (struct dm_user_message*)buf.get();
+                }
+
+                if (lseek(block_fd.get(), msg->sector * 512, SEEK_SET) < 0) {
+                    PLOG(ERROR) << "lseek failed: " << device;
+                    return 7;
+                }
+                if (!android::base::ReadFully(block_fd.get(), msg->buf, msg->len)) {
+                    PLOG(ERROR) << "read failed: " << device;
+                    return 7;
+                }
+
+                if (!android::base::WriteFully(ctrl_fd.get(), buf.get(), sizeof(*msg) + msg->len)) {
+                    PLOG(ERROR) << "write control failed";
+                    return 3;
+                }
+                break;
+            }
+
+            case DM_USER_MAP_WRITE:
+                abort();
+                break;
+        }
+
+        LOG(DEBUG) << "read() finished, next message";
+    }
+
+    return 0;
+}
+
+int main([[maybe_unused]] int argc, char** argv) {
+    android::base::InitLogging(argv, &android::base::KernelLogger);
+    daemon_main(argv[1]);
+    return 0;
+}
diff --git a/init/block_dev_initializer.cpp b/init/block_dev_initializer.cpp
index b423f86..8db9793 100644
--- a/init/block_dev_initializer.cpp
+++ b/init/block_dev_initializer.cpp
@@ -37,7 +37,15 @@
 }
 
 bool BlockDevInitializer::InitDeviceMapper() {
-    const std::string dm_path = "/devices/virtual/misc/device-mapper";
+    return InitMiscDevice("device-mapper");
+}
+
+bool BlockDevInitializer::InitDmUser() {
+    return InitMiscDevice("dm-user");
+}
+
+bool BlockDevInitializer::InitMiscDevice(const std::string& name) {
+    const std::string dm_path = "/devices/virtual/misc/" + name;
     bool found = false;
     auto dm_callback = [this, &dm_path, &found](const Uevent& uevent) {
         if (uevent.path == dm_path) {
@@ -49,13 +57,13 @@
     };
     uevent_listener_.RegenerateUeventsForPath("/sys" + dm_path, dm_callback);
     if (!found) {
-        LOG(INFO) << "device-mapper device not found in /sys, waiting for its uevent";
+        LOG(INFO) << name << " device not found in /sys, waiting for its uevent";
         Timer t;
         uevent_listener_.Poll(dm_callback, 10s);
-        LOG(INFO) << "Wait for device-mapper returned after " << t;
+        LOG(INFO) << "Wait for " << name << " returned after " << t;
     }
     if (!found) {
-        LOG(ERROR) << "device-mapper device not found after polling timeout";
+        LOG(ERROR) << name << " device not found after polling timeout";
         return false;
     }
     return true;
diff --git a/init/block_dev_initializer.h b/init/block_dev_initializer.h
index 0d4c6e9..b8dd3f1 100644
--- a/init/block_dev_initializer.h
+++ b/init/block_dev_initializer.h
@@ -27,12 +27,15 @@
     BlockDevInitializer();
 
     bool InitDeviceMapper();
+    bool InitDmUser();
     bool InitDevices(std::set<std::string> devices);
     bool InitDmDevice(const std::string& device);
 
   private:
     ListenerAction HandleUevent(const Uevent& uevent, std::set<std::string>* devices);
 
+    bool InitMiscDevice(const std::string& name);
+
     std::unique_ptr<DeviceHandler> device_handler_;
     UeventListener uevent_listener_;
 };
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index 5805a4d..b9fc82e 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -203,6 +203,7 @@
     { 00755, AID_ROOT,      AID_ROOT,      0, "first_stage_ramdisk/system/bin/e2fsck" },
     { 00755, AID_ROOT,      AID_ROOT,      0, "first_stage_ramdisk/system/bin/tune2fs" },
     { 00755, AID_ROOT,      AID_ROOT,      0, "first_stage_ramdisk/system/bin/resize2fs" },
+    { 00755, AID_ROOT,      AID_ROOT,      0, "first_stage_ramdisk/system/bin/snapuserd" },
     // generic defaults
     { 00755, AID_ROOT,      AID_ROOT,      0, "bin/*" },
     { 00640, AID_ROOT,      AID_SHELL,     0, "fstab.*" },