xref: /linux/drivers/android/binder/error.rs (revision 784faa8eca8270671e0ed6d9d21f04bbb80fc5f7)
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