diff options
| -rw-r--r-- | libs/binder/Debug.h | 3 | ||||
| -rw-r--r-- | libs/binder/Parcel.cpp | 70 | ||||
| -rw-r--r-- | libs/binder/TEST_MAPPING | 3 | ||||
| -rw-r--r-- | libs/binder/ndk/include_ndk/android/binder_ibinder.h | 5 | ||||
| -rw-r--r-- | libs/binder/ndk/include_ndk/android/binder_status.h | 17 | ||||
| -rw-r--r-- | libs/binder/ndk/include_platform/android/binder_parcel_platform.h | 8 | ||||
| -rw-r--r-- | libs/binder/ndk/libbinder_ndk.map.txt | 2 | ||||
| -rw-r--r-- | libs/binder/rust/src/binder.rs | 64 | ||||
| -rw-r--r-- | libs/binder/rust/src/lib.rs | 5 | ||||
| -rw-r--r-- | libs/binder/rust/src/native.rs | 54 | ||||
| -rw-r--r-- | libs/binder/rust/sys/BinderBindings.hpp | 2 |
11 files changed, 182 insertions, 51 deletions
diff --git a/libs/binder/Debug.h b/libs/binder/Debug.h index 68d811bb48..7ca087e7d2 100644 --- a/libs/binder/Debug.h +++ b/libs/binder/Debug.h @@ -37,8 +37,7 @@ void printHexData(int32_t indent, const void *buf, size_t length, size_t alignment=0, bool cArrayStyle=false, debugPrintFunc func = nullptr, void* cookie = nullptr); - -ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf); +extern "C" ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf); // --------------------------------------------------------------------------- } // namespace android diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index b91d72b87a..34a474b252 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -41,11 +41,12 @@ #include <binder/TextOutput.h> #include <cutils/ashmem.h> +#include <cutils/compiler.h> #include <utils/Flattenable.h> #include <utils/Log.h> -#include <utils/misc.h> -#include <utils/String8.h> #include <utils/String16.h> +#include <utils/String8.h> +#include <utils/misc.h> #include <private/binder/binder_module.h> #include "RpcState.h" @@ -590,12 +591,14 @@ status_t Parcel::writeInterfaceToken(const String16& interface) } status_t Parcel::writeInterfaceToken(const char16_t* str, size_t len) { - const IPCThreadState* threadState = IPCThreadState::self(); - writeInt32(threadState->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER); - updateWorkSourceRequestHeaderPosition(); - writeInt32(threadState->shouldPropagateWorkSource() ? - threadState->getCallingWorkSourceUid() : IPCThreadState::kUnsetWorkSource); - writeInt32(kHeader); + if (CC_LIKELY(!isForRpc())) { + const IPCThreadState* threadState = IPCThreadState::self(); + writeInt32(threadState->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER); + updateWorkSourceRequestHeaderPosition(); + writeInt32(threadState->shouldPropagateWorkSource() ? threadState->getCallingWorkSourceUid() + : IPCThreadState::kUnsetWorkSource); + writeInt32(kHeader); + } // currently the interface identification token is just its name as a string return writeString16(str, len); @@ -642,31 +645,34 @@ bool Parcel::enforceInterface(const char16_t* interface, size_t len, IPCThreadState* threadState) const { - // StrictModePolicy. - int32_t strictPolicy = readInt32(); - if (threadState == nullptr) { - threadState = IPCThreadState::self(); - } - if ((threadState->getLastTransactionBinderFlags() & - IBinder::FLAG_ONEWAY) != 0) { - // For one-way calls, the callee is running entirely - // disconnected from the caller, so disable StrictMode entirely. - // Not only does disk/network usage not impact the caller, but - // there's no way to commuicate back any violations anyway. - threadState->setStrictModePolicy(0); - } else { - threadState->setStrictModePolicy(strictPolicy); - } - // WorkSource. - updateWorkSourceRequestHeaderPosition(); - int32_t workSource = readInt32(); - threadState->setCallingWorkSourceUidWithoutPropagation(workSource); - // vendor header - int32_t header = readInt32(); - if (header != kHeader) { - ALOGE("Expecting header 0x%x but found 0x%x. Mixing copies of libbinder?", kHeader, header); - return false; + if (CC_LIKELY(!isForRpc())) { + // StrictModePolicy. + int32_t strictPolicy = readInt32(); + if (threadState == nullptr) { + threadState = IPCThreadState::self(); + } + if ((threadState->getLastTransactionBinderFlags() & IBinder::FLAG_ONEWAY) != 0) { + // For one-way calls, the callee is running entirely + // disconnected from the caller, so disable StrictMode entirely. + // Not only does disk/network usage not impact the caller, but + // there's no way to communicate back violations anyway. + threadState->setStrictModePolicy(0); + } else { + threadState->setStrictModePolicy(strictPolicy); + } + // WorkSource. + updateWorkSourceRequestHeaderPosition(); + int32_t workSource = readInt32(); + threadState->setCallingWorkSourceUidWithoutPropagation(workSource); + // vendor header + int32_t header = readInt32(); + if (header != kHeader) { + ALOGE("Expecting header 0x%x but found 0x%x. Mixing copies of libbinder?", kHeader, + header); + return false; + } } + // Interface descriptor. size_t parcel_interface_len; const char16_t* parcel_interface = readString16Inplace(&parcel_interface_len); diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING index 7490b88210..b58d919d33 100644 --- a/libs/binder/TEST_MAPPING +++ b/libs/binder/TEST_MAPPING @@ -43,6 +43,9 @@ "name": "aidl_integration_test" }, { + "name": "memunreachable_binder_test" + }, + { "name": "libbinderthreadstateutils_test" }, { diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h index a44c261b3b..8941e4996c 100644 --- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h +++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h @@ -36,11 +36,6 @@ __BEGIN_DECLS -#ifndef __ANDROID_API__ -#error Android builds must be compiled against a specific API. If this is an \ - android platform host build, you must use libbinder_ndk_host_user. -#endif - typedef uint32_t binder_flags_t; enum { /** diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h index 05b25e7c40..b4dc08a49b 100644 --- a/libs/binder/ndk/include_ndk/android/binder_status.h +++ b/libs/binder/ndk/include_ndk/android/binder_status.h @@ -32,6 +32,16 @@ __BEGIN_DECLS +#ifndef __ANDROID_API__ +#error Android builds must be compiled against a specific API. If this is an \ + android platform host build, you must use libbinder_ndk_host_user. +#endif + +/** + * Low-level status types for use in binder. This is the least preferable way to + * return an error for binder services (where binder_exception_t should be used, + * particularly EX_SERVICE_SPECIFIC). + */ enum { STATUS_OK = 0, @@ -62,6 +72,10 @@ enum { */ typedef int32_t binder_status_t; +/** + * Top level exceptions types for Android binder errors, mapping to Java + * exceptions. Also see Parcel.java. + */ enum { EX_NONE = 0, EX_SECURITY = -1, @@ -170,7 +184,8 @@ __attribute__((warn_unused_result)) AStatus* AStatus_fromServiceSpecificErrorWit /** * New status with binder_status_t. This is typically for low level failures when a binder_status_t * is returned by an API on AIBinder or AParcel, and that is to be returned from a method returning - * an AStatus instance. + * an AStatus instance. This is the least preferable way to return errors. + * Prefer exceptions (particularly service-specific errors) when possible. * * Available since API level 29. * diff --git a/libs/binder/ndk/include_platform/android/binder_parcel_platform.h b/libs/binder/ndk/include_platform/android/binder_parcel_platform.h index d54c1a18ba..6372449716 100644 --- a/libs/binder/ndk/include_platform/android/binder_parcel_platform.h +++ b/libs/binder/ndk/include_platform/android/binder_parcel_platform.h @@ -20,9 +20,7 @@ __BEGIN_DECLS -#if defined(__ANDROID_APEX__) || defined(__ANDROID_VNDK__) -#error this is only for platform code -#endif +#if !defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__) /** * Gets whether or not FDs are allowed by this AParcel @@ -33,6 +31,9 @@ __BEGIN_DECLS */ bool AParcel_getAllowFds(const AParcel*); +#endif + +#if !defined(__ANDROID_APEX__) /** * Data written to the parcel will be zero'd before being deleted or realloced. * @@ -43,5 +44,6 @@ bool AParcel_getAllowFds(const AParcel*); * \param parcel The parcel to clear associated data from. */ void AParcel_markSensitive(const AParcel* parcel); +#endif __END_DECLS diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt index 8d08275eec..f1db653e07 100644 --- a/libs/binder/ndk/libbinder_ndk.map.txt +++ b/libs/binder/ndk/libbinder_ndk.map.txt @@ -117,6 +117,7 @@ LIBBINDER_NDK31 { # introduced=31 ABinderProcess_setupPolling; # apex AIBinder_getCallingSid; # apex AIBinder_setRequestingSid; # apex + AParcel_markSensitive; # llndk AServiceManager_isDeclared; # apex llndk AServiceManager_forEachDeclaredInstance; # apex llndk AServiceManager_registerLazyService; # llndk @@ -139,7 +140,6 @@ LIBBINDER_NDK31 { # introduced=31 LIBBINDER_NDK_PLATFORM { global: AParcel_getAllowFds; - AParcel_markSensitive; extern "C++" { AIBinder_fromPlatformBinder*; AIBinder_toPlatformBinder*; diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs index 3899d47bd6..321b422185 100644 --- a/libs/binder/rust/src/binder.rs +++ b/libs/binder/rust/src/binder.rs @@ -56,6 +56,26 @@ pub trait Interface: Send { } } +/// Interface stability promise +/// +/// An interface can promise to be a stable vendor interface ([`Vintf`]), or +/// makes no stability guarantees ([`Local`]). [`Local`] is +/// currently the default stability. +pub enum Stability { + /// Default stability, visible to other modules in the same compilation + /// context (e.g. modules on system.img) + Local, + + /// A Vendor Interface Object, which promises to be stable + Vintf, +} + +impl Default for Stability { + fn default() -> Self { + Stability::Local + } +} + /// A local service that can be remotable via Binder. /// /// An object that implement this interface made be made into a Binder service @@ -94,6 +114,8 @@ pub const LAST_CALL_TRANSACTION: TransactionCode = sys::LAST_CALL_TRANSACTION; pub const FLAG_ONEWAY: TransactionFlags = sys::FLAG_ONEWAY; /// Corresponds to TF_CLEAR_BUF -- clear transaction buffers after call is made. pub const FLAG_CLEAR_BUF: TransactionFlags = sys::FLAG_CLEAR_BUF; +/// Set to the vendor flag if we are building for the VNDK, 0 otherwise +pub const FLAG_PRIVATE_LOCAL: TransactionFlags = sys::FLAG_PRIVATE_LOCAL; /// Internal interface of binder local or remote objects for making /// transactions. @@ -602,6 +624,23 @@ macro_rules! declare_binder_interface { $interface[$descriptor] { native: $native($on_transact), proxy: $proxy {}, + stability: $crate::Stability::default(), + } + } + }; + + { + $interface:path[$descriptor:expr] { + native: $native:ident($on_transact:path), + proxy: $proxy:ident, + stability: $stability:expr, + } + } => { + $crate::declare_binder_interface! { + $interface[$descriptor] { + native: $native($on_transact), + proxy: $proxy {}, + stability: $stability, } } }; @@ -616,12 +655,33 @@ macro_rules! declare_binder_interface { } => { $crate::declare_binder_interface! { $interface[$descriptor] { + native: $native($on_transact), + proxy: $proxy { + $($fname: $fty = $finit),* + }, + stability: $crate::Stability::default(), + } + } + }; + + { + $interface:path[$descriptor:expr] { + native: $native:ident($on_transact:path), + proxy: $proxy:ident { + $($fname:ident: $fty:ty = $finit:expr),* + }, + stability: $stability:expr, + } + } => { + $crate::declare_binder_interface! { + $interface[$descriptor] { @doc[concat!("A binder [`Remotable`]($crate::Remotable) that holds an [`", stringify!($interface), "`] object.")] native: $native($on_transact), @doc[concat!("A binder [`Proxy`]($crate::Proxy) that holds an [`", stringify!($interface), "`] remote interface.")] proxy: $proxy { $($fname: $fty = $finit),* }, + stability: $stability, } } }; @@ -635,6 +695,8 @@ macro_rules! declare_binder_interface { proxy: $proxy:ident { $($fname:ident: $fty:ty = $finit:expr),* }, + + stability: $stability:expr, } } => { #[doc = $proxy_doc] @@ -669,7 +731,7 @@ macro_rules! declare_binder_interface { impl $native { /// Create a new binder service. pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T) -> $crate::Strong<dyn $interface> { - let binder = $crate::Binder::new($native(Box::new(inner))); + let binder = $crate::Binder::new_with_stability($native(Box::new(inner)), $stability); $crate::Strong::new(Box::new(binder)) } } diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs index 5bbd2a3870..30928a5cff 100644 --- a/libs/binder/rust/src/lib.rs +++ b/libs/binder/rust/src/lib.rs @@ -107,8 +107,9 @@ use binder_ndk_sys as sys; pub mod parcel; pub use crate::binder::{ - FromIBinder, IBinder, IBinderInternal, Interface, InterfaceClass, Remotable, Strong, - TransactionCode, TransactionFlags, Weak, FIRST_CALL_TRANSACTION, FLAG_CLEAR_BUF, FLAG_ONEWAY, + FromIBinder, IBinder, IBinderInternal, Interface, InterfaceClass, Remotable, + Stability, Strong, TransactionCode, TransactionFlags, Weak, + FIRST_CALL_TRANSACTION, FLAG_CLEAR_BUF, FLAG_ONEWAY, FLAG_PRIVATE_LOCAL, LAST_CALL_TRANSACTION, }; pub use error::{status_t, ExceptionCode, Result, Status, StatusCode}; diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs index 185645ef4a..3b3fd08cdc 100644 --- a/libs/binder/rust/src/native.rs +++ b/libs/binder/rust/src/native.rs @@ -14,7 +14,7 @@ * limitations under the License. */ -use crate::binder::{AsNative, Interface, InterfaceClassMethods, Remotable, TransactionCode}; +use crate::binder::{AsNative, Interface, InterfaceClassMethods, Remotable, Stability, TransactionCode}; use crate::error::{status_result, status_t, Result, StatusCode}; use crate::parcel::{Parcel, Serialize}; use crate::proxy::SpIBinder; @@ -49,11 +49,19 @@ pub struct Binder<T: Remotable> { unsafe impl<T: Remotable> Send for Binder<T> {} impl<T: Remotable> Binder<T> { - /// Create a new Binder remotable object. + /// Create a new Binder remotable object with default stability /// /// This moves the `rust_object` into an owned [`Box`] and Binder will /// manage its lifetime. pub fn new(rust_object: T) -> Binder<T> { + Self::new_with_stability(rust_object, Stability::default()) + } + + /// Create a new Binder remotable object with the given stability + /// + /// This moves the `rust_object` into an owned [`Box`] and Binder will + /// manage its lifetime. + pub fn new_with_stability(rust_object: T, stability: Stability) -> Binder<T> { let class = T::get_class(); let rust_object = Box::into_raw(Box::new(rust_object)); let ibinder = unsafe { @@ -65,10 +73,12 @@ impl<T: Remotable> Binder<T> { // ends. sys::AIBinder_new(class.into(), rust_object as *mut c_void) }; - Binder { + let mut binder = Binder { ibinder, rust_object, - } + }; + binder.mark_stability(stability); + binder } /// Set the extension of a binder interface. This allows a downstream @@ -161,6 +171,42 @@ impl<T: Remotable> Binder<T> { pub fn get_descriptor() -> &'static str { T::get_descriptor() } + + /// Mark this binder object with the given stability guarantee + fn mark_stability(&mut self, stability: Stability) { + match stability { + Stability::Local => self.mark_local_stability(), + Stability::Vintf => { + unsafe { + // Safety: Self always contains a valid `AIBinder` pointer, so + // we can always call this C API safely. + sys::AIBinder_markVintfStability(self.as_native_mut()); + } + } + } + } + + /// Mark this binder object with local stability, which is vendor if we are + /// building for the VNDK and system otherwise. + #[cfg(vendor_ndk)] + fn mark_local_stability(&mut self) { + unsafe { + // Safety: Self always contains a valid `AIBinder` pointer, so + // we can always call this C API safely. + sys::AIBinder_markVendorStability(self.as_native_mut()); + } + } + + /// Mark this binder object with local stability, which is vendor if we are + /// building for the VNDK and system otherwise. + #[cfg(not(vendor_ndk))] + fn mark_local_stability(&mut self) { + unsafe { + // Safety: Self always contains a valid `AIBinder` pointer, so + // we can always call this C API safely. + sys::AIBinder_markSystemStability(self.as_native_mut()); + } + } } impl<T: Remotable> Interface for Binder<T> { diff --git a/libs/binder/rust/sys/BinderBindings.hpp b/libs/binder/rust/sys/BinderBindings.hpp index ef142b5cf8..65fa2ca905 100644 --- a/libs/binder/rust/sys/BinderBindings.hpp +++ b/libs/binder/rust/sys/BinderBindings.hpp @@ -21,6 +21,7 @@ #include <android/binder_parcel_platform.h> #include <android/binder_process.h> #include <android/binder_shell.h> +#include <android/binder_stability.h> #include <android/binder_status.h> namespace android { @@ -80,6 +81,7 @@ enum { enum { FLAG_ONEWAY = FLAG_ONEWAY, FLAG_CLEAR_BUF = FLAG_CLEAR_BUF, + FLAG_PRIVATE_LOCAL = FLAG_PRIVATE_LOCAL, }; } // namespace consts |