2
2
extern crate clap;
3
3
4
4
use clap:: Arg ;
5
+ use human_size:: { Byte , Size } ;
5
6
use lucet_runtime:: { self , DlModule , Limits , MmapRegion , Module , Region } ;
7
+ use lucet_runtime_internals:: module:: ModuleInternal ;
6
8
use lucet_wasi:: { hostcalls, WasiCtxBuilder } ;
7
9
use std:: fs:: File ;
8
10
use std:: sync:: Arc ;
@@ -12,6 +14,7 @@ struct Config<'a> {
12
14
guest_args : Vec < & ' a str > ,
13
15
entrypoint : & ' a str ,
14
16
preopen_dirs : Vec < ( File , & ' a str ) > ,
17
+ limits : Limits ,
15
18
}
16
19
17
20
fn main ( ) {
@@ -41,10 +44,10 @@ fn main() {
41
44
virtual filesystem. Each directory is specified as \
42
45
--dir `host_path:guest_path`, where `guest_path` specifies the path that will \
43
46
correspond to `host_path` for calls like `fopen` in the guest.\
44
- \
47
+ \n \n \
45
48
For example, `--dir /home/host_user/wasi_sandbox:/sandbox` will make \
46
49
`/home/host_user/wasi_sandbox` available within the guest as `/sandbox`.\
47
- \
50
+ \n \n \
48
51
Guests will be able to access any files and directories under the \
49
52
`host_path`, but will be unable to access other parts of the host \
50
53
filesystem through relative paths (e.g., `/sandbox/../some_other_file`) \
@@ -56,6 +59,27 @@ fn main() {
56
59
. required ( true )
57
60
. help ( "Path to the `lucetc`-compiled WASI module" ) ,
58
61
)
62
+ . arg (
63
+ Arg :: with_name ( "heap_memory_size" )
64
+ . long ( "max-heap-size" )
65
+ . takes_value ( true )
66
+ . default_value ( "4 GiB" )
67
+ . help ( "Maximum heap size (must be a multiple of 4 KiB)" ) ,
68
+ )
69
+ . arg (
70
+ Arg :: with_name ( "heap_address_space_size" )
71
+ . long ( "heap-address-space" )
72
+ . takes_value ( true )
73
+ . default_value ( "8 GiB" )
74
+ . help ( "Maximum heap address space size (must be a multiple of 4 KiB, and >= `max-heap-size`)" ) ,
75
+ )
76
+ . arg (
77
+ Arg :: with_name ( "stack_size" )
78
+ . long ( "stack-size" )
79
+ . takes_value ( true )
80
+ . default_value ( "8 MiB" )
81
+ . help ( "Maximum stack size (must be a multiple of 4 KiB)" ) ,
82
+ )
59
83
. arg (
60
84
Arg :: with_name ( "guest_args" )
61
85
. required ( false )
@@ -65,7 +89,9 @@ fn main() {
65
89
. get_matches ( ) ;
66
90
67
91
let entrypoint = matches. value_of ( "entrypoint" ) . unwrap ( ) ;
92
+
68
93
let lucet_module = matches. value_of ( "lucet_module" ) . unwrap ( ) ;
94
+
69
95
let preopen_dirs = matches
70
96
. values_of ( "preopen_dirs" )
71
97
. map ( |vals| {
@@ -84,25 +110,66 @@ fn main() {
84
110
. collect ( )
85
111
} )
86
112
. unwrap_or ( vec ! [ ] ) ;
113
+
114
+ let heap_memory_size = value_t ! ( matches, "heap_memory_size" , Size )
115
+ . unwrap_or_else ( |e| e. exit ( ) )
116
+ . into :: < Byte > ( )
117
+ . value ( ) as usize ;
118
+ let heap_address_space_size = value_t ! ( matches, "heap_address_space_size" , Size )
119
+ . unwrap_or_else ( |e| e. exit ( ) )
120
+ . into :: < Byte > ( )
121
+ . value ( ) as usize ;
122
+
123
+ if heap_memory_size > heap_address_space_size {
124
+ println ! ( "`heap-address-space` must be at least as large as `max-heap-size`" ) ;
125
+ println ! ( "{}" , matches. usage( ) ) ;
126
+ std:: process:: exit ( 1 ) ;
127
+ }
128
+
129
+ let stack_size = value_t ! ( matches, "stack_size" , Size )
130
+ . unwrap_or_else ( |e| e. exit ( ) )
131
+ . into :: < Byte > ( )
132
+ . value ( ) as usize ;
133
+
134
+ let limits = Limits {
135
+ heap_memory_size,
136
+ heap_address_space_size,
137
+ stack_size,
138
+ globals_size : 0 , // calculated from module
139
+ } ;
140
+
87
141
let guest_args = matches
88
142
. values_of ( "guest_args" )
89
143
. map ( |vals| vals. collect ( ) )
90
144
. unwrap_or ( vec ! [ ] ) ;
145
+
91
146
let config = Config {
92
147
lucet_module,
93
148
guest_args,
94
149
entrypoint,
95
150
preopen_dirs,
151
+ limits,
96
152
} ;
153
+
97
154
run ( config)
98
155
}
99
156
100
157
fn run ( config : Config ) {
101
158
lucet_wasi:: hostcalls:: ensure_linked ( ) ;
102
159
let exitcode = {
103
160
// doing all of this in a block makes sure everything gets dropped before exiting
104
- let region = MmapRegion :: create ( 1 , & Limits :: default ( ) ) . expect ( "region can be created" ) ;
105
161
let module = DlModule :: load ( & config. lucet_module ) . expect ( "module can be loaded" ) ;
162
+ let min_globals_size = module. globals ( ) . len ( ) * std:: mem:: size_of :: < u64 > ( ) ;
163
+ let globals_size = ( ( min_globals_size + 4096 - 1 ) / 4096 ) * 4096 ;
164
+
165
+ let region = MmapRegion :: create (
166
+ 1 ,
167
+ & Limits {
168
+ globals_size,
169
+ ..config. limits
170
+ } ,
171
+ )
172
+ . expect ( "region can be created" ) ;
106
173
107
174
// put the path to the module on the front for argv[0]
108
175
let args = std:: iter:: once ( config. lucet_module )
0 commit comments