diff options
author | Elliott Hughes <enh@google.com> | 2017-04-06 18:20:53 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-04-06 18:20:53 +0000 |
commit | 13bbe5ac7dfa5fed10cb6c0346cba55e3c506fd7 (patch) | |
tree | 0042c5148071c78240b2915f3f053ac82406402c | |
parent | 1a114d46f8c962a4d8885c1811de0adfae600fcb (diff) | |
parent | f971076ac9586e844bb8f342f5f3a12b91d934fb (diff) | |
download | android_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.md | 6 | ||||
-rw-r--r-- | libc/private/CachedProperty.h | 87 | ||||
-rw-r--r-- | linker/linker.cpp | 2 | ||||
-rw-r--r-- | linker/linker_logger.cpp | 84 | ||||
-rw-r--r-- | linker/linker_logger.h | 4 |
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_ */ |