---
title: 'Guest and Host System'
source: 'https://academia.sh/en/courses/it-fundamentals/guest-and-host-system'
course: 'Information Technology and Systems Fundamentals'
language: en
updated: '2026-09-13T05:08:04+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Counts the items the guest and host share and writes how many paths each item opens'
    - 'Splits paths into transit, data, and information effect and measures how many paths each class loses when closed'
    - 'States the cost of closing in two units: changed legitimate work steps and additional host memory'
---

# Guest and Host System

Measuring escape risk by the number of shared items: the eleven items the guest and host share, the path each item opens and its classification by transit, data, or information effect, the paths closed by turning off optional shares along with their cost in work steps and host memory, and the six paths that cannot be closed while the guest is running.

The previous lesson counted layers stacked on top of one another: guest, hypervisor, host,
hardware. In that ordering, each layer carried the one before it. But there is not just a single
stack between guest and host; while both run, they use a set of items **at the same time**. The
same scheduler queues both sides' threads, the same physical memory pages get merged, the disk and
network card the guest sees are emulation code running on the host, and on top of that there is a
shared folder, a clipboard, and an agent channel opened for convenience.

Escape is the guest boundary being crossed once and something on the host side being reached. This
lesson measures escape not as a probability but as **the number of shared items**: how many items
the guest and host share, how many paths each shared item opens, and how many of those paths can be
closed. The escape step itself is not written; the path's name, its effect, and its cost are
written. Trying an escape path on a real system, without written authorization and a defined scope,
is both illegal and unprofessional.

**VR7 — A shared item is a component used jointly with the host while the guest runs**; the list on
the fictional branch server is a model, the count is real. **VR8 — A path is an outcome reached on
the host side through a single shared item.** **VR9 — A path's effect is one of three classes:
transit** (running code in the host process), **data** (touching host data), **information**
(inference only). **VR10 — A required item is an item that cannot be closed while the guest is
running.** **VR11 — Cost is written in two units: changed legitimate work steps and additional host
memory.** **VR12 — The branch server has four guests, split into two trust levels.**

## Shared Items

Shared items are of two kinds. One part exists as long as the guest runs: the guest must obtain
processor time, see a disk, and write to a network card, and that disk and network card are also
emulation code running on the host. The other part is opened for convenience and can be closed with
a single configuration item.

```js
// sharing.mjs — items the guest and host share, and the paths each item opens (MODEL).
// Paths are named on the defense axis; not exploit code, only the path's name and effect are written.
// effect: transit = moving into the host process, data = touching host data, information = inference.

// [item, required?, [[path, effect], ...], [changed legitimate work steps, extra host memory MiB]]
export const SHARING = [
  ['scheduler', true, [["neighboring guest's activity timing", 'information']], [0, 0]],
  ['processor cache', true, [['access pattern from a shared cache line', 'information']], [0, 0]],
  ['clock source', true, [["inferring the host's maintenance window", 'information']], [0, 0]],
  ['disk controller emulation', true, [['transit into the host process via an emulation bug', 'transit']], [0, 0]],
  ['network interface emulation', true, [['transit into the host process via an emulation bug', 'transit'],
    ["guest packet into the host's network stack", 'data']], [0, 0]],
  ['memory page merging', false, [['measuring whether the same page exists', 'information'],
    ['page sharing inferred from write latency', 'information']], [0, 1856]],
  ['display controller emulation', false, [['transit into the host process via an emulation bug', 'transit']], [2, 0]],
  ['shared folder', false, [["writing to the host's file system", 'data'],
    ['a file from the host running inside the guest', 'data']], [2, 0]],
  ['clipboard', false, [["reading the host's clipboard", 'data'], ['passing data from host to guest', 'data']], [1, 0]],
  ['guest agent channel', false, [['running a command in the guest from the host', 'data'],
    ["reading the guest's file system from the host", 'information']], [4, 0]],
  ['USB passthrough', false, [["a plugged-in device reaching the host's driver", 'transit']], [1, 0]],
];
export const EFFECT = ['transit', 'data', 'information']; const WIDTH = { transit: 9, data: 6, information: 13 };
export const pathCount = (list) => list.reduce((t, [, , y]) => t + y.length, 0);
export const effectCount = (list, e) => list.reduce((t, [, , y]) => t + y.filter(([, k]) => k === e).length, 0);

if (import.meta.url === `file://${process.argv[1]}`) {
  const s = (x, n) => String(x).padStart(n);
  const T = pathCount(SHARING);
  console.log(`${SHARING.length} shared items, ${T} paths; average per item `
    + `${(T / SHARING.length).toFixed(2)} paths`);
  console.log(`\n${'item'.padEnd(30)}${'type'.padEnd(14)}${s('paths', 7)}${s('transit', 9)}${s('data', 6)}`
    + `${s('information', 13)}${s('extra steps', 13)}${s('extra memory', 14)}`);
  for (const k of SHARING) {
    const [ad, required, y, [adim, mib]] = k;
    console.log(`${ad.padEnd(30)}${(required ? 'required' : 'optional').padEnd(14)}${s(y.length, 7)}`
      + EFFECT.map((e) => s(effectCount([k], e), WIDTH[e])).join('')
      + `${s(required ? '-' : adim, 13)}${s(required ? '-' : mib, 14)}`);
  }
  for (const [ad, f] of [['required total', true], ['optional total', false]]) {
    const g = SHARING.filter(([, z]) => z === f);
    const [adim, mib] = g.reduce(([a, m], [, , , [x, y]]) => [a + x, m + y], [0, 0]);
    console.log(`${ad.padEnd(44)}${s(pathCount(g), 7)}` + EFFECT.map((e) => s(effectCount(g, e), WIDTH[e])).join('')
      + `${s(f ? '-' : adim, 13)}${s(f ? '-' : mib, 14)}`);
  }
}
```

```
11 shared items, 16 paths; average per item 1.45 paths

