Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions libc/bionic/system_property_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,8 @@ int __system_properties_zygote_reload(void) {
CHECK(getpid() == gettid());
return system_properties.EnableOverrides() ? 0 : -1;
}

__BIONIC_WEAK_FOR_NATIVE_BRIDGE
int __system_properties_enable_extended_override(void) {
return system_properties.EnableExtendedOverrides() ? 0 : -1;
}
2 changes: 2 additions & 0 deletions libc/include/sys/system_properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@ int __system_property_update(prop_info* _Nonnull __pi, const char* _Nonnull __va
* Available since API level 35.
*/
int __system_properties_zygote_reload(void) __INTRODUCED_IN(35);

int __system_properties_enable_extended_override(void);
#endif

/**
Expand Down
1 change: 1 addition & 0 deletions libc/libc.map.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1612,6 +1612,7 @@ LIBC_V { # introduced=35
tzfree;
wcsrtombs_l;
__system_properties_zygote_reload; # apex
__system_properties_enable_extended_override; # apex
} LIBC_U;

LIBC_36 { # introduced=36
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class SystemProperties {

bool Init(const char* filename);
bool EnableOverrides();
bool EnableExtendedOverrides();
bool AreaInit(const char* filename, bool* fsetxattr_failed);
bool AreaInit(const char* filename, bool* fsetxattr_failed, bool load_default_path);
uint32_t AreaSerial();
Expand Down Expand Up @@ -91,6 +92,7 @@ class SystemProperties {

bool initialized_;
bool use_appcompat_override_;
bool use_extended_override_;
PropertiesFilename properties_filename_;
PropertiesFilename appcompat_filename_;
};
42 changes: 42 additions & 0 deletions libc/system_properties/system_properties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#define SERIAL_VALUE_LEN(serial) ((serial) >> 24)
#define APPCOMPAT_PREFIX "ro.appcompat_override."
#define APPCOMPAT_OVERRIDE_ENV_VAR "BIONIC_APPCOMPAT_OVERRIDE"
#define EXTENDED_OVERRIDE_ENV_VAR "GOS_HIDE_CARRIER_INFO_PROP_OVERRIDE"

static bool is_dir(const char* pathname) {
struct stat info;
Expand Down Expand Up @@ -81,6 +82,11 @@ bool SystemProperties::Init(const char* filename) {
use_appcompat_override_ = true;
}

if (getenv(EXTENDED_OVERRIDE_ENV_VAR) != nullptr) {
use_appcompat_override_ = true;
use_extended_override_ = true;
}

initialized_ = true;
return true;
}
Expand Down Expand Up @@ -151,6 +157,33 @@ bool SystemProperties::EnableOverrides() {
return true;
}

bool SystemProperties::EnableExtendedOverrides() {
CHECK(initialized_);
use_appcompat_override_ = true;
use_extended_override_ = true;
putenv(const_cast<char*>(APPCOMPAT_OVERRIDE_ENV_VAR "=1"));
putenv(const_cast<char*>(EXTENDED_OVERRIDE_ENV_VAR "=1"));
return true;
}

static const char* const kHideCarrierInfoDeniedProps[] = {
"gsm.sim.operator.alpha",
"gsm.sim.operator.numeric",
"gsm.sim.operator.iso-country",
"gsm.operator.alpha",
"gsm.operator.numeric",
"gsm.operator.iso-country",
"gsm.operator.isroaming",
"gsm.sim.state",
};

static bool is_hide_carrier_info_denied(const char* name) {
for (const char* denied : kHideCarrierInfoDeniedProps) {
if (strcmp(name, denied) == 0) return true;
}
return false;
}

uint32_t SystemProperties::AreaSerial() {
if (!initialized_) {
return -1;
Expand All @@ -170,6 +203,10 @@ const prop_info* SystemProperties::Find(const char* name) {
return nullptr;
}

if (use_extended_override_ && is_hide_carrier_info_denied(name)) {
return nullptr;
}

// if appcompat override is enabled, we first try finding APPCOMPAT_PREFIXed system
// property
if (use_appcompat_override_) {
Expand Down Expand Up @@ -428,6 +465,11 @@ int SystemProperties::Add(const char* name, unsigned int namelen, const char* va
CHECK(getpid() == 1 || getuid() == 0);
atomic_thread_fence(memory_order_release);
memcpy(other_pi->value, value, valuelen + 1);
// the high byte of serial encodes value length, we need to update it so readers
// (that use SERIAL_VALUE_LEN) return the full overridden string.
uint32_t old_serial = atomic_load_explicit(&other_pi->serial, memory_order_relaxed);
uint32_t new_serial = (valuelen << 24) | (old_serial & 0x00ffffff);
atomic_store_explicit(&other_pi->serial, new_serial, memory_order_release);
}
}

Expand Down
48 changes: 48 additions & 0 deletions tests/Android.bp
Original file line number Diff line number Diff line change
Expand Up @@ -1322,6 +1322,54 @@ cc_test {
],
}

// minial static binary for just the system properties tests
cc_test {
name: "bionic-sysprop-tests",
gtest: false,
defaults: [
"bionic_tests_defaults",
"large_system_property_node_defaults",
],
host_supported: false,
test_suites: ["general-tests"],

srcs: [
"gtest_globals.cpp",
"gtest_main.cpp",
"system_properties_test.cpp",
"utils.cpp",
],

include_dirs: [
"bionic/libc",
],

target: {
bionic: {
whole_static_libs: [
"libasync_safe",
"libprocinfo",
"libsystemproperties",
],
},
},

static_libs: [
"libm",
"libc",
"libdl",
"liblog",
"libbase",
"libgtest_isolated",
],

static_executable: true,
stl: "libc++_static",
lto: {
never: true,
},
}

// -----------------------------------------------------------------------------
// Tests to run on the host and linked against glibc. Run with:
// cd bionic/tests; mm bionic-unit-tests-glibc-run
Expand Down
65 changes: 65 additions & 0 deletions tests/system_properties_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,71 @@ TEST(properties, __system_property_getprop_appcompat) {
#endif // __BIONIC__
}

TEST(properties, __system_property_add_extended_override) {
#if defined(__BIONIC__)
SystemPropertiesTest system_properties;
ASSERT_TRUE(system_properties.valid());

ASSERT_EQ(0, system_properties.Add("gsm.sim.operator.numeric", 24, "123456", 6));
ASSERT_EQ(0, system_properties.Add("ro.other.prop", 13, "value", 5));

char propvalue[PROP_VALUE_MAX];

// before enabling: denied prop is readable
ASSERT_EQ(6, system_properties.Get("gsm.sim.operator.numeric", propvalue));
ASSERT_STREQ(propvalue, "123456");
ASSERT_NE(nullptr, system_properties.Find("gsm.sim.operator.numeric"));

system_properties.EnableExtendedOverrides();

// after enabling: denied prop hidden from Find and Get
ASSERT_EQ(nullptr, system_properties.Find("gsm.sim.operator.numeric"));
ASSERT_EQ(0, system_properties.Get("gsm.sim.operator.numeric", propvalue));
ASSERT_STREQ(propvalue, "");

// non-denied prop unaffected
ASSERT_EQ(5, system_properties.Get("ro.other.prop", propvalue));
ASSERT_STREQ(propvalue, "value");
#else // __BIONIC__
GTEST_SKIP() << "bionic-only test";
#endif // __BIONIC__
}

TEST(properties, __system_property_update_extended_override_denylist) {
#if defined(__BIONIC__)
SystemPropertiesTest system_properties;
ASSERT_TRUE(system_properties.valid());

ASSERT_EQ(0, system_properties.Add("gsm.sim.operator.numeric", 24, "123456", 6));
ASSERT_EQ(0, system_properties.Add("gsm.version.baseband", 20, "v1", 2));

// capture prop_info* before enabling override (Find returns nullptr afterward for denied props)
const prop_info* denied_pi = system_properties.Find("gsm.sim.operator.numeric");
ASSERT_NE(nullptr, denied_pi);
const prop_info* allowed_pi = system_properties.Find("gsm.version.baseband");
ASSERT_NE(nullptr, allowed_pi);

system_properties.EnableExtendedOverrides();

// update underlying values (as init would)
system_properties.Update(const_cast<prop_info*>(denied_pi), "654321", 6);
system_properties.Update(const_cast<prop_info*>(allowed_pi), "v2", 2);

char propvalue[PROP_VALUE_MAX];

// denied prop still hidden after update
ASSERT_EQ(nullptr, system_properties.Find("gsm.sim.operator.numeric"));
ASSERT_EQ(0, system_properties.Get("gsm.sim.operator.numeric", propvalue));
ASSERT_STREQ(propvalue, "");

// allowed prop updated normally
ASSERT_EQ(2, system_properties.Get("gsm.version.baseband", propvalue));
ASSERT_STREQ(propvalue, "v2");
#else // __BIONIC__
GTEST_SKIP() << "bionic-only test";
#endif // __BIONIC__
}

TEST(properties, __system_property_update) {
#if defined(__BIONIC__)
SystemPropertiesTest system_properties;
Expand Down