Merge "Gatekeeper: Add missing user_id."
diff --git a/debuggerd/proto/tombstone.proto b/debuggerd/proto/tombstone.proto
index 38a06f4..2c7156b 100644
--- a/debuggerd/proto/tombstone.proto
+++ b/debuggerd/proto/tombstone.proto
@@ -3,6 +3,9 @@
option java_package = "com.android.server.os";
option java_outer_classname = "TombstoneProtos";
+// NOTE TO OEMS:
+// If you add custom fields to this proto, do not use numbers in the reserved range.
+
message Tombstone {
Architecture arch = 1;
string build_fingerprint = 2;
@@ -24,6 +27,8 @@
repeated MemoryMapping memory_mappings = 17;
repeated LogBuffer log_buffers = 18;
repeated FD open_fds = 19;
+
+ reserved 20 to 999;
}
enum Architecture {
@@ -31,6 +36,8 @@
ARM64 = 1;
X86 = 2;
X86_64 = 3;
+
+ reserved 4 to 999;
}
message Signal {
@@ -46,15 +53,21 @@
bool has_fault_address = 8;
uint64 fault_address = 9;
+
+ reserved 10 to 999;
}
message Cause {
string human_readable = 1;
+
+ reserved 2 to 999;
}
message Register {
string name = 1;
uint64 u64 = 2;
+
+ reserved 3 to 999;
}
message Thread {
@@ -63,6 +76,8 @@
repeated Register registers = 3;
repeated BacktraceFrame current_backtrace = 4;
repeated MemoryDump memory_dump = 5;
+
+ reserved 6 to 999;
}
message BacktraceFrame {
@@ -76,6 +91,8 @@
string file_name = 6;
uint64 file_map_offset = 7;
string build_id = 8;
+
+ reserved 9 to 999;
}
message MemoryDump {
@@ -83,6 +100,8 @@
string mapping_name = 2;
uint64 begin_address = 3;
bytes memory = 4;
+
+ reserved 5 to 999;
}
message MemoryMapping {
@@ -97,6 +116,8 @@
string mapping_name = 7;
string build_id = 8;
uint64 load_bias = 9;
+
+ reserved 10 to 999;
}
message FD {
@@ -104,11 +125,15 @@
string path = 2;
string owner = 3;
uint64 tag = 4;
+
+ reserved 5 to 999;
}
message LogBuffer {
string name = 1;
repeated LogMessage logs = 2;
+
+ reserved 3 to 999;
}
message LogMessage {
@@ -118,4 +143,6 @@
uint32 priority = 4;
string tag = 5;
string message = 6;
+
+ reserved 7 to 999;
}
diff --git a/fs_mgr/libfiemap/fiemap_writer.cpp b/fs_mgr/libfiemap/fiemap_writer.cpp
index 621031a..8acb885 100644
--- a/fs_mgr/libfiemap/fiemap_writer.cpp
+++ b/fs_mgr/libfiemap/fiemap_writer.cpp
@@ -52,7 +52,7 @@
static constexpr const uint32_t kUnsupportedExtentFlags =
FIEMAP_EXTENT_UNKNOWN | FIEMAP_EXTENT_UNWRITTEN | FIEMAP_EXTENT_DELALLOC |
FIEMAP_EXTENT_NOT_ALIGNED | FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_DATA_TAIL |
- FIEMAP_EXTENT_UNWRITTEN | FIEMAP_EXTENT_SHARED | FIEMAP_EXTENT_MERGED;
+ FIEMAP_EXTENT_UNWRITTEN | FIEMAP_EXTENT_SHARED;
// Large file support must be enabled.
static_assert(sizeof(off_t) == sizeof(uint64_t));
diff --git a/fs_mgr/libsnapshot/cow_reader.cpp b/fs_mgr/libsnapshot/cow_reader.cpp
index 75c05d1..cf9f6ea 100644
--- a/fs_mgr/libsnapshot/cow_reader.cpp
+++ b/fs_mgr/libsnapshot/cow_reader.cpp
@@ -237,6 +237,7 @@
[](CowOperation& op) { return IsMetadataOp(op); }),
ops_.get()->end());
+ set_total_data_ops(ops_->size());
// We will re-arrange the vector in such a way that
// kernel can batch merge. Ex:
//
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
index 62b54f9..1de7473 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
@@ -142,6 +142,10 @@
void InitializeMerge();
+ void set_total_data_ops(uint64_t size) { total_data_ops_ = size; }
+
+ uint64_t total_data_ops() { return total_data_ops_; }
+
private:
bool ParseOps(std::optional<uint64_t> label);
@@ -152,6 +156,7 @@
uint64_t fd_size_;
std::optional<uint64_t> last_label_;
std::shared_ptr<std::vector<CowOperation>> ops_;
+ uint64_t total_data_ops_;
};
} // namespace snapshot
diff --git a/fs_mgr/libsnapshot/snapuserd.cpp b/fs_mgr/libsnapshot/snapuserd.cpp
index 0a02bd0..d620300 100644
--- a/fs_mgr/libsnapshot/snapuserd.cpp
+++ b/fs_mgr/libsnapshot/snapuserd.cpp
@@ -424,6 +424,7 @@
}
SNAP_LOG(DEBUG) << "Merge success: " << merged_ops_cur_iter << "chunk: " << chunk;
+ merge_initiated_ = true;
return true;
}
@@ -445,6 +446,19 @@
return next_chunk;
}
+void Snapuserd::CheckMergeCompletionStatus() {
+ CowHeader header;
+
+ if (merge_initiated_) {
+ reader_->GetHeader(&header);
+ SNAP_LOG(INFO) << "Merge-status: Total-Merged-ops: " << header.num_merge_ops
+ << " Total-data-ops: " << reader_->total_data_ops();
+ } else {
+ SNAP_LOG(INFO) << "Merge was not initiated. Total-Merged-ops: " << header.num_merge_ops
+ << " Total-data-ops: " << reader_->total_data_ops();
+ }
+}
+
/*
* Read the metadata from COW device and
* construct the metadata as required by the kernel.
@@ -818,11 +832,13 @@
<< " Num Sector: " << ChunkToSector(data_chunk_id)
<< " Replace-ops: " << replace_ops << " Zero-ops: " << zero_ops
<< " Copy-ops: " << copy_ops << " Areas: " << vec_.size()
- << " Num-ops-merged: " << header.num_merge_ops;
+ << " Num-ops-merged: " << header.num_merge_ops
+ << " Total-data-ops: " << reader_->total_data_ops();
// Total number of sectors required for creating dm-user device
num_sectors_ = ChunkToSector(data_chunk_id);
metadata_read_done_ = true;
+ merge_initiated_ = false;
return true;
}
diff --git a/fs_mgr/libsnapshot/snapuserd.h b/fs_mgr/libsnapshot/snapuserd.h
index dba3186..518d08b 100644
--- a/fs_mgr/libsnapshot/snapuserd.h
+++ b/fs_mgr/libsnapshot/snapuserd.h
@@ -70,6 +70,7 @@
const std::string& GetMiscName() { return misc_name_; }
uint64_t GetNumSectors() { return num_sectors_; }
bool IsAttached() const { return ctrl_fd_ >= 0; }
+ void CheckMergeCompletionStatus();
void CloseFds() {
ctrl_fd_ = {};
cow_fd_ = {};
@@ -141,6 +142,7 @@
std::map<sector_t, const CowOperation*> chunk_map_;
bool metadata_read_done_ = false;
+ bool merge_initiated_ = false;
BufferSink bufsink_;
};
diff --git a/fs_mgr/libsnapshot/snapuserd_server.cpp b/fs_mgr/libsnapshot/snapuserd_server.cpp
index 68a00a0..017de3b 100644
--- a/fs_mgr/libsnapshot/snapuserd_server.cpp
+++ b/fs_mgr/libsnapshot/snapuserd_server.cpp
@@ -214,6 +214,7 @@
auto misc_name = handler->misc_name();
LOG(INFO) << "Handler thread about to exit: " << misc_name;
+ handler->snapuserd()->CheckMergeCompletionStatus();
{
std::lock_guard<std::mutex> lock(lock_);
diff --git a/libcutils/trace-dev.inc b/libcutils/trace-dev.inc
index 6543426..80205bc 100644
--- a/libcutils/trace-dev.inc
+++ b/libcutils/trace-dev.inc
@@ -21,6 +21,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <fnmatch.h>
#include <limits.h>
#include <pthread.h>
#include <stdatomic.h>
@@ -116,7 +117,7 @@
for (int i = 0; i < count; i++) {
snprintf(buf, sizeof(buf), "debug.atrace.app_%d", i);
property_get(buf, value, "");
- if (strcmp(value, "*") == 0 || strcmp(value, cmdline) == 0) {
+ if (fnmatch(value, cmdline, FNM_NOESCAPE) == 0) {
return true;
}
}
diff --git a/libprocessgroup/include/processgroup/processgroup.h b/libprocessgroup/include/processgroup/processgroup.h
index 1cadc9f..1aaed7b 100644
--- a/libprocessgroup/include/processgroup/processgroup.h
+++ b/libprocessgroup/include/processgroup/processgroup.h
@@ -36,7 +36,8 @@
static constexpr const char* CGROUPS_RC_PATH = "/dev/cgroup_info/cgroup.rc";
// Path to test against for freezer support
-static constexpr const char* CGROUP_FREEZE_PATH = "/sys/fs/cgroup/freezer/cgroup.freeze";
+// TODO: remove and replace with a function call, see http://b/180056337
+static constexpr const char* CGROUP_FREEZE_PATH = "/sys/fs/cgroup/uid_0/cgroup.freeze";
bool UsePerAppMemcg();
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index d669ebe..209ccd9 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -131,13 +131,25 @@
return StringPrintf("%s/uid_%d/pid_%d", cgroup, uid, pid);
}
-static int RemoveProcessGroup(const char* cgroup, uid_t uid, int pid) {
- int ret;
-
+static int RemoveProcessGroup(const char* cgroup, uid_t uid, int pid, unsigned int retries) {
+ int ret = 0;
auto uid_pid_path = ConvertUidPidToPath(cgroup, uid, pid);
- ret = rmdir(uid_pid_path.c_str());
-
auto uid_path = ConvertUidToPath(cgroup, uid);
+
+ if (retries == 0) {
+ retries = 1;
+ }
+
+ while (retries--) {
+ ret = rmdir(uid_pid_path.c_str());
+ if (!ret || errno != EBUSY) break;
+ std::this_thread::sleep_for(5ms);
+ }
+
+ // With the exception of boot or shutdown, system uid_ folders are always populated. Spinning
+ // here would needlessly delay most pid removals. Additionally, once empty a uid_ cgroup won't
+ // have processes hanging on it (we've already spun for all its pid_), so there's no need to
+ // spin anyway.
rmdir(uid_path.c_str());
return ret;
@@ -176,7 +188,7 @@
std::vector<std::string> cgroups;
std::string path;
- if (CgroupGetControllerPath("cpuacct", &path)) {
+ if (CgroupGetControllerPath(CGROUPV2_CONTROLLER_NAME, &path)) {
cgroups.push_back(path);
}
if (CgroupGetControllerPath("memory", &path)) {
@@ -212,19 +224,49 @@
}
}
+/**
+ * Process groups are primarily created by the Zygote, meaning that uid/pid groups are created by
+ * the user root. Ownership for the newly created cgroup and all of its files must thus be
+ * transferred for the user/group passed as uid/gid before system_server can properly access them.
+ */
static bool MkdirAndChown(const std::string& path, mode_t mode, uid_t uid, gid_t gid) {
if (mkdir(path.c_str(), mode) == -1 && errno != EEXIST) {
return false;
}
- if (chown(path.c_str(), uid, gid) == -1) {
- int saved_errno = errno;
- rmdir(path.c_str());
- errno = saved_errno;
- return false;
+ auto dir = std::unique_ptr<DIR, decltype(&closedir)>(opendir(path.c_str()), closedir);
+
+ if (dir == NULL) {
+ PLOG(ERROR) << "opendir failed for " << path;
+ goto err;
+ }
+
+ struct dirent* dir_entry;
+ while ((dir_entry = readdir(dir.get()))) {
+ if (!strcmp("..", dir_entry->d_name)) {
+ continue;
+ }
+
+ std::string file_path = path + "/" + dir_entry->d_name;
+
+ if (lchown(file_path.c_str(), uid, gid) < 0) {
+ PLOG(ERROR) << "lchown failed for " << file_path;
+ goto err;
+ }
+
+ if (fchmodat(AT_FDCWD, file_path.c_str(), mode, AT_SYMLINK_NOFOLLOW) != 0) {
+ PLOG(ERROR) << "fchmodat failed for " << file_path;
+ goto err;
+ }
}
return true;
+err:
+ int saved_errno = errno;
+ rmdir(path.c_str());
+ errno = saved_errno;
+
+ return false;
}
// Returns number of processes killed on success
@@ -302,17 +344,9 @@
static int KillProcessGroup(uid_t uid, int initialPid, int signal, int retries,
int* max_processes) {
- std::string cpuacct_path;
- std::string memory_path;
-
- CgroupGetControllerPath("cpuacct", &cpuacct_path);
- CgroupGetControllerPath("memory", &memory_path);
- memory_path += "/apps";
-
- const char* cgroup =
- (!access(ConvertUidPidToPath(cpuacct_path.c_str(), uid, initialPid).c_str(), F_OK))
- ? cpuacct_path.c_str()
- : memory_path.c_str();
+ std::string hierarchy_root_path;
+ CgroupGetControllerPath(CGROUPV2_CONTROLLER_NAME, &hierarchy_root_path);
+ const char* cgroup = hierarchy_root_path.c_str();
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
@@ -355,7 +389,17 @@
LOG(INFO) << "Successfully killed process cgroup uid " << uid << " pid " << initialPid
<< " in " << static_cast<int>(ms) << "ms";
}
- return RemoveProcessGroup(cgroup, uid, initialPid);
+
+ int err = RemoveProcessGroup(cgroup, uid, initialPid, retries);
+
+ if (isMemoryCgroupSupported() && UsePerAppMemcg()) {
+ std::string memory_path;
+ CgroupGetControllerPath("memory", &memory_path);
+ memory_path += "/apps";
+ if (RemoveProcessGroup(memory_path.c_str(), uid, initialPid, retries)) return -1;
+ }
+
+ return err;
} else {
if (retries > 0) {
LOG(ERROR) << "Failed to kill process cgroup uid " << uid << " pid " << initialPid
@@ -374,25 +418,30 @@
return KillProcessGroup(uid, initialPid, signal, 0 /*retries*/, max_processes);
}
-int createProcessGroup(uid_t uid, int initialPid, bool memControl) {
- std::string cgroup;
- if (isMemoryCgroupSupported() && (memControl || UsePerAppMemcg())) {
- CgroupGetControllerPath("memory", &cgroup);
- cgroup += "/apps";
- } else {
- CgroupGetControllerPath("cpuacct", &cgroup);
- }
-
+static int createProcessGroupInternal(uid_t uid, int initialPid, std::string cgroup) {
auto uid_path = ConvertUidToPath(cgroup.c_str(), uid);
- if (!MkdirAndChown(uid_path, 0750, AID_SYSTEM, AID_SYSTEM)) {
+ struct stat cgroup_stat;
+ mode_t cgroup_mode = 0750;
+ gid_t cgroup_uid = AID_SYSTEM;
+ uid_t cgroup_gid = AID_SYSTEM;
+
+ if (stat(cgroup.c_str(), &cgroup_stat) == 1) {
+ PLOG(ERROR) << "Failed to get stats for " << cgroup;
+ } else {
+ cgroup_mode = cgroup_stat.st_mode;
+ cgroup_uid = cgroup_stat.st_uid;
+ cgroup_gid = cgroup_stat.st_gid;
+ }
+
+ if (!MkdirAndChown(uid_path, cgroup_mode, cgroup_uid, cgroup_gid)) {
PLOG(ERROR) << "Failed to make and chown " << uid_path;
return -errno;
}
auto uid_pid_path = ConvertUidPidToPath(cgroup.c_str(), uid, initialPid);
- if (!MkdirAndChown(uid_pid_path, 0750, AID_SYSTEM, AID_SYSTEM)) {
+ if (!MkdirAndChown(uid_pid_path, cgroup_mode, cgroup_uid, cgroup_gid)) {
PLOG(ERROR) << "Failed to make and chown " << uid_pid_path;
return -errno;
}
@@ -408,6 +457,27 @@
return ret;
}
+int createProcessGroup(uid_t uid, int initialPid, bool memControl) {
+ std::string cgroup;
+
+ if (memControl && !UsePerAppMemcg()) {
+ PLOG(ERROR) << "service memory controls are used without per-process memory cgroup support";
+ return -EINVAL;
+ }
+
+ if (isMemoryCgroupSupported() && UsePerAppMemcg()) {
+ CgroupGetControllerPath("memory", &cgroup);
+ cgroup += "/apps";
+ int ret = createProcessGroupInternal(uid, initialPid, cgroup);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
+ CgroupGetControllerPath(CGROUPV2_CONTROLLER_NAME, &cgroup);
+ return createProcessGroupInternal(uid, initialPid, cgroup);
+}
+
static bool SetProcessGroupValue(int tid, const std::string& attr_name, int64_t value) {
if (!isMemoryCgroupSupported()) {
PLOG(ERROR) << "Memcg is not mounted.";
diff --git a/libprocessgroup/profiles/cgroups.json b/libprocessgroup/profiles/cgroups.json
index 5b7a28a..7bcb94b 100644
--- a/libprocessgroup/profiles/cgroups.json
+++ b/libprocessgroup/profiles/cgroups.json
@@ -15,11 +15,6 @@
"GID": "system"
},
{
- "Controller": "cpuacct",
- "Path": "/acct",
- "Mode": "0555"
- },
- {
"Controller": "cpuset",
"Path": "/dev/cpuset",
"Mode": "0755",
diff --git a/libprocessgroup/profiles/cgroups.recovery.json b/libprocessgroup/profiles/cgroups.recovery.json
index f0bf5fd..e275252 100644
--- a/libprocessgroup/profiles/cgroups.recovery.json
+++ b/libprocessgroup/profiles/cgroups.recovery.json
@@ -1,9 +1,8 @@
{
- "Cgroups": [
- {
- "Controller": "cpuacct",
- "Path": "/acct",
- "Mode": "0555"
- }
- ]
+ "Cgroups2": {
+ "Path": "/sys/fs/cgroup",
+ "Mode": "0755",
+ "UID": "root",
+ "GID": "root"
+ }
}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 3cabecc..863cf6c 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -655,6 +655,7 @@
mkdir /data/apex 0755 root system encryption=None
mkdir /data/apex/active 0755 root system
mkdir /data/apex/backup 0700 root system
+ mkdir /data/apex/decompressed 0700 root system encryption=Require
mkdir /data/apex/hashtree 0700 root system
mkdir /data/apex/sessions 0700 root system
mkdir /data/app-staging 0751 system system encryption=DeleteIfNecessary
diff --git a/trusty/confirmationui/Android.bp b/trusty/confirmationui/Android.bp
index 60e0e71..09d48ad 100644
--- a/trusty/confirmationui/Android.bp
+++ b/trusty/confirmationui/Android.bp
@@ -54,6 +54,7 @@
"android.hardware.confirmationui@1.0",
"android.hardware.keymaster@4.0",
"libbase",
+ "libdmabufheap",
"libhidlbase",
"libteeui_hal_support",
"libtrusty",
@@ -92,4 +93,4 @@
"-Werror",
"-DTEEUI_USE_STD_VECTOR",
],
-}
\ No newline at end of file
+}
diff --git a/trusty/confirmationui/TrustyApp.cpp b/trusty/confirmationui/TrustyApp.cpp
index e4c68f9..0e84b19 100644
--- a/trusty/confirmationui/TrustyApp.cpp
+++ b/trusty/confirmationui/TrustyApp.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2020, The Android Open Source Project
+ * Copyright 2021, 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.
@@ -15,140 +15,155 @@
*/
#include "TrustyApp.h"
+#include "TrustyIpc.h"
+#include <BufferAllocator/BufferAllocator.h>
#include <android-base/logging.h>
+#include <sys/mman.h>
#include <sys/uio.h>
#include <trusty/tipc.h>
+#define countof(arr) (sizeof(arr) / sizeof(arr[0]))
+
namespace android {
namespace trusty {
-// 0x1000 is the message buffer size but we need to leave some space for a protocol header.
-// This assures that packets can always be read/written in one read/write operation.
-static constexpr const uint32_t kPacketSize = 0x1000 - 32;
+using ::android::base::unique_fd;
-enum class PacketType : uint32_t {
- SND,
- RCV,
- ACK,
-};
-
-struct PacketHeader {
- PacketType type;
- uint32_t remaining;
-};
-
-const char* toString(PacketType t) {
- switch (t) {
- case PacketType::SND:
- return "SND";
- case PacketType::RCV:
- return "RCV";
- case PacketType::ACK:
- return "ACK";
- default:
- return "UNKNOWN";
- }
+static inline uintptr_t RoundPageUp(uintptr_t val) {
+ return (val + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
}
-static constexpr const uint32_t kHeaderSize = sizeof(PacketHeader);
-static constexpr const uint32_t kPayloadSize = kPacketSize - kHeaderSize;
+ssize_t TrustyApp::TrustyRpc(const uint8_t* obegin, const uint8_t* oend, uint8_t* ibegin,
+ uint8_t* iend) {
+ uint32_t olen = oend - obegin;
-ssize_t TrustyRpc(int handle, const uint8_t* obegin, const uint8_t* oend, uint8_t* ibegin,
- uint8_t* iend) {
- while (obegin != oend) {
- PacketHeader header = {
- .type = PacketType::SND,
- .remaining = uint32_t(oend - obegin),
- };
- uint32_t body_size = std::min(kPayloadSize, header.remaining);
- iovec iov[] = {
- {
- .iov_base = &header,
- .iov_len = kHeaderSize,
- },
- {
- .iov_base = const_cast<uint8_t*>(obegin),
- .iov_len = body_size,
- },
- };
- int rc = writev(handle, iov, 2);
- if (!rc) {
- PLOG(ERROR) << "Error sending SND message. " << rc;
- return rc;
- }
-
- obegin += body_size;
-
- rc = read(handle, &header, kHeaderSize);
- if (!rc) {
- PLOG(ERROR) << "Error reading ACK. " << rc;
- return rc;
- }
-
- if (header.type != PacketType::ACK || header.remaining != oend - obegin) {
- LOG(ERROR) << "malformed ACK";
- return -1;
- }
+ if (olen > shm_len_) {
+ LOG(ERROR) << AT << "request message too long to fit in shared memory";
+ return -1;
}
- ssize_t remaining = 0;
- auto begin = ibegin;
- do {
- PacketHeader header = {
- .type = PacketType::RCV,
- .remaining = 0,
- };
+ memcpy(shm_base_, obegin, olen);
- iovec iov[] = {
- {
- .iov_base = &header,
- .iov_len = kHeaderSize,
- },
- {
- .iov_base = begin,
- .iov_len = uint32_t(iend - begin),
- },
- };
+ confirmationui_hdr hdr = {
+ .cmd = CONFIRMATIONUI_CMD_MSG,
+ };
+ confirmationui_msg_args args = {
+ .msg_len = olen,
+ };
+ iovec iov[] = {
+ {
+ .iov_base = &hdr,
+ .iov_len = sizeof(hdr),
+ },
+ {
+ .iov_base = &args,
+ .iov_len = sizeof(args),
+ },
+ };
- ssize_t rc = writev(handle, iov, 1);
- if (!rc) {
- PLOG(ERROR) << "Error sending RCV message. " << rc;
- return rc;
- }
+ int rc = tipc_send(handle_, iov, countof(iov), NULL, 0);
+ if (rc != static_cast<int>(sizeof(hdr) + sizeof(args))) {
+ LOG(ERROR) << AT << "failed to send MSG request";
+ return -1;
+ }
- rc = readv(handle, iov, 2);
- if (rc < 0) {
- PLOG(ERROR) << "Error reading response. " << rc;
- return rc;
- }
+ rc = readv(handle_, iov, countof(iov));
+ if (rc != static_cast<int>(sizeof(hdr) + sizeof(args))) {
+ LOG(ERROR) << AT << "failed to receive MSG response";
+ return -1;
+ }
- uint32_t body_size = std::min(kPayloadSize, header.remaining);
- if (body_size != rc - kHeaderSize) {
- LOG(ERROR) << "Unexpected amount of data: " << rc;
- return -1;
- }
+ if (hdr.cmd != (CONFIRMATIONUI_CMD_MSG | CONFIRMATIONUI_RESP_BIT)) {
+ LOG(ERROR) << AT << "unknown response command: " << hdr.cmd;
+ return -1;
+ }
- remaining = header.remaining - body_size;
- begin += body_size;
- } while (remaining);
+ uint32_t ilen = iend - ibegin;
+ if (args.msg_len > ilen) {
+ LOG(ERROR) << AT << "response message too long to fit in return buffer";
+ return -1;
+ }
- return begin - ibegin;
+ memcpy(ibegin, shm_base_, args.msg_len);
+
+ return args.msg_len;
}
TrustyApp::TrustyApp(const std::string& path, const std::string& appname)
: handle_(kInvalidHandle) {
- handle_ = tipc_connect(path.c_str(), appname.c_str());
- if (handle_ == kInvalidHandle) {
+ unique_fd tipc_handle(tipc_connect(path.c_str(), appname.c_str()));
+ if (tipc_handle < 0) {
LOG(ERROR) << AT << "failed to connect to Trusty TA \"" << appname << "\" using dev:"
<< "\"" << path << "\"";
+ return;
}
+
+ uint32_t shm_len = RoundPageUp(CONFIRMATIONUI_MAX_MSG_SIZE);
+ BufferAllocator allocator;
+ unique_fd dma_buf(allocator.Alloc("system", shm_len));
+ if (dma_buf < 0) {
+ LOG(ERROR) << AT << "failed to allocate shared memory buffer";
+ return;
+ }
+
+ if (dma_buf < 0) {
+ LOG(ERROR) << AT << "failed to allocate shared memory buffer";
+ return;
+ }
+
+ confirmationui_hdr hdr = {
+ .cmd = CONFIRMATIONUI_CMD_INIT,
+ };
+ confirmationui_init_req args = {
+ .shm_len = shm_len,
+ };
+ iovec iov[] = {
+ {
+ .iov_base = &hdr,
+ .iov_len = sizeof(hdr),
+ },
+ {
+ .iov_base = &args,
+ .iov_len = sizeof(args),
+ },
+ };
+ trusty_shm shm = {
+ .fd = dma_buf,
+ .transfer = TRUSTY_SHARE,
+ };
+
+ int rc = tipc_send(tipc_handle, iov, 2, &shm, 1);
+ if (rc != static_cast<int>(sizeof(hdr) + sizeof(args))) {
+ LOG(ERROR) << AT << "failed to send INIT request";
+ return;
+ }
+
+ rc = read(tipc_handle, &hdr, sizeof(hdr));
+ if (rc != static_cast<int>(sizeof(hdr))) {
+ LOG(ERROR) << AT << "failed to receive INIT response";
+ return;
+ }
+
+ if (hdr.cmd != (CONFIRMATIONUI_CMD_INIT | CONFIRMATIONUI_RESP_BIT)) {
+ LOG(ERROR) << AT << "unknown response command: " << hdr.cmd;
+ return;
+ }
+
+ void* shm_base = mmap(0, shm_len, PROT_READ | PROT_WRITE, MAP_SHARED, dma_buf, 0);
+ if (shm_base == MAP_FAILED) {
+ LOG(ERROR) << AT << "failed to mmap() shared memory buffer";
+ return;
+ }
+
+ handle_ = std::move(tipc_handle);
+ shm_base_ = shm_base;
+ shm_len_ = shm_len;
+
LOG(INFO) << AT << "succeeded to connect to Trusty TA \"" << appname << "\"";
}
+
TrustyApp::~TrustyApp() {
- if (handle_ != kInvalidHandle) {
- tipc_close(handle_);
- }
LOG(INFO) << "Done shutting down TrustyApp";
}
diff --git a/trusty/confirmationui/TrustyApp.h b/trusty/confirmationui/TrustyApp.h
index 05a25f6..406f439 100644
--- a/trusty/confirmationui/TrustyApp.h
+++ b/trusty/confirmationui/TrustyApp.h
@@ -16,7 +16,10 @@
#pragma once
+#include "TrustyIpc.h"
+
#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
#include <errno.h>
#include <poll.h>
#include <stdio.h>
@@ -60,19 +63,11 @@
MSG_TOO_LONG = -2,
};
-/*
- * There is a hard limitation of 0x1800 bytes for the to-be-signed message size. The protocol
- * overhead is limited, so that 0x2000 is a buffer size that will be sufficient in any benign
- * mode of operation.
- */
-static constexpr const size_t kSendBufferSize = 0x2000;
-
-ssize_t TrustyRpc(int handle, const uint8_t* obegin, const uint8_t* oend, uint8_t* ibegin,
- uint8_t* iend);
-
class TrustyApp {
private:
- int handle_;
+ android::base::unique_fd handle_;
+ void* shm_base_;
+ size_t shm_len_;
static constexpr const int kInvalidHandle = -1;
/*
* This mutex serializes communication with the trusted app, not handle_.
@@ -84,6 +79,8 @@
TrustyApp(const std::string& path, const std::string& appname);
~TrustyApp();
+ ssize_t TrustyRpc(const uint8_t* obegin, const uint8_t* oend, uint8_t* ibegin, uint8_t* iend);
+
template <typename Request, typename Response, typename... T>
std::tuple<TrustyAppError, msg2tuple_t<Response>> issueCmd(const T&... args) {
std::lock_guard<std::mutex> lock(mutex_);
@@ -93,7 +90,7 @@
return {TrustyAppError::ERROR, {}};
}
- uint8_t buffer[kSendBufferSize];
+ uint8_t buffer[CONFIRMATIONUI_MAX_MSG_SIZE];
WriteStream out(buffer);
out = write(Request(), out, args...);
@@ -102,8 +99,8 @@
return {TrustyAppError::MSG_TOO_LONG, {}};
}
- auto rc = TrustyRpc(handle_, &buffer[0], const_cast<const uint8_t*>(out.pos()), &buffer[0],
- &buffer[kSendBufferSize]);
+ auto rc = TrustyRpc(&buffer[0], const_cast<const uint8_t*>(out.pos()), &buffer[0],
+ &buffer[CONFIRMATIONUI_MAX_MSG_SIZE]);
if (rc < 0) return {TrustyAppError::ERROR, {}};
ReadStream in(&buffer[0], rc);
@@ -125,7 +122,7 @@
return TrustyAppError::ERROR;
}
- uint8_t buffer[kSendBufferSize];
+ uint8_t buffer[CONFIRMATIONUI_MAX_MSG_SIZE];
WriteStream out(buffer);
out = write(Request(), out, args...);
@@ -134,8 +131,8 @@
return TrustyAppError::MSG_TOO_LONG;
}
- auto rc = TrustyRpc(handle_, &buffer[0], const_cast<const uint8_t*>(out.pos()), &buffer[0],
- &buffer[kSendBufferSize]);
+ auto rc = TrustyRpc(&buffer[0], const_cast<const uint8_t*>(out.pos()), &buffer[0],
+ &buffer[CONFIRMATIONUI_MAX_MSG_SIZE]);
if (rc < 0) {
LOG(ERROR) << "send command failed: " << strerror(errno) << " (" << errno << ")";
return TrustyAppError::ERROR;
diff --git a/trusty/confirmationui/TrustyConfirmationUI.cpp b/trusty/confirmationui/TrustyConfirmationUI.cpp
index 6b25893..c8b24e3 100644
--- a/trusty/confirmationui/TrustyConfirmationUI.cpp
+++ b/trusty/confirmationui/TrustyConfirmationUI.cpp
@@ -71,7 +71,7 @@
using TeeuiRc = ::teeui::ResponseCode;
constexpr const char kTrustyDeviceName[] = "/dev/trusty-ipc-dev0";
-constexpr const char kConfirmationuiAppName[] = "com.android.trusty.confirmationui";
+constexpr const char kConfirmationuiAppName[] = CONFIRMATIONUI_PORT;
namespace {
diff --git a/trusty/confirmationui/TrustyIpc.h b/trusty/confirmationui/TrustyIpc.h
new file mode 100644
index 0000000..eb764bc
--- /dev/null
+++ b/trusty/confirmationui/TrustyIpc.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2021 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+/*
+ * This interface is shared between Android and Trusty. There is a copy in each
+ * repository. They must be kept in sync.
+ */
+
+#define CONFIRMATIONUI_PORT "com.android.trusty.confirmationui"
+
+/**
+ * enum confirmationui_cmd - command identifiers for ConfirmationUI interface
+ * @CONFIRMATIONUI_RESP_BIT: response bit set as part of response
+ * @CONFIRMATIONUI_REQ_SHIFT: number of bits used by response bit
+ * @CONFIRMATIONUI_CMD_INIT: command to initialize session
+ * @CONFIRMATIONUI_CMD_MSG: command to send ConfirmationUI messages
+ */
+enum confirmationui_cmd : uint32_t {
+ CONFIRMATIONUI_RESP_BIT = 1,
+ CONFIRMATIONUI_REQ_SHIFT = 1,
+
+ CONFIRMATIONUI_CMD_INIT = (1 << CONFIRMATIONUI_REQ_SHIFT),
+ CONFIRMATIONUI_CMD_MSG = (2 << CONFIRMATIONUI_REQ_SHIFT),
+};
+
+/**
+ * struct confirmationui_hdr - header for ConfirmationUI messages
+ * @cmd: command identifier
+ *
+ * Note that no messages return a status code. Any error on the server side
+ * results in the connection being closed. So, operations can be assumed to be
+ * successful if they return a response.
+ */
+struct confirmationui_hdr {
+ uint32_t cmd;
+};
+
+/**
+ * struct confirmationui_init_req - arguments for request to initialize a
+ * session
+ * @shm_len: length of memory region being shared
+ *
+ * A handle to a memory region must be sent along with this message. This memory
+ * is send to ConfirmationUI messages.
+ */
+struct confirmationui_init_req {
+ uint32_t shm_len;
+};
+
+/**
+ * struct confirmationui_msg_args - arguments for sending a message
+ * @msg_len: length of message being sent
+ *
+ * Contents of the message are located in the shared memory region that is
+ * established using %CONFIRMATIONUI_CMD_INIT.
+ *
+ * ConfirmationUI messages can travel both ways.
+ */
+struct confirmationui_msg_args {
+ uint32_t msg_len;
+};
+
+#define CONFIRMATIONUI_MAX_MSG_SIZE 0x2000
diff --git a/trusty/confirmationui/android.hardware.confirmationui@1.0-service.trusty.rc b/trusty/confirmationui/android.hardware.confirmationui@1.0-service.trusty.rc
index dc7a03b..3ba6fc0 100644
--- a/trusty/confirmationui/android.hardware.confirmationui@1.0-service.trusty.rc
+++ b/trusty/confirmationui/android.hardware.confirmationui@1.0-service.trusty.rc
@@ -1,4 +1,4 @@
service confirmationui-1-0 /vendor/bin/hw/android.hardware.confirmationui@1.0-service.trusty
class hal
- user nobody
- group drmrpc input
+ user system
+ group drmrpc input system
diff --git a/trusty/coverage/coverage.cpp b/trusty/coverage/coverage.cpp
index 5eccdc5..3c6b5c5 100644
--- a/trusty/coverage/coverage.cpp
+++ b/trusty/coverage/coverage.cpp
@@ -29,6 +29,7 @@
#include <trusty/coverage/record.h>
#include <trusty/coverage/tipc.h>
#include <trusty/tipc.h>
+#include <iostream>
#define COVERAGE_CLIENT_PORT "com.android.trusty.coverage.client"
@@ -122,7 +123,9 @@
int fd = tipc_connect(tipc_dev_.c_str(), COVERAGE_CLIENT_PORT);
if (fd < 0) {
- return ErrnoError() << "failed to connect to Trusty coverarge server: ";
+ // Don't error out to support fuzzing builds without coverage, e.g. for repros.
+ std::cerr << "WARNING!!! Failed to connect to Trusty coverarge server." << std::endl;
+ return {};
}
coverage_srv_fd_.reset(fd);
@@ -130,7 +133,7 @@
req.open_args.uuid = uuid_;
auto ret = Rpc(&req, -1, &resp);
if (!ret.ok()) {
- return Error() << "failed to open coverage client: ";
+ return Error() << "failed to open coverage client: " << ret.error();
}
record_len_ = resp.open_args.record_len;
shm_len_ = RoundPageUp(record_len_);
@@ -153,13 +156,17 @@
req.share_record_args.shm_len = shm_len_;
ret = Rpc(&req, dma_buf, &resp);
if (!ret.ok()) {
- return Error() << "failed to send shared memory: ";
+ return Error() << "failed to send shared memory: " << ret.error();
}
shm_ = shm;
return {};
}
+bool CoverageRecord::IsOpen() {
+ return shm_;
+}
+
void CoverageRecord::ResetFullRecord() {
auto header_region = GetRegionBounds(COV_START);
if (!header_region.ok()) {
diff --git a/trusty/coverage/include/trusty/coverage/coverage.h b/trusty/coverage/include/trusty/coverage/coverage.h
index 5da68da..9ccc981 100644
--- a/trusty/coverage/include/trusty/coverage/coverage.h
+++ b/trusty/coverage/include/trusty/coverage/coverage.h
@@ -47,6 +47,7 @@
~CoverageRecord();
Result<void> Open();
+ bool IsOpen();
void ResetFullRecord();
void ResetCounts();
void ResetPCs();
diff --git a/trusty/fuzz/counters.cpp b/trusty/fuzz/counters.cpp
index 1e863ac..4d34059 100644
--- a/trusty/fuzz/counters.cpp
+++ b/trusty/fuzz/counters.cpp
@@ -41,6 +41,10 @@
namespace fuzz {
ExtraCounters::ExtraCounters(coverage::CoverageRecord* record) : record_(record) {
+ if (!record_->IsOpen()) {
+ return;
+ }
+
assert(fuzzer::ExtraCountersBegin());
assert(fuzzer::ExtraCountersEnd());
@@ -51,10 +55,18 @@
}
ExtraCounters::~ExtraCounters() {
+ if (!record_->IsOpen()) {
+ return;
+ }
+
Flush();
}
void ExtraCounters::Reset() {
+ if (!record_->IsOpen()) {
+ return;
+ }
+
record_->ResetCounts();
fuzzer::ClearExtraCounters();
}
diff --git a/trusty/fuzz/utils.cpp b/trusty/fuzz/utils.cpp
index f4cf0b6..3526337 100644
--- a/trusty/fuzz/utils.cpp
+++ b/trusty/fuzz/utils.cpp
@@ -113,7 +113,7 @@
int rc = write(ta_fd_, buf, len);
alarm(0);
if (rc < 0) {
- return Error() << "failed to read TIPC message from TA: ";
+ return Error() << "failed to write TIPC message to TA: ";
}
return {};