forked from bazelbuild/sandboxfs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sandboxfs.1
612 lines (612 loc) · 18.6 KB
/
sandboxfs.1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
.\" Copyright 2017 Google Inc.
.\"
.\" Licensed under the Apache License, Version 2.0 (the "License"); you may not
.\" use this file except in compliance with the License. You may obtain a copy
.\" of the License at:
.\"
.\" http://www.apache.org/licenses/LICENSE-2.0
.\"
.\" Unless required by applicable law or agreed to in writing, software
.\" distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
.\" WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
.\" License for the specific language governing permissions and limitations
.\" under the License.
.Dd March 11, 2020
.Dt SANDBOXFS 1
.Os
.Sh NAME
.Nm sandboxfs
.Nd A virtual file system for sandboxing
.Sh SYNOPSIS
.Nm
.Op Fl -allow Ar who
.Op Fl -cpu_profile Ar path
.Op Fl -input Ar path
.Op Fl -help
.Op Fl -mapping Ar type:mapping:target
.Op Fl -node_cache
.Op Fl -output Ar path
.Op Fl -reconfig_threads Ar count
.Op Fl -ttl Ar duration
.Op Fl -version
.Op Fl -xattrs
.Ar mount_point
.Sh DESCRIPTION
.Nm
is a FUSE file system that exposes a combination of multiple files and
directories from the host's file system in the form of a virtual tree with an
arbitrary layout.
You can think of a sandbox as an arbitrary view into the host's file system with
different access privileges per directory.
.Pp
.Nm
is designed to allow running commands with limited access to the file system by
using the virtual tree as their new root, and to do so consistently across a
variety of platforms.
.Pp
The sandbox instance mounted at
.Ar mount_point
is initially configured with the mapping specifications provided via repeated
instances of
.Fl -mapping .
Once running, the mount point can be reconfigured any number of times:
.Nm
listens for reconfiguration requests on the file specified by
.Fl -input
and reconfigures the mappings as requested, emiting a response on the file
specified by
.Fl -output .
.Pp
The following flags are recognized:
.Bl -tag -width XXXX
.It Fl -allow Ar who
Specifies who should have access to the file system.
.Ar who
must be one of:
.Sq other
to indicate that everyone, including root, can access the file system;
.Sq root
to indicate that only the current user and root can access the file system; and
.Sq self
to indicate that only the current user can access the file system.
.Pp
The default value is
.Sq self
because the standard FUSE configuration does not allow more relaxed
permissions, and it would be a pity if you couldn't run
.Nm
successfully without additional configuration.
To change this behavior, add
.Sq user_allow_other
to
.Pa /etc/fuse.conf
on Linux or set the
.Sq vfs.generic.osxfuse.tunables.allow_other
.Xr sysctl 8
tunable to 1 on macOS.
.Pp
Note that, at least on macOS, you will need to consider granting
.Sq other
permissions if you intend to run signed binaries through the sandbox.
This is because the
.Xr amfid 8
daemon, which implements the signature validation, runs as a different user
and must be able to access the executables.
.It Fl -cpu_profile Ar path
Enables CPU profiling and stores the pprof log to the given
.Ar path .
This feature is only available if
.Nm
was built with gperftools support (i.e. with the compile-time
.Sq profiler
feature).
Passing this flag when support is not enabled results in an error.
.It Fl -input Ar path
Points to the file from which to read new configuration requests, or
.Sq -
(the default) for stdin.
See the
.Sx Reconfigurations
subsection for details on the contents and behavior of the input file.
.It Fl -help
Prints global help details and exits.
Specifying this flag causes all other valid flags and arguments to be ignored.
.It Fl -mapping Ar type:mapping:target
Registers a new mapping.
This flag can be given an arbitrary number of times as long as the same
.Ar mapping
is not repeated.
See the
.Sx Mapping specifications
subsection for details on how a mapping is specified.
.It Fl -node_cache
Enables the path-based node cache, which causes nodes to be reused across
reconfigurations when they map to the same underlying paths.
This should offer a performance boost when the same set of files are mapped
over and over again across different reconfiguration operations.
.Pp
This cache used to be enabled by default but it turned out to be problematic.
For example, on macOS, OSXFUSE seems to keep track of the path where a node
first appeared, which causes trouble if the node disappears and then reappears
in a different location (for example,
.Xr dladdr 3
returns invalid paths).
For this reason, the cache is now disabled by default but is still kept around
in the code for experimentation.
.Em The cache may be removed in a future release altogether if these problems
.Em cannot be worked around.
.It Fl -output Ar path
Points to the file to which to write confirmations of reconfiguration, or
.Sq -
(the default) for stdout.
See the
.Sx Reconfigurations
subsection for details on the contents and behavior of the output file.
.It Fl -ttl Ar duration
Specifies how long the kernel is allowed to cache file metadata for.
The duration is currently specified as a number of seconds followed by the
.Sq s
suffix.
.It Fl -reconfig_threads Ar count
Sets the number of threads to use to process reconfiguration requests.
Defaults to the number of logical CPUs in the system.
.It Fl -version
Prints version information and exits.
Specifying this flag causes all other valid flags and arguments to be ignored
except for
.Fl -help ,
which has priority over this one.
.Pp
The first line printed to stdout is machine parseable and follows the following
structure:
.Bd -literal -offset indent
sandboxfs MAJOR.MINOR[.ADDITIONAL OPTIONAL QUALIFIERS]
.Ed
.Pp
Programs automating invocations of
.Nm
can use this information to determine the correct command-line syntax to use.
.It Fl -xattrs
Enables support for extended attributes, which causes all extended attribute
operations to propagate to the underlying files.
.Pp
When disabled (the default), the behavior of extended attribute operations is
platform-dependent: they may either fail as not supported or they may act as
no-op stubs.
The reason is that this feature is disabled by telling the kernel that none of
these operations are implemented in
.Nm ,
which then causes the kernel to never contact the daemon for them.
Keeping extended attributes disabled can result in a performance boost.
.El
.Ss Mapping specifications
The basic concept behind a
.Nm
instance is the
.Em mapping specification .
A mapping specification defines how an arbitrary location within the sandbox
relates to another arbitrary location on the host file system.
Mapping specifications have three components: the
.Em target ,
which is a path to a file or directory into the host file system (i.e. outside
of the mount point); the
.Em mapping ,
which is an absolute path within the mount point in which the target is exposed;
and the
.Em type ,
which specifies the permissions of the mapping.
.Pp
The target must exist but the mapping may not: in particular, any path
subcomponents of the mapping that have not been previously mapped
within the sandbox will be created as virtual read-only nodes.
This means that the ordering of the mappings matters.
.Pp
For example: consider a
.Nm
instance mounted onto
.Pa /mnt
that maps
.Pa /my/custom/bin
to the
.Pa /usr/bin
target.
With this setup,
.Pa /mnt/my/custom/bin
will expose the contents of the real
.Pa /usr/bin
directory.
.Pp
The following types are currently supported:
.Bl -tag -width XXXX
.It ro
A read-only mapping.
The contents of the target are exposed verbatim at the mapping point and they
cannot be modified through the mount point.
Any write access will result in an
.Dv EPERM .
.It rw
A read/write mapping.
The contents of the target are exposed verbatim at the mapping point and they
can be modified at will through the mount point.
Writes through the moint point are applied immediately to the underlying target
directory.
.El
.Ss Reconfigurations
While a mount point is live,
.Nm
listens for reconfiguration requests on the file specified by
.Fl -input
and writes reconfiguration responses to the file specified by
.Fl -output .
These two files essentially implement a rudimentary RPC system subject to
change.
.Pp
The mount point can be configured any number of times while mounted,
which allows for processes to efficiently change the view of the sandbox at will
without having to remount it.
Closing the input file causes
.Nm
to freeze its configuration and not accept any more requests for
reconfiguration, but the file system will continue to operate normally until
it is either unmounted or signaled.
.Pp
Reconfiguration requests can be issued at any time.
However, it is impossible for
.Nm
to properly deal with ongoing file system operations or with open file handles
in a deterministic manner.
Due to this, the behavior of ongoing file system activity while a
reconfiguration happens is unspecified but can be assumed to be stable (i.e.
.Nm
will not deadlock nor crash).
As a result, it is highly recommended that you only send reconfiguration
requests when you know that the file system is quiescent.
.Pp
Configuration requests are provided as a stream of JSON objects.
Each request is an object with just one of the following keys:
.Sq CreateSandbox ,
which requests the creation of a new top-level directory with a given set of
mappings; and
.Sq DestroySandbox ,
which requests the deletion of the mappings at an existing top-level directory.
.Pp
.Pp
A
.Sq CreateSandbox
operation contains an object with three keys:
.Sq id
specifies the name of the top-level directory to create,
.Sq mappings
contains an array of all mappings to apply within that directory, and
.Sq prefixes
contains a dictionary of all new prefixes to register for prefix-encoded paths.
Each mapping entry is an object with the following keys:
.Sq path
and
.Sq underlying_path ,
which define the mapping paths;
.Sq path_prefix
and
.Sq underlying_path_prefix ,
which identify the prefixes for the provided paths, respectively; and
.Sq writable ,
which if set to true indicates a read/write mapping.
The mapping must not yet exist in the file system.
Each entry in the prefixes dictionary is keyed by the numerical identifier of
the prefix (supplied as a string due to JSON limitations), and the value is the
absolute path for that prefix.
.Pp
Prefix-encoded paths serve to minimize the size of the requests but their use
is optional.
To specify a path in its prefix-encoded form,
.Sq path
and/or
.Sq underlying_path
must be relative and
.Sq path_prefix
and/or
.Sq underlying_path_prefix
must indicate a positive non-zero integer.
The referenced prefix must be registered in the same request or a previous
request, but if the prefix is repeated across requests, it must point to the
same location.
To avoid prefix-encoded form, paths must be given as absolute and they need to
reference the special prefix 0.
.Pp
A
.Sq DestroySandbox
operation simply contains the
.Sq id
of a previously-created sandbox as a string.
The whole tree hierarchy is unmapped.
.Pp
Each configuration request is paired with a response, which are also provided
as a stream of JSON objects.
Each response is a map with an optional
.sq id
field, which corresponds to the identifier given in the request, and an optional
.Sq error
field, which is empty if the request was successful and contains an error
message otherwise.
Responses with a missing identifier indicate fatal failures during the
reconfiguration (e.g. due to a syntax error) and are not recoverable.
.Pp
To minimize the size of the requests, all fields support aliases and default
values as follows:
.Pp
.Bl -tag -offset XXXXXX -width underlyingXpathXprefixXX -compact
.It Sq CreateSandbox
Alias:
.Sq C .
.It Sq DestroySandbox
Alias:
.Sq D .
.It Sq id
Alias:
.Sq i .
.It Sq mappings
Alias:
.Sq m .
Default value: empty array.
.It Sq prefixes
Alias:
.Sq q .
Default value: empty object.
.It Sq path
Alias:
.Sq p .
.It Sq path_prefix
Alias:
.Sq x .
Default value:
.Sq 0 .
.It Sq underlying_path
Alias:
.Sq u .
.It Sq underlying_path_prefix
Alias:
.Sq y .
Default value:
.Sq 0 .
.It Sq writable
Alias:
.Sq w .
Default value:
.Sq false .
.El
.Sh EXIT STATUS
.Nm
exits with 0 if the file system was both mounted and unmounted cleanly; 1 on a
controlled error condition encountered during the execution of a command; or 2
on a usage error.
.Pp
Sending a termination signal to
.Nm
will cause the file system to exit in a controlled manner, ensuring that the
mount point is released.
If the file system is busy, the signal will be queued until all open file
descriptors on the file system are released at which point the file system
will try to exit cleanly again.
Note that, due to limitations in signal handling in Rust (which is the language
in which
.Nm
is implemented), the reception of a signal will cause
.Nm
to return 1 instead of terminating with a signal condition.
.Sh ENVIRONMENT
.Nm
recognizes the following environment variables:
.Bl -tag -width XXXX
.It Va RUST_LOG
Sets the maximum level of logging messages sent to stderr.
Possible values include
.Sq error ,
.Sq warn ,
.Sq info
and
.Sq debug ,
though many more syntaxes are supported.
See the documentation for Rust's
.Sq env_logger
crate for more details.
.El
.Pp
.Nm
may recognize other standard Rust variables like
.Va RUST_BACKTRACE
but the list above attempts to describe the ones a user may find most useful.
.Sh EXAMPLES
.Ss Command-line invocation
This example configures a sandbox that maps the whole host's
file system but clears
.Pa /tmp
to point into a sandbox-specific writable directory:
.Bd -literal -offset indent
sandboxfs --mapping=ro:/:/ --mapping=rw:/tmp:/tmp/fresh-tmp /mnt
.Ed
.Ss Reconfiguration request
This example creates a new sandbox under
.Pa /first
with a single mapping that will appear as
.Pa /first/tmp
and that is mapped to
.Pa /tmp/abc ;
then deletes said sandbox, and then creates a different sandbox under
.Pa /second
with a single mapping that will appear as
.Pa /foo/bar
and that is mapped to
.Pa /tmp/x/y :
.Bd -literal -offset indent
[
{"CreateSandbox": {
"id": "first",
"mappings": [
{"path": "/tmp", "underlying_path": "/tmp/abc", "writable": true}
]
}},
{"DestroySandbox": "first"}
{"CreateSandbox": {
"id": "second",
"mappings": [
{"path": "/foo/bar", "underlying_path": "/tmp/x/y",
"writable": false}
]
}}
]
.Ed
.Pp
When sending this request, we obtain the following response:
.Bd -literal -offset indent
{"id": "first", "error": null}
{"id": "first", "error": null}
{"id": "second", "error": null}
.Ed
.Ss Prefix-encoded reconfiguration request
This example is the same as above, but this time using prefix-encoded paths:
.Bd -literal -offset indent
[
{"CreateSandbox": {
"id": "first",
"mappings": [
{"path": "", "path_prefix": 1,
"underlying_path": "abc", "underlying_path_prefix": 1,
"writable": true}
],
"prefixes": {
"1": "/tmp"
}
}},
{"DestroySandbox": "first"}
{"CreateSandbox": {
"id": "second",
"mappings": [
{"path": "bar", "path_prefix": 2,
"underlying_path": "x/y", "underlying_path_prefix": 1,
"writable": false}
],
"prefixes": {
"2": "/foo"
}
}}
]
.Ed
.Ss Minimized reconfiguraton request
This example is the same as above, but this time using field aliases and
default values to minimize the message:
.Bd -literal -offset indent
[
{"C": {
"i": "first",
"m": [
{"p": "", "x": 1, "u": "abc", "y": 1, "w": true}
],
"q": {
"1": "/tmp"
}
}},
{"D": "first"}
{"C": {
"i": "second",
"m": [
{"p": "bar", "x": 2, "u": "x/y", "y": 1}
],
"q": {
"2": "/foo"
}
}}
]
.Ed
.Sh AUTHORS
.An -nosplit
The
.Nm
was originally developed as a Go program by
.An Pallav Agarwal
.Aq pallavag@google.com
with guidance from
.An Julio Merino
.Aq jmmv@google.com .
The program was later reimplemented in Rust by the latter.
.Sh BUGS
The following are known limitations of
.Nm :
.Bl -bullet
.It
Hard links are not supported.
.It
Mapping the same external file or directory under two different locations within
the mount point results in undefined behavior.
Writes may not be reflected at both mapped locations at the same time, which
can lead to data corruption.
This is true even for read-only mappings because each separate view within
the mount point may have cached different contents, returning different data
than what's truly on disk.
Using
.Fl -node_cache
may help mitigate this issue but it doesn't always do.
.It
The
.Fl -allow Ar root
setting does not work on Linux; use
.Fl -allow Ar other
as the alternative.
See https://github.com/bazil/fuse/issues/144 for details.
.It
It is currently impossible to terminate
.Nm
cleanly while the file system is busy.
Signals received while the file system is in use will be queued as described in
.Sx EXIT STATUS
and fatal signals will cause
.Nm
to leak the mount point (possibly irrecoverably without a reboot because of
kernel bugs).
.It
Any explicitly-mapped directories and any scaffold directories (those
directories that appear to represent intermediate path components that do not
exist anywhere else in the file system) cannot be removed.
Attempts to remove them will result in a
.Dq permission denied
error.
While it could be possible to implement some different behavior, this is what
.Nm
currently exposes.
You may or may not consider this to be a bug.
.It
If
.Fl -node_cache
is enabled, node data is cached in-memory for all files accessed through a
.Nm
instance in order to offer good performance across reconfigurations.
However, this cache does not currently implement any expiration policy, which
means that memory usage can grow unboundedly if many different files are
mapped and accessed through the sandbox.
.It
If a FIFO is used for
.Fl input ,
.Nm
will block until a separate process opens the FIFO for writing.
This happens even before the file system starts serving, which means the file
system is not usable until the FIFO is opened.
.It
While it is possible to reconfigure the entries of the root directory of a
running file system, it is not possible to reconfigure the root mapping itself
to point to a different location or to change its writability properties.
.It
Unmapping entries doesn't fully work.
The FUSE library that
.Nm
currently uses does not support sending cache invalidation requests to the
kernel, which means unmapped entries will not vanish immediately from the
file system.
You may be able to mitigate this by setting a low node TTL with the
.Fl -ttl
flag, but this doesn't work on macOS either because OSXFUSE does not honor
node TTLs.
.It
Handling of extended attributes on open-but-deleted-files does not work
properly.
Those files will appear as if they didn't have any extended attributes any
longer, and attempts to modify them will fail.
.El