item                          type            paths  transit  data  information  extra steps  extra memory
scheduler                     required            1        0     0            1            -             -
processor cache               required            1        0     0            1            -             -
clock source                  required            1        0     0            1            -             -
disk controller emulation     required            1        1     0            0            -             -
network interface emulation   required            2        1     1            0            -             -
memory page merging           optional            2        0     0            2            0          1856
display controller emulation  optional            1        1     0            0            2             0
shared folder                 optional            2        0     2            0            2             0
clipboard                     optional            2        0     2            0            1             0
guest agent channel           optional            2        0     1            1            4             0
USB passthrough               optional            1        1     0            0            1             0
required total                                    6        2     1            3            -             -
optional total                                   10        2     5            3           10          1856
```

Eleven items open sixteen paths; the average per item is 1.45. That average alone is a warning:
closing a shared item does not always close one path — five of the eleven carry **two**, as does
leaving one open.

The effect columns split the list in two. The five required items open six paths, and three of
those are pure information inference: when the neighbor runs, which memory page is shared, the
host's maintenance window. Two are transit, and both come from a piece of emulation code. Since the
guest must see a disk and a network card, those two pieces of emulation code run on the host in
every run; these two transit paths **are not a closable item.**

The six optional items open ten paths and the distribution flips: five of six **data** paths are
here. The clipboard, the shared folder, and the agent channel — all three items
opened to make one person's work easier — carry five of the six host-data paths. The
right two columns write the cost of that: ten work steps and 1,856 MiB of host memory.

## What Closing Closes, and What It Leaves

The run below closes the optional items one by one — first the one that opens the most paths, and
on a tie the cheaper one — and writes the closed path together with its cost at each step.

```js
// closing.mjs — optional shares are closed one by one; the closed path and its cost are counted together.
import { SHARING, EFFECT, pathCount, effectCount } from './sharing.mjs';

const T = pathCount(SHARING);
const optional = SHARING.filter(([, z]) => !z)
  .sort((a, b) => b[2].length - a[2].length || a[3][0] - b[3][0]);   // most paths first, then the cheaper one
const s = (x, n) => String(x).padStart(n);
console.log(`${'closed item'.padEnd(30)}${s('closed', 8)}${s('total', 7)}${s('remaining', 11)}`
  + `${s('extra steps', 13)}${s('extra memory', 14)}`);
let closed = 0, steps = 0, mem = 0;
for (const [ad, , y, [a, m]] of optional) {
  closed += y.length; steps += a; mem += m;
  console.log(`${ad.padEnd(30)}${s(y.length, 8)}${s(closed, 7)}${s(T - closed, 11)}${s(steps, 13)}${s(mem, 14)}`);
}

const remaining = SHARING.filter(([, z]) => z);
console.log(`\nclosable ${optional.length}/${SHARING.length} items, closed ${closed}/${T} paths `
  + `(${((100 * closed) / T).toFixed(1)}%); cost ${steps} work steps and ${mem} MiB of host memory`);
