starnix_core/vfs/
access_check.rs1use crate::security::PermissionFlags;
6use starnix_uapi::open_flags::OpenFlags;
7
8#[derive(Debug, Copy, Clone, PartialEq, Eq)]
10pub enum CheckAccessReason {
11 Access,
13 Chdir,
15 Chroot,
17 Exec,
19 ChangeTimestamps { now: bool },
21 InternalPermissionChecks,
23}
24
25#[derive(Debug, Copy, Clone, PartialEq, Eq)]
27pub struct AccessCheck {
28 permission_flags: PermissionFlags,
29 reason: CheckAccessReason,
30}
31
32impl AccessCheck {
33 pub fn for_internal(permissions: impl Into<PermissionFlags>) -> Self {
35 Self {
36 permission_flags: permissions.into(),
37 reason: CheckAccessReason::InternalPermissionChecks,
38 }
39 }
40
41 pub fn for_chdir() -> Self {
43 Self { permission_flags: PermissionFlags::EXEC, reason: CheckAccessReason::Chdir }
44 }
45
46 pub fn for_chroot() -> Self {
48 Self { permission_flags: PermissionFlags::EXEC, reason: CheckAccessReason::Chroot }
49 }
50
51 pub fn for_access(permissions: impl Into<PermissionFlags>) -> Self {
53 Self { permission_flags: permissions.into(), reason: CheckAccessReason::Access }
54 }
55
56 pub fn permission_flags(&self) -> PermissionFlags {
58 self.permission_flags
59 }
60
61 pub fn reason(&self) -> CheckAccessReason {
63 self.reason
64 }
65}
66
67#[derive(Debug, Copy, Clone, PartialEq, Eq)]
69pub struct OpenAccessCheck {
70 open_flags: OpenFlags,
71 access_check: AccessCheck,
72}
73
74impl From<OpenFlags> for OpenAccessCheck {
75 fn from(open_flags: OpenFlags) -> Self {
76 Self {
77 open_flags,
78 access_check: AccessCheck {
79 permission_flags: open_flags.into(),
80 reason: CheckAccessReason::InternalPermissionChecks,
81 },
82 }
83 }
84}
85
86impl OpenAccessCheck {
87 pub fn new(open_flags: OpenFlags, access_check: AccessCheck) -> Self {
89 Self { open_flags, access_check }
90 }
91
92 pub fn skip(open_flags: OpenFlags) -> Self {
94 Self {
95 open_flags,
96 access_check: AccessCheck {
97 permission_flags: PermissionFlags::empty(),
98 reason: CheckAccessReason::InternalPermissionChecks,
99 },
100 }
101 }
102
103 pub fn for_exec() -> Self {
105 Self {
106 open_flags: OpenFlags::RDONLY,
107 access_check: AccessCheck {
108 permission_flags: PermissionFlags::EXEC,
109 reason: CheckAccessReason::Exec,
110 },
111 }
112 }
113
114 pub fn open_flags(&self) -> OpenFlags {
116 self.open_flags
117 }
118
119 pub fn access_check(&self) -> AccessCheck {
121 self.access_check
122 }
123}
124
125#[cfg(test)]
126mod test {
127 use super::*;
128 use starnix_uapi::file_mode::Access;
129 use starnix_uapi::open_flags::OpenFlags;
130
131 #[::fuchsia::test]
132 fn test_access_check() {
133 let for_internal_access = AccessCheck::for_internal(Access::READ);
134 assert_eq!(for_internal_access.permission_flags(), PermissionFlags::READ);
135 assert_eq!(for_internal_access.reason(), CheckAccessReason::InternalPermissionChecks);
136
137 let for_internal_perms = AccessCheck::for_internal(PermissionFlags::EXEC);
138 assert_eq!(for_internal_perms.permission_flags(), PermissionFlags::EXEC);
139 assert_eq!(for_internal_perms.reason(), CheckAccessReason::InternalPermissionChecks);
140
141 let for_chdir = AccessCheck::for_chdir();
142 assert_eq!(for_chdir.permission_flags(), PermissionFlags::EXEC);
143 assert_eq!(for_chdir.reason(), CheckAccessReason::Chdir);
144
145 let for_chroot = AccessCheck::for_chroot();
146 assert_eq!(for_chroot.permission_flags(), PermissionFlags::EXEC);
147 assert_eq!(for_chroot.reason(), CheckAccessReason::Chroot);
148
149 let for_access = AccessCheck::for_access(Access::READ | Access::WRITE);
150 assert_eq!(for_access.permission_flags(), PermissionFlags::READ | PermissionFlags::WRITE);
151 assert_eq!(for_access.reason(), CheckAccessReason::Access);
152 }
153
154 #[::fuchsia::test]
155 fn test_open_access_check() {
156 let from_flags = OpenAccessCheck::from(OpenFlags::RDWR);
157 assert_eq!(from_flags.open_flags(), OpenFlags::RDWR);
158 assert_eq!(
159 from_flags.access_check().permission_flags(),
160 PermissionFlags::READ | PermissionFlags::WRITE
161 );
162 assert_eq!(from_flags.access_check().reason(), CheckAccessReason::InternalPermissionChecks);
163
164 let skip_check = OpenAccessCheck::skip(OpenFlags::RDWR | OpenFlags::CREAT);
165 assert_eq!(skip_check.open_flags(), OpenFlags::RDWR | OpenFlags::CREAT);
166 assert_eq!(skip_check.access_check().permission_flags(), PermissionFlags::empty());
167 assert_eq!(skip_check.access_check().reason(), CheckAccessReason::InternalPermissionChecks);
168
169 let for_exec = OpenAccessCheck::for_exec();
170 assert_eq!(for_exec.open_flags(), OpenFlags::RDONLY);
171 assert_eq!(for_exec.access_check().permission_flags(), PermissionFlags::EXEC);
172 assert_eq!(for_exec.access_check().reason(), CheckAccessReason::Exec);
173
174 let custom =
175 OpenAccessCheck::new(OpenFlags::RDONLY, AccessCheck::for_internal(Access::READ));
176 assert_eq!(custom.open_flags(), OpenFlags::RDONLY);
177 assert_eq!(custom.access_check().permission_flags(), PermissionFlags::READ);
178 }
179}