1 // SPDX-License-Identifier: GPL-2.0 2 3 // Copyright (C) 2025 Google LLC. 4 5 use kernel::fmt; 6 use kernel::prelude::*; 7 8 use crate::defs::*; 9 10 pub(crate) type BinderResult<T = ()> = core::result::Result<T, BinderError>; 11 12 /// An error that will be returned to userspace via the `BINDER_WRITE_READ` ioctl rather than via 13 /// errno. 14 pub(crate) struct BinderError { 15 pub(crate) reply: u32, 16 source: Option<Error>, 17 } 18 19 impl BinderError { new_dead() -> Self20 pub(crate) fn new_dead() -> Self { 21 Self { 22 reply: BR_DEAD_REPLY, 23 source: None, 24 } 25 } 26 new_frozen() -> Self27 pub(crate) fn new_frozen() -> Self { 28 Self { 29 reply: BR_FROZEN_REPLY, 30 source: None, 31 } 32 } 33 new_frozen_oneway() -> Self34 pub(crate) fn new_frozen_oneway() -> Self { 35 Self { 36 reply: BR_TRANSACTION_PENDING_FROZEN, 37 source: None, 38 } 39 } 40 is_dead(&self) -> bool41 pub(crate) fn is_dead(&self) -> bool { 42 self.reply == BR_DEAD_REPLY 43 } 44 as_errno(&self) -> kernel::ffi::c_int45 pub(crate) fn as_errno(&self) -> kernel::ffi::c_int { 46 self.source.unwrap_or(EINVAL).to_errno() 47 } 48 should_pr_warn(&self) -> bool49 pub(crate) fn should_pr_warn(&self) -> bool { 50 self.source.is_some() 51 } 52 } 53 54 /// Convert an errno into a `BinderError` and store the errno used to construct it. The errno 55 /// should be stored as the thread's extended error when given to userspace. 56 impl From<Error> for BinderError { from(source: Error) -> Self57 fn from(source: Error) -> Self { 58 Self { 59 reply: BR_FAILED_REPLY, 60 source: Some(source), 61 } 62 } 63 } 64 65 impl From<kernel::fs::file::BadFdError> for BinderError { from(source: kernel::fs::file::BadFdError) -> Self66 fn from(source: kernel::fs::file::BadFdError) -> Self { 67 BinderError::from(Error::from(source)) 68 } 69 } 70 71 impl From<kernel::alloc::AllocError> for BinderError { from(_: kernel::alloc::AllocError) -> Self72 fn from(_: kernel::alloc::AllocError) -> Self { 73 Self { 74 reply: BR_FAILED_REPLY, 75 source: Some(ENOMEM), 76 } 77 } 78 } 79 80 impl fmt::Debug for BinderError { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 82 match self.reply { 83 BR_FAILED_REPLY => match self.source.as_ref() { 84 Some(source) => f 85 .debug_struct("BR_FAILED_REPLY") 86 .field("source", source) 87 .finish(), 88 None => f.pad("BR_FAILED_REPLY"), 89 }, 90 BR_DEAD_REPLY => f.pad("BR_DEAD_REPLY"), 91 BR_FROZEN_REPLY => f.pad("BR_FROZEN_REPLY"), 92 BR_TRANSACTION_PENDING_FROZEN => f.pad("BR_TRANSACTION_PENDING_FROZEN"), 93 BR_TRANSACTION_COMPLETE => f.pad("BR_TRANSACTION_COMPLETE"), 94 _ => f 95 .debug_struct("BinderError") 96 .field("reply", &self.reply) 97 .finish(), 98 } 99 } 100 } 101