console.log(`${'effect'.padEnd(13)}${s('initial paths', 15)}${s('remaining paths', 17)}`);
for (const e of EFFECT)
  console.log(`${e.padEnd(13)}${s(effectCount(SHARING, e), 15)}${s(effectCount(remaining, e), 17)}`);
console.log(`while the guest runs, ${remaining.length} items cannot be closed, leaving ${pathCount(remaining)} paths`);

// Layout: four fictional guests on the same host, two trust levels.
const GUESTS = [['aggregator', 'high'], ['validator', 'high'], ['field portal', 'low'], ['test', 'low']];
const pairs = GUESTS.flatMap((a, i) => GUESTS.slice(i + 1).map((b) => [a[1], b[1]]));
const mixed = pairs.filter(([a, b]) => a !== b).length;
console.log(`\nsingle host: ${GUESTS.length} guests, ${pairs.length} neighbor pairs, ${mixed} pairs from different levels`);
console.log(`separate host per level: ${pairs.length - mixed} pairs, 0 from different levels; `
  + `remaining paths still ${pathCount(remaining)}, cost: 1 more machine`);
```

```
closed item                     closed  total  remaining  extra steps  extra memory
memory page merging                  2      2         14            0          1856
clipboard                            2      4         12            1          1856
shared folder                        2      6         10            3          1856
guest agent channel                  2      8          8            7          1856
USB passthrough                      1      9          7            8          1856
display controller emulation         1     10          6           10          1856

closable 6/11 items, closed 10/16 paths (62.5%); cost 10 work steps and 1856 MiB of host memory
effect         initial paths  remaining paths
transit                    4                2
data                       6                1
information                6                3
while the guest runs, 5 items cannot be closed, leaving 6 paths

single host: 4 guests, 6 neighbor pairs, 4 pairs from different levels
separate host per level: 2 pairs, 0 from different levels; remaining paths still 6, cost: 1 more machine
```

When six items are closed, ten of the sixteen paths close and six remain. The first row looks free
at first glance: memory page merging closes two information paths and the changed work step count is
zero. The cost is not in the workflow but in memory — 1,856 MiB of host memory, because merged pages
are now kept separately. **An item whose cost looks like zero usually has its cost in another
column.**

The effect table shows the real gain. Data paths drop from six to **one**; the single remaining data
path is the one carried by the network emulation. So five out of six paths touching host data were
inside the closable convenience items. Transit paths drop from four to two, information paths from
six to three. The total cost is ten work steps: file transfer is done over the network, closing and
reopening procedures are run by hand, and reading field devices moves to the branch client.

The remaining six paths are this lesson's boundary. As long as the guest runs, a scheduler, a
processor cache, a clock source, a disk, and a network interface are shared. These cannot be closed,
because closing them means the guest does not run either. What remains is to ask **how readily**
those six paths operate.

## Items Required per Path

Up to this point, every path was matched with a single shared item. Read that way, it looks as if
the share's existence is the path's only condition; for most paths that is not true. The run below
gives each path the extra conditions required **on top of** the share and works out how many items
must be true at the same time to cross the boundary.

```js
// conditions.mjs — number of items that must be true at the same time, for each path (MODEL).
// The shared item's existence is one item; the list below gives it EXTRA conditions.
import { SHARING } from './sharing.mjs';

const EXTRA = {
  "neighboring guest's activity timing": [],
  'access pattern from a shared cache line': ['being scheduled onto the same core as the neighbor'],
  "inferring the host's maintenance window": [],
  'transit into the host process via an emulation bug': ['an unpatched emulation bug'],
  "guest packet into the host's network stack": ['the host interface being bridged to the guest network'],
  'measuring whether the same page exists': ['identical page content in the neighbor'],
  'page sharing inferred from write latency': ['identical page content in the neighbor'],
  "writing to the host's file system": ['the mount being writable'],
  'a file from the host running inside the guest': ['execute permission in the guest', 'the file being opened'],
  "reading the host's clipboard": [], 'passing data from host to guest': [],
  'running a command in the guest from the host': ['agent privilege on the host side'],
  "reading the guest's file system from the host": ['agent privilege on the host side'],
  "a plugged-in device reaching the host's driver": ['physical access', 'an unpatched driver bug'],
};
// [required items, path name, from a required item?]
const PATHS = SHARING.flatMap(([, z, y]) => y.map(([ad]) => [1 + EXTRA[ad].length, ad, z]));

