Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2
3// Copyright (C) 2025 Google LLC.
4
5use kernel::prelude::*;
6
7use crate::defs::*;
8
9pub(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.
13pub(crate) struct BinderError {
14 pub(crate) reply: u32,
15 source: Option<Error>,
16}
17
18impl 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.
55impl 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
64impl 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
70impl 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
79impl 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}