Merge changes I49495684,I0db2e0f4,I07bb811b

* changes:
  init: Initiate other misc devices from BlockDevInitializer.
  Allow snapuserd to be included in the initial ramdisk.
  Add experimental daemon for handling dm-user requests.
This commit is contained in:
David Anderson 2020-07-24 19:18:45 +00:00 committed by Gerrit Code Review
commit 67665a4571
6 changed files with 176 additions and 4 deletions

View file

@ -42,6 +42,7 @@ cc_library_static {
enabled: false,
},
},
ramdisk_available: true,
}
filegroup {

View file

@ -310,3 +310,36 @@ cc_test {
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: [],
}

View file

@ -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;
}

View file

@ -37,7 +37,15 @@ BlockDevInitializer::BlockDevInitializer() : uevent_listener_(16 * 1024 * 1024)
}
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 @@ bool BlockDevInitializer::InitDeviceMapper() {
};
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;

View file

@ -27,12 +27,15 @@ class BlockDevInitializer final {
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_;
};

View file

@ -203,6 +203,7 @@ static const struct fs_path_config android_files[] = {
{ 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.*" },