vm_tools: vsh: create vsh-specific README

vsh is used in most VM development workflows, so provide a brief README
that includes motivation and some helpful usage examples.

BUG=none
TEST=none

Change-Id: I0b3ff2dbeb8e80278712871971615c4005901662
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2234534
Commit-Queue: Stephen Barber <smbarber@chromium.org>
Tested-by: Stephen Barber <smbarber@chromium.org>
Reviewed-by: David Munro <davidmunro@google.com>
Reviewed-by: Fergus Dall <sidereal@google.com>
diff --git a/vm_tools/README.md b/vm_tools/README.md
index a493c15..9896d23 100644
--- a/vm_tools/README.md
+++ b/vm_tools/README.md
@@ -104,9 +104,9 @@
 ## vsh
 
 `vsh` is a vsock-based remote shell utility. `vshd` runs on the guest/server,
-and `vsh` runs on the host/client. For now, this is only capable of launching
-a shell on the VM itself, but this may later be extended to launch a shell in
-a specific container inside of the VM.
+and `vsh` runs on the host/client.
+
+For more detailed docs, see [`vsh`](vsh/).
 
 ## vm_syslog
 
diff --git a/vm_tools/vsh/README.md b/vm_tools/vsh/README.md
new file mode 100644
index 0000000..b181090
--- /dev/null
+++ b/vm_tools/vsh/README.md
@@ -0,0 +1,123 @@
+# vsh - Vsock SHell
+
+vsh is a remote shell that operates over [vsock]. Think of ssh, but replace
+the first 's' with a 'v'.
+
+[TOC]
+
+## Why vsh?
+
+SSH is the de-facto standard for getting a shell on a remote machine over a
+network. This makes a lot of sense for a machine under your desk or a VM in the
+cloud.
+
+The most critical features SSH provides are:
+*  Host authentication ensures you're talking to the right machine.
+*  User authentication ensures only authorized users can sign in, and only as
+   themselves.
+*  Encryption prevents parties between the two machines snooping on your
+   traffic.
+
+vsh is focused on one use case only: connect to a VM on the same machine. This
+lets us simplify the requirements substantially.
+
+*  Host authentication is provided by [vsock]. Unlike IP, a VM cannot spoof its
+   [vsock] context id. [vsock] is machine-local, so there is no concern with
+   MitM attacks.
+
+*  User authentication is not required. vsh is used exclusively from host to
+   guest, and the host is always considered more privileged.
+
+*  Encryption isn't necessary since [vsock] cannot be routed, and the traffic
+   will transit directly between host and guest memory. Without a host kernel
+   exploit, a VM cannot observe traffic intended for another VM.
+
+Without the need for any encryption, vsh is simple to set up, and easily
+integrated into a VM project. There's no need to have the guest OS configure
+a network, since [vsock] does not require guest-side configuration.
+
+>**NOTE:** Although the guest-side `vshd` does not authenticate users, it does
+limit which user a shell can be launched with. For example, Crostini's `termina`
+VM will only allow logging in as `chronos`. Developers must build a `test` image
+of `termina` to allow logging in as `root`.
+
+## Features
+
+vsh can:
+
+*  Run both interactive shells (like `bash`), as well as one-shot commands.
+
+*  Detect interactive vs non-interactive usage. This allows piping binary data
+   through vsh without triggering terminal escape codes, as well as using vsh to
+   pipe `stdout` and `stderr` output separately.
+
+*  Forward exit status from the guest-side process.
+
+*  Forward certain signals. Sending `SIGHUP`, `SIGINT`, `SIGQUIT`, or `SIGTERM`
+   will forward the signal to the remote process. This is useful in
+   non-interactive environments such as [Tast] to force the guest-side process
+   to exit cleanly.
+
+## Usage examples
+
+Launches a shell on the VM with [vsock] cid 3. This will work even with a
+manually launched `crosvm` instance, as long as the guest is running `vshd`.
+
+```bash
+(device) # vsh --cid=3
+```
+
+Launches a shell on the VM named `foo`. Names are managed by [`vm_concierge`],
+so this VM must have been started through the [`vm_concierge`] API. The
+`$CROS_USER_ID_HASH` variable is only set for crosh-spawned shells. The
+included one-liner can set it for you.
+
+```bash
+(device) # export CROS_USER_ID_HASH="$(cryptohome --action=status | \
+                                       python3 -c 'import sys, json; \
+                                                   print(json.load(sys.stdin)["mounts"][0]["owner"])')"
+
+(device) # vsh --vm_name=foo --owner_id="${CROS_USER_ID_HASH}"
+```
+
+Launches a root shell on the VM named `foo`. This may require that the VM is
+running a developer-built `test` image.
+
+```bash
+(device) # vsh --vm_name=foo --owner_id="${CROS_USER_ID_HASH}" --user=root
+```
+
+Runs `lxc list` in the `termina` VM with required environment variables set.
+
+```bash
+(device) # vsh --vm_name=termina \
+               --owner_id="${CROS_USER_ID_HASH}" \
+               -- \
+               LXD_DIR=/mnt/stateful/lxd \
+               LXD_CONF=/mnt/stateful/lxd_conf \
+               lxc list
+```
+
+Writes a host file `foo` to `/bar` in the crostini container `penguin`.
+
+```bash
+(device) # cat foo | vsh --vm_name=termina \
+                         --owner_id="${CROS_USER_ID_HASH}" \
+                         --target_container=penguin \
+                         -- \
+                         sh -c "cat - > /bar"
+```
+
+Writes a file `/foo` from crostini container `penguin` to `bar` on the host.
+
+```bash
+(device) # vsh --vm_name=termina \
+               --owner_id="${CROS_USER_ID_HASH}" \
+               --target_container=penguin \
+               -- \
+               cat /foo > bar
+```
+
+[Tast]: https://chromium.googlesource.com/chromiumos/platform/tast/+/HEAD/README.md
+[`vm_concierge`]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/vm_tools/concierge
+[vsock]: https://www.man7.org/linux/man-pages/man7/vsock.7.html