mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2025-07-19 07:39:54 +02:00

When a process is frozen, incoming oneway transactions are held in a queue until the process is unfrozen. If many oneway transactions are sent, then the process could run out of space for them. This patch adds a flag that avoids this by replacing previous oneway transactions in the queue to avoid having transactions of the same type build up. This can be useful when only the most recent transaction is necessary. Link: https://lore.kernel.org/rust-for-linux/20231101-rust-binder-v1-16-08ba9197f637@google.com/ Change-Id: I2f99cc54a065c0eef60324e860610b562e910a8d Signed-off-by: Alice Ryhl <aliceryhl@google.com> Bug: 278052745
176 lines
5.0 KiB
Rust
176 lines
5.0 KiB
Rust
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
// Copyright (C) 2024 Google LLC.
|
|
|
|
use core::mem::MaybeUninit;
|
|
use core::ops::{Deref, DerefMut};
|
|
use kernel::{
|
|
bindings::{self, *},
|
|
types::{AsBytes, FromBytes},
|
|
};
|
|
|
|
macro_rules! pub_no_prefix {
|
|
($prefix:ident, $($newname:ident),+) => {
|
|
$(pub(crate) const $newname: u32 = kernel::macros::concat_idents!($prefix, $newname);)+
|
|
};
|
|
}
|
|
|
|
pub_no_prefix!(
|
|
binder_driver_return_protocol_,
|
|
BR_TRANSACTION,
|
|
BR_TRANSACTION_SEC_CTX,
|
|
BR_REPLY,
|
|
BR_DEAD_REPLY,
|
|
BR_FAILED_REPLY,
|
|
BR_FROZEN_REPLY,
|
|
BR_NOOP,
|
|
BR_SPAWN_LOOPER,
|
|
BR_TRANSACTION_COMPLETE,
|
|
BR_OK,
|
|
BR_ERROR,
|
|
BR_INCREFS,
|
|
BR_ACQUIRE,
|
|
BR_RELEASE,
|
|
BR_DECREFS,
|
|
BR_DEAD_BINDER,
|
|
BR_CLEAR_DEATH_NOTIFICATION_DONE
|
|
);
|
|
|
|
pub_no_prefix!(
|
|
binder_driver_command_protocol_,
|
|
BC_TRANSACTION,
|
|
BC_TRANSACTION_SG,
|
|
BC_REPLY,
|
|
BC_REPLY_SG,
|
|
BC_FREE_BUFFER,
|
|
BC_ENTER_LOOPER,
|
|
BC_EXIT_LOOPER,
|
|
BC_REGISTER_LOOPER,
|
|
BC_INCREFS,
|
|
BC_ACQUIRE,
|
|
BC_RELEASE,
|
|
BC_DECREFS,
|
|
BC_INCREFS_DONE,
|
|
BC_ACQUIRE_DONE,
|
|
BC_REQUEST_DEATH_NOTIFICATION,
|
|
BC_CLEAR_DEATH_NOTIFICATION,
|
|
BC_DEAD_BINDER_DONE
|
|
);
|
|
|
|
pub_no_prefix!(
|
|
flat_binder_object_flags_,
|
|
FLAT_BINDER_FLAG_ACCEPTS_FDS,
|
|
FLAT_BINDER_FLAG_TXN_SECURITY_CTX
|
|
);
|
|
|
|
pub_no_prefix!(
|
|
transaction_flags_,
|
|
TF_ONE_WAY,
|
|
TF_ACCEPT_FDS,
|
|
TF_CLEAR_BUF,
|
|
TF_UPDATE_TXN
|
|
);
|
|
|
|
pub(crate) use bindings::{
|
|
BINDER_TYPE_BINDER, BINDER_TYPE_FD, BINDER_TYPE_FDA, BINDER_TYPE_HANDLE, BINDER_TYPE_PTR,
|
|
BINDER_TYPE_WEAK_BINDER, BINDER_TYPE_WEAK_HANDLE,
|
|
};
|
|
|
|
macro_rules! decl_wrapper {
|
|
($newname:ident, $wrapped:ty) => {
|
|
// Define a wrapper around the C type. Use `MaybeUninit` to enforce that the value of
|
|
// padding bytes must be preserved.
|
|
#[derive(Copy, Clone)]
|
|
#[repr(transparent)]
|
|
pub(crate) struct $newname(MaybeUninit<$wrapped>);
|
|
|
|
// SAFETY: This macro is only used with types where this is ok.
|
|
unsafe impl FromBytes for $newname {}
|
|
unsafe impl AsBytes for $newname {}
|
|
|
|
impl Deref for $newname {
|
|
type Target = $wrapped;
|
|
fn deref(&self) -> &Self::Target {
|
|
// SAFETY: We use `MaybeUninit` only to preserve padding. The value must still
|
|
// always be valid.
|
|
unsafe { self.0.assume_init_ref() }
|
|
}
|
|
}
|
|
|
|
impl DerefMut for $newname {
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
// SAFETY: We use `MaybeUninit` only to preserve padding. The value must still
|
|
// always be valid.
|
|
unsafe { self.0.assume_init_mut() }
|
|
}
|
|
}
|
|
|
|
impl Default for $newname {
|
|
fn default() -> Self {
|
|
// Create a new value of this type where all bytes (including padding) are zeroed.
|
|
Self(MaybeUninit::zeroed())
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
decl_wrapper!(BinderNodeDebugInfo, bindings::binder_node_debug_info);
|
|
decl_wrapper!(BinderNodeInfoForRef, bindings::binder_node_info_for_ref);
|
|
decl_wrapper!(FlatBinderObject, bindings::flat_binder_object);
|
|
decl_wrapper!(BinderFdObject, bindings::binder_fd_object);
|
|
decl_wrapper!(BinderFdArrayObject, bindings::binder_fd_array_object);
|
|
decl_wrapper!(BinderObjectHeader, bindings::binder_object_header);
|
|
decl_wrapper!(BinderBufferObject, bindings::binder_buffer_object);
|
|
decl_wrapper!(BinderTransactionData, bindings::binder_transaction_data);
|
|
decl_wrapper!(
|
|
BinderTransactionDataSecctx,
|
|
bindings::binder_transaction_data_secctx
|
|
);
|
|
decl_wrapper!(
|
|
BinderTransactionDataSg,
|
|
bindings::binder_transaction_data_sg
|
|
);
|
|
decl_wrapper!(BinderWriteRead, bindings::binder_write_read);
|
|
decl_wrapper!(BinderVersion, bindings::binder_version);
|
|
decl_wrapper!(BinderFrozenStatusInfo, bindings::binder_frozen_status_info);
|
|
decl_wrapper!(BinderFreezeInfo, bindings::binder_freeze_info);
|
|
decl_wrapper!(ExtendedError, bindings::binder_extended_error);
|
|
|
|
impl BinderVersion {
|
|
pub(crate) fn current() -> Self {
|
|
Self(MaybeUninit::new(bindings::binder_version {
|
|
protocol_version: bindings::BINDER_CURRENT_PROTOCOL_VERSION as _,
|
|
}))
|
|
}
|
|
}
|
|
|
|
impl BinderTransactionData {
|
|
pub(crate) fn with_buffers_size(self, buffers_size: u64) -> BinderTransactionDataSg {
|
|
BinderTransactionDataSg(MaybeUninit::new(bindings::binder_transaction_data_sg {
|
|
transaction_data: *self,
|
|
buffers_size,
|
|
}))
|
|
}
|
|
}
|
|
|
|
impl BinderTransactionDataSecctx {
|
|
/// View the inner data as wrapped in `BinderTransactionData`.
|
|
pub(crate) fn tr_data(&mut self) -> &mut BinderTransactionData {
|
|
// SAFETY: Transparent wrapper is safe to transmute.
|
|
unsafe {
|
|
&mut *(&mut self.transaction_data as *mut bindings::binder_transaction_data
|
|
as *mut BinderTransactionData)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ExtendedError {
|
|
pub(crate) fn new(id: u32, command: u32, param: i32) -> Self {
|
|
Self(MaybeUninit::new(bindings::binder_extended_error {
|
|
id,
|
|
command,
|
|
param,
|
|
}))
|
|
}
|
|
}
|