const s = (x, n) => String(x).padStart(n);
console.log(`${'required items'.padEnd(16)}${s('paths', 6)}   example`);
for (const g of [...new Set(PATHS.map(([n]) => n))].sort()) {
  const k = PATHS.filter(([n]) => n === g);
  console.log(`${String(g).padEnd(16)}${s(k.length, 6)}   ${k[0][1]}`);
}
const required = PATHS.filter(([, , z]) => z);
console.log(`\nrequired items in the ${required.length} paths that cannot be closed: `
  + [...new Set(required.map(([n]) => n))].sort()
    .map((g) => `${g} -> ${required.filter(([n]) => n === g).length} paths`).join(', '));
const secondary = PATHS.flatMap(([, ad]) => EXTRA[ad]);
const counts = [...new Set(secondary)].map((k) => [k, secondary.filter((x) => x === k).length])
  .sort((a, b) => b[1] - a[1]);
console.log(`most frequent extra condition: ${counts[0][0]} (${counts[0][1]} paths); total ${secondary.length} extra conditions, `
  + `${counts.length} distinct items`);
```

```
required items   paths   example
1                    4   neighboring guest's activity timing
2                   10   access pattern from a shared cache line
3                    2   a file from the host running inside the guest

required items in the 6 paths that cannot be closed: 1 -> 2 paths, 2 -> 4 paths
most frequent extra condition: an unpatched emulation bug (3 paths); total 14 extra conditions, 10 distinct items
```

**Four** of the sixteen paths work with a single item: if the share is open, the path is open, no
other condition is required. Those four are the scheduler, the clock source, and the clipboard's two
directions; none of the three depends on a bug or a placement — each exists merely by the share's
definition. Ten paths need two items, two paths need three items.

Two of the six paths that cannot be closed work with a single item, and both are information paths.
The remaining four want a second item, and the most frequently required second item is **an
unpatched emulation bug** — the same condition in three paths. This ties the measure of crossing the
boundary to patching: on a host where the emulation code is patched, those three paths require two
items and the second is not in place. The patch program itself is not this course's subject, but the
number here writes what it changes: **it closes the second item of three transit paths.**

## The Six Paths That Cannot Be Closed

What can be done for a path that cannot be closed is changing **where it reaches**. The last two
rows measure this. While four guests run on the same host, six neighbor pairs form, and four of them
are between different trust levels: the guest that aggregates meter readings and the test guest, the
validator and the field portal. The remaining six paths work between these four pairs.

Distributing the guests across two separate hosts by trust level closes none of the paths — each
host still has six paths — but it drops different-level pairs from four to **zero**.
In the remaining two pairs, the neighbors are already systems that access the same data; the
information one neighbor extracts from the other is information it already has within its own
boundary. The cost is one machine.

This measurement gives an ordering, not a preference. First the six optional items are closed: ten
paths go, at a cost of ten work steps and 1,856 MiB. Then the layout is corrected: no path goes, but
the ends of the remaining six paths are tied to the same trust level, at a cost of one machine. There
is no third step; as long as the guest runs, those six paths are open, and the defense's answer there
is not closing but **watching** — which piece of emulation code returns an unexpected error, which
guest shows activity during its neighbor's maintenance window.

## Summary

- The guest and host share eleven items, and these items open sixteen paths; the average per item is
  1.45 paths.
- The five required items open six paths: two transit, one data, three information. The two transit
  paths come from disk and network emulation and cannot be closed while the guest runs.
- The six optional items open ten paths and carry five of the six data paths; closing them, data
  paths drop from six to one, transit from four to two, information from six to three.
- Cost is written in two columns: ten changed work steps and 1,856 MiB of host memory. Memory page
  merging's work-step cost is zero; its cost is in memory.
- Four of the sixteen paths work with a single item; of the six remaining paths, two need one item
  and four need two, and the most frequently required second item is an unpatched emulation bug.
- Splitting the layout by trust level does not change the path count; it drops the different-level
  neighbor pair count from four to zero, at a cost of one machine.

## Next Step

This lesson's and the previous lesson's measurement were both about a **running** guest: which layer
it stands beneath, which items it shares with the host. But a virtual machine's real distinguishing
feature does not show up while it runs, but while it is **stopped and copied**. A guest snapshot can
be taken and stored, an image can be cloned thirty times and distributed to thirty machines, a state
from a week ago can be returned to in a few seconds. The next lesson measures these three operations
in boundary items: how many secret items a clone carries to how many copies, how many sound links a
rollback needs as the snapshot chain grows longer, and how many closed vulnerabilities returning to
a week ago reopens.
