Experiment 1 · Exercises: isolation

Exercises: isolating a run

The access rules of Experiment 1, §2.4, as textbook exercises. The code runs in your browser.

1. File permissions

(the permission check) [Kerrisk, TLPI, §15.4.3; Stevens & Rago, APUE, §4.5]

A file \(f\) has an owner, a group and a mode \(m\in\{0,\dots,7\}^3\) (bits r, w, x for u, g, o). A process \(p\) has a uid and a set of gids. Exactly one class applies:

$$\operatorname{cls}(p,f)=\begin{cases}u&\operatorname{uid}(p)=\operatorname{owner}(f),\\ g&\text{else, if }\operatorname{group}(f)\in\operatorname{gids}(p),\\ o&\text{else.}\end{cases}$$ $$\operatorname{may}(p,/d_1/\cdots/d_k/f,\ w)\iff \text{x}\in m_{\operatorname{cls}}(/),\,m_{\operatorname{cls}}(/d_1),\dots,m_{\operatorname{cls}}(/d_1/\cdots/d_k)\ \text{ and }\ w\in m_{\operatorname{cls}}(f);\qquad \operatorname{uid}(p)=0\Rightarrow\text{yes}.$$

On a directory, r lists its names and x lets a path pass through it.

(this Mac today) predict

/Users/miltonlin is drwxr-x---, owner miltonlin, group staff; everything below it is 755 or 644. A new standard account exp1runner is in staff. Can it read ~miltonlin/Projects/Trees/README.md?

(the check, in code) code

Write cls and finish may. The tests include homes 711 and 744: decide before running whether either keeps exp1runner out.

Ctrl/⌘ + Enter

2. Which hosts the proxy refuses

(domain match) [RFC 6265, §5.1.3; RFC 9110, §9.3.6]

A client behind the proxy opens each HTTPS connection with CONNECT host:port; the rest is encrypted. After lower-casing and removing the port and a final dot, a host \(h\) matches a domain \(d\) if

$$h=d\qquad\text{or}\qquad h=s.d\ \text{ for some nonempty label string } s.$$

(the proxy's test) code

Write blocked for netproxy.py, with \(X\)'s host cwlin4916.github.io as the deny list.

Ctrl/⌘ + Enter

(what the proxy cannot see) predict

A run fetches https://web.archive.org/web/2026/cwlin4916.github.io/Trees/. Can netproxy.py refuse it and still allow the rest of web.archive.org?

3. Reads inside the run folder

(path containment) code [TLPI, §18.13; normpath]

The scan after a run (reads.txt) asks of each path read whether it lies in \(D_r\) = /Users/exp1runner/run. Write inside, lexically: no file is opened.

Ctrl/⌘ + Enter

4. Firewall rules

(pf's rule order) [pf.conf(5); Hansteen, The Book of PF, ch. 3]

Rules \(\rho_1,\dots,\rho_n\) are read top to bottom; a packet \(q\) gets

$$\operatorname{act}(q)=\begin{cases}\operatorname{act}(\rho_i)&i=\min\{j:\rho_j\text{ matches }q,\ \rho_j\text{ quick}\}\text{ if that set is nonempty},\\ \operatorname{act}(\rho_i)&i=\max\{j:\rho_j\text{ matches }q\}\text{ else, if some rule matches},\\ \text{pass}&\text{else.}\end{cases}$$

(the runner's anchor) code

Write decide. The tests run the anchor of §2.4.3 and two reorderings of it.

Ctrl/⌘ + Enter

5. Independence as reads-from

(reads-from) [Bernstein, Hadzilacos & Goodman, ch. 2]

In a log of writes, reads and resets in time order, \(r\) reads \(p\) from \(w\) if \(w\) wrote \(p\) at \(t_w\lt t_r\) and nothing wrote \(p\) or reset in \((t_w,t_r)\). The condition \(\operatorname{reads}(r)\cap\operatorname{writes}(r')=\varnothing\) of §2.4.1 is about what was written, not about names:

$$r\ \text{independent}\iff\nexists\,(p,w):\ r\text{ reads }p\text{ from }w,\ \ w\notin\{r,\ \text{setup}\}.$$

(the violations in a log) code

Every run writes tree.json in the same folder. Write violations; one test shows why comparing names would be wrong.

Ctrl/⌘ + Enter

Your code is saved in this browser only. Python (Pyodide v0.26.4) loads from cdn.jsdelivr.net on the first run.