Merge "String16: remove integer overflows"
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index e5666bc..31cb853 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -77,6 +77,7 @@
static void intentionally_leak() {
void* p = ::operator new(1);
+ // The analyzer is upset about this leaking. NOLINTNEXTLINE
LOG(INFO) << "leaking pointer " << p;
}
diff --git a/init/Android.bp b/init/Android.bp
index 60394ef..31c8efb 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -201,7 +201,7 @@
name: "generated_stub_builtin_function_map",
out: ["generated_stub_builtin_function_map.h"],
srcs: ["builtins.cpp"],
- cmd: "sed -n '/Builtin-function-map start/{:a;n;/Builtin-function-map end/q;p;ba}' $(in) | sed -e 's/do_[^}]*/do_stub/g' > $(out)"
+ cmd: "sed -n '/Builtin-function-map start/{:a;n;/Builtin-function-map end/q;p;ba}' $(in) | sed -e 's/do_[^}]*/do_stub/g' > $(out)",
}
cc_binary {
@@ -247,6 +247,14 @@
type: "lite",
},
generated_headers: ["generated_stub_builtin_function_map"],
+ target: {
+ android: {
+ enabled: false,
+ },
+ darwin: {
+ enabled: false,
+ },
+ },
}
subdirs = ["*"]
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 51c2c9b..fc74dda 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -285,8 +285,11 @@
if (e4crypt_is_native()) {
if (e4crypt_set_directory_policy(args[1].c_str())) {
- reboot_into_recovery(
- {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + args[1]});
+ const std::vector<std::string> options = {
+ "--prompt_and_wipe_data",
+ "--reason=set_policy_failed:"s + args[1]};
+ reboot_into_recovery(options);
+ return Success();
}
}
return Success();
@@ -984,24 +987,6 @@
return android::base::GetProperty("ro.crypto.type", "") == "file";
}
-static Result<Success> ExecWithRebootOnFailure(const std::string& reboot_reason,
- const std::vector<std::string>& args) {
- auto service = Service::MakeTemporaryOneshotService(args);
- if (!service) {
- return Error() << "Could not create exec service";
- }
- service->AddReapCallback([reboot_reason](const siginfo_t& siginfo) {
- if (siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) {
- reboot_into_recovery({"--prompt_and_wipe_data", "--reason="s + reboot_reason});
- }
- });
- if (auto result = service->ExecStart(); !result) {
- return Error() << "Could not start exec service: " << result.error();
- }
- ServiceList::GetInstance().AddService(std::move(service));
- return Success();
-}
-
static Result<Success> do_installkey(const BuiltinArguments& args) {
if (!is_file_crypto()) return Success();
@@ -1009,13 +994,15 @@
if (!make_dir(unencrypted_dir, 0700) && errno != EEXIST) {
return ErrnoError() << "Failed to create " << unencrypted_dir;
}
- return ExecWithRebootOnFailure("enablefilecrypto_failed", {"exec", "/system/bin/vdc", "--wait",
- "cryptfs", "enablefilecrypto"});
+ std::vector<std::string> exec_args = {"exec", "/system/bin/vdc", "--wait", "cryptfs",
+ "enablefilecrypto"};
+ return do_exec({std::move(exec_args), args.context});
}
static Result<Success> do_init_user0(const BuiltinArguments& args) {
- return ExecWithRebootOnFailure("init_user0_failed",
- {"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"});
+ std::vector<std::string> exec_args = {"exec", "/system/bin/vdc", "--wait", "cryptfs",
+ "init_user0"};
+ return do_exec({std::move(exec_args), args.context});
}
// Builtin-function-map start
diff --git a/init/host_init_stubs.cpp b/init/host_init_stubs.cpp
index cde747d..e6cc08a 100644
--- a/init/host_init_stubs.cpp
+++ b/init/host_init_stubs.cpp
@@ -43,8 +43,8 @@
// property_service.h
uint32_t (*property_set)(const std::string& name, const std::string& value) = nullptr;
-uint32_t HandlePropertySet(const std::string&, const std::string&, const std::string&,
- const ucred&) {
+uint32_t HandlePropertySet(const std::string&, const std::string&, const std::string&, const ucred&,
+ std::string*) {
return 0;
}
diff --git a/init/host_init_stubs.h b/init/host_init_stubs.h
index af96aea..f31ece6 100644
--- a/init/host_init_stubs.h
+++ b/init/host_init_stubs.h
@@ -48,7 +48,7 @@
// property_service.h
extern uint32_t (*property_set)(const std::string& name, const std::string& value);
uint32_t HandlePropertySet(const std::string& name, const std::string& value,
- const std::string& source_context, const ucred& cr);
+ const std::string& source_context, const ucred& cr, std::string* error);
// selinux.h
void SelabelInitialize();
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 338c05a..95ef35c 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -59,8 +59,11 @@
#include "init.h"
#include "persistent_properties.h"
#include "property_type.h"
+#include "subcontext.h"
#include "util.h"
+using namespace std::literals;
+
using android::base::ReadFileToString;
using android::base::Split;
using android::base::StartsWith;
@@ -117,23 +120,21 @@
return has_access;
}
-static uint32_t PropertySetImpl(const std::string& name, const std::string& value) {
+static uint32_t PropertySet(const std::string& name, const std::string& value, std::string* error) {
size_t valuelen = value.size();
if (!IsLegalPropertyName(name)) {
- LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: bad name";
+ *error = "Illegal property name";
return PROP_ERROR_INVALID_NAME;
}
if (valuelen >= PROP_VALUE_MAX && !StartsWith(name, "ro.")) {
- LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
- << "value too long";
+ *error = "Property value too long";
return PROP_ERROR_INVALID_VALUE;
}
if (mbstowcs(nullptr, value.data(), 0) == static_cast<std::size_t>(-1)) {
- LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
- << "value not a UTF8 encoded string";
+ *error = "Value is not a UTF8 encoded string";
return PROP_ERROR_INVALID_VALUE;
}
@@ -141,8 +142,7 @@
if (pi != nullptr) {
// ro.* properties are actually "write-once".
if (StartsWith(name, "ro.")) {
- LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
- << "property already set";
+ *error = "Read-only property was already set";
return PROP_ERROR_READ_ONLY_PROPERTY;
}
@@ -150,8 +150,7 @@
} else {
int rc = __system_property_add(name.c_str(), name.size(), value.c_str(), valuelen);
if (rc < 0) {
- LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
- << "__system_property_add failed";
+ *error = "__system_property_add failed";
return PROP_ERROR_SET_FAILED;
}
}
@@ -205,8 +204,10 @@
if (info.pid != pid) {
return false;
}
- if (PropertySetImpl(info.name, info.value) != PROP_SUCCESS) {
- LOG(ERROR) << "Failed to set async property " << info.name;
+ std::string error;
+ if (PropertySet(info.name, info.value, &error) != PROP_SUCCESS) {
+ LOG(ERROR) << "Failed to set async property " << info.name << " to " << info.value << ": "
+ << error;
}
property_children.pop();
if (!property_children.empty()) {
@@ -216,9 +217,9 @@
}
static uint32_t PropertySetAsync(const std::string& name, const std::string& value,
- PropertyAsyncFunc func) {
+ PropertyAsyncFunc func, std::string* error) {
if (value.empty()) {
- return PropertySetImpl(name, value);
+ return PropertySet(name, value, error);
}
PropertyChildInfo info;
@@ -236,30 +237,27 @@
return selinux_android_restorecon(value.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE);
}
-uint32_t PropertySet(const std::string& name, const std::string& value) {
- if (name == "selinux.restorecon_recursive") {
- return PropertySetAsync(name, value, RestoreconRecursiveAsync);
- }
-
- return PropertySetImpl(name, value);
-}
-
uint32_t InitPropertySet(const std::string& name, const std::string& value) {
if (StartsWith(name, "ctl.")) {
- LOG(ERROR) << "Do not set ctl. properties from init; call the Service functions directly";
+ LOG(ERROR) << "InitPropertySet: Do not set ctl. properties from init; call the Service "
+ "functions directly";
+ return PROP_ERROR_INVALID_NAME;
+ }
+ if (name == "selinux.restorecon_recursive") {
+ LOG(ERROR) << "InitPropertySet: Do not set selinux.restorecon_recursive from init; use the "
+ "restorecon builtin directly";
return PROP_ERROR_INVALID_NAME;
}
- const char* type = nullptr;
- property_info_area->GetPropertyInfo(name.c_str(), nullptr, &type);
-
- if (type == nullptr || !CheckType(type, value)) {
- LOG(ERROR) << "property_set: name: '" << name << "' type check failed, type: '"
- << (type ?: "(null)") << "' value: '" << value << "'";
- return PROP_ERROR_INVALID_VALUE;
+ uint32_t result = 0;
+ ucred cr = {.pid = 1, .uid = 0, .gid = 0};
+ std::string error;
+ result = HandlePropertySet(name, value, kInitContext.c_str(), cr, &error);
+ if (result != PROP_SUCCESS) {
+ LOG(ERROR) << "Init cannot set '" << name << "' to '" << value << "': " << error;
}
- return PropertySet(name, value);
+ return result;
}
class SocketConnection {
@@ -390,9 +388,9 @@
// This returns one of the enum of PROP_SUCCESS or PROP_ERROR*.
uint32_t HandlePropertySet(const std::string& name, const std::string& value,
- const std::string& source_context, const ucred& cr) {
+ const std::string& source_context, const ucred& cr, std::string* error) {
if (!IsLegalPropertyName(name)) {
- LOG(ERROR) << "PropertySet: illegal property name \"" << name << "\"";
+ *error = "Illegal property name";
return PROP_ERROR_INVALID_NAME;
}
@@ -405,9 +403,7 @@
const char* type = nullptr;
property_info_area->GetPropertyInfo(control_string.c_str(), &target_context, &type);
if (!CheckMacPerms(control_string, target_context, source_context.c_str(), cr)) {
- LOG(ERROR) << "PropertySet: Unable to " << (name.c_str() + 4) << " service ctl ["
- << value << "]"
- << " uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid;
+ *error = StringPrintf("Unable to '%s' service %s", name.c_str() + 4, value.c_str());
return PROP_ERROR_HANDLE_CONTROL_MESSAGE;
}
@@ -420,13 +416,13 @@
property_info_area->GetPropertyInfo(name.c_str(), &target_context, &type);
if (!CheckMacPerms(name, target_context, source_context.c_str(), cr)) {
- LOG(ERROR) << "PropertySet: permission denied uid:" << cr.uid << " name:" << name;
+ *error = "SELinux permission check failed";
return PROP_ERROR_PERMISSION_DENIED;
}
if (type == nullptr || !CheckType(type, value)) {
- LOG(ERROR) << "PropertySet: name: '" << name << "' type check failed, type: '"
- << (type ?: "(null)") << "' value: '" << value << "'";
+ *error = StringPrintf("Property type check failed, value doesn't match expected type '%s'",
+ (type ?: "(null)"));
return PROP_ERROR_INVALID_VALUE;
}
@@ -445,7 +441,11 @@
<< process_log_string;
}
- return PropertySet(name, value);
+ if (name == "selinux.restorecon_recursive") {
+ return PropertySetAsync(name, value, RestoreconRecursiveAsync, error);
+ }
+
+ return PropertySet(name, value, error);
}
static void handle_property_set_fd() {
@@ -488,7 +488,16 @@
prop_name[PROP_NAME_MAX-1] = 0;
prop_value[PROP_VALUE_MAX-1] = 0;
- HandlePropertySet(prop_value, prop_value, socket.source_context(), socket.cred());
+ const auto& cr = socket.cred();
+ std::string error;
+ uint32_t result =
+ HandlePropertySet(prop_name, prop_value, socket.source_context(), cr, &error);
+ if (result != PROP_SUCCESS) {
+ LOG(ERROR) << "Unable to set property '" << prop_name << "' to '" << prop_value
+ << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": "
+ << error;
+ }
+
break;
}
@@ -502,7 +511,14 @@
return;
}
- auto result = HandlePropertySet(name, value, socket.source_context(), socket.cred());
+ const auto& cr = socket.cred();
+ std::string error;
+ uint32_t result = HandlePropertySet(name, value, socket.source_context(), cr, &error);
+ if (result != PROP_SUCCESS) {
+ LOG(ERROR) << "Unable to set property '" << name << "' to '" << value
+ << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": "
+ << error;
+ }
socket.SendUint32(result);
break;
}
@@ -520,11 +536,17 @@
* Filter is used to decide which properties to load: NULL loads all keys,
* "ro.foo.*" is a prefix match, and "ro.foo.bar" is an exact match.
*/
-static void load_properties(char *data, const char *filter)
-{
+static void LoadProperties(char* data, const char* filter, const char* filename) {
char *key, *value, *eol, *sol, *tmp, *fn;
size_t flen = 0;
+ const char* context = kInitContext.c_str();
+ for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
+ if (StartsWith(filename, path_prefix)) {
+ context = secontext;
+ }
+ }
+
if (filter) {
flen = strlen(filter);
}
@@ -571,7 +593,21 @@
}
}
- property_set(key, value);
+ if (StartsWith(key, "ctl.") || key == "sys.powerctl"s ||
+ key == "selinux.restorecon_recursive"s) {
+ LOG(ERROR) << "Ignoring disallowed property '" << key
+ << "' with special meaning in prop file '" << filename << "'";
+ continue;
+ }
+
+ uint32_t result = 0;
+ ucred cr = {.pid = 1, .uid = 0, .gid = 0};
+ std::string error;
+ result = HandlePropertySet(key, value, context, cr, &error);
+ if (result != PROP_SUCCESS) {
+ LOG(ERROR) << "Unable to set property '" << key << "' to '" << value
+ << "' in property file '" << filename << "': " << error;
+ }
}
}
}
@@ -587,7 +623,8 @@
return false;
}
file_contents->push_back('\n');
- load_properties(file_contents->data(), filter);
+
+ LoadProperties(file_contents->data(), filter, filename);
LOG(VERBOSE) << "(Loading properties from " << filename << " took " << t << ".)";
return true;
}
diff --git a/init/property_service.h b/init/property_service.h
index d4973fc..29eaaa9 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -32,7 +32,7 @@
extern uint32_t (*property_set)(const std::string& name, const std::string& value);
uint32_t HandlePropertySet(const std::string& name, const std::string& value,
- const std::string& source_context, const ucred& cr);
+ const std::string& source_context, const ucred& cr, std::string* error);
extern bool PropertyChildReap(pid_t pid);
diff --git a/init/service.cpp b/init/service.cpp
index 09d8dae..8130e73 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -303,7 +303,7 @@
}
}
-void Service::Reap(const siginfo_t& siginfo) {
+void Service::Reap() {
if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) {
KillProcessGroup(SIGKILL);
}
@@ -312,10 +312,6 @@
std::for_each(descriptors_.begin(), descriptors_.end(),
std::bind(&DescriptorInfo::Clean, std::placeholders::_1));
- for (const auto& f : reap_callbacks_) {
- f(siginfo);
- }
-
if (flags_ & SVC_EXEC) UnSetExec();
if (flags_ & SVC_TEMPORARY) return;
diff --git a/init/service.h b/init/service.h
index bcf1943..d46a413 100644
--- a/init/service.h
+++ b/init/service.h
@@ -17,7 +17,6 @@
#ifndef _INIT_SERVICE_H
#define _INIT_SERVICE_H
-#include <signal.h>
#include <sys/resource.h>
#include <sys/types.h>
@@ -82,7 +81,7 @@
void Stop();
void Terminate();
void Restart();
- void Reap(const siginfo_t& siginfo);
+ void Reap();
void DumpState() const;
void SetShutdownCritical() { flags_ |= SVC_SHUTDOWN_CRITICAL; }
bool IsShutdownCritical() const { return (flags_ & SVC_SHUTDOWN_CRITICAL) != 0; }
@@ -90,9 +89,6 @@
is_exec_service_running_ = false;
flags_ &= ~SVC_EXEC;
}
- void AddReapCallback(std::function<void(const siginfo_t& siginfo)> callback) {
- reap_callbacks_.emplace_back(std::move(callback));
- }
static bool is_exec_service_running() { return is_exec_service_running_; }
@@ -214,8 +210,6 @@
std::vector<std::pair<int, rlimit>> rlimits_;
std::vector<std::string> args_;
-
- std::vector<std::function<void(const siginfo_t& siginfo)>> reap_callbacks_;
};
class ServiceList {
diff --git a/init/sigchld_handler.cpp b/init/sigchld_handler.cpp
index badacaf..072a0fb 100644
--- a/init/sigchld_handler.cpp
+++ b/init/sigchld_handler.cpp
@@ -84,15 +84,16 @@
}
}
- if (siginfo.si_code == CLD_EXITED) {
- LOG(INFO) << name << " exited with status " << siginfo.si_status << wait_string;
- } else {
- LOG(INFO) << name << " received signal " << siginfo.si_status << wait_string;
+ auto status = siginfo.si_status;
+ if (WIFEXITED(status)) {
+ LOG(INFO) << name << " exited with status " << WEXITSTATUS(status) << wait_string;
+ } else if (WIFSIGNALED(status)) {
+ LOG(INFO) << name << " killed by signal " << WTERMSIG(status) << wait_string;
}
if (!service) return true;
- service->Reap(siginfo);
+ service->Reap();
if (service->flags() & SVC_TEMPORARY) {
ServiceList::GetInstance().RemoveService(*service);
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index faab368..c1846f7 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -49,6 +49,11 @@
const std::string kInitContext = "u:r:init:s0";
const std::string kVendorContext = "u:r:vendor_init:s0";
+const char* const paths_and_secontexts[2][2] = {
+ {"/vendor", kVendorContext.c_str()},
+ {"/odm", kVendorContext.c_str()},
+};
+
namespace {
constexpr size_t kBufferSize = 4096;
@@ -297,7 +302,11 @@
for (const auto& property : subcontext_reply->properties_to_set()) {
ucred cr = {.pid = pid_, .uid = 0, .gid = 0};
- HandlePropertySet(property.name(), property.value(), context_, cr);
+ std::string error;
+ if (HandlePropertySet(property.name(), property.value(), context_, cr, &error) != 0) {
+ LOG(ERROR) << "Subcontext init could not set '" << property.name() << "' to '"
+ << property.value() << "': " << error;
+ }
}
if (subcontext_reply->reply_case() == SubcontextReply::kFailure) {
@@ -345,9 +354,6 @@
static std::vector<Subcontext> subcontexts;
std::vector<Subcontext>* InitializeSubcontexts() {
- static const char* const paths_and_secontexts[][2] = {
- {"/vendor", kVendorContext.c_str()},
- };
for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
subcontexts.emplace_back(path_prefix, secontext);
}
diff --git a/init/subcontext.h b/init/subcontext.h
index 5601b80..22d7d43 100644
--- a/init/subcontext.h
+++ b/init/subcontext.h
@@ -33,6 +33,7 @@
extern const std::string kInitContext;
extern const std::string kVendorContext;
+extern const char* const paths_and_secontexts[2][2];
class Subcontext {
public:
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index f9f8c73..5e5e7af 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -224,7 +224,9 @@
return kInvalidOffset;
}
if (eocd->num_records == 0) {
+#if defined(__ANDROID__)
ALOGW("Zip: empty archive?");
+#endif
return kEmptyArchive;
}
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 560f490..b8af2f0 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -198,7 +198,7 @@
int LogBuffer::log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
pid_t tid, const char* msg, unsigned short len) {
- if ((log_id >= LOG_ID_MAX) || (log_id < 0)) {
+ if (log_id >= LOG_ID_MAX) {
return -EINVAL;
}