summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Cherry2018-05-03 18:57:19 -0500
committerTom Cherry2018-05-22 15:44:34 -0500
commit5ab2e1c8f7d19713869e45c3f006b9ad7abb7753 (patch)
treeb2522ab9894cf5965fde32bb692a21d7b293e635
parent827de1993271f28110696df6ff809947184ba550 (diff)
downloadplatform-system-core-5ab2e1c8f7d19713869e45c3f006b9ad7abb7753.tar.gz
platform-system-core-5ab2e1c8f7d19713869e45c3f006b9ad7abb7753.tar.xz
platform-system-core-5ab2e1c8f7d19713869e45c3f006b9ad7abb7753.zip
init: finer grained permissions for ctl. properties
Currently, permissions for ctl. property apply to each action verb, so if a domain has permissions for controlling service 'foo', then it can start, stop, and restart foo. This change implements finer grainer permissions such that permission can be given to strictly start a given service, but not stop or restart it. This new permission scheme is mandatory for the new control functions, sigstop_on, sigstop_off, interface_start, interface_stop, interface_restart. Bug: 78511553 Test: see appropriate successes and failures based on permissions Merged-In: I6ce915ae39954a67eb6fe1795a93cf715c352ae4 Change-Id: I6ce915ae39954a67eb6fe1795a93cf715c352ae4 (cherry picked from commit 1debdcf1cf3d45ba9185ab47a265995c676280d8)
-rw-r--r--init/property_service.cpp50
-rw-r--r--init/property_service.h5
2 files changed, 39 insertions, 16 deletions
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 741fde0b9..d1c427dba 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -95,6 +95,11 @@ uint32_t (*property_set)(const std::string& name, const std::string& value) = In
95 95
96void CreateSerializedPropertyInfo(); 96void CreateSerializedPropertyInfo();
97 97
98struct PropertyAuditData {
99 const ucred* cr;
100 const char* name;
101};
102
98void property_init() { 103void property_init() {
99 mkdir("/dev/__properties__", S_IRWXU | S_IXGRP | S_IXOTH); 104 mkdir("/dev/__properties__", S_IRWXU | S_IXGRP | S_IXOTH);
100 CreateSerializedPropertyInfo(); 105 CreateSerializedPropertyInfo();
@@ -111,7 +116,7 @@ static bool CheckMacPerms(const std::string& name, const char* target_context,
111 return false; 116 return false;
112 } 117 }
113 118
114 property_audit_data audit_data; 119 PropertyAuditData audit_data;
115 120
116 audit_data.name = name.c_str(); 121 audit_data.name = name.c_str();
117 audit_data.cr = &cr; 122 audit_data.cr = &cr;
@@ -393,6 +398,35 @@ class SocketConnection {
393 DISALLOW_IMPLICIT_CONSTRUCTORS(SocketConnection); 398 DISALLOW_IMPLICIT_CONSTRUCTORS(SocketConnection);
394}; 399};
395 400
401bool CheckControlPropertyPerms(const std::string& name, const std::string& value,
402 const std::string& source_context, const ucred& cr) {
403 // We check the legacy method first but these properties are dontaudit, so we only log an audit
404 // if the newer method fails as well. We only do this with the legacy ctl. properties.
405 if (name == "ctl.start" || name == "ctl.stop" || name == "ctl.restart") {
406 // The legacy permissions model is that ctl. properties have their name ctl.<action> and
407 // their value is the name of the service to apply that action to. Permissions for these
408 // actions are based on the service, so we must create a fake name of ctl.<service> to
409 // check permissions.
410 auto control_string_legacy = "ctl." + value;
411 const char* target_context_legacy = nullptr;
412 const char* type_legacy = nullptr;
413 property_info_area->GetPropertyInfo(control_string_legacy.c_str(), &target_context_legacy,
414 &type_legacy);
415
416 if (CheckMacPerms(control_string_legacy, target_context_legacy, source_context.c_str(), cr)) {
417 return true;
418 }
419 }
420
421 auto control_string_full = name + "$" + value;
422 const char* target_context_full = nullptr;
423 const char* type_full = nullptr;
424 property_info_area->GetPropertyInfo(control_string_full.c_str(), &target_context_full,
425 &type_full);
426
427 return CheckMacPerms(control_string_full, target_context_full, source_context.c_str(), cr);
428}
429
396// This returns one of the enum of PROP_SUCCESS or PROP_ERROR*. 430// This returns one of the enum of PROP_SUCCESS or PROP_ERROR*.
397uint32_t HandlePropertySet(const std::string& name, const std::string& value, 431uint32_t HandlePropertySet(const std::string& name, const std::string& value,
398 const std::string& source_context, const ucred& cr, std::string* error) { 432 const std::string& source_context, const ucred& cr, std::string* error) {
@@ -402,15 +436,9 @@ uint32_t HandlePropertySet(const std::string& name, const std::string& value,
402 } 436 }
403 437
404 if (StartsWith(name, "ctl.")) { 438 if (StartsWith(name, "ctl.")) {
405 // ctl. properties have their name ctl.<action> and their value is the name of the service 439 if (!CheckControlPropertyPerms(name, value, source_context, cr)) {
406 // to apply that action to. Permissions for these actions are based on the service, so we 440 *error = StringPrintf("Invalid permissions to perform '%s' on '%s'", name.c_str() + 4,
407 // must create a fake name of ctl.<service> to check permissions. 441 value.c_str());
408 auto control_string = "ctl." + value;
409 const char* target_context = nullptr;
410 const char* type = nullptr;
411 property_info_area->GetPropertyInfo(control_string.c_str(), &target_context, &type);
412 if (!CheckMacPerms(control_string, target_context, source_context.c_str(), cr)) {
413 *error = StringPrintf("Unable to '%s' service %s", name.c_str() + 4, value.c_str());
414 return PROP_ERROR_HANDLE_CONTROL_MESSAGE; 442 return PROP_ERROR_HANDLE_CONTROL_MESSAGE;
415 } 443 }
416 444
@@ -742,7 +770,7 @@ void load_system_props() {
742} 770}
743 771
744static int SelinuxAuditCallback(void* data, security_class_t /*cls*/, char* buf, size_t len) { 772static int SelinuxAuditCallback(void* data, security_class_t /*cls*/, char* buf, size_t len) {
745 property_audit_data* d = reinterpret_cast<property_audit_data*>(data); 773 auto* d = reinterpret_cast<PropertyAuditData*>(data);
746 774
747 if (!d || !d->name || !d->cr) { 775 if (!d || !d->name || !d->cr) {
748 LOG(ERROR) << "AuditCallback invoked with null data arguments!"; 776 LOG(ERROR) << "AuditCallback invoked with null data arguments!";
diff --git a/init/property_service.h b/init/property_service.h
index 4a354c27f..cacd987f7 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -26,11 +26,6 @@
26namespace android { 26namespace android {
27namespace init { 27namespace init {
28 28
29struct property_audit_data {
30 const ucred* cr;
31 const char* name;
32};
33
34extern uint32_t (*property_set)(const std::string& name, const std::string& value); 29extern uint32_t (*property_set)(const std::string& name, const std::string& value);
35 30
36uint32_t HandlePropertySet(const std::string& name, const std::string& value, 31uint32_t HandlePropertySet(const std::string& name, const std::string& value,