executable/
lib.rs

1#![no_std]
2
3extern crate alloc;
4
5#[cfg(feature = "building")]
6mod building;
7mod device_trait;
8mod error;
9mod read_data;
10mod standard;
11
12use alloc::string::String;
13#[cfg(feature = "building")]
14pub use building::*;
15pub use device_trait::*;
16pub use error::*;
17pub use read_data::*;
18pub use standard::*;
19
20use task::{JoinHandle, TaskIdentifier};
21use users::UserIdentifier;
22use virtual_file_system::File;
23
24use file_system::{Path, Statistics_type};
25
26async fn is_execute_allowed(statistics: &Statistics_type, user: UserIdentifier) -> bool {
27    // - Check if the file can executed by anyone
28    if statistics.get_permissions().get_others().get_execute() {
29        return true;
30    }
31
32    // - Check if the user is the owner and has the execute permission
33    if user == UserIdentifier::ROOT {
34        return true;
35    }
36    if (statistics.get_user() == user) && statistics.get_permissions().get_user().get_execute() {
37        return true;
38    }
39
40    // - Check if the user is in the group
41    let is_in_group = users::get_instance()
42        .is_in_group(user, statistics.get_group())
43        .await;
44
45    // - Check if the user is in the group
46    if (is_in_group) && statistics.get_permissions().get_group().get_execute() {
47        return true;
48    }
49
50    false
51}
52
53async fn get_overridden_user(
54    statistics: &Statistics_type,
55    task: TaskIdentifier,
56) -> Result<Option<UserIdentifier>> {
57    if !statistics
58        .get_permissions()
59        .get_special()
60        .get_set_user_identifier()
61    {
62        return Ok(None);
63    }
64
65    let current_user = task::get_instance().get_user(task).await?;
66
67    let new_user = statistics.get_user();
68
69    if current_user != users::UserIdentifier::ROOT || new_user != current_user {
70        return Err(Error::PermissionDenied);
71    }
72
73    Ok(Some(new_user))
74}
75
76pub async fn execute(
77    path: impl AsRef<Path>,
78    inputs: String,
79    standard: Standard,
80) -> Result<JoinHandle<isize>> {
81    let task_instance = task::get_instance();
82
83    let task = task_instance.get_current_task_identifier().await;
84
85    let file = File::open(
86        virtual_file_system::get_instance(),
87        &path,
88        file_system::Mode::READ_WRITE.into(),
89    )
90    .await?;
91
92    // - Check the executable bit
93    if !is_execute_allowed(
94        &file.get_statistics().await?,
95        task_instance.get_user(task).await?,
96    )
97    .await
98    {
99        return Err(Error::PermissionDenied);
100    }
101
102    // - Check if the user can override the user identifier
103    let new_user = get_overridden_user(&file.get_statistics().await?, task).await?;
104
105    let file_name = path
106        .as_ref()
107        .get_file_name()
108        .ok_or(file_system::Error::InvalidPath)?;
109
110    let mut read_data = ReadData::new_default();
111    file.read(&mut read_data).await?;
112    let read_data: ReadData = read_data.try_into().unwrap();
113
114    let main = read_data.get_main().ok_or(Error::FailedToGetMainFunction)?;
115
116    let (join_handle, _) = task_instance
117        .spawn(task, file_name, None, async move |task| {
118            if let Some(new_user) = new_user {
119                task::get_instance().set_user(task, new_user).await.unwrap();
120            }
121
122            let standard = standard.transfert(task).await.unwrap();
123
124            match main(standard, inputs).await {
125                Ok(_) => 0_isize,
126                Err(error) => -(error.get() as isize),
127            }
128        })
129        .await?;
130
131    Ok(join_handle)
132}
133
134#[cfg(test)]
135mod tests {
136    extern crate std;
137
138    use file_system::Time;
139
140    use task::test;
141
142    use super::*;
143
144    #[test]
145    async fn is_user_allowed_test() {
146        let statistics = Statistics_type::new(
147            file_system::FileSystemIdentifier::new(0),
148            file_system::Inode::new(0),
149            1,
150            0_usize.into(),
151            Time::new(0),
152            Time::new(0),
153            Time::new(0),
154            file_system::Kind::File,
155            file_system::Permissions::from_octal(0o777).unwrap(),
156            users::UserIdentifier::ROOT,
157            users::GroupIdentifier::ROOT,
158        );
159
160        assert!(is_execute_allowed(&statistics, users::UserIdentifier::ROOT).await);
161        assert!(is_execute_allowed(&statistics, users::UserIdentifier::ROOT).await);
162        assert!(is_execute_allowed(&statistics, users::UserIdentifier::ROOT).await);
163    }
164}