Merge "Revert "fs_mgr_overlayfs: Revert to use /data only if VAB""
diff --git a/code_coverage/Android.bp b/code_coverage/Android.bp
index 2cb1617..d18e7a8 100644
--- a/code_coverage/Android.bp
+++ b/code_coverage/Android.bp
@@ -24,6 +24,14 @@
},
},
},
+ riscv64: {
+ src: "empty_policy/code_coverage.riscv64.policy",
+ product_variables: {
+ native_coverage: {
+ src: "seccomp_policy/code_coverage.riscv64.policy",
+ },
+ },
+ },
x86: {
src: "empty_policy/code_coverage.x86.policy",
product_variables: {
@@ -67,6 +75,10 @@
},
},
},
+ riscv64: {
+ // riscv64 doesn't have a secondary architecture.
+ enabled: false,
+ },
x86: {
src: "empty_policy/code_coverage.x86_64.policy",
product_variables: {
diff --git a/code_coverage/empty_policy/code_coverage.riscv64.policy b/code_coverage/empty_policy/code_coverage.riscv64.policy
new file mode 100644
index 0000000..9456932
--- /dev/null
+++ b/code_coverage/empty_policy/code_coverage.riscv64.policy
@@ -0,0 +1,2 @@
+# empty unless code_coverage is enabled.
+# code_coverage.riscv64.policy
diff --git a/code_coverage/seccomp_policy/code_coverage.riscv64.policy b/code_coverage/seccomp_policy/code_coverage.riscv64.policy
new file mode 100644
index 0000000..fdb4d1e
--- /dev/null
+++ b/code_coverage/seccomp_policy/code_coverage.riscv64.policy
@@ -0,0 +1,15 @@
+close: 1
+fchmod: 1
+mkdirat: 1
+msync: 1
+munmap: 1
+openat: 1
+write: 1
+fcntl: 1
+fstat: 1
+ftruncate: 1
+geteuid: 1
+lseek: 1
+mmap: 1
+rt_sigreturn: 1
+prctl: 1
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 1c89472..1be69c3 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -461,6 +461,9 @@
arm64: {
src: "seccomp_policy/crash_dump.arm64.policy",
},
+ riscv64: {
+ src: "seccomp_policy/crash_dump.riscv64.policy",
+ },
x86: {
src: "seccomp_policy/crash_dump.x86.policy",
},
diff --git a/debuggerd/crasher/Android.bp b/debuggerd/crasher/Android.bp
index 799163e..effd480 100644
--- a/debuggerd/crasher/Android.bp
+++ b/debuggerd/crasher/Android.bp
@@ -27,6 +27,9 @@
arm64: {
srcs: ["arm64/crashglue.S"],
},
+ riscv64: {
+ srcs: ["riscv64/crashglue.S"],
+ },
x86: {
srcs: ["x86/crashglue.S"],
},
diff --git a/debuggerd/crasher/crasher.cpp b/debuggerd/crasher/crasher.cpp
index 55490b5..4eb7382 100644
--- a/debuggerd/crasher/crasher.cpp
+++ b/debuggerd/crasher/crasher.cpp
@@ -303,6 +303,8 @@
__asm__ volatile(".word 0xe7f0def0\n");
#elif defined(__i386__) || defined(__x86_64__)
__asm__ volatile("ud2\n");
+#elif defined(__riscv)
+ __asm__ volatile("unimp\n");
#else
#error
#endif
diff --git a/debuggerd/crasher/riscv64/crashglue.S b/debuggerd/crasher/riscv64/crashglue.S
new file mode 100644
index 0000000..47dd93b
--- /dev/null
+++ b/debuggerd/crasher/riscv64/crashglue.S
@@ -0,0 +1,45 @@
+
+ .globl crash1
+ .globl crashnostack
+
+crash1:
+ li x0,0xdead0000+0
+ li x1,0xdead0000+1
+ li x2,0xdead0000+2
+ li x3,0xdead0000+3
+ li x4,0xdead0000+4
+ li x5,0xdead0000+5
+ li x6,0xdead0000+6
+ li x7,0xdead0000+7
+ li x8,0xdead0000+8
+ li x9,0xdead0000+9
+ li x10,0xdead0000+10
+ li x11,0xdead0000+11
+ li x12,0xdead0000+12
+ li x13,0xdead0000+13
+ li x14,0xdead0000+14
+ li x15,0xdead0000+15
+ li x16,0xdead0000+16
+ li x17,0xdead0000+17
+ li x18,0xdead0000+18
+ li x19,0xdead0000+19
+ li x20,0xdead0000+20
+ li x21,0xdead0000+21
+ li x22,0xdead0000+22
+ li x23,0xdead0000+23
+ li x24,0xdead0000+24
+ li x25,0xdead0000+25
+ li x26,0xdead0000+26
+ li x27,0xdead0000+27
+ li x28,0xdead0000+28
+ # don't trash the stack otherwise the signal handler won't run
+ #li $29,0xdead0000+29
+ li x30,0xdead0000+30
+ li x31,0xdead0000+31
+
+ j .
+
+
+crashnostack:
+ li sp, 0
+ j .
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index aca476f..c08721b 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -406,10 +406,10 @@
result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x[01]00000000000dead)");
}
-// Marked as weak to prevent the compiler from removing the malloc in the caller. In theory, the
-// compiler could still clobber the argument register before trapping, but that's unlikely.
-__attribute__((weak)) void CrasherTest::Trap(void* ptr ATTRIBUTE_UNUSED) {
- __builtin_trap();
+void CrasherTest::Trap(void* ptr) {
+ void (*volatile f)(void*) = nullptr;
+ __asm__ __volatile__("" : : "r"(f) : "memory");
+ f(ptr);
}
TEST_F(CrasherTest, heap_addr_in_register) {
@@ -828,7 +828,7 @@
StartIntercept(&output_fd);
FinishCrasher();
- AssertDeath(SIGTRAP);
+ AssertDeath(SIGSEGV);
FinishIntercept(&intercept_result);
ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp
index 159ebc8..9a565de 100644
--- a/debuggerd/libdebuggerd/tombstone_proto.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto.cpp
@@ -82,6 +82,8 @@
return Architecture::X86;
#elif defined(__x86_64__)
return Architecture::X86_64;
+#elif defined(__riscv) && (__riscv_xlen == 64)
+ return Architecture::RISCV64;
#else
#error Unknown architecture!
#endif
diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
index 0265641..28154a7 100644
--- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
@@ -47,6 +47,8 @@
return "arm";
case Architecture::ARM64:
return "arm64";
+ case Architecture::RISCV64:
+ return "riscv64";
case Architecture::X86:
return "x86";
case Architecture::X86_64:
@@ -62,6 +64,8 @@
return 4;
case Architecture::ARM64:
return 8;
+ case Architecture::RISCV64:
+ return 8;
case Architecture::X86:
return 4;
case Architecture::X86_64:
@@ -119,6 +123,10 @@
special_registers = {"ip", "lr", "sp", "pc", "pst"};
break;
+ case Architecture::RISCV64:
+ special_registers = {"ra", "sp", "pc"};
+ break;
+
case Architecture::X86:
special_registers = {"ebp", "esp", "eip"};
break;
diff --git a/debuggerd/proto/tombstone.proto b/debuggerd/proto/tombstone.proto
index f0d3d3f..49865a2 100644
--- a/debuggerd/proto/tombstone.proto
+++ b/debuggerd/proto/tombstone.proto
@@ -48,8 +48,9 @@
ARM64 = 1;
X86 = 2;
X86_64 = 3;
+ RISCV64 = 4;
- reserved 4 to 999;
+ reserved 5 to 999;
}
message Signal {
diff --git a/debuggerd/seccomp_policy/crash_dump.riscv64.policy b/debuggerd/seccomp_policy/crash_dump.riscv64.policy
new file mode 100644
index 0000000..21887ab
--- /dev/null
+++ b/debuggerd/seccomp_policy/crash_dump.riscv64.policy
@@ -0,0 +1,37 @@
+read: 1
+write: 1
+exit: 1
+rt_sigreturn: 1
+exit_group: 1
+clock_gettime: 1
+gettimeofday: 1
+futex: 1
+getrandom: 1
+getpid: 1
+gettid: 1
+ppoll: 1
+pipe2: 1
+openat: 1
+dup: 1
+close: 1
+lseek: 1
+getdents64: 1
+faccessat: 1
+recvmsg: 1
+recvfrom: 1
+process_vm_readv: 1
+tgkill: 1
+rt_sigprocmask: 1
+rt_sigaction: 1
+rt_tgsigqueueinfo: 1
+prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41 || arg0 == PR_PAC_RESET_KEYS
+madvise: 1
+mprotect: arg2 in 0x1|0x2
+munmap: 1
+getuid: 1
+fstat: 1
+mmap: arg2 in 0x1|0x2
+geteuid: 1
+getgid: 1
+getegid: 1
+getgroups: 1
diff --git a/debuggerd/seccomp_policy/generate.sh b/debuggerd/seccomp_policy/generate.sh
index 8c58b05..c467d9e 100755
--- a/debuggerd/seccomp_policy/generate.sh
+++ b/debuggerd/seccomp_policy/generate.sh
@@ -6,5 +6,6 @@
CPP='cpp -undef -E -P crash_dump.policy.def'
$CPP -D__arm__ -o crash_dump.arm.policy
$CPP -D__aarch64__ -D__LP64__ -o crash_dump.arm64.policy
+$CPP -D__riscv -D__LP64__ -o crash_dump.riscv64.policy
$CPP -D__i386__ -o crash_dump.x86.policy
$CPP -D__x86_64__ -D__LP64__ -o crash_dump.x86_64.policy
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index cc09d09..ef426dc 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -68,6 +68,8 @@
namespace {
+constexpr char kDataScratchSizeMbProp[] = "fs_mgr.overlayfs.data_scratch_size_mb";
+
bool fs_mgr_access(const std::string& path) {
return access(path.c_str(), F_OK) == 0;
}
@@ -120,13 +122,9 @@
return !stat(path.c_str(), &st) && S_ISDIR(st.st_mode);
}
-// Similar test as overlayfs workdir= validation in the kernel for read-write
-// validation, except we use fs_mgr_work. Covers space and storage issues.
-bool fs_mgr_dir_is_writable(const std::string& path) {
- auto test_directory = path + "/fs_mgr_work";
- rmdir(test_directory.c_str());
- auto ret = !mkdir(test_directory.c_str(), 0700);
- return ret | !rmdir(test_directory.c_str());
+bool fs_mgr_rw_access(const std::string& path) {
+ if (path.empty()) return false;
+ return access(path.c_str(), R_OK | W_OK) == 0;
}
// At less than 1% or 8MB of free space return value of false,
@@ -204,6 +202,24 @@
return (info.feat_ro_compat & EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS) != 0;
}
+#define F2FS_SUPER_OFFSET 1024
+#define F2FS_FEATURE_OFFSET 2180
+#define F2FS_FEATURE_RO 0x4000
+bool fs_mgr_is_read_only_f2fs(const std::string& dev) {
+ if (!fs_mgr_is_f2fs(dev)) return false;
+
+ android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC));
+ if (fd < 0) return false;
+
+ __le32 feat;
+ if ((TEMP_FAILURE_RETRY(lseek64(fd, F2FS_SUPER_OFFSET + F2FS_FEATURE_OFFSET, SEEK_SET)) < 0) ||
+ (TEMP_FAILURE_RETRY(read(fd, &feat, sizeof(feat))) < 0)) {
+ return false;
+ }
+
+ return (feat & cpu_to_le32(F2FS_FEATURE_RO)) != 0;
+}
+
bool fs_mgr_overlayfs_enabled(FstabEntry* entry) {
// readonly filesystem, can not be mount -o remount,rw
// for squashfs, erofs or if free space is (near) zero making such a remount
@@ -218,6 +234,11 @@
return true;
}
+ // f2fs read-only mode doesn't support remount,rw
+ if (fs_mgr_is_read_only_f2fs(entry->blk_device)) {
+ return true;
+ }
+
// check if ext4 de-dupe
auto has_shared_blocks = fs_mgr_has_shared_blocks(entry->mount_point, entry->blk_device);
if (!has_shared_blocks && (entry->mount_point == "/system")) {
@@ -280,7 +301,7 @@
if (!fs_mgr_is_dir(upper)) continue;
auto work = dir + kWorkName;
if (!fs_mgr_is_dir(work)) continue;
- if (!fs_mgr_dir_is_writable(work)) continue;
+ if (!fs_mgr_rw_access(work)) continue;
return dir;
}
return "";
@@ -317,11 +338,6 @@
return "/system";
}
-bool fs_mgr_rw_access(const std::string& path) {
- if (path.empty()) return false;
- return access(path.c_str(), R_OK | W_OK) == 0;
-}
-
constexpr char kOverlayfsFileContext[] = "u:object_r:overlayfs_file:s0";
class AutoSetFsCreateCon final {
@@ -1070,7 +1086,10 @@
return false;
}
if (!images->BackingImageExists(partition_name)) {
- uint64_t size = GetIdealDataScratchSize();
+ auto size = android::base::GetUintProperty<uint64_t>(kDataScratchSizeMbProp, 0) * 1_MiB;
+ if (!size) {
+ size = GetIdealDataScratchSize();
+ }
if (!size) {
size = 2_GiB;
}
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index d5e85e6..474d482 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -173,10 +173,11 @@
"libsnapshot_cow_defaults",
],
srcs: [
- "cow_decompress.cpp",
- "cow_reader.cpp",
- "cow_writer.cpp",
- "cow_format.cpp",
+ "libsnapshot_cow/cow_decompress.cpp",
+ "libsnapshot_cow/cow_reader.cpp",
+ "libsnapshot_cow/cow_writer.cpp",
+ "libsnapshot_cow/cow_format.cpp",
+ "libsnapshot_cow/cow_compress.cpp",
],
host_supported: true,
recovery_available: true,
@@ -424,7 +425,7 @@
"libsnapshot_cow_defaults",
],
srcs: [
- "cow_api_test.cpp",
+ "libsnapshot_cow/cow_api_test.cpp",
],
cflags: [
"-D_FILE_OFFSET_BITS=64",
@@ -546,7 +547,7 @@
shared_libs: [
],
srcs: [
- "inspect_cow.cpp",
+ "libsnapshot_cow/inspect_cow.cpp",
],
}
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
index e7a2f02..19f3649 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
@@ -52,8 +52,9 @@
virtual ~ICowWriter() {}
// Encode an operation that copies the contents of |old_block| to the
- // location of |new_block|.
- bool AddCopy(uint64_t new_block, uint64_t old_block);
+ // location of |new_block|. 'num_blocks' is the number of contiguous
+ // COPY operations from |old_block| to |new_block|.
+ bool AddCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1);
// Encode a sequence of raw blocks. |size| must be a multiple of the block size.
bool AddRawBlocks(uint64_t new_block_start, const void* data, size_t size);
@@ -84,7 +85,7 @@
const CowOptions& options() { return options_; }
protected:
- virtual bool EmitCopy(uint64_t new_block, uint64_t old_block) = 0;
+ virtual bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) = 0;
virtual bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) = 0;
virtual bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size,
uint32_t old_block, uint16_t offset) = 0;
@@ -122,7 +123,7 @@
uint32_t GetCowVersion() { return header_.major_version; }
protected:
- virtual bool EmitCopy(uint64_t new_block, uint64_t old_block) override;
+ virtual bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override;
virtual bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
virtual bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size,
uint32_t old_block, uint16_t offset) override;
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h
index b0be5a5..29828bc 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h
@@ -34,7 +34,7 @@
// Returns true if AddCopy() operations are supported.
MOCK_METHOD(bool, SupportsCopyOperation, (), (const override));
- MOCK_METHOD(bool, EmitCopy, (uint64_t, uint64_t), (override));
+ MOCK_METHOD(bool, EmitCopy, (uint64_t, uint64_t, uint64_t), (override));
MOCK_METHOD(bool, EmitRawBlocks, (uint64_t, const void*, size_t), (override));
MOCK_METHOD(bool, EmitXorBlocks, (uint32_t, const void*, size_t, uint32_t, uint16_t),
(override));
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 34c7baf..cdff06e 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -332,10 +332,13 @@
// Helper function for second stage init to restorecon on the rollback indicator.
static std::string GetGlobalRollbackIndicatorPath();
- // Detach dm-user devices from the current snapuserd, and populate
- // |snapuserd_argv| with the necessary arguments to restart snapuserd
- // and reattach them.
- bool DetachSnapuserdForSelinux(std::vector<std::string>* snapuserd_argv);
+ // Populate |snapuserd_argv| with the necessary arguments to restart snapuserd
+ // after loading selinux policy.
+ bool PrepareSnapuserdArgsForSelinux(std::vector<std::string>* snapuserd_argv);
+
+ // Detach dm-user devices from the first stage snapuserd. Load
+ // new dm-user tables after loading selinux policy.
+ bool DetachFirstStageSnapuserdForSelinux();
// Perform the transition from the selinux stage of snapuserd into the
// second-stage of snapuserd. This process involves re-creating the dm-user
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h
index 545f117..0e3b1db 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h
@@ -74,7 +74,7 @@
bool VerifyMergeOps() const noexcept;
protected:
- bool EmitCopy(uint64_t new_block, uint64_t old_block) override;
+ bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override;
bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block,
uint16_t offset) override;
@@ -113,7 +113,7 @@
bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override;
bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block,
uint16_t offset) override;
- bool EmitCopy(uint64_t new_block, uint64_t old_block) override;
+ bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override;
bool EmitLabel(uint64_t label) override;
bool EmitSequenceData(size_t num_ops, const uint32_t* data) override;
diff --git a/fs_mgr/libsnapshot/cow_api_test.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_api_test.cpp
similarity index 96%
rename from fs_mgr/libsnapshot/cow_api_test.cpp
rename to fs_mgr/libsnapshot/libsnapshot_cow/cow_api_test.cpp
index ba4044f..2c1187f 100644
--- a/fs_mgr/libsnapshot/cow_api_test.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_api_test.cpp
@@ -62,6 +62,48 @@
std::string stream_;
};
+TEST_F(CowTest, CopyContiguous) {
+ CowOptions options;
+ options.cluster_ops = 0;
+ CowWriter writer(options);
+
+ ASSERT_TRUE(writer.Initialize(cow_->fd));
+
+ ASSERT_TRUE(writer.AddCopy(10, 1000, 100));
+ ASSERT_TRUE(writer.Finalize());
+ ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
+
+ CowReader reader;
+ CowHeader header;
+ CowFooter footer;
+ ASSERT_TRUE(reader.Parse(cow_->fd));
+ ASSERT_TRUE(reader.GetHeader(&header));
+ ASSERT_TRUE(reader.GetFooter(&footer));
+ ASSERT_EQ(header.magic, kCowMagicNumber);
+ ASSERT_EQ(header.major_version, kCowVersionMajor);
+ ASSERT_EQ(header.minor_version, kCowVersionMinor);
+ ASSERT_EQ(header.block_size, options.block_size);
+ ASSERT_EQ(footer.op.num_ops, 100);
+
+ auto iter = reader.GetOpIter();
+ ASSERT_NE(iter, nullptr);
+ ASSERT_FALSE(iter->Done());
+
+ size_t i = 0;
+ while (!iter->Done()) {
+ auto op = &iter->Get();
+ ASSERT_EQ(op->type, kCowCopyOp);
+ ASSERT_EQ(op->compression, kCowCompressNone);
+ ASSERT_EQ(op->data_length, 0);
+ ASSERT_EQ(op->new_block, 10 + i);
+ ASSERT_EQ(op->source, 1000 + i);
+ iter->Next();
+ i += 1;
+ }
+
+ ASSERT_EQ(i, 100);
+}
+
TEST_F(CowTest, ReadWrite) {
CowOptions options;
options.cluster_ops = 0;
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
new file mode 100644
index 0000000..e58f45a
--- /dev/null
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
@@ -0,0 +1,98 @@
+//
+// 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 <sys/types.h>
+#include <unistd.h>
+
+#include <limits>
+#include <queue>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+#include <brotli/encode.h>
+#include <libsnapshot/cow_format.h>
+#include <libsnapshot/cow_reader.h>
+#include <libsnapshot/cow_writer.h>
+#include <lz4.h>
+#include <zlib.h>
+
+namespace android {
+namespace snapshot {
+
+std::basic_string<uint8_t> CowWriter::Compress(const void* data, size_t length) {
+ switch (compression_) {
+ case kCowCompressGz: {
+ const auto bound = compressBound(length);
+ std::basic_string<uint8_t> buffer(bound, '\0');
+
+ uLongf dest_len = bound;
+ auto rv = compress2(buffer.data(), &dest_len, reinterpret_cast<const Bytef*>(data),
+ length, Z_BEST_COMPRESSION);
+ if (rv != Z_OK) {
+ LOG(ERROR) << "compress2 returned: " << rv;
+ return {};
+ }
+ buffer.resize(dest_len);
+ return buffer;
+ }
+ case kCowCompressBrotli: {
+ const auto bound = BrotliEncoderMaxCompressedSize(length);
+ if (!bound) {
+ LOG(ERROR) << "BrotliEncoderMaxCompressedSize returned 0";
+ return {};
+ }
+ std::basic_string<uint8_t> buffer(bound, '\0');
+
+ size_t encoded_size = bound;
+ auto rv = BrotliEncoderCompress(
+ BROTLI_DEFAULT_QUALITY, BROTLI_DEFAULT_WINDOW, BROTLI_DEFAULT_MODE, length,
+ reinterpret_cast<const uint8_t*>(data), &encoded_size, buffer.data());
+ if (!rv) {
+ LOG(ERROR) << "BrotliEncoderCompress failed";
+ return {};
+ }
+ buffer.resize(encoded_size);
+ return buffer;
+ }
+ case kCowCompressLz4: {
+ const auto bound = LZ4_compressBound(length);
+ if (!bound) {
+ LOG(ERROR) << "LZ4_compressBound returned 0";
+ return {};
+ }
+ std::basic_string<uint8_t> buffer(bound, '\0');
+
+ const auto compressed_size = LZ4_compress_default(
+ static_cast<const char*>(data), reinterpret_cast<char*>(buffer.data()), length,
+ buffer.size());
+ if (compressed_size <= 0) {
+ LOG(ERROR) << "LZ4_compress_default failed, input size: " << length
+ << ", compression bound: " << bound << ", ret: " << compressed_size;
+ return {};
+ }
+ buffer.resize(compressed_size);
+ return buffer;
+ }
+ default:
+ LOG(ERROR) << "unhandled compression type: " << compression_;
+ break;
+ }
+ return {};
+}
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/cow_decompress.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp
similarity index 100%
rename from fs_mgr/libsnapshot/cow_decompress.cpp
rename to fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp
diff --git a/fs_mgr/libsnapshot/cow_decompress.h b/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.h
similarity index 100%
rename from fs_mgr/libsnapshot/cow_decompress.h
rename to fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.h
diff --git a/fs_mgr/libsnapshot/cow_format.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp
similarity index 100%
rename from fs_mgr/libsnapshot/cow_format.cpp
rename to fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp
diff --git a/fs_mgr/libsnapshot/cow_reader.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
similarity index 100%
rename from fs_mgr/libsnapshot/cow_reader.cpp
rename to fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
diff --git a/fs_mgr/libsnapshot/cow_writer.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp
similarity index 86%
rename from fs_mgr/libsnapshot/cow_writer.cpp
rename to fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp
index 7281fc2..015bff0 100644
--- a/fs_mgr/libsnapshot/cow_writer.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp
@@ -38,11 +38,16 @@
using android::base::borrowed_fd;
using android::base::unique_fd;
-bool ICowWriter::AddCopy(uint64_t new_block, uint64_t old_block) {
- if (!ValidateNewBlock(new_block)) {
- return false;
+bool ICowWriter::AddCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks) {
+ CHECK(num_blocks != 0);
+
+ for (size_t i = 0; i < num_blocks; i++) {
+ if (!ValidateNewBlock(new_block + i)) {
+ return false;
+ }
}
- return EmitCopy(new_block, old_block);
+
+ return EmitCopy(new_block, old_block, num_blocks);
}
bool ICowWriter::AddRawBlocks(uint64_t new_block_start, const void* data, size_t size) {
@@ -286,13 +291,20 @@
return EmitClusterIfNeeded();
}
-bool CowWriter::EmitCopy(uint64_t new_block, uint64_t old_block) {
+bool CowWriter::EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks) {
CHECK(!merge_in_progress_);
- CowOperation op = {};
- op.type = kCowCopyOp;
- op.new_block = new_block;
- op.source = old_block;
- return WriteOperation(op);
+
+ for (size_t i = 0; i < num_blocks; i++) {
+ CowOperation op = {};
+ op.type = kCowCopyOp;
+ op.new_block = new_block + i;
+ op.source = old_block + i;
+ if (!WriteOperation(op)) {
+ return false;
+ }
+ }
+
+ return true;
}
bool CowWriter::EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) {
@@ -404,67 +416,6 @@
return true;
}
-std::basic_string<uint8_t> CowWriter::Compress(const void* data, size_t length) {
- switch (compression_) {
- case kCowCompressGz: {
- const auto bound = compressBound(length);
- std::basic_string<uint8_t> buffer(bound, '\0');
-
- uLongf dest_len = bound;
- auto rv = compress2(buffer.data(), &dest_len, reinterpret_cast<const Bytef*>(data),
- length, Z_BEST_COMPRESSION);
- if (rv != Z_OK) {
- LOG(ERROR) << "compress2 returned: " << rv;
- return {};
- }
- buffer.resize(dest_len);
- return buffer;
- }
- case kCowCompressBrotli: {
- const auto bound = BrotliEncoderMaxCompressedSize(length);
- if (!bound) {
- LOG(ERROR) << "BrotliEncoderMaxCompressedSize returned 0";
- return {};
- }
- std::basic_string<uint8_t> buffer(bound, '\0');
-
- size_t encoded_size = bound;
- auto rv = BrotliEncoderCompress(
- BROTLI_DEFAULT_QUALITY, BROTLI_DEFAULT_WINDOW, BROTLI_DEFAULT_MODE, length,
- reinterpret_cast<const uint8_t*>(data), &encoded_size, buffer.data());
- if (!rv) {
- LOG(ERROR) << "BrotliEncoderCompress failed";
- return {};
- }
- buffer.resize(encoded_size);
- return buffer;
- }
- case kCowCompressLz4: {
- const auto bound = LZ4_compressBound(length);
- if (!bound) {
- LOG(ERROR) << "LZ4_compressBound returned 0";
- return {};
- }
- std::basic_string<uint8_t> buffer(bound, '\0');
-
- const auto compressed_size = LZ4_compress_default(
- static_cast<const char*>(data), reinterpret_cast<char*>(buffer.data()), length,
- buffer.size());
- if (compressed_size <= 0) {
- LOG(ERROR) << "LZ4_compress_default failed, input size: " << length
- << ", compression bound: " << bound << ", ret: " << compressed_size;
- return {};
- }
- buffer.resize(compressed_size);
- return buffer;
- }
- default:
- LOG(ERROR) << "unhandled compression type: " << compression_;
- break;
- }
- return {};
-}
-
// TODO: Fix compilation issues when linking libcrypto library
// when snapuserd is compiled as part of ramdisk.
static void SHA256(const void*, size_t, uint8_t[]) {
diff --git a/fs_mgr/libsnapshot/inspect_cow.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp
similarity index 100%
rename from fs_mgr/libsnapshot/inspect_cow.cpp
rename to fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 59abd6f..6fed09c 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -1746,13 +1746,6 @@
auto misc_name = user_cow_name;
- DmTable table;
- table.Emplace<DmTargetUser>(0, target.spec.length, misc_name);
- if (!dm_.LoadTableAndActivate(user_cow_name, table)) {
- LOG(ERROR) << "Unable to swap tables for " << misc_name;
- continue;
- }
-
std::string source_device_name;
if (snapshot_status.old_partition_size() > 0) {
source_device_name = GetSourceDeviceName(snapshot);
@@ -1780,13 +1773,6 @@
continue;
}
- // Wait for ueventd to acknowledge and create the control device node.
- std::string control_device = "/dev/dm-user/" + misc_name;
- if (!WaitForDevice(control_device, 10s)) {
- LOG(ERROR) << "dm-user control device no found: " << misc_name;
- continue;
- }
-
if (transition == InitTransition::SELINUX_DETACH) {
if (!UpdateUsesUserSnapshots(lock.get())) {
auto message = misc_name + "," + cow_image_device + "," + source_device;
@@ -1804,6 +1790,20 @@
continue;
}
+ DmTable table;
+ table.Emplace<DmTargetUser>(0, target.spec.length, misc_name);
+ if (!dm_.LoadTableAndActivate(user_cow_name, table)) {
+ LOG(ERROR) << "Unable to swap tables for " << misc_name;
+ continue;
+ }
+
+ // Wait for ueventd to acknowledge and create the control device node.
+ std::string control_device = "/dev/dm-user/" + misc_name;
+ if (!WaitForDevice(control_device, 10s)) {
+ LOG(ERROR) << "dm-user control device no found: " << misc_name;
+ continue;
+ }
+
uint64_t base_sectors;
if (!UpdateUsesUserSnapshots(lock.get())) {
base_sectors =
@@ -4136,10 +4136,71 @@
return status.state() != UpdateState::None && status.using_snapuserd();
}
-bool SnapshotManager::DetachSnapuserdForSelinux(std::vector<std::string>* snapuserd_argv) {
+bool SnapshotManager::PrepareSnapuserdArgsForSelinux(std::vector<std::string>* snapuserd_argv) {
return PerformInitTransition(InitTransition::SELINUX_DETACH, snapuserd_argv);
}
+bool SnapshotManager::DetachFirstStageSnapuserdForSelinux() {
+ LOG(INFO) << "Detaching first stage snapuserd";
+
+ auto lock = LockExclusive();
+ if (!lock) return false;
+
+ std::vector<std::string> snapshots;
+ if (!ListSnapshots(lock.get(), &snapshots)) {
+ LOG(ERROR) << "Failed to list snapshots.";
+ return false;
+ }
+
+ size_t num_cows = 0;
+ size_t ok_cows = 0;
+ for (const auto& snapshot : snapshots) {
+ std::string user_cow_name = GetDmUserCowName(snapshot, GetSnapshotDriver(lock.get()));
+
+ if (dm_.GetState(user_cow_name) == DmDeviceState::INVALID) {
+ continue;
+ }
+
+ DeviceMapper::TargetInfo target;
+ if (!GetSingleTarget(user_cow_name, TableQuery::Table, &target)) {
+ continue;
+ }
+
+ auto target_type = DeviceMapper::GetTargetType(target.spec);
+ if (target_type != "user") {
+ LOG(ERROR) << "Unexpected target type for " << user_cow_name << ": " << target_type;
+ continue;
+ }
+
+ num_cows++;
+ auto misc_name = user_cow_name;
+
+ DmTable table;
+ table.Emplace<DmTargetUser>(0, target.spec.length, misc_name);
+ if (!dm_.LoadTableAndActivate(user_cow_name, table)) {
+ LOG(ERROR) << "Unable to swap tables for " << misc_name;
+ continue;
+ }
+
+ // Wait for ueventd to acknowledge and create the control device node.
+ std::string control_device = "/dev/dm-user/" + misc_name;
+ if (!WaitForDevice(control_device, 10s)) {
+ LOG(ERROR) << "dm-user control device no found: " << misc_name;
+ continue;
+ }
+
+ ok_cows++;
+ LOG(INFO) << "control device is ready: " << control_device;
+ }
+
+ if (ok_cows != num_cows) {
+ LOG(ERROR) << "Could not transition all snapuserd consumers.";
+ return false;
+ }
+
+ return true;
+}
+
bool SnapshotManager::PerformSecondStageInitTransition() {
return PerformInitTransition(InitTransition::SECOND_STAGE);
}
diff --git a/fs_mgr/libsnapshot/snapshot_writer.cpp b/fs_mgr/libsnapshot/snapshot_writer.cpp
index 48b7d80..6aad3d1 100644
--- a/fs_mgr/libsnapshot/snapshot_writer.cpp
+++ b/fs_mgr/libsnapshot/snapshot_writer.cpp
@@ -111,8 +111,9 @@
return reader;
}
-bool CompressedSnapshotWriter::EmitCopy(uint64_t new_block, uint64_t old_block) {
- return cow_->AddCopy(new_block, old_block);
+bool CompressedSnapshotWriter::EmitCopy(uint64_t new_block, uint64_t old_block,
+ uint64_t num_blocks) {
+ return cow_->AddCopy(new_block, old_block, num_blocks);
}
bool CompressedSnapshotWriter::EmitRawBlocks(uint64_t new_block_start, const void* data,
@@ -191,19 +192,29 @@
return true;
}
-bool OnlineKernelSnapshotWriter::EmitCopy(uint64_t new_block, uint64_t old_block) {
+bool OnlineKernelSnapshotWriter::EmitCopy(uint64_t new_block, uint64_t old_block,
+ uint64_t num_blocks) {
auto source_fd = GetSourceFd();
if (source_fd < 0) {
return false;
}
- std::string buffer(options_.block_size, 0);
- uint64_t offset = old_block * options_.block_size;
- if (!android::base::ReadFullyAtOffset(source_fd, buffer.data(), buffer.size(), offset)) {
- PLOG(ERROR) << "EmitCopy read";
- return false;
+ CHECK(num_blocks != 0);
+
+ for (size_t i = 0; i < num_blocks; i++) {
+ std::string buffer(options_.block_size, 0);
+ uint64_t offset = (old_block + i) * options_.block_size;
+ if (!android::base::ReadFullyAtOffset(source_fd, buffer.data(), buffer.size(), offset)) {
+ PLOG(ERROR) << "EmitCopy read";
+ return false;
+ }
+ if (!EmitRawBlocks(new_block + i, buffer.data(), buffer.size())) {
+ PLOG(ERROR) << "EmitRawBlocks failed";
+ return false;
+ }
}
- return EmitRawBlocks(new_block, buffer.data(), buffer.size());
+
+ return true;
}
bool OnlineKernelSnapshotWriter::EmitLabel(uint64_t) {
diff --git a/fs_mgr/libsnapshot/utility.cpp b/fs_mgr/libsnapshot/utility.cpp
index 0a1be0d..cadd24d 100644
--- a/fs_mgr/libsnapshot/utility.cpp
+++ b/fs_mgr/libsnapshot/utility.cpp
@@ -153,9 +153,23 @@
}
bool WriteStringToFileAtomic(const std::string& content, const std::string& path) {
- std::string tmp_path = path + ".tmp";
- if (!android::base::WriteStringToFile(content, tmp_path)) {
- return false;
+ const std::string tmp_path = path + ".tmp";
+ {
+ const int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY;
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(tmp_path.c_str(), flags, 0666)));
+ if (fd == -1) {
+ PLOG(ERROR) << "Failed to open " << path;
+ return false;
+ }
+ if (!android::base::WriteStringToFd(content, fd)) {
+ PLOG(ERROR) << "Failed to write to fd " << fd;
+ return false;
+ }
+ // rename() without fsync() is not safe. Data could still be living on page cache. To ensure
+ // atomiticity, call fsync()
+ if (fsync(fd) != 0) {
+ PLOG(ERROR) << "Failed to fsync " << tmp_path;
+ }
}
if (rename(tmp_path.c_str(), path.c_str()) == -1) {
PLOG(ERROR) << "rename failed from " << tmp_path << " to " << path;
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index eba4f6e..68f8152 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -1423,7 +1423,7 @@
is_bootloader_fastboot=true
# cuttlefish?
-[[ "$(get_property ro.product.device)" == vsoc* ]] &&
+[[ "$(get_property ro.product.vendor.device)" == vsoc_* ]] &&
is_bootloader_fastboot=false
is_userspace_fastboot=false
diff --git a/init/Android.bp b/init/Android.bp
index f0e362c..f6f1e8c 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -308,7 +308,7 @@
name: "init_first_stage_cc_defaults",
module_type: "cc_defaults",
config_namespace: "ANDROID",
- bool_variables: ["BOARD_BUILD_SYSTEM_ROOT_IMAGE", "BOARD_USES_RECOVERY_AS_BOOT"],
+ bool_variables: ["BOARD_USES_RECOVERY_AS_BOOT"],
properties: ["installable"],
}
@@ -317,9 +317,6 @@
init_first_stage_cc_defaults {
name: "init_first_stage_defaults",
soong_config_variables: {
- BOARD_BUILD_SYSTEM_ROOT_IMAGE: {
- installable: false,
- },
BOARD_USES_RECOVERY_AS_BOOT: {
installable: false,
},
diff --git a/init/Android.mk b/init/Android.mk
index c08fe03..4b85c15 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -8,11 +8,9 @@
LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
LOCAL_LICENSE_CONDITIONS := notice
LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
-ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
ifneq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
LOCAL_REQUIRED_MODULES := \
init_first_stage \
endif # BOARD_USES_RECOVERY_AS_BOOT
-endif # BOARD_BUILD_SYSTEM_ROOT_IMAGE
include $(BUILD_PHONY_PACKAGE)
diff --git a/init/epoll.cpp b/init/epoll.cpp
index 0580f86..dc21043 100644
--- a/init/epoll.cpp
+++ b/init/epoll.cpp
@@ -54,9 +54,7 @@
}
epoll_event ev;
ev.events = events;
- // std::map's iterators do not get invalidated until erased, so we use the
- // pointer to the std::function in the map directly for epoll_ctl.
- ev.data.ptr = reinterpret_cast<void*>(&it->second);
+ ev.data.fd = fd;
if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &ev) == -1) {
Result<void> result = ErrnoError() << "epoll_ctl failed to add fd";
epoll_handlers_.erase(fd);
@@ -75,6 +73,10 @@
return {};
}
+void Epoll::SetFirstCallback(std::function<void()> first_callback) {
+ first_callback_ = std::move(first_callback);
+}
+
Result<std::vector<std::shared_ptr<Epoll::Handler>>> Epoll::Wait(
std::optional<std::chrono::milliseconds> timeout) {
int timeout_ms = -1;
@@ -87,9 +89,16 @@
if (num_events == -1) {
return ErrnoError() << "epoll_wait failed";
}
+ if (num_events > 0 && first_callback_) {
+ first_callback_();
+ }
std::vector<std::shared_ptr<Handler>> pending_functions;
for (int i = 0; i < num_events; ++i) {
- auto& info = *reinterpret_cast<Info*>(ev[i].data.ptr);
+ const auto it = epoll_handlers_.find(ev[i].data.fd);
+ if (it == epoll_handlers_.end()) {
+ continue;
+ }
+ const Info& info = it->second;
if ((info.events & (EPOLLIN | EPOLLPRI)) == (EPOLLIN | EPOLLPRI) &&
(ev[i].events & EPOLLIN) != ev[i].events) {
// This handler wants to know about exception events, and just got one.
diff --git a/init/epoll.h b/init/epoll.h
index f58ae8d..e26e319 100644
--- a/init/epoll.h
+++ b/init/epoll.h
@@ -42,6 +42,7 @@
Result<void> Open();
Result<void> RegisterHandler(int fd, Handler handler, uint32_t events = EPOLLIN);
Result<void> UnregisterHandler(int fd);
+ void SetFirstCallback(std::function<void()> first_callback);
Result<std::vector<std::shared_ptr<Handler>>> Wait(
std::optional<std::chrono::milliseconds> timeout);
@@ -53,6 +54,7 @@
android::base::unique_fd epoll_fd_;
std::map<int, Info> epoll_handlers_;
+ std::function<void()> first_callback_;
};
} // namespace init
diff --git a/init/epoll_test.cpp b/init/epoll_test.cpp
index 9236cd5..3f8b5a4 100644
--- a/init/epoll_test.cpp
+++ b/init/epoll_test.cpp
@@ -21,6 +21,7 @@
#include <unordered_set>
#include <android-base/file.h>
+#include <android-base/logging.h>
#include <gtest/gtest.h>
namespace android {
@@ -30,14 +31,10 @@
class CatchDtor final {
public:
- CatchDtor() { sValidObjects.emplace(this); }
- CatchDtor(const CatchDtor&) { sValidObjects.emplace(this); }
- ~CatchDtor() {
- auto iter = sValidObjects.find(this);
- if (iter != sValidObjects.end()) {
- sValidObjects.erase(iter);
- }
- }
+ CatchDtor() { CHECK(sValidObjects.emplace(this).second); }
+ CatchDtor(const CatchDtor&) { CHECK(sValidObjects.emplace(this).second); }
+ CatchDtor(const CatchDtor&&) { CHECK(sValidObjects.emplace(this).second); }
+ ~CatchDtor() { CHECK_EQ(sValidObjects.erase(this), size_t{1}); }
};
TEST(epoll, UnregisterHandler) {
@@ -48,11 +45,13 @@
ASSERT_EQ(pipe(fds), 0);
CatchDtor catch_dtor;
- bool handler_invoked;
+ bool handler_invoked = false;
auto handler = [&, catch_dtor]() -> void {
auto result = epoll.UnregisterHandler(fds[0]);
ASSERT_EQ(result.ok(), !handler_invoked);
handler_invoked = true;
+ // The assert statement below verifies that the UnregisterHandler() call
+ // above did not destroy the current std::function<> instance.
ASSERT_NE(sValidObjects.find((void*)&catch_dtor), sValidObjects.end());
};
diff --git a/init/init.cpp b/init/init.cpp
index ce668d7..cd0ee58 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -1061,6 +1061,11 @@
PLOG(FATAL) << result.error();
}
+ // We always reap children before responding to the other pending functions. This is to
+ // prevent a race where other daemons see that a service has exited and ask init to
+ // start it again via ctl.start before init has reaped it.
+ epoll.SetFirstCallback(ReapAnyOutstandingChildren);
+
InstallSignalFdHandler(&epoll);
InstallInitNotifier(&epoll);
StartPropertyService(&property_fd);
@@ -1176,10 +1181,6 @@
if (!pending_functions.ok()) {
LOG(ERROR) << pending_functions.error();
} else if (!pending_functions->empty()) {
- // We always reap children before responding to the other pending functions. This is to
- // prevent a race where other daemons see that a service has exited and ask init to
- // start it again via ctl.start before init has reaped it.
- ReapAnyOutstandingChildren();
for (const auto& function : *pending_functions) {
(*function)();
}
diff --git a/init/snapuserd_transition.cpp b/init/snapuserd_transition.cpp
index 5c821b0..6972f30 100644
--- a/init/snapuserd_transition.cpp
+++ b/init/snapuserd_transition.cpp
@@ -226,12 +226,9 @@
argv_.emplace_back("snapuserd");
argv_.emplace_back("-no_socket");
- if (!sm_->DetachSnapuserdForSelinux(&argv_)) {
+ if (!sm_->PrepareSnapuserdArgsForSelinux(&argv_)) {
LOG(FATAL) << "Could not perform selinux transition";
}
-
- // Make sure the process is gone so we don't have any selinux audits.
- KillFirstStageSnapuserd(old_pid_);
}
void SnapuserdSelinuxHelper::FinishTransition() {
@@ -301,6 +298,12 @@
}
void SnapuserdSelinuxHelper::RelaunchFirstStageSnapuserd() {
+ if (!sm_->DetachFirstStageSnapuserdForSelinux()) {
+ LOG(FATAL) << "Could not perform selinux transition";
+ }
+
+ KillFirstStageSnapuserd(old_pid_);
+
auto fd = GetRamdiskSnapuserdFd();
if (!fd) {
LOG(FATAL) << "Environment variable " << kSnapuserdFirstStageFdVar << " was not set!";
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index fde30ad..b135e57 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -193,6 +193,9 @@
],
},
android: {
+ sanitize: {
+ misc_undefined: ["integer"],
+ },
static_libs: [
"libasync_safe",
],
@@ -209,32 +212,6 @@
],
},
- android_arm: {
- sanitize: {
- misc_undefined: ["integer"],
- },
- },
- android_arm64: {
- sanitize: {
- misc_undefined: ["integer"],
- },
- },
-
- android_x86: {
- // TODO: This is to work around b/29412086.
- // Remove once __mulodi4 is available and move the "sanitize" block
- // to the android target.
- sanitize: {
- misc_undefined: [],
- },
- },
-
- android_x86_64: {
- sanitize: {
- misc_undefined: ["integer"],
- },
- },
-
// qtaguid.cpp loads libnetd_client.so with dlopen(). Since
// the interface of libnetd_client.so may vary between AOSP
// releases, exclude qtaguid.cpp from the VNDK-SP variant.
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index 744710f..35adf36 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -287,7 +287,7 @@
if (cache_type == ResourceCacheType::RCT_TASK &&
fd_[cache_type] == FdCacheHelper::FDS_APP_DEPENDENT) {
// application-dependent path can't be used with tid
- PLOG(ERROR) << "Application profile can't be applied to a thread";
+ LOG(ERROR) << Name() << ": application profile can't be applied to a thread";
return ProfileAction::FAIL;
}
@@ -304,7 +304,7 @@
std::string procs_path = controller()->GetProcsFilePath(path_, uid, pid);
unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(procs_path.c_str(), O_WRONLY | O_CLOEXEC)));
if (tmp_fd < 0) {
- PLOG(WARNING) << "Failed to open " << procs_path;
+ PLOG(WARNING) << Name() << "::" << __func__ << ": failed to open " << procs_path;
return false;
}
if (!AddTidToCgroup(pid, tmp_fd, controller()->name())) {
@@ -325,7 +325,7 @@
std::string tasks_path = controller()->GetTasksFilePath(path_);
unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(tasks_path.c_str(), O_WRONLY | O_CLOEXEC)));
if (tmp_fd < 0) {
- PLOG(WARNING) << "Failed to open " << tasks_path;
+ PLOG(WARNING) << Name() << "::" << __func__ << ": failed to open " << tasks_path;
return false;
}
if (!AddTidToCgroup(tid, tmp_fd, controller()->name())) {
@@ -394,7 +394,7 @@
unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_WRONLY | O_CLOEXEC)));
if (tmp_fd < 0) {
- if (logfailures) PLOG(WARNING) << "Failed to open " << path;
+ if (logfailures) PLOG(WARNING) << Name() << "::" << __func__ << ": failed to open " << path;
return false;
}
@@ -431,7 +431,7 @@
if (cache_type == ResourceCacheType::RCT_TASK &&
fd_[cache_type] == FdCacheHelper::FDS_APP_DEPENDENT) {
// application-dependent path can't be used with tid
- PLOG(ERROR) << "Application profile can't be applied to a thread";
+ LOG(ERROR) << Name() << ": application profile can't be applied to a thread";
return ProfileAction::FAIL;
}
return ProfileAction::UNUSED;
diff --git a/rootdir/etc/public.libraries.wear.txt b/rootdir/etc/public.libraries.wear.txt
index 82196e4..ea1e234 100644
--- a/rootdir/etc/public.libraries.wear.txt
+++ b/rootdir/etc/public.libraries.wear.txt
@@ -10,6 +10,7 @@
libGLESv1_CM.so
libGLESv2.so
libGLESv3.so
+libicu.so
libicui18n.so
libicuuc.so
libjnigraphics.so
diff --git a/trusty/keymaster/TrustyKeymaster.cpp b/trusty/keymaster/TrustyKeymaster.cpp
index e77940a..ac98695 100644
--- a/trusty/keymaster/TrustyKeymaster.cpp
+++ b/trusty/keymaster/TrustyKeymaster.cpp
@@ -178,6 +178,11 @@
ForwardCommand(KM_GENERATE_CSR, request, response);
}
+void TrustyKeymaster::GenerateCsrV2(const GenerateCsrV2Request& request,
+ GenerateCsrV2Response* response) {
+ ForwardCommand(KM_GENERATE_CSR_V2, request, response);
+}
+
void TrustyKeymaster::GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
GetKeyCharacteristicsResponse* response) {
ForwardCommand(KM_GET_KEY_CHARACTERISTICS, request, response);
@@ -285,4 +290,10 @@
return response;
}
+GetHwInfoResponse TrustyKeymaster::GetHwInfo() {
+ GetHwInfoResponse response(message_version());
+ ForwardCommand(KM_GET_HW_INFO, GetHwInfoRequest(message_version()), &response);
+ return response;
+}
+
} // namespace keymaster
diff --git a/trusty/keymaster/include/trusty_keymaster/TrustyKeymaster.h b/trusty/keymaster/include/trusty_keymaster/TrustyKeymaster.h
index 9f4f39b..60d3f87 100644
--- a/trusty/keymaster/include/trusty_keymaster/TrustyKeymaster.h
+++ b/trusty/keymaster/include/trusty_keymaster/TrustyKeymaster.h
@@ -44,6 +44,7 @@
void GenerateKey(const GenerateKeyRequest& request, GenerateKeyResponse* response);
void GenerateRkpKey(const GenerateRkpKeyRequest& request, GenerateRkpKeyResponse* response);
void GenerateCsr(const GenerateCsrRequest& request, GenerateCsrResponse* response);
+ void GenerateCsrV2(const GenerateCsrV2Request& request, GenerateCsrV2Response* response);
void GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
GetKeyCharacteristicsResponse* response);
void ImportKey(const ImportKeyRequest& request, ImportKeyResponse* response);
@@ -67,6 +68,7 @@
ConfigureVendorPatchlevelResponse ConfigureVendorPatchlevel(
const ConfigureVendorPatchlevelRequest& request);
GetRootOfTrustResponse GetRootOfTrust(const GetRootOfTrustRequest& request);
+ GetHwInfoResponse GetHwInfo();
uint32_t message_version() const { return message_version_; }
diff --git a/trusty/keymaster/include/trusty_keymaster/TrustyRemotelyProvisionedComponentDevice.h b/trusty/keymaster/include/trusty_keymaster/TrustyRemotelyProvisionedComponentDevice.h
index d544b51..dbb7fff 100644
--- a/trusty/keymaster/include/trusty_keymaster/TrustyRemotelyProvisionedComponentDevice.h
+++ b/trusty/keymaster/include/trusty_keymaster/TrustyRemotelyProvisionedComponentDevice.h
@@ -46,6 +46,10 @@
DeviceInfo* deviceInfo, ProtectedData* protectedData,
std::vector<uint8_t>* keysToSignMac) override;
+ ScopedAStatus generateCertificateRequestV2(const std::vector<MacedPublicKey>& keysToSign,
+ const std::vector<uint8_t>& challenge,
+ std::vector<uint8_t>* csr) override;
+
private:
std::shared_ptr<::keymaster::TrustyKeymaster> impl_;
};
diff --git a/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h b/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h
index bf0cb70..f767d40 100644
--- a/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h
+++ b/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h
@@ -60,6 +60,8 @@
KM_GENERATE_CSR = (32 << KEYMASTER_REQ_SHIFT),
KM_CONFIGURE_VENDOR_PATCHLEVEL = (33 << KEYMASTER_REQ_SHIFT),
KM_GET_ROOT_OF_TRUST = (34 << KEYMASTER_REQ_SHIFT),
+ KM_GET_HW_INFO = (35 << KEYMASTER_REQ_SHIFT),
+ KM_GENERATE_CSR_V2 = (36 << KEYMASTER_REQ_SHIFT),
// Bootloader/provisioning calls.
KM_SET_BOOT_PARAMS = (0x1000 << KEYMASTER_REQ_SHIFT),
diff --git a/trusty/keymaster/keymint/TrustyRemotelyProvisionedComponentDevice.cpp b/trusty/keymaster/keymint/TrustyRemotelyProvisionedComponentDevice.cpp
index 099f189..c6800cd 100644
--- a/trusty/keymaster/keymint/TrustyRemotelyProvisionedComponentDevice.cpp
+++ b/trusty/keymaster/keymint/TrustyRemotelyProvisionedComponentDevice.cpp
@@ -28,9 +28,14 @@
using keymaster::GenerateCsrRequest;
using keymaster::GenerateCsrResponse;
+using keymaster::GenerateCsrV2Request;
+using keymaster::GenerateCsrV2Response;
using keymaster::GenerateRkpKeyRequest;
using keymaster::GenerateRkpKeyResponse;
+using keymaster::GetHwInfoRequest;
+using keymaster::GetHwInfoResponse;
using keymaster::KeymasterBlob;
+using km_utils::kmError2ScopedAStatus;
using ::std::string;
using ::std::unique_ptr;
using ::std::vector;
@@ -71,10 +76,15 @@
} // namespace
ScopedAStatus TrustyRemotelyProvisionedComponentDevice::getHardwareInfo(RpcHardwareInfo* info) {
- info->versionNumber = 2;
- info->rpcAuthorName = "Google";
- info->supportedEekCurve = RpcHardwareInfo::CURVE_25519;
- info->uniqueId = "Trusty: My password is ******";
+ GetHwInfoResponse response = impl_->GetHwInfo();
+ if (response.error != KM_ERROR_OK) {
+ return Status(-static_cast<int32_t>(response.error), "Failed to get hardware info.");
+ }
+
+ info->versionNumber = response.version;
+ info->rpcAuthorName = std::move(response.rpcAuthorName);
+ info->supportedEekCurve = response.supportedEekCurve;
+ info->uniqueId = std::move(response.uniqueId);
return ScopedAStatus::ok();
}
@@ -118,4 +128,25 @@
return ScopedAStatus::ok();
}
+ScopedAStatus TrustyRemotelyProvisionedComponentDevice::generateCertificateRequestV2(
+ const std::vector<MacedPublicKey>& keysToSign, const std::vector<uint8_t>& challenge,
+ std::vector<uint8_t>* csr) {
+ GenerateCsrV2Request request(impl_->message_version());
+ if (!request.InitKeysToSign(keysToSign.size())) {
+ return kmError2ScopedAStatus(static_cast<keymaster_error_t>(STATUS_FAILED));
+ }
+ for (size_t i = 0; i < keysToSign.size(); i++) {
+ request.SetKeyToSign(i, keysToSign[i].macedKey.data(), keysToSign[i].macedKey.size());
+ }
+ request.SetChallenge(challenge.data(), challenge.size());
+ GenerateCsrV2Response response(impl_->message_version());
+ impl_->GenerateCsrV2(request, &response);
+
+ if (response.error != KM_ERROR_OK) {
+ return Status(-static_cast<int32_t>(response.error), "Failure in CSR v2 generation.");
+ }
+ *csr = km_utils::kmBlob2vector(response.csr);
+ return ScopedAStatus::ok();
+}
+
} // namespace aidl::android::hardware::security::keymint::trusty
diff --git a/trusty/keymaster/keymint/android.hardware.security.keymint-service.trusty.xml b/trusty/keymaster/keymint/android.hardware.security.keymint-service.trusty.xml
index 0b995a2..77dc854 100644
--- a/trusty/keymaster/keymint/android.hardware.security.keymint-service.trusty.xml
+++ b/trusty/keymaster/keymint/android.hardware.security.keymint-service.trusty.xml
@@ -14,7 +14,7 @@
</hal>
<hal format="aidl">
<name>android.hardware.security.keymint</name>
- <version>2</version>
+ <version>3</version>
<fqname>IRemotelyProvisionedComponent/default</fqname>
</hal>
</manifest>
diff --git a/trusty/storage/interface/include/trusty/interface/storage.h b/trusty/storage/interface/include/trusty/interface/storage.h
index 255ade1..3291607 100644
--- a/trusty/storage/interface/include/trusty/interface/storage.h
+++ b/trusty/storage/interface/include/trusty/interface/storage.h
@@ -53,6 +53,8 @@
/* transaction support */
STORAGE_END_TRANSACTION = 9 << STORAGE_REQ_SHIFT,
+
+ STORAGE_FILE_GET_MAX_SIZE = 12 << STORAGE_REQ_SHIFT,
};
/**
@@ -184,6 +186,24 @@
};
/**
+ * struct storage_file_get_max_size_req - request format for
+ * STORAGE_FILE_GET_MAX_SIZE
+ * @handle: the handle for the file whose max size is requested
+ */
+struct storage_file_get_max_size_req {
+ uint32_t handle;
+};
+
+/**
+ * struct storage_file_get_max_size_resp - response format for
+ * STORAGE_FILE_GET_MAX_SIZE
+ * @max_size: the maximum size of the file
+ */
+struct storage_file_get_max_size_resp {
+ uint64_t max_size;
+};
+
+/**
* struct storage_file_read_req - request format for STORAGE_FILE_READ
* @handle: the handle for the file from which to read
* @size: the quantity of bytes to read from the file