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