55// Uses notify for watching the directory.
66// Manages current profile, handles start/stop/status/logs.
77// For sandboxing, uses nix to spawn processes in namespaces.
8-
98use anyhow:: { Context , Result } ;
10- use cgroups_rs:: { cgroup_builder:: CgroupBuilder , hierarchies, Cgroup } ;
9+ use cgroups_rs:: { cgroup_builder:: CgroupBuilder , hierarchies} ;
1110use log:: { error, info} ;
1211use nix:: sched:: { unshare, CloneFlags } ;
1312use nix:: sys:: wait:: waitpid;
@@ -17,15 +16,13 @@ use serde::{Deserialize, Serialize};
1716use serde_json;
1817use std:: collections:: HashMap ;
1918use std:: fs:: { self , File } ;
20- use std:: io:: { self , Write } ;
21- use std:: path:: { Path , PathBuf } ;
19+ use std:: io:: Write ;
20+ use std:: path:: Path ;
2221use std:: sync:: { Arc , Mutex } ;
23- use std:: thread:: sleep;
24- use std:: time:: Duration ;
25- use tokio; // For async, but using sync for simplicity now
22+ use std:: os:: unix:: process:: CommandExt ;
23+ use chrono:: prelude:: * ;
2624
2725const TMP_DIR : & str = "/tmp/Security-Mode" ;
28-
2926#[ derive( Serialize , Deserialize , Debug , Clone ) ]
3027struct Command {
3128 command : String ,
@@ -35,21 +32,18 @@ struct Command {
3532 module : Option < String > ,
3633 args : Option < Vec < String > > ,
3734}
38-
3935#[ derive( Serialize , Deserialize , Debug , Clone ) ]
4036struct Status {
4137 running : bool ,
4238 profile : String ,
4339 timestamp : String ,
4440}
45-
4641#[ derive( Serialize , Deserialize , Debug , Clone ) ]
4742struct ProfileConfig {
48- capabilities : Vec < String > , // e.g., ["CAP_NET_ADMIN"]
49- network : String , // "bridge" or "isolated"
50- disk_access : String , // "full" or "read-only" or "none"
43+ capabilities : Vec < String > , // e.g., ["CAP_NET_ADMIN"]
44+ network : String , // "bridge" or "isolated"
45+ disk_access : String , // "full" or "read-only" or "none"
5146}
52-
5347fn get_profile_config ( profile : & str ) -> ProfileConfig {
5448 match profile {
5549 "agresywny" => ProfileConfig {
@@ -74,59 +68,50 @@ fn get_profile_config(profile: &str) -> ProfileConfig {
7468 } ,
7569 }
7670}
77-
7871struct DaemonState {
7972 current_status : Status ,
8073 logs : Vec < String > ,
8174}
82-
8375fn ensure_tmp_dir ( ) -> Result < ( ) > {
8476 fs:: create_dir_all ( TMP_DIR ) . context ( "Failed to create tmp dir" )
8577}
86-
8778fn write_json < P : AsRef < Path > , T : Serialize > ( path : P , data : & T ) -> Result < ( ) > {
8879 let json = serde_json:: to_string ( data) ?;
8980 let mut file = File :: create ( path) ?;
9081 file. write_all ( json. as_bytes ( ) ) ?;
9182 Ok ( ( ) )
9283}
93-
9484fn read_json < P : AsRef < Path > , T : for < ' de > Deserialize < ' de > > ( path : P ) -> Result < T > {
9585 let contents = fs:: read_to_string ( path) ?;
9686 Ok ( serde_json:: from_str ( & contents) ?)
9787}
98-
9988fn handle_start ( profile : & str , state : & mut DaemonState ) -> Result < ( ) > {
10089 info ! ( "Starting with profile: {}" , profile) ;
10190 state. current_status = Status {
10291 running : true ,
10392 profile : profile. to_string ( ) ,
104- timestamp : chrono :: Utc :: now ( ) . to_rfc3339 ( ) ,
93+ timestamp : Utc :: now ( ) . to_rfc3339 ( ) ,
10594 } ;
10695 write_json ( format ! ( "{}/status.json" , TMP_DIR ) , & state. current_status ) ?;
10796 state. logs . push ( format ! ( "Started with profile: {}" , profile) ) ;
10897 Ok ( ( ) )
10998}
110-
11199fn handle_stop ( state : & mut DaemonState ) -> Result < ( ) > {
112100 info ! ( "Stopping" ) ;
113101 state. current_status . running = false ;
114102 write_json ( format ! ( "{}/status.json" , TMP_DIR ) , & state. current_status ) ?;
115103 state. logs . push ( "Stopped" . to_string ( ) ) ;
116104 Ok ( ( ) )
117105}
118-
119106fn handle_logs_request ( state : & DaemonState ) -> Result < ( ) > {
120107 info ! ( "Logs requested" ) ;
121108 let logs_data: HashMap < String , Vec < String > > = [ ( "logs" . to_string ( ) , state. logs . clone ( ) ) ] . iter ( ) . cloned ( ) . collect ( ) ;
122109 write_json ( format ! ( "{}/logs.json" , TMP_DIR ) , & logs_data) ?;
123110 Ok ( ( ) )
124111}
125-
126112fn handle_run_module ( module : & str , args : & [ String ] , profile : & str ) -> Result < ( ) > {
127113 info ! ( "Running module: {} with args: {:?} under {}" , module, args, profile) ;
128114 let config = get_profile_config ( profile) ;
129-
130115 // Simulate sandbox: use unshare for namespaces
131116 // This is simplified; in reality, drop caps, apply seccomp, etc.
132117 match unsafe { fork ( ) } {
@@ -136,7 +121,6 @@ fn handle_run_module(module: &str, args: &[String], profile: &str) -> Result<()>
136121 Ok ( ForkResult :: Child ) => {
137122 // In child: unshare namespaces
138123 unshare ( CloneFlags :: CLONE_NEWUSER | CloneFlags :: CLONE_NEWNET | CloneFlags :: CLONE_NEWUTS ) . unwrap ( ) ;
139-
140124 // Setup cgroups
141125 let hier = hierarchies:: auto ( ) ;
142126 let cg = CgroupBuilder :: new ( "security_mode" )
@@ -145,44 +129,36 @@ fn handle_run_module(module: &str, args: &[String], profile: &str) -> Result<()>
145129 . done ( )
146130 . build ( hier)
147131 . unwrap ( ) ;
148-
149132 // Add current pid to cgroup
150133 let pid = cgroups_rs:: CgroupPid :: from ( std:: process:: id ( ) as u64 ) ;
151134 cg. add_task ( pid) . unwrap ( ) ;
152-
153135 // Run module-runner
154136 // Write module_command.json
155137 let command = Command {
156138 command : "run" . to_string ( ) ,
157139 profile : Some ( profile. to_string ( ) ) ,
158- timestamp : chrono :: Utc :: now ( ) . to_rfc3339 ( ) ,
140+ timestamp : Utc :: now ( ) . to_rfc3339 ( ) ,
159141 module : Some ( module. to_string ( ) ) ,
160142 args : Some ( args. to_vec ( ) ) ,
161143 } ;
162144 write_json ( format ! ( "{}/module_command.json" , TMP_DIR ) , & command) ?;
163-
164145 // Exec module-runner
165- let module_runner_path = "/home/user/.hackeros/Security-Mode/bin/module-runner" ; // Adjust path
166- std:: process:: Command :: new ( module_runner_path)
167- . exec ( ) ; // Replaces child process
168-
169- // If exec fails, exit
146+ let module_runner_path = "/home/user/.hackeros/Security-Mode/bin/module-runner" ; // Adjust path
147+ let err = unsafe { std:: process:: Command :: new ( module_runner_path) . exec ( ) } ;
148+ error ! ( "Exec failed: {}" , err) ;
170149 std:: process:: exit ( 1 ) ;
171150 }
172151 Err ( e) => {
173152 error ! ( "Fork failed: {}" , e) ;
174153 }
175154 }
176-
177155 // After run, read output and log
178156 if let Ok ( output) = read_json :: < _ , HashMap < String , String > > ( format ! ( "{}/module_output.json" , TMP_DIR ) ) {
179157 info ! ( "Module output: {:?}" , output) ;
180158 // Append to logs or something
181159 }
182-
183160 Ok ( ( ) )
184161}
185-
186162fn process_command_file ( file : & Path , state : & mut DaemonState ) -> Result < ( ) > {
187163 let filename = file. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
188164 match filename {
@@ -214,43 +190,38 @@ fn process_command_file(file: &Path, state: &mut DaemonState) -> Result<()> {
214190 }
215191 Ok ( ( ) )
216192}
217-
218193fn main ( ) -> Result < ( ) > {
219194 env_logger:: init ( ) ;
220195 info ! ( "Core daemon starting" ) ;
221-
222196 ensure_tmp_dir ( ) ?;
223-
224197 let state = Arc :: new ( Mutex :: new ( DaemonState {
225198 current_status : Status {
226199 running : false ,
227200 profile : "none" . to_string ( ) ,
228- timestamp : chrono :: Utc :: now ( ) . to_rfc3339 ( ) ,
201+ timestamp : Utc :: now ( ) . to_rfc3339 ( ) ,
229202 } ,
230203 logs : vec ! [ ] ,
231204 } ) ) ;
232-
233205 // Write initial status
234206 write_json ( format ! ( "{}/status.json" , TMP_DIR ) , & state. lock ( ) . unwrap ( ) . current_status ) ?;
235-
236207 // Setup file watcher
237208 let ( tx, rx) = std:: sync:: mpsc:: channel ( ) ;
238209 let mut watcher: RecommendedWatcher = Watcher :: new ( tx, notify:: Config :: default ( ) ) ?;
239210 watcher. watch ( Path :: new ( TMP_DIR ) , RecursiveMode :: NonRecursive ) ?;
240-
241211 loop {
242212 match rx. recv ( ) {
243- Ok ( event) => {
244- if let Some ( path) = event. paths . first ( ) {
245- let mut state_guard = state. lock ( ) . unwrap ( ) ;
246- if let Err ( e) = process_command_file ( path, & mut state_guard) {
247- error ! ( "Error processing file: {}" , e) ;
213+ Ok ( res) => match res {
214+ Ok ( event) => {
215+ if let Some ( path) = event. paths . first ( ) {
216+ let mut state_guard = state. lock ( ) . unwrap ( ) ;
217+ if let Err ( e) = process_command_file ( path, & mut state_guard) {
218+ error ! ( "Error processing file: {}" , e) ;
219+ }
248220 }
249221 }
250- }
251- Err ( e) => error ! ( "Watcher error: {}" , e) ,
222+ Err ( e) => error ! ( "Notify error: {}" , e) ,
223+ } ,
224+ Err ( e) => error ! ( "Channel error: {}" , e) ,
252225 }
253226 }
254-
255- Ok ( ( ) )
256227}
0 commit comments