#ifdefined(__ANDROID__) // Generated android_ids array #include"generated_android_ids.h" #else // Empty array for host; everything is from the database files #include"empty_android_ids.h" #endif
// POSIX seems to envisage an implementation where the <pwd.h> functions are // implemented by brute-force searching with getpwent(3), and the <grp.h> // functions are implemented similarly with getgrent(3). This means that it's // okay for all the <grp.h> functions to share state, and all the <passwd.h> // functions to share state, but <grp.h> functions can't clobber <passwd.h> // functions' state and vice versa. #include"bionic/pthread_internal.h"
group* gr = &state->group_;
gr->gr_gid = iinfo->aid; return gr;
}
staticconst android_id_info* find_android_id_info(unsigned id) { for (size_t n = 0; n < android_id_count; ++n) { if (android_ids[n].aid == id) { return &android_ids[n];
}
} return nullptr;
}
staticconst android_id_info* find_android_id_info(constchar* name) { for (size_t n = 0; n < android_id_count; ++n) { if (!strcmp(android_ids[n].name, name)) { return &android_ids[n];
}
} return nullptr;
}
// These are a list of the reserved app ranges, and should never contain anything below // AID_APP_START. They exist per user, so a given uid/gid modulo AID_USER_OFFSET will map // to these ranges. struct IdRange {
id_t start;
id_t end;
};
template <class T, size_t N> static constexpr bool verify_user_ranges_ascending(T (&ranges)[N]) { auto array_size = N; if (array_size < 2) returnfalse;
if (ranges[0].start > ranges[0].end) returnfalse;
for (size_t i = 1; i < array_size; ++i) { if (ranges[i].start > ranges[i].end) returnfalse; if (ranges[i - 1].end > ranges[i].start) returnfalse;
} returntrue;
}
static_assert(verify_user_ranges_ascending(user_ranges), "user_ranges must have ascending ranges");
static_assert(verify_user_ranges_ascending(group_ranges), "user_ranges must have ascending ranges");
// This list comes from PackageManagerService.java, where platform AIDs are added to list of valid // AIDs for packages via addSharedUserLPw(). static constexpr const id_t secondary_user_platform_ids[] = {
AID_SYSTEM, AID_RADIO, AID_LOG, AID_NFC, AID_BLUETOOTH,
AID_SHELL, AID_SECURE_ELEMENT, AID_NETWORK_STACK,
};
staticbool platform_id_secondary_user_allowed(id_t id) { for (constauto& allowed_id : secondary_user_platform_ids) { if (allowed_id == id) { returntrue;
}
} returnfalse;
}
// AID_OVERFLOWUID is never a valid app id, so we explicitly return false to ensure this. // This is true across all users, as there is no reason to ever map this id into any user range. if (appid == AID_OVERFLOWUID) { returnfalse;
}
auto ranges_size = is_group ? arraysize(group_ranges) : arraysize(user_ranges); auto ranges = is_group ? group_ranges : user_ranges;
// If we're checking an appid that resolves below the user range, then it's a platform AID for a // seconary user. We only allow a reduced set of these, so we must check that it is allowed. if (appid < ranges[0].start && platform_id_secondary_user_allowed(appid)) { returntrue;
}
// The shared GID range is only valid for the first user. if (appid >= AID_SHARED_GID_START && appid <= AID_SHARED_GID_END && appid != id) { returnfalse;
}
// Otherwise check that the appid is in one of the reserved ranges. for (size_t i = 0; i < ranges_size; ++i) { if (appid >= ranges[i].start && appid <= ranges[i].end) { returntrue;
}
}
returnfalse;
} #else staticbool is_valid_app_id(id_t, bool) { // Host doesn't have the concept of app_id returnfalse;
} #endif// if defined(__ANDROID__)
// This provides an iterator for app_ids within the first user's app id's. static id_t get_next_app_id(id_t current_id, bool is_group) { auto ranges_size = is_group ? arraysize(group_ranges) : arraysize(user_ranges); auto ranges = is_group ? group_ranges : user_ranges;
// If current_id is below the first of the ranges, then we're uninitialized, and return the first // valid id. if (current_id < ranges[0].start) { return ranges[0].start;
}
id_t incremented_id = current_id + 1;
// Check to see if our incremented_id is between two ranges, and if so, return the beginning of // the next valid range. for (size_t i = 1; i < ranges_size; ++i) { if (incremented_id > ranges[i - 1].end && incremented_id < ranges[i].start) { return ranges[i].start;
}
}
// Check to see if our incremented_id is above final range, and return -1 to indicate that we've // completed if so. if (incremented_id > ranges[ranges_size - 1].end) { return -1;
}
// Otherwise the incremented_id is valid, so return it. return incremented_id;
}
// Translate a user/group name to the corresponding user/group id. // all_a1234 -> 0 * AID_USER_OFFSET + AID_SHARED_GID_START + 1234 (group name only) // u0_a1234_ext_cache -> 0 * AID_USER_OFFSET + AID_EXT_CACHE_GID_START + 1234 (group name only) // u0_a1234_ext -> 0 * AID_USER_OFFSET + AID_EXT_GID_START + 1234 (group name only) // u0_a1234_cache -> 0 * AID_USER_OFFSET + AID_CACHE_GID_START + 1234 (group name only) // u0_a1234 -> 0 * AID_USER_OFFSET + AID_APP_START + 1234 // u2_i1000 -> 2 * AID_USER_OFFSET + AID_ISOLATED_START + 1000 // u1_system -> 1 * AID_USER_OFFSET + android_ids['system'] // returns 0 and sets errno to ENOENT in case of error. static id_t app_id_from_name(constchar* name, bool is_group) { char* end; unsignedlong userid; bool is_shared_gid = false;
#ifdefined(__ANDROID__) staticbool device_launched_before_api_29() { // Check if ro.product.first_api_level is set to a value > 0 and < 29, if so, this device was // launched before API 29 (Q). Any other value is considered to be either in development or // launched after. // Cache the value as __system_property_get() is expensive and this may be called often. staticbool result = [] { char value[PROP_VALUE_MAX] = { 0 }; if (__system_property_get("ro.product.first_api_level", value) == 0) { returnfalse;
} int value_int = atoi(value); return value_int != 0 && value_int < 29;
}(); return result;
}
// oem_XXXX -> uid // Supported ranges: // AID_OEM_RESERVED_START to AID_OEM_RESERVED_END (2900-2999) // AID_OEM_RESERVED_2_START to AID_OEM_RESERVED_2_END (5000-5999) // Check OEM id is within range. staticbool is_oem_id(id_t id) { // Upgrading devices launched before API level 29 may not comply with the below check. // Due to the difficulty in changing uids after launch, it is waived for these devices. // The legacy range: // AID_OEM_RESERVED_START to AID_EVERYBODY (2900-9996), excluding builtin AIDs. if (device_launched_before_api_29() && id >= AID_OEM_RESERVED_START && id < AID_EVERYBODY &&
find_android_id_info(id) == nullptr) { returntrue;
}
return (id >= AID_OEM_RESERVED_START && id <= AID_OEM_RESERVED_END) ||
(id >= AID_OEM_RESERVED_2_START && id <= AID_OEM_RESERVED_2_END);
} #else staticbool is_oem_id(id_t) { // no OEM ids in host returnfalse;
} #endif// if defined(__ANDROID__)
// Translate an OEM name to the corresponding user/group id. static id_t oem_id_from_name(constchar* name) { unsignedint id; if (sscanf(name, "oem_%u", &id) != 1) { return0;
} if (!is_oem_id(id)) { return0;
} returnstatic_cast<id_t>(id);
}
// Find an entry from the database file for (auto& passwd_file : passwd_files) { if (passwd_file.FindByName(login, state)) { return &state->passwd_;
}
}
// All users are in just one group, the one passed in. // In practice, id(1) will show you in a lot more groups, because adbd // adds you to a lot of supplementary groups when dropping privileges. int getgrouplist(constchar* /*user*/, gid_t group, gid_t* groups, int* ngroups) { if (*ngroups < 1) {
*ngroups = 1; return -1;
}
groups[0] = group; return (*ngroups = 1);
}
// See getgrouplist() to understand why we don't call it. int initgroups(constchar* /*user*/, gid_t group) {
gid_t groups[] = {group}; return setgroups(1, groups);
}
char* getlogin() { // NOLINT: implementing bad function.
passwd *pw = getpwuid(getuid()); // NOLINT: implementing bad function in terms of bad function. return pw ? pw->pw_name : nullptr;
}
start = end;
end += AID_SYSTEM_EXT_RESERVED_END - AID_SYSTEM_RESERVED_START + 1;
if (state->getpwent_idx < end) { // No one calls this enough to worry about how inefficient the below is. auto* oem_passwd =
oem_id_to_passwd(state->getpwent_idx++ - start + AID_SYSTEM_RESERVED_START, state); while (oem_passwd == nullptr && state->getpwent_idx < end) {
oem_passwd =
oem_id_to_passwd(state->getpwent_idx++ - start + AID_SYSTEM_RESERVED_START, state);
} if (oem_passwd != nullptr) { return oem_passwd;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.