Loading libs/binder/BpBinder.cpp +6 −5 Original line number Diff line number Diff line Loading @@ -223,13 +223,14 @@ status_t BpBinder::transact( if (code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION) { using android::internal::Stability; auto stability = Stability::get(this); auto required = privateVendor ? Stability::VENDOR : Stability::getLocalStability(); auto category = Stability::getCategory(this); Stability::Level required = privateVendor ? Stability::VENDOR : Stability::getLocalLevel(); if (CC_UNLIKELY(!Stability::check(stability, required))) { if (CC_UNLIKELY(!Stability::check(category, required))) { ALOGE("Cannot do a user transaction on a %s binder in a %s context.", Stability::stabilityString(stability).c_str(), Stability::stabilityString(required).c_str()); category.debugString().c_str(), Stability::levelString(required).c_str()); return BAD_TYPE; } } Loading libs/binder/Parcel.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -171,7 +171,8 @@ status_t Parcel::finishFlattenBinder( if (status != OK) return status; internal::Stability::tryMarkCompilationUnit(binder.get()); return writeInt32(internal::Stability::get(binder.get())); auto category = internal::Stability::getCategory(binder.get()); return writeInt32(category.repr()); } status_t Parcel::finishUnflattenBinder( Loading @@ -181,7 +182,7 @@ status_t Parcel::finishUnflattenBinder( status_t status = readInt32(&stability); if (status != OK) return status; status = internal::Stability::set(binder.get(), stability, true /*log*/); status = internal::Stability::setRepr(binder.get(), stability, true /*log*/); if (status != OK) return status; *out = binder; Loading libs/binder/Stability.cpp +74 −31 Original line number Diff line number Diff line Loading @@ -13,6 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "Stability" #include <binder/Stability.h> #include <binder/BpBinder.h> Loading @@ -21,34 +23,59 @@ namespace android { namespace internal { // the libbinder parcel format is currently unstable // oldest version which is supported constexpr uint8_t kBinderWireFormatOldest = 1; // current version constexpr uint8_t kBinderWireFormatVersion = 1; Stability::Category Stability::Category::currentFromLevel(Level level) { return { .version = kBinderWireFormatVersion, .reserved = {0}, .level = level, }; } std::string Stability::Category::debugString() { return levelString(level) + " wire protocol version " + std::to_string(version); } void Stability::markCompilationUnit(IBinder* binder) { status_t result = set(binder, getLocalStability(), true /*log*/); auto stability = Category::currentFromLevel(getLocalLevel()); status_t result = setRepr(binder, stability.repr(), true /*log*/); LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object."); } void Stability::markVintf(IBinder* binder) { status_t result = set(binder, Level::VINTF, true /*log*/); auto stability = Category::currentFromLevel(Level::VINTF); status_t result = setRepr(binder, stability.repr(), true /*log*/); LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object."); } void Stability::debugLogStability(const std::string& tag, const sp<IBinder>& binder) { ALOGE("%s: stability is %s", tag.c_str(), stabilityString(get(binder.get())).c_str()); auto stability = getCategory(binder.get()); ALOGE("%s: stability is %s", tag.c_str(), stability.debugString().c_str()); } void Stability::markVndk(IBinder* binder) { status_t result = set(binder, Level::VENDOR, true /*log*/); auto stability = Category::currentFromLevel(Level::VENDOR); status_t result = setRepr(binder, stability.repr(), true /*log*/); LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object."); } bool Stability::requiresVintfDeclaration(const sp<IBinder>& binder) { return check(get(binder.get()), Level::VINTF); return check(getCategory(binder.get()), Level::VINTF); } void Stability::tryMarkCompilationUnit(IBinder* binder) { (void) set(binder, getLocalStability(), false /*log*/); auto stability = Category::currentFromLevel(getLocalLevel()); (void) setRepr(binder, stability.repr(), false /*log*/); } Stability::Level Stability::getLocalStability() { Stability::Level Stability::getLocalLevel() { #ifdef __ANDROID_VNDK__ #ifdef __ANDROID_APEX__ // TODO(b/142684679) avoid use_vendor on system APEXes Loading @@ -67,65 +94,81 @@ Stability::Level Stability::getLocalStability() { #endif } status_t Stability::set(IBinder* binder, int32_t stability, bool log) { Level currentStability = get(binder); status_t Stability::setRepr(IBinder* binder, int32_t representation, bool log) { auto current = getCategory(binder); auto setting = Category::fromRepr(representation); // If we have ahold of a binder with a newer declared version, then it // should support older versions, and we will simply write our parcels with // the current wire parcel format. if (setting.version < kBinderWireFormatOldest) { // always log, because this shouldn't happen ALOGE("Cannot accept binder with older binder wire protocol version " "%u. Versions less than %u are unsupported.", setting.version, kBinderWireFormatOldest); return BAD_TYPE; } // null binder is always written w/ 'UNDECLARED' stability if (binder == nullptr) { if (stability == UNDECLARED) { if (setting.level == UNDECLARED) { return OK; } else { if (log) { ALOGE("Null binder written with stability %s.", stabilityString(stability).c_str()); levelString(setting.level).c_str()); } return BAD_TYPE; } } if (!isDeclaredStability(stability)) { if (!isDeclaredLevel(setting.level)) { if (log) { ALOGE("Can only set known stability, not %d.", stability); ALOGE("Can only set known stability, not %u.", setting.level); } return BAD_TYPE; } if (currentStability != Level::UNDECLARED && currentStability != stability) { if (current.repr() != 0 && current != setting) { if (log) { ALOGE("Interface being set with %s but it is already marked as %s.", stabilityString(stability).c_str(), stabilityString(currentStability).c_str()); ALOGE("Interface being set with %s but it is already marked as %s", setting.debugString().c_str(), current.debugString().c_str()); } return BAD_TYPE; } if (currentStability == stability) return OK; if (current == setting) return OK; BBinder* local = binder->localBinder(); if (local != nullptr) { local->mStability = static_cast<int32_t>(stability); local->mStability = setting.repr(); } else { binder->remoteBinder()->mStability = static_cast<int32_t>(stability); binder->remoteBinder()->mStability = setting.repr(); } return OK; } Stability::Level Stability::get(IBinder* binder) { if (binder == nullptr) return UNDECLARED; Stability::Category Stability::getCategory(IBinder* binder) { if (binder == nullptr) { return Category::currentFromLevel(Level::UNDECLARED); } BBinder* local = binder->localBinder(); if (local != nullptr) { return static_cast<Stability::Level>(local->mStability); return Category::fromRepr(local->mStability); } return static_cast<Stability::Level>(binder->remoteBinder()->mStability); return Category::fromRepr(binder->remoteBinder()->mStability); } bool Stability::check(int32_t provided, Level required) { bool stable = (provided & required) == required; bool Stability::check(Category provided, Level required) { bool stable = (provided.level & required) == required; if (!isDeclaredStability(provided) && provided != UNDECLARED) { ALOGE("Unknown stability when checking interface stability %d.", provided); if (provided.level != UNDECLARED && !isDeclaredLevel(provided.level)) { ALOGE("Unknown stability when checking interface stability %d.", provided.level); stable = false; } Loading @@ -133,18 +176,18 @@ bool Stability::check(int32_t provided, Level required) { return stable; } bool Stability::isDeclaredStability(int32_t stability) { bool Stability::isDeclaredLevel(Level stability) { return stability == VENDOR || stability == SYSTEM || stability == VINTF; } std::string Stability::stabilityString(int32_t stability) { switch (stability) { std::string Stability::levelString(Level level) { switch (level) { case Level::UNDECLARED: return "undeclared stability"; case Level::VENDOR: return "vendor stability"; case Level::SYSTEM: return "system stability"; case Level::VINTF: return "vintf stability"; } return "unknown stability " + std::to_string(stability); return "unknown stability " + std::to_string(level); } } // namespace internal Loading libs/binder/include/binder/Stability.h +65 −7 Original line number Diff line number Diff line Loading @@ -26,6 +26,29 @@ class ProcessState; namespace internal { // Stability encodes how a binder changes over time. There are two levels of // stability: // 1). the interface stability - this is how a particular set of API calls (a // particular ordering of things like writeInt32/readInt32) are changed over // time. If one release, we have 'writeInt32' and the next release, we have // 'writeInt64', then this interface doesn't have a very stable // Stability::Level. Usually this ordering is controlled by a .aidl file. // 2). the wire format stability - this is how these API calls map to actual // bytes that are written to the wire (literally, this is how they are written // to the kernel inside of IBinder::transact, but it may be expanded to other // wires in the future). For instance, writeInt32 in binder translates to // writing a 4-byte little-endian integer in two's complement. You can imagine // in the future, we change writeInt32/readInt32 to instead write 8-bytes with // that integer and some check bits. In this case, the wire format changes, // but as long as a client libbinder knows to keep on writing a 4-byte value // to old servers, and new servers know how to interpret the 8-byte result, // they can still communicate. // // Every binder object has a stability level associated with it, and when // communicating with a binder, we make sure that the command we sent is one // that it knows how to process. The summary of stability of a binder is // represented by a Stability::Category object. // WARNING: These APIs are only ever expected to be called by auto-generated code. // Instead of calling them, you should set the stability of a .aidl interface class Stability final { Loading Loading @@ -73,7 +96,7 @@ private: static void tryMarkCompilationUnit(IBinder* binder); enum Level : int32_t { enum Level : uint8_t { UNDECLARED = 0, VENDOR = 0b000011, Loading @@ -81,19 +104,54 @@ private: VINTF = 0b111111, }; // This is the format of stability passed on the wire. struct Category { static inline Category fromRepr(int32_t representation) { return *reinterpret_cast<Category*>(&representation); } int32_t repr() const { return *reinterpret_cast<const int32_t*>(this); } static inline Category currentFromLevel(Level level); bool operator== (const Category& o) const { return repr() == o.repr(); } bool operator!= (const Category& o) const { return !(*this == o); } std::string debugString(); // This is the version of the wire protocol associated with the host // process of a particular binder. As the wire protocol changes, if // sending a transaction to a binder with an old version, the Parcel // class must write parcels according to the version documented here. uint8_t version; uint8_t reserved[2]; // bitmask of Stability::Level Level level; }; static_assert(sizeof(Category) == sizeof(int32_t)); // returns the stability according to how this was built static Level getLocalStability(); static Level getLocalLevel(); // applies stability to binder if stability level is known __attribute__((warn_unused_result)) static status_t set(IBinder* binder, int32_t stability, bool log); static status_t setRepr(IBinder* binder, int32_t representation, bool log); static Level get(IBinder* binder); // get stability information as encoded on the wire static Category getCategory(IBinder* binder); static bool check(int32_t provided, Level required); // whether a transaction on binder is allowed, if the transaction // is done from a context with a specific stability level static bool check(Category provided, Level required); static bool isDeclaredStability(int32_t stability); static std::string stabilityString(int32_t stability); static bool isDeclaredLevel(Level level); static std::string levelString(Level level); Stability(); }; Loading Loading
libs/binder/BpBinder.cpp +6 −5 Original line number Diff line number Diff line Loading @@ -223,13 +223,14 @@ status_t BpBinder::transact( if (code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION) { using android::internal::Stability; auto stability = Stability::get(this); auto required = privateVendor ? Stability::VENDOR : Stability::getLocalStability(); auto category = Stability::getCategory(this); Stability::Level required = privateVendor ? Stability::VENDOR : Stability::getLocalLevel(); if (CC_UNLIKELY(!Stability::check(stability, required))) { if (CC_UNLIKELY(!Stability::check(category, required))) { ALOGE("Cannot do a user transaction on a %s binder in a %s context.", Stability::stabilityString(stability).c_str(), Stability::stabilityString(required).c_str()); category.debugString().c_str(), Stability::levelString(required).c_str()); return BAD_TYPE; } } Loading
libs/binder/Parcel.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -171,7 +171,8 @@ status_t Parcel::finishFlattenBinder( if (status != OK) return status; internal::Stability::tryMarkCompilationUnit(binder.get()); return writeInt32(internal::Stability::get(binder.get())); auto category = internal::Stability::getCategory(binder.get()); return writeInt32(category.repr()); } status_t Parcel::finishUnflattenBinder( Loading @@ -181,7 +182,7 @@ status_t Parcel::finishUnflattenBinder( status_t status = readInt32(&stability); if (status != OK) return status; status = internal::Stability::set(binder.get(), stability, true /*log*/); status = internal::Stability::setRepr(binder.get(), stability, true /*log*/); if (status != OK) return status; *out = binder; Loading
libs/binder/Stability.cpp +74 −31 Original line number Diff line number Diff line Loading @@ -13,6 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "Stability" #include <binder/Stability.h> #include <binder/BpBinder.h> Loading @@ -21,34 +23,59 @@ namespace android { namespace internal { // the libbinder parcel format is currently unstable // oldest version which is supported constexpr uint8_t kBinderWireFormatOldest = 1; // current version constexpr uint8_t kBinderWireFormatVersion = 1; Stability::Category Stability::Category::currentFromLevel(Level level) { return { .version = kBinderWireFormatVersion, .reserved = {0}, .level = level, }; } std::string Stability::Category::debugString() { return levelString(level) + " wire protocol version " + std::to_string(version); } void Stability::markCompilationUnit(IBinder* binder) { status_t result = set(binder, getLocalStability(), true /*log*/); auto stability = Category::currentFromLevel(getLocalLevel()); status_t result = setRepr(binder, stability.repr(), true /*log*/); LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object."); } void Stability::markVintf(IBinder* binder) { status_t result = set(binder, Level::VINTF, true /*log*/); auto stability = Category::currentFromLevel(Level::VINTF); status_t result = setRepr(binder, stability.repr(), true /*log*/); LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object."); } void Stability::debugLogStability(const std::string& tag, const sp<IBinder>& binder) { ALOGE("%s: stability is %s", tag.c_str(), stabilityString(get(binder.get())).c_str()); auto stability = getCategory(binder.get()); ALOGE("%s: stability is %s", tag.c_str(), stability.debugString().c_str()); } void Stability::markVndk(IBinder* binder) { status_t result = set(binder, Level::VENDOR, true /*log*/); auto stability = Category::currentFromLevel(Level::VENDOR); status_t result = setRepr(binder, stability.repr(), true /*log*/); LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object."); } bool Stability::requiresVintfDeclaration(const sp<IBinder>& binder) { return check(get(binder.get()), Level::VINTF); return check(getCategory(binder.get()), Level::VINTF); } void Stability::tryMarkCompilationUnit(IBinder* binder) { (void) set(binder, getLocalStability(), false /*log*/); auto stability = Category::currentFromLevel(getLocalLevel()); (void) setRepr(binder, stability.repr(), false /*log*/); } Stability::Level Stability::getLocalStability() { Stability::Level Stability::getLocalLevel() { #ifdef __ANDROID_VNDK__ #ifdef __ANDROID_APEX__ // TODO(b/142684679) avoid use_vendor on system APEXes Loading @@ -67,65 +94,81 @@ Stability::Level Stability::getLocalStability() { #endif } status_t Stability::set(IBinder* binder, int32_t stability, bool log) { Level currentStability = get(binder); status_t Stability::setRepr(IBinder* binder, int32_t representation, bool log) { auto current = getCategory(binder); auto setting = Category::fromRepr(representation); // If we have ahold of a binder with a newer declared version, then it // should support older versions, and we will simply write our parcels with // the current wire parcel format. if (setting.version < kBinderWireFormatOldest) { // always log, because this shouldn't happen ALOGE("Cannot accept binder with older binder wire protocol version " "%u. Versions less than %u are unsupported.", setting.version, kBinderWireFormatOldest); return BAD_TYPE; } // null binder is always written w/ 'UNDECLARED' stability if (binder == nullptr) { if (stability == UNDECLARED) { if (setting.level == UNDECLARED) { return OK; } else { if (log) { ALOGE("Null binder written with stability %s.", stabilityString(stability).c_str()); levelString(setting.level).c_str()); } return BAD_TYPE; } } if (!isDeclaredStability(stability)) { if (!isDeclaredLevel(setting.level)) { if (log) { ALOGE("Can only set known stability, not %d.", stability); ALOGE("Can only set known stability, not %u.", setting.level); } return BAD_TYPE; } if (currentStability != Level::UNDECLARED && currentStability != stability) { if (current.repr() != 0 && current != setting) { if (log) { ALOGE("Interface being set with %s but it is already marked as %s.", stabilityString(stability).c_str(), stabilityString(currentStability).c_str()); ALOGE("Interface being set with %s but it is already marked as %s", setting.debugString().c_str(), current.debugString().c_str()); } return BAD_TYPE; } if (currentStability == stability) return OK; if (current == setting) return OK; BBinder* local = binder->localBinder(); if (local != nullptr) { local->mStability = static_cast<int32_t>(stability); local->mStability = setting.repr(); } else { binder->remoteBinder()->mStability = static_cast<int32_t>(stability); binder->remoteBinder()->mStability = setting.repr(); } return OK; } Stability::Level Stability::get(IBinder* binder) { if (binder == nullptr) return UNDECLARED; Stability::Category Stability::getCategory(IBinder* binder) { if (binder == nullptr) { return Category::currentFromLevel(Level::UNDECLARED); } BBinder* local = binder->localBinder(); if (local != nullptr) { return static_cast<Stability::Level>(local->mStability); return Category::fromRepr(local->mStability); } return static_cast<Stability::Level>(binder->remoteBinder()->mStability); return Category::fromRepr(binder->remoteBinder()->mStability); } bool Stability::check(int32_t provided, Level required) { bool stable = (provided & required) == required; bool Stability::check(Category provided, Level required) { bool stable = (provided.level & required) == required; if (!isDeclaredStability(provided) && provided != UNDECLARED) { ALOGE("Unknown stability when checking interface stability %d.", provided); if (provided.level != UNDECLARED && !isDeclaredLevel(provided.level)) { ALOGE("Unknown stability when checking interface stability %d.", provided.level); stable = false; } Loading @@ -133,18 +176,18 @@ bool Stability::check(int32_t provided, Level required) { return stable; } bool Stability::isDeclaredStability(int32_t stability) { bool Stability::isDeclaredLevel(Level stability) { return stability == VENDOR || stability == SYSTEM || stability == VINTF; } std::string Stability::stabilityString(int32_t stability) { switch (stability) { std::string Stability::levelString(Level level) { switch (level) { case Level::UNDECLARED: return "undeclared stability"; case Level::VENDOR: return "vendor stability"; case Level::SYSTEM: return "system stability"; case Level::VINTF: return "vintf stability"; } return "unknown stability " + std::to_string(stability); return "unknown stability " + std::to_string(level); } } // namespace internal Loading
libs/binder/include/binder/Stability.h +65 −7 Original line number Diff line number Diff line Loading @@ -26,6 +26,29 @@ class ProcessState; namespace internal { // Stability encodes how a binder changes over time. There are two levels of // stability: // 1). the interface stability - this is how a particular set of API calls (a // particular ordering of things like writeInt32/readInt32) are changed over // time. If one release, we have 'writeInt32' and the next release, we have // 'writeInt64', then this interface doesn't have a very stable // Stability::Level. Usually this ordering is controlled by a .aidl file. // 2). the wire format stability - this is how these API calls map to actual // bytes that are written to the wire (literally, this is how they are written // to the kernel inside of IBinder::transact, but it may be expanded to other // wires in the future). For instance, writeInt32 in binder translates to // writing a 4-byte little-endian integer in two's complement. You can imagine // in the future, we change writeInt32/readInt32 to instead write 8-bytes with // that integer and some check bits. In this case, the wire format changes, // but as long as a client libbinder knows to keep on writing a 4-byte value // to old servers, and new servers know how to interpret the 8-byte result, // they can still communicate. // // Every binder object has a stability level associated with it, and when // communicating with a binder, we make sure that the command we sent is one // that it knows how to process. The summary of stability of a binder is // represented by a Stability::Category object. // WARNING: These APIs are only ever expected to be called by auto-generated code. // Instead of calling them, you should set the stability of a .aidl interface class Stability final { Loading Loading @@ -73,7 +96,7 @@ private: static void tryMarkCompilationUnit(IBinder* binder); enum Level : int32_t { enum Level : uint8_t { UNDECLARED = 0, VENDOR = 0b000011, Loading @@ -81,19 +104,54 @@ private: VINTF = 0b111111, }; // This is the format of stability passed on the wire. struct Category { static inline Category fromRepr(int32_t representation) { return *reinterpret_cast<Category*>(&representation); } int32_t repr() const { return *reinterpret_cast<const int32_t*>(this); } static inline Category currentFromLevel(Level level); bool operator== (const Category& o) const { return repr() == o.repr(); } bool operator!= (const Category& o) const { return !(*this == o); } std::string debugString(); // This is the version of the wire protocol associated with the host // process of a particular binder. As the wire protocol changes, if // sending a transaction to a binder with an old version, the Parcel // class must write parcels according to the version documented here. uint8_t version; uint8_t reserved[2]; // bitmask of Stability::Level Level level; }; static_assert(sizeof(Category) == sizeof(int32_t)); // returns the stability according to how this was built static Level getLocalStability(); static Level getLocalLevel(); // applies stability to binder if stability level is known __attribute__((warn_unused_result)) static status_t set(IBinder* binder, int32_t stability, bool log); static status_t setRepr(IBinder* binder, int32_t representation, bool log); static Level get(IBinder* binder); // get stability information as encoded on the wire static Category getCategory(IBinder* binder); static bool check(int32_t provided, Level required); // whether a transaction on binder is allowed, if the transaction // is done from a context with a specific stability level static bool check(Category provided, Level required); static bool isDeclaredStability(int32_t stability); static std::string stabilityString(int32_t stability); static bool isDeclaredLevel(Level level); static std::string levelString(Level level); Stability(); }; Loading