#
Chapter 9
Security

MzScheme offers several mechanisms for managing security:

- Custodians (section 9.2) manage resource allocation.

- Security guards (section 9.1) control access to the filesystem and network.

- Inspectors (section 4.5) control access to the content of otherwise opaque structures.

- Namespaces (section 8) control access to Scheme bindings.

All security mechanisms rely on thread-specific parameters (see section 7.7).

## 9.1 Security Guards

A security guard provides a set of access-checking procedures to be called when a thread initiates access of a file, directory, or network connection through a primitive procedure. For example, when a thread calls ``open-input-file``, the thread's current security guard is consulted to check whether the thread is allowed read access to the file. If access is granted, the thread receives a port that it may use indefinitely, regardless of changes to the security guard (although the port's custodian could shut down the port; see section 9.2).

A thread's current security guard is determined by the `current-security-guard` parameter (see section 7.7.1.8). Every security guard has a parent, and a parent's access procedures are called whenever a child's access procedures are called. Thus, a thread cannot increase its own access arbitrarily by installing a new guard. The initial security guard enforces no access restrictions other than those enforced by the host platform.

`(make-security-guard``` `parent-security-guard file-proc network-proc``)` creates a new security guard whose parent is `parent-security-guard`.

The `file-proc` procedure must accept three arguments:

- a symbol for the primitive procedure that triggered the access check, which is useful for raising an exception to deny access.

- an immutable string representing a pathname, or `#f` to check access for pathless queries, such as `(`current-directory`)`, `(`filesystem-root-list`)`, and `(`find-system-path` ...)`. A path string provided to `file-proc` is not processed at all before checking access; it may be a relative path, and it may be ill-formed.

- an immutable list containing one or more of the following symbols:

  - `'read` -- read a file or directory

  - `'write` -- modify or create a file or directory

  - `'execute` -- execute a file

  - `'delete` -- delete a file or directory

  - `'exists` -- determine whether a file or directory exists, or that a path string is well-formed

  The `'exists` symbol is never combined with other symbols in the last argument to `file-proc`, but any other combination is possible. When the second argument to `file-proc` is `#f`, the last argument always contains only `'exists`.

The `network-proc` procedure must accept four arguments:

- a symbol for the primitive operation that triggered the access check, which is useful for raising an exception to deny access.

- an immutable string representing the target hostname for a client connection or the accepting hostname for a listening server; `#f` for a listening server or UDP socket that accepts connections at all of the host's address; or `#f` an unbound UDP socket.

- an exact integer between `1` and `65535` (inclusive) representing the port number, or `#f` for an unbound UDP socket. In the case of a client connection, the port number is the target port on the server. For a listening server, the port number is the local port number.

- a symbol, either `'client` or `'server`, indicating whether the check is for the creation of a client connection or a listening server. The opening of an unbound UDP socket is identified as a `'client` connection; explicitly binding the socket is identified as a `'server` action.

The return value of `file-proc` or `network-proc` is ignored. To deny access, the procedure must raise an exception or otherwise escape from the context of the primitive call. If the procedure returns, the parent's corresponding procedure is called on the same inputs, and so on up the chain of security guards.

The `file-proc` and `network-proc` procedures are invoked in the thread that called the access-checked primitive. Breaks may or may not be enabled (see section 6.6). Full continuation jumps are blocked going into or out of the `file-proc` or `network-proc` call (see section 6.3).

`(security-guard?``` `v``)` returns `#t` if `v` is a security guard value, `#f` otherwise.

## 9.2 Custodians

A custodian manages a collection of threads, file-stream ports, subprocess ports, TCP ports, TCP listeners, and UDP sockets.14 Whenever a thread, file-stream port, process port, TCP port, TCP listener, or UDP socket is created, it is placed under the management of the current custodian (as determined by the `current-custodian` parameter; see section 7.7.1.8).

The only operation on a custodian is to shut down all of its managed values via ``custodian-shutdown-all``. In other words, ``custodian-shutdown-all`` generalizes ``kill-thread`` to forcibly and immediately close a set of ports, TCP connections, etc., as well as terminate a set of threads. For example, web server might use a custodian to manage all of the resources of a particular session so that the session can be cleanly terminated if it exceeds its allowed lifetime.

The values managed by a custodian are only weakly held by the custodian. As a result, a will (see section 13.2) can be executed for a value that is managed by a custodian.

`(make-custodian``` [`custodian`]`)` creates a new custodian that is subordinate to the custodian `custodian`. When `custodian` is directed (via ``custodian-shutdown-all``) to shut down all of its managed values, the new subordinate custodian is automatically directed to shut down its managed values as well. The default value for `custodian` is the current custodian.

`(custodian-shutdown-all``` `custodian``)` kills all threads,15 closes all open ports, and closes all active TCP listeners and UDP sockets that are managed by the custodian `custodian`. If `custodian` manages the current thread, the custodian shuts down all other objects before killing the current thread.

`(custodian?``` `v``)` returns `#t` if `v` is a custodian value, `#f` otherwise.

`(custodian-require-memory``` `need-k thunk``)` registers a require check if MzScheme is compiled with support for memory accounting, otherwise the `exn:misc:unsupported` exception is raised. If a check is registered, and if MzScheme later reaches a state after garbage collection (see section 13.3) where `need-k` bytes are not available to the current custodian, `thunk` is invoked.

`(custodian-limit-memory``` `custodian limit-k thunk``)` registers a limit check if MzScheme is compiled with support for memory accounting, otherwise the `exn:misc:unsupported` exception is raised. If a check is registered, and if MzScheme later reaches a state after garbage collection (see section 13.3) where `custodian` owns more than `limit-k` bytes, then `thunk` is invoked.

14 In MrEd, custodians also manage eventspaces.

15 ``Killing'' a thread created with `thread/suspend-to-kill` merely suspends the thread.