1
1
use crate :: ffi_util:: ToCString ;
2
2
use crate :: { Command , Namespace } ;
3
- use libc:: { MNT_DETACH , MS_BIND , MS_PRIVATE , MS_RDONLY , MS_REC , MS_REMOUNT } ;
3
+ use libc:: {
4
+ MNT_DETACH , MS_BIND , MS_PRIVATE , MS_RDONLY , MS_REC , MS_REMOUNT , O_CLOEXEC , O_CREAT , O_RDONLY ,
5
+ } ;
4
6
use std:: ffi:: { c_char, c_void, CString } ;
5
7
use std:: path:: Path ;
6
8
@@ -29,6 +31,16 @@ impl Command {
29
31
self . config . fake_root_base = Some ( base. to_cstring ( ) ) ;
30
32
}
31
33
34
+ fn fakeroot_mkdir ( & mut self , base : & str , dir : & Path ) {
35
+ dir. parent ( ) . map ( |parent_dir| {
36
+ if dir != parent_dir {
37
+ self . fakeroot_mkdir ( base, parent_dir) ;
38
+ let outer_dir = format ! ( "{}/{}" , base, dir. to_str( ) . unwrap( ) ) ;
39
+ self . config . fake_root_mkdirs . push ( outer_dir. to_cstring ( ) ) ;
40
+ }
41
+ } ) ;
42
+ }
43
+
32
44
/// Add an existing directory to the fakeroot.
33
45
///
34
46
/// fakeroot_enable() must be called first, otherwise this function will panic.
@@ -46,7 +58,39 @@ impl Command {
46
58
. as_ref ( )
47
59
. expect ( "call fakeroot_enable() first!" )
48
60
. to_str ( )
49
- . unwrap ( ) ;
61
+ . unwrap ( )
62
+ . to_owned ( ) ;
63
+ self . fakeroot_mkdir ( base. as_ref ( ) , Path :: new ( dst) ) ;
64
+ self . config . fake_root_mounts . push ( FakeRootMount {
65
+ mountpoint : dst. to_cstring ( ) ,
66
+ mountpoint_outer : format ! ( "{}/{}" , base, dst) . to_cstring ( ) ,
67
+ src : src. as_ref ( ) . to_cstring ( ) ,
68
+ readonly,
69
+ is_special_fs : false ,
70
+ } ) ;
71
+ }
72
+
73
+ /// Add an existing file or device to the fakeroot.
74
+ ///
75
+ /// fakeroot_enable() must be called first, otherwise this function will panic.
76
+ ///
77
+ /// Example usage:
78
+ /// cmd.fakeroot_mount_file("/dev/urandom", "/dev/urandom", false);
79
+ pub fn fakeroot_mount_file < P : AsRef < Path > > ( & mut self , src : P , dst : & str , readonly : bool ) {
80
+ let base = self
81
+ . config
82
+ . fake_root_base
83
+ . as_ref ( )
84
+ . expect ( "call fakeroot_enable() first!" )
85
+ . to_str ( )
86
+ . unwrap ( )
87
+ . to_owned ( ) ;
88
+ Path :: new ( dst) . parent ( ) . map ( |parent_dir| {
89
+ self . fakeroot_mkdir ( base. as_ref ( ) , parent_dir) ;
90
+ } ) ;
91
+ self . config
92
+ . fake_root_touchs
93
+ . push ( format ! ( "{}/{}" , base, dst) . to_cstring ( ) ) ;
50
94
self . config . fake_root_mounts . push ( FakeRootMount {
51
95
mountpoint : dst. to_cstring ( ) ,
52
96
mountpoint_outer : format ! ( "{}/{}" , base, dst) . to_cstring ( ) ,
@@ -69,7 +113,9 @@ impl Command {
69
113
. as_ref ( )
70
114
. expect ( "call fakeroot_enable() first!" )
71
115
. to_str ( )
72
- . unwrap ( ) ;
116
+ . unwrap ( )
117
+ . to_owned ( ) ;
118
+ self . fakeroot_mkdir ( base. as_ref ( ) , Path :: new ( dst) ) ;
73
119
self . config . fake_root_mounts . push ( FakeRootMount {
74
120
mountpoint : dst. to_cstring ( ) ,
75
121
mountpoint_outer : format ! ( "{}/{}" , base, dst) . to_cstring ( ) ,
@@ -81,7 +127,12 @@ impl Command {
81
127
}
82
128
83
129
/// This syscall sequence is more or less taken from nsjail (https://github.com/google/nsjail).
84
- pub ( crate ) unsafe fn build_fakeroot ( base : & CString , mountpoints : & [ FakeRootMount ] ) -> bool {
130
+ pub ( crate ) unsafe fn build_fakeroot (
131
+ base : & CString ,
132
+ mkdirs : & [ CString ] ,
133
+ touchs : & [ CString ] ,
134
+ mountpoints : & [ FakeRootMount ] ,
135
+ ) -> bool {
85
136
// define some libc constants
86
137
let null_char = 0 as * const c_char ;
87
138
let null_void = 0 as * const c_void ;
@@ -100,9 +151,19 @@ pub(crate) unsafe fn build_fakeroot(base: &CString, mountpoints: &[FakeRootMount
100
151
return false ;
101
152
}
102
153
154
+ // create mount points
155
+ for dir in mkdirs {
156
+ libc:: mkdir ( dir. as_ptr ( ) , 0o777 ) ;
157
+ }
158
+ for file in touchs {
159
+ let fd = libc:: open ( file. as_ptr ( ) , O_RDONLY | O_CREAT | O_CLOEXEC ) ;
160
+ if fd >= 0 {
161
+ libc:: close ( fd) ;
162
+ }
163
+ }
164
+
103
165
// mount directories - still read-write (because MS_BIND + MS_RDONLY are not supported)
104
166
for mount in mountpoints {
105
- libc:: mkdir ( mount. mountpoint_outer . as_ptr ( ) , 0o777 ) ;
106
167
let ( src, fstype, flags) = if mount. is_special_fs {
107
168
( null_char, mount. src . as_ptr ( ) , 0 )
108
169
} else {
0 commit comments