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