aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2017-04-06 18:20:53 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-04-06 18:20:53 +0000
commit13bbe5ac7dfa5fed10cb6c0346cba55e3c506fd7 (patch)
tree0042c5148071c78240b2915f3f053ac82406402c
parent1a114d46f8c962a4d8885c1811de0adfae600fcb (diff)
parentf971076ac9586e844bb8f342f5f3a12b91d934fb (diff)
downloadandroid_bionic-13bbe5ac7dfa5fed10cb6c0346cba55e3c506fd7.tar.gz
android_bionic-13bbe5ac7dfa5fed10cb6c0346cba55e3c506fd7.tar.bz2
android_bionic-13bbe5ac7dfa5fed10cb6c0346cba55e3c506fd7.zip
Merge "Add support for disabling the greylist." into oc-dev
am: f971076ac9 Change-Id: Ibb341dc707295b9df812a81d76f47c83da869f59
-rw-r--r--android-changes-for-ndk-developers.md6
-rw-r--r--libc/private/CachedProperty.h87
-rw-r--r--linker/linker.cpp2
-rw-r--r--linker/linker_logger.cpp84
-rw-r--r--linker/linker_logger.h4
5 files changed, 142 insertions, 41 deletions
diff --git a/android-changes-for-ndk-developers.md b/android-changes-for-ndk-developers.md
index ebdae838a..527911834 100644
--- a/android-changes-for-ndk-developers.md
+++ b/android-changes-for-ndk-developers.md
@@ -145,6 +145,12 @@ and libssl.so). In order to give you more time to transition, we will
temporarily support these libraries; so if you see a warning that means
your code will not work in a future release -- please fix it now!
+In O and later, the system property `debug.ld.greylist_disabled` can be
+used to deny access to the greylist even to an app that would normally
+be allowed it. This allows you to test compatibility without bumping the
+app's `targetSdkVersion`. Use `setprop debug.ld.greylist_disabled true`
+to turn this on (any other value leaves the greylist enabled).
+
```
$ readelf --dynamic libBroken.so | grep NEEDED
0x00000001 (NEEDED) Shared library: [libnativehelper.so]
diff --git a/libc/private/CachedProperty.h b/libc/private/CachedProperty.h
new file mode 100644
index 000000000..0a41abf80
--- /dev/null
+++ b/libc/private/CachedProperty.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <string.h>
+
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+
+#include "private/bionic_lock.h"
+
+class CachedProperty {
+ public:
+ CachedProperty(const char* property_name)
+ : property_name_(property_name),
+ prop_info_(nullptr),
+ cached_area_serial_(0),
+ cached_property_serial_(0) {
+ cached_value_[0] = '\0';
+ }
+
+ const char* Get() {
+ lock_.lock();
+
+ // Do we have a `struct prop_info` yet?
+ if (prop_info_ == nullptr) {
+ // `__system_property_find` is expensive, so only retry if a property
+ // has been created since last time we checked.
+ uint32_t property_area_serial = __system_property_area_serial();
+ if (property_area_serial != cached_area_serial_) {
+ prop_info_ = __system_property_find(property_name_);
+ cached_area_serial_ = property_area_serial;
+ }
+ }
+
+ if (prop_info_ != nullptr) {
+ // Only bother re-reading the property if it's actually changed since last time.
+ uint32_t property_serial = __system_property_serial(prop_info_);
+ if (property_serial != cached_property_serial_) {
+ __system_property_read_callback(prop_info_, &CachedProperty::Callback, this);
+ }
+ }
+
+ lock_.unlock();
+ return cached_value_;
+ }
+
+ private:
+ Lock lock_;
+ const char* property_name_;
+ const prop_info* prop_info_;
+ uint32_t cached_area_serial_;
+ uint32_t cached_property_serial_;
+ char cached_value_[PROP_VALUE_MAX];
+
+ static void Callback(void* data, const char*, const char* value, uint32_t serial) {
+ CachedProperty* instance = reinterpret_cast<CachedProperty*>(data);
+ instance->cached_property_serial_ = serial;
+ strcpy(instance->cached_value_, value);
+ }
+};
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 1647db70b..2777d7384 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -185,7 +185,7 @@ static bool is_greylisted(android_namespace_t* ns, const char* name, const soinf
};
// If you're targeting N, you don't get the greylist.
- if (get_application_target_sdk_version() >= __ANDROID_API_N__) {
+ if (g_greylist_disabled || get_application_target_sdk_version() >= __ANDROID_API_N__) {
return false;
}
diff --git a/linker/linker_logger.cpp b/linker/linker_logger.cpp
index b2ea320ea..717667ca8 100644
--- a/linker/linker_logger.cpp
+++ b/linker/linker_logger.cpp
@@ -26,32 +26,21 @@
* SUCH DAMAGE.
*/
+#include "linker_logger.h"
+
#include <string.h>
#include <sys/prctl.h>
-#include <sys/system_properties.h>
#include <unistd.h>
#include <string>
#include <vector>
#include "android-base/strings.h"
-#include "linker_logger.h"
+#include "private/CachedProperty.h"
#include "private/libc_logging.h"
LinkerLogger g_linker_logger;
-
-static const char* kSystemLdDebugProperty = "debug.ld.all";
-static const char* kLdDebugPropertyPrefix = "debug.ld.app.";
-
-static const char* kOptionErrors = "dlerror";
-static const char* kOptionDlopen = "dlopen";
-static const char* kOptionDlsym = "dlsym";
-
-static std::string property_get(const char* name) {
- char value[PROP_VALUE_MAX] = {};
- __system_property_get(name, value);
- return value;
-}
+bool g_greylist_disabled = false;
static uint32_t ParseProperty(const std::string& value) {
if (value.empty()) {
@@ -63,53 +52,69 @@ static uint32_t ParseProperty(const std::string& value) {
uint32_t flags = 0;
for (const auto& o : options) {
- if (o == kOptionErrors) {
+ if (o == "dlerror") {
flags |= kLogErrors;
- } else if (o == kOptionDlopen){
+ } else if (o == "dlopen") {
flags |= kLogDlopen;
- } else if (o == kOptionDlsym){
+ } else if (o == "dlsym") {
flags |= kLogDlsym;
} else {
- __libc_format_log(ANDROID_LOG_WARN, "linker", "Unknown debug.ld option \"%s\", will ignore.", o.c_str());
+ __libc_format_log(ANDROID_LOG_WARN, "linker", "Ignoring unknown debug.ld option \"%s\"",
+ o.c_str());
}
}
return flags;
}
+static void GetAppSpecificProperty(char* buffer) {
+ // Get process basename.
+ const char* process_name_start = basename(g_argv[0]);
+
+ // Remove ':' and everything after it. This is the naming convention for
+ // services: https://developer.android.com/guide/components/services.html
+ const char* process_name_end = strchr(process_name_start, ':');
+
+ std::string process_name = (process_name_end != nullptr) ?
+ std::string(process_name_start, (process_name_end - process_name_start)) :
+ std::string(process_name_start);
+
+ std::string property_name = std::string("debug.ld.app.") + process_name;
+ __system_property_get(property_name.c_str(), buffer);
+}
+
void LinkerLogger::ResetState() {
- // the most likely scenario app is not debuggable and
- // is running on user build - the logging is disabled.
+ // The most likely scenario app is not debuggable and
+ // is running on a user build, in which case logging is disabled.
if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) {
return;
}
+ // This is a convenient place to check whether the greylist should be disabled for testing.
+ static CachedProperty greylist_disabled("debug.ld.greylist_disabled");
+ bool old_value = g_greylist_disabled;
+ g_greylist_disabled = (strcmp(greylist_disabled.Get(), "true") == 0);
+ if (g_greylist_disabled != old_value) {
+ __libc_format_log(ANDROID_LOG_INFO, "linker", "%s greylist",
+ g_greylist_disabled ? "Disabling" : "Enabling");
+ }
+
flags_ = 0;
- // Check flag applied to all processes first.
- std::string value = property_get(kSystemLdDebugProperty);
- flags_ |= ParseProperty(value);
+ // For logging, check the flag applied to all processes first.
+ static CachedProperty debug_ld_all("debug.ld.all");
+ flags_ |= ParseProperty(debug_ld_all.Get());
// Ignore processes started without argv (http://b/33276926).
if (g_argv[0] == nullptr) {
return;
}
- // Get process basename.
- const char* process_name_start = basename(g_argv[0]);
-
- // Remove ':' and everything after it. This is the naming convention for
- // services: https://developer.android.com/guide/components/services.html
- const char* process_name_end = strchr(process_name_start, ':');
-
- std::string process_name = (process_name_end != nullptr) ?
- std::string(process_name_start, (process_name_end - process_name_start)) :
- std::string(process_name_start);
-
- std::string property_name = std::string(kLdDebugPropertyPrefix) + process_name;
-
- value = property_get(property_name.c_str());
- flags_ |= ParseProperty(value);
+ // Otherwise check the app-specific property too.
+ // We can't easily cache the property here because argv[0] changes.
+ char debug_ld_app[PROP_VALUE_MAX] = {};
+ GetAppSpecificProperty(debug_ld_app);
+ flags_ |= ParseProperty(debug_ld_app);
}
void LinkerLogger::Log(uint32_t type, const char* format, ...) {
@@ -122,4 +127,3 @@ void LinkerLogger::Log(uint32_t type, const char* format, ...) {
__libc_format_log_va_list(ANDROID_LOG_DEBUG, "linker", format, ap);
va_end(ap);
}
-
diff --git a/linker/linker_logger.h b/linker/linker_logger.h
index f37b9740e..3e53f7404 100644
--- a/linker/linker_logger.h
+++ b/linker/linker_logger.h
@@ -58,4 +58,8 @@ class LinkerLogger {
extern LinkerLogger g_linker_logger;
extern char** g_argv;
+// If the system property debug.ld.greylist_disabled is true, we'll not use the greylist
+// regardless of API level.
+extern bool g_greylist_disabled;
+
#endif /* _LINKER_LOGGER_H_ */