1#![no_std]
2
3extern crate alloc;
4
5mod arguments_parser;
6#[cfg(feature = "building")]
7mod building;
8mod error;
9mod standard;
10mod traits;
11
12pub use arguments_parser::*;
13#[cfg(feature = "building")]
14pub use building::*;
15pub use error::*;
16pub use file_system as exported_file_system;
17pub use standard::*;
18pub use task as exported_task;
19pub use traits::*;
20pub use virtual_file_system as exported_virtual_file_system;
21
22use alloc::{string::String, vec::Vec};
23use file_system::{AccessFlags, Path, Permission, Statistics};
24use task::{JoinHandle, SpawnerIdentifier, TaskIdentifier};
25use users::UserIdentifier;
26use virtual_file_system::File;
27
28async fn is_execute_allowed(statistics: &Statistics, user: UserIdentifier) -> bool {
29 if statistics
30 .permissions
31 .get_others()
32 .contains(Permission::Execute)
33 {
34 return true;
35 }
36
37 let is_user_allowed = user == UserIdentifier::ROOT || user == statistics.user;
38 if is_user_allowed
39 && statistics
40 .permissions
41 .get_user()
42 .contains(Permission::Execute)
43 {
44 return true;
45 }
46
47 let is_in_group = users::get_instance()
48 .is_in_group(user, statistics.group)
49 .await
50 || user == UserIdentifier::ROOT;
51 if (is_in_group)
52 && statistics
53 .permissions
54 .get_group()
55 .contains(Permission::Execute)
56 {
57 return true;
58 }
59
60 false
61}
62
63async fn get_overridden_user(
64 statistics: &Statistics,
65 task: TaskIdentifier,
66) -> Result<Option<UserIdentifier>> {
67 if !statistics
68 .permissions
69 .get_special()
70 .get_set_user_identifier()
71 {
72 return Ok(None);
73 }
74
75 let current_user = task::get_instance().get_user(task).await?;
76
77 let new_user = statistics.user;
78
79 if current_user != users::UserIdentifier::ROOT || new_user != current_user {
80 return Err(Error::PermissionDenied);
81 }
82
83 Ok(Some(new_user))
84}
85
86pub async fn execute(
87 path: impl AsRef<Path>,
88 inputs: Vec<String>,
89 standard: Standard,
90 spawner: Option<SpawnerIdentifier>,
91) -> Result<JoinHandle<isize>> {
92 let task_instance = task::get_instance();
93
94 let task = task_instance.get_current_task_identifier().await;
95
96 let virtual_file_system = virtual_file_system::get_instance();
97
98 let statistics = virtual_file_system.get_statistics(&path.as_ref()).await?;
99
100 if !is_execute_allowed(&statistics, task_instance.get_user(task).await?).await {
102 return Err(Error::PermissionDenied);
103 }
104
105 let mut file = File::open(virtual_file_system, task, &path, AccessFlags::Read.into()).await?;
106
107 let new_user = get_overridden_user(&statistics, task).await?;
109
110 let file_name = path
111 .as_ref()
112 .get_file_name()
113 .ok_or(virtual_file_system::Error::InvalidPath)?;
114
115 let main_function: MainFunction = file.control(GET_MAIN_FUNCTION, &()).await?;
116
117 let main = main_function.ok_or(Error::FailedToGetMainFunction)?;
118
119 let (join_handle, _) = task_instance
120 .spawn(task, file_name, spawner, async move |task| {
121 if let Some(new_user) = new_user {
122 task::get_instance().set_user(task, new_user).await.unwrap();
123 }
124
125 match main(standard, inputs).await {
126 Ok(_) => 0_isize,
127 Err(error) => -(error.get() as isize),
128 }
129 })
130 .await?;
131
132 Ok(join_handle)
133}
134
135#[cfg(test)]
136mod tests {
137 extern crate std;
138
139 use file_system::{Permissions, Time};
140
141 use task::test;
142 use users::GroupIdentifier;
143
144 use super::*;
145
146 fn get_statistics_with_permissions(permissions: Permissions) -> Statistics {
147 Statistics::new(
148 0,
149 1,
150 0,
151 Time::new(0),
152 Time::new(0),
153 Time::new(0),
154 Time::new(0),
155 file_system::Kind::File,
156 permissions,
157 UserIdentifier::ROOT,
158 GroupIdentifier::ROOT,
159 )
160 }
161
162 #[test]
163 async fn test_is_execute_allowed() {
164 users::initialize();
165
166 let statistics = get_statistics_with_permissions(Permissions::ALL_FULL);
167 assert!(is_execute_allowed(&statistics, UserIdentifier::ROOT).await);
168
169 let statistics = get_statistics_with_permissions(Permissions::EXECUTABLE);
170 assert!(is_execute_allowed(&statistics, UserIdentifier::ROOT).await);
171
172 let statistics = get_statistics_with_permissions(Permissions::from_octal(0o007).unwrap());
173 assert!(is_execute_allowed(&statistics, UserIdentifier::ROOT).await);
174
175 let statistics = get_statistics_with_permissions(Permissions::from_octal(0o070).unwrap());
176 assert!(is_execute_allowed(&statistics, UserIdentifier::ROOT).await);
177
178 let statistics = get_statistics_with_permissions(Permissions::from_octal(0o100).unwrap());
179 assert!(is_execute_allowed(&statistics, UserIdentifier::ROOT).await);
180
181 let statistics = get_statistics_with_permissions(Permissions::USER_READ_WRITE);
182 assert!(!is_execute_allowed(&statistics, UserIdentifier::ROOT).await);
183
184 let statistics = get_statistics_with_permissions(Permissions::NONE);
185 assert!(!is_execute_allowed(&statistics, UserIdentifier::ROOT).await);
186
187 let statistics = get_statistics_with_permissions(Permissions::ALL_READ_WRITE);
188 assert!(!is_execute_allowed(&statistics, UserIdentifier::ROOT).await);
189 }
190}