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 pub(crate) source: Option<Error>, 17 } 18 19 impl BinderError { 20 pub(crate) fn new_dead() -> Self { 21 Self { 22 reply: BR_DEAD_REPLY, 23 source: None, 24 } 25 } 26 27 pub(crate) fn new_frozen() -> Self { 28 Self { 29 reply: BR_FROZEN_REPLY, 30 source: None, 31 } 32 } 33 34 pub(crate) fn new_frozen_oneway() -> Self { 35 Self { 36 reply: BR_TRANSACTION_PENDING_FROZEN, 37 source: None, 38 } 39 } 40 41 pub(crate) fn is_dead(&self) -> bool { 42 self.reply == BR_DEAD_REPLY 43 } 44 } 45 46 /// Convert an errno into a `BinderError` and store the errno used to construct it. The errno 47 /// should be stored as the thread's extended error when given to userspace. 48 impl From<Error> for BinderError { 49 fn from(source: Error) -> Self { 50 Self { 51 reply: BR_FAILED_REPLY, 52 source: Some(source), 53 } 54 } 55 } 56 57 impl From<kernel::fs::file::BadFdError> for BinderError { 58 fn from(source: kernel::fs::file::BadFdError) -> Self { 59 BinderError::from(Error::from(source)) 60 } 61 } 62 63 impl From<kernel::alloc::AllocError> for BinderError { 64 fn from(_: kernel::alloc::AllocError) -> Self { 65 Self { 66 reply: BR_FAILED_REPLY, 67 source: Some(ENOMEM), 68 } 69 } 70 } 71 72 impl fmt::Debug for BinderError { 73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 74 match self.reply { 75 BR_FAILED_REPLY => match self.source.as_ref() { 76 Some(source) => f 77 .debug_struct("BR_FAILED_REPLY") 78 .field("source", source) 79 .finish(), 80 None => f.pad("BR_FAILED_REPLY"), 81 }, 82 BR_DEAD_REPLY => f.pad("BR_DEAD_REPLY"), 83 BR_FROZEN_REPLY => f.pad("BR_FROZEN_REPLY"), 84 BR_TRANSACTION_PENDING_FROZEN => f.pad("BR_TRANSACTION_PENDING_FROZEN"), 85 BR_TRANSACTION_COMPLETE => f.pad("BR_TRANSACTION_COMPLETE"), 86 _ => f 87 .debug_struct("BinderError") 88 .field("reply", &self.reply) 89 .finish(), 90 } 91 } 92 } 93