Merge "Avoid signed extension of chars for build ids."
diff --git a/adb/client/adb_install.cpp b/adb/client/adb_install.cpp
index 3869945..2bf2924 100644
--- a/adb/client/adb_install.cpp
+++ b/adb/client/adb_install.cpp
@@ -550,6 +550,10 @@
std::string multi_package_cmd =
android::base::StringPrintf("%s install-create --multi-package", install_cmd.c_str());
+ for (int i = 1; i < first_package; i++) {
+ multi_package_cmd += " " + escape_arg(argv[i]);
+ }
+
if (apex_found) {
multi_package_cmd += " --staged";
}
diff --git a/libkeyutils/Android.bp b/libkeyutils/Android.bp
index b388e95..e816926 100644
--- a/libkeyutils/Android.bp
+++ b/libkeyutils/Android.bp
@@ -16,3 +16,16 @@
srcs: ["keyutils_test.cpp"],
test_suites: ["device-tests"],
}
+
+cc_binary {
+ name: "mini-keyctl",
+ srcs: ["mini_keyctl.cpp"],
+
+ shared_libs: [
+ "libbase",
+ "libkeyutils",
+ "liblog",
+ ],
+
+ cflags: ["-Werror", "-Wall", "-Wextra"],
+}
diff --git a/libkeyutils/include/keyutils.h b/libkeyutils/include/keyutils.h
index 585767d..c508f27 100644
--- a/libkeyutils/include/keyutils.h
+++ b/libkeyutils/include/keyutils.h
@@ -51,6 +51,10 @@
long keyctl_unlink(key_serial_t key, key_serial_t keyring);
+long keyctl_restrict_keyring(key_serial_t keyring, const char* type, const char* restriction);
+
+long keyctl_get_security(key_serial_t key, char* buffer, size_t buflen);
+
__END_DECLS
#endif
diff --git a/libkeyutils/keyutils.cpp b/libkeyutils/keyutils.cpp
index 58a2a17..8f63f70 100644
--- a/libkeyutils/keyutils.cpp
+++ b/libkeyutils/keyutils.cpp
@@ -69,3 +69,11 @@
long keyctl_unlink(key_serial_t key, key_serial_t keyring) {
return keyctl(KEYCTL_UNLINK, key, keyring);
}
+
+long keyctl_restrict_keyring(key_serial_t keyring, const char* type, const char* restriction) {
+ return keyctl(KEYCTL_RESTRICT_KEYRING, keyring, type, restriction);
+}
+
+long keyctl_get_security(key_serial_t id, char* buffer, size_t buflen) {
+ return keyctl(KEYCTL_GET_SECURITY, id, buffer, buflen);
+}
diff --git a/libkeyutils/mini_keyctl.cpp b/libkeyutils/mini_keyctl.cpp
new file mode 100644
index 0000000..abc8f82
--- /dev/null
+++ b/libkeyutils/mini_keyctl.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+/*
+ * A tool loads keys to keyring.
+ */
+
+#include <dirent.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <fstream>
+#include <iostream>
+#include <iterator>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <keyutils.h>
+
+static constexpr int kMaxCertSize = 4096;
+
+// Add all the certs from directory path to keyring with keyring_id. Returns the number of keys
+// added.
+int AddKeys(const std::string& path, const key_serial_t keyring_id, const std::string& keyring_desc,
+ int start_index) {
+ std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(path.c_str()), closedir);
+ if (!dir) {
+ PLOG(WARNING) << "Failed to open directory " << path;
+ return 0;
+ }
+ int keys_added = 0;
+ struct dirent* dp;
+ while ((dp = readdir(dir.get())) != NULL) {
+ if (dp->d_type != DT_REG) {
+ continue;
+ }
+ std::string cert_path = path + "/" + dp->d_name;
+ std::string cert_buf;
+ if (!android::base::ReadFileToString(cert_path, &cert_buf, false /* follow_symlinks */)) {
+ LOG(ERROR) << "Failed to read " << cert_path;
+ continue;
+ }
+
+ if (cert_buf.size() > kMaxCertSize) {
+ LOG(ERROR) << "Certficate size too large: " << cert_path;
+ continue;
+ }
+
+ // Add key to keyring.
+ int key_desc_index = keys_added + start_index;
+ std::string key_desc = keyring_desc + "-key" + std::to_string(key_desc_index);
+ key_serial_t key =
+ add_key("asymmetric", key_desc.c_str(), &cert_buf[0], cert_buf.size(), keyring_id);
+ if (key < 0) {
+ PLOG(ERROR) << "Failed to add key to keyring: " << cert_path;
+ continue;
+ }
+ keys_added++;
+ }
+ return keys_added;
+}
+
+std::vector<std::string> SplitBySpace(const std::string& s) {
+ std::istringstream iss(s);
+ return std::vector<std::string>{std::istream_iterator<std::string>{iss},
+ std::istream_iterator<std::string>{}};
+}
+
+// Find the keyring id. Because request_key(2) syscall is not available or the key is
+// kernel keyring, the id is looked up from /proc/keys. The keyring description may contain other
+// information in the descritption section depending on the key type, only the first word in the
+// keyring description is used for searching.
+bool GetKeyringId(const std::string& keyring_desc, key_serial_t* keyring_id) {
+ if (!keyring_id) {
+ LOG(ERROR) << "keyring_id is null";
+ return false;
+ }
+
+ // Only keys allowed by SELinux rules will be shown here.
+ std::ifstream proc_keys_file("/proc/keys");
+ if (!proc_keys_file.is_open()) {
+ PLOG(ERROR) << "Failed to open /proc/keys";
+ return false;
+ }
+
+ std::string line;
+ while (getline(proc_keys_file, line)) {
+ std::vector<std::string> tokens = SplitBySpace(line);
+ if (tokens.size() < 9) {
+ continue;
+ }
+ std::string key_id = tokens[0];
+ std::string key_type = tokens[7];
+ // The key description may contain space.
+ std::string key_desc_prefix = tokens[8];
+ // The prefix has a ":" at the end
+ std::string key_desc_pattern = keyring_desc + ":";
+ if (key_type != "keyring" || key_desc_prefix != key_desc_pattern) {
+ continue;
+ }
+ *keyring_id = std::stoi(key_id, nullptr, 16);
+ return true;
+ }
+ return false;
+}
+
+static void Usage(int exit_code) {
+ fprintf(stderr, "usage: mini-keyctl -c PATHS -s DESCRIPTION\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "-c, --cert_dirs the certificate locations, separated by comma\n");
+ fprintf(stderr, "-k, --keyring the keyring description\n");
+ _exit(exit_code);
+}
+
+int main(int argc, char** argv) {
+ if (argc < 5) Usage(1);
+
+ std::string arg_cert_dirs;
+ std::string arg_keyring_desc;
+
+ for (int i = 1; i < argc; i++) {
+ std::string option = argv[i];
+ if (option == "-c" || option == "--cert_dirs") {
+ if (i + 1 < argc) arg_cert_dirs = argv[++i];
+ } else if (option == "-k" || option == "--keyring") {
+ if (i + 1 < argc) arg_keyring_desc = argv[++i];
+ }
+ }
+
+ if (arg_cert_dirs.empty() || arg_keyring_desc.empty()) {
+ LOG(ERROR) << "Missing cert_dirs or keyring desc";
+ Usage(1);
+ }
+
+ // Get the keyring id
+ key_serial_t key_ring_id;
+ if (!GetKeyringId(arg_keyring_desc, &key_ring_id)) {
+ PLOG(ERROR) << "Can't find keyring with " << arg_keyring_desc;
+ return 1;
+ }
+
+ std::vector<std::string> cert_dirs = android::base::Split(arg_cert_dirs, ",");
+ int start_index = 0;
+ for (const auto& cert_dir : cert_dirs) {
+ int keys_added = AddKeys(cert_dir, key_ring_id, arg_keyring_desc, start_index);
+ start_index += keys_added;
+ }
+
+ // Prevent new keys to be added.
+ if (!android::base::GetBoolProperty("ro.debuggable", false) &&
+ keyctl_restrict_keyring(key_ring_id, nullptr, nullptr) < 0) {
+ PLOG(ERROR) << "Failed to restrict key ring " << arg_keyring_desc;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/libmeminfo/libdmabufinfo/dmabufinfo.cpp b/libmeminfo/libdmabufinfo/dmabufinfo.cpp
index 41ecc51..b4ad667 100644
--- a/libmeminfo/libdmabufinfo/dmabufinfo.cpp
+++ b/libmeminfo/libdmabufinfo/dmabufinfo.cpp
@@ -119,9 +119,23 @@
return false;
}
- DmaBuffer& buf =
+ uint64_t inode = sb.st_ino;
+ auto buf = std::find_if(dmabufs->begin(), dmabufs->end(),
+ [&inode](const DmaBuffer& dbuf) { return dbuf.inode() == inode; });
+ if (buf != dmabufs->end()) {
+ if (buf->name() == "" || buf->name() == "<unknown>")
+ buf->SetName(name);
+ if (buf->exporter() == "" || buf->exporter() == "<unknown>")
+ buf->SetExporter(exporter);
+ if (buf->count() == 0)
+ buf->SetCount(count);
+ buf->AddFdRef(pid);
+ return true;
+ }
+
+ DmaBuffer& db =
dmabufs->emplace_back(sb.st_ino, sb.st_blocks * 512, count, exporter, name);
- buf.AddFdRef(pid);
+ db.AddFdRef(pid);
}
return true;
@@ -225,6 +239,10 @@
bool ReadDmaBufInfo(pid_t pid, std::vector<DmaBuffer>* dmabufs) {
dmabufs->clear();
+ return AppendDmaBufInfo(pid, dmabufs);
+}
+
+bool AppendDmaBufInfo(pid_t pid, std::vector<DmaBuffer>* dmabufs) {
if (!ReadDmaBufFdRefs(pid, dmabufs)) {
LOG(ERROR) << "Failed to read dmabuf fd references";
return false;
diff --git a/libmeminfo/libdmabufinfo/dmabufinfo_test.cpp b/libmeminfo/libdmabufinfo/dmabufinfo_test.cpp
index aa5f16c..95aa2c7 100644
--- a/libmeminfo/libdmabufinfo/dmabufinfo_test.cpp
+++ b/libmeminfo/libdmabufinfo/dmabufinfo_test.cpp
@@ -21,6 +21,7 @@
#include <string>
#include <vector>
+#include <unordered_map>
#include <android-base/file.h>
#include <android-base/logging.h>
@@ -61,18 +62,16 @@
#define EXPECT_PID_IN_FDREFS(_bufptr, _pid, _expect) \
do { \
- const std::vector<pid_t>& _fdrefs = _bufptr->fdrefs(); \
- auto _ref = std::find_if(_fdrefs.begin(), _fdrefs.end(), \
- [&](const pid_t& p) { return p == _pid; }); \
- EXPECT_EQ((_ref == _fdrefs.end()), _expect); \
+ const std::unordered_map<pid_t, int>& _fdrefs = _bufptr->fdrefs(); \
+ auto _ref = _fdrefs.find(_pid); \
+ EXPECT_EQ((_ref != _fdrefs.end()), _expect); \
} while (0)
#define EXPECT_PID_IN_MAPREFS(_bufptr, _pid, _expect) \
do { \
- const std::vector<pid_t>& _maprefs = _bufptr->maprefs(); \
- auto _ref = std::find_if(_maprefs.begin(), _maprefs.end(), \
- [&](const pid_t& p) { return p == _pid; }); \
- EXPECT_EQ((_ref == _maprefs.end()), _expect); \
+ const std::unordered_map<pid_t, int>& _maprefs = _bufptr->maprefs(); \
+ auto _ref = _maprefs.find(_pid); \
+ EXPECT_EQ((_ref != _maprefs.end()), _expect); \
} while (0)
TEST(DmaBufInfoParser, TestReadDmaBufInfo) {
diff --git a/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h b/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h
index 29ce4d0..74eff3c 100644
--- a/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h
+++ b/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h
@@ -21,6 +21,7 @@
#include <string>
#include <vector>
+#include <unordered_map>
namespace android {
namespace dmabufinfo {
@@ -33,20 +34,27 @@
~DmaBuffer() = default;
// Adds one file descriptor reference for the given pid
- void AddFdRef(pid_t pid) { fdrefs_.emplace_back(pid); }
+ void AddFdRef(pid_t pid) {
+ AddRefToPidMap(pid, &fdrefs_);
+ }
// Adds one map reference for the given pid
- void AddMapRef(pid_t pid) { maprefs_.emplace_back(pid); }
+ void AddMapRef(pid_t pid) {
+ AddRefToPidMap(pid, &maprefs_);
+ }
// Getters for each property
uint64_t size() { return size_; }
- const std::vector<pid_t>& fdrefs() const { return fdrefs_; }
- const std::vector<pid_t>& maprefs() const { return maprefs_; }
+ const std::unordered_map<pid_t, int>& fdrefs() const { return fdrefs_; }
+ const std::unordered_map<pid_t, int>& maprefs() const { return maprefs_; }
ino_t inode() const { return inode_; }
uint64_t total_refs() const { return fdrefs_.size() + maprefs_.size(); }
uint64_t count() const { return count_; };
const std::string& name() const { return name_; }
const std::string& exporter() const { return exporter_; }
+ void SetName(const std::string& name) { name_ = name; }
+ void SetExporter(const std::string& exporter) { exporter_ = exporter; }
+ void SetCount(uint64_t count) { count_ = count; }
private:
ino_t inode_;
@@ -54,20 +62,37 @@
uint64_t count_;
std::string exporter_;
std::string name_;
- std::vector<pid_t> fdrefs_;
- std::vector<pid_t> maprefs_;
+ std::unordered_map<pid_t, int> fdrefs_;
+ std::unordered_map<pid_t, int> maprefs_;
+ void AddRefToPidMap(pid_t pid, std::unordered_map<pid_t, int>* map) {
+ // The first time we find a ref, we set the ref count to 1
+ // otherwise, increment the existing ref count
+ auto [it, inserted] = map->insert(std::make_pair(pid, 1));
+ if (!inserted)
+ it->second++;
+ }
};
// Read and return current dma buf objects from
// DEBUGFS/dma_buf/bufinfo. The references to each dma buffer are not
// populated here and will return an empty vector.
+//
// Returns false if something went wrong with the function, true otherwise.
bool ReadDmaBufInfo(std::vector<DmaBuffer>* dmabufs,
const std::string& path = "/sys/kernel/debug/dma_buf/bufinfo");
+
// Read and return dmabuf objects for a given process without the help
// of DEBUGFS
+//
+// Returns false if something went wrong with the function, true otherwise.
bool ReadDmaBufInfo(pid_t pid, std::vector<DmaBuffer>* dmabufs);
+// Append dmabuf objects for a given process without the help
+// of DEBUGFS to an existing vector
+//
+// Returns false if something went wrong with the function, true otherwise.
+bool AppendDmaBufInfo(pid_t pid, std::vector<DmaBuffer>* dmabufs);
+
} // namespace dmabufinfo
} // namespace android