13 KiB
13 KiB
Changelog
Docs: README · SPEC · ARCHITECTURE · RESEARCH · COMPARISON · AGENTS · CHANGELOG · CI
1.6.0 - 2026-10-25
--mount/--davmountwith adav://,davs://,http://orhttps://source: auto-mounts WebDAV. doos downloads, GPG-verifies against a pinned key and installsrcloneonce under$DOOS_HOME/tools/(never the system, neverPATH, same trust model as the catalog images), then drives it on the host with an on-the-fly connection string (no config file, password passed throughrclone obscure, never on the mount's command line) before the container's namespaces exist. The mount is deduplicated by target (url + credentials + vendor), reused across containers and attaches, and runs detached so it outlives theattachthat created it.--dav-user,--dav-pass,--dav-vendorand--dav-insecureconfigure a target without putting credentials in the URL. Tracked as gap G13 in RESEARCH; measured there against a localrclone serve webdavfixture (install, reuse at ~40 ms, write-back durability, and each failure mode: wrong credentials, unreachable server, non-WebDAV endpoint).doos davmount list/doos davmount umount [--yes] ID: inspect or tear down a managed WebDAV mount; dry-run by default likedelete/image delete.- Fix (found while building the above): the classic
--mount SRC:DST[:ro]could not take credentials with:/;in them because mounts were serialized as one delimited line; containermetanow stores mounts as indexed keys (one field per line), with the old single-line format still read for containers created under 1.5.0. - Refactor:
curl/gpg download-and-verify helpers moved fromimage.cppintoutil.{hpp,cpp}(fetchText,fetchFile,TempDir,isHex64,verifyDetachedSignature,verifyClearsignedSignature) sodavmount.cppreuses the exact same, already-tested verification code instead of a second copy; no behavior change (full image signature test suite re-passes). - New dependency, only for davmount:
unzip(to unpack rclone's release archive) andfusermount3/fusermount(to unmount it); documented in README/AGENTS. - Tests: 10 new end-to-end checks against a real local WebDAV server (read, write durability, idempotent reuse,
--davmountwith--dav-user/--dav-pass, read-only, wrong-password classification, unknown vendor rejected,davmount list/umount). - Docs: COMPARISON section 4's "Where Docker is better" no longer lists bind mounts as a doos gap (stale since 1.5.0); charts and generated numbers re-measured.
1.5.0 - 2026-10-24
--mount SRC:DST[:ro](repeatable, max 8): bind-mounts a host directory into the container, outside the--sizecap. Lets a container reach storage that is not local, for example a WebDAV share mounted on the host first withrclone mountordavfs2; doos never speaks a network filesystem protocol itself, it only bind-mounts what the host already mounted. Changeable like--memory/--pids/--cpus: replaces the whole mount list, applies at the next start. Tracked as gap G12 in RESEARCH; 5 new end-to-end checks (read, write, read-only, missing source rejected, too many rejected).- Docs: COMPARISON section 1 and the gaps list updated (doos now has host-dir bind mounts); charts and generated numbers re-measured (
make bench && make charts).
1.4.0 - 2026-10-24
- CI:
.gitea/workflows/ci.yml(Gitea Actions) runsbuild,valgrind,testandauditon every push.build/valgrindrun on any Docker-mode runner;test/auditneed a self-hosted host-mode runner (real namespaces, cgroup v2 delegation, the AppArmor profile), documented with its one-time setup in the new docs/CI.md. Every step wraps its owntimeout, since Gitea Actions parses but does not enforcetimeout-minutes/concurrency(checked against the 1.25 docs). - Fixed, from review2.md:
parseSize(src/util.cpp) overflowed silently on an oversized input (--size 16777217twas accepted as exactly1.0Tinstead of rejected); now checked before the shift and rejected. Tracked as gap G9 in RESEARCH; regression case added totests/run.sh. - Fixed, from review2.md:
newuidmap,newgidmap,slirp4netnsandpastawere each pinned to one hardcoded/usr/bin/...path; they now go throughresolveBinary()(state-dir override, then a fixed list of system directories), the same resolutioncurl/tar/sha256sum/gpgalready used. Tracked as gap G10. - Docs: the
setns-before-hardening ordering invariant inSandbox::joinandSandbox::start(seccomp deniessetns, and a filter is inherited for life) is now a comment at both call sites, not only in reviewer heads. The hand-rolled Alpine/Debian catalog parsers are logged as an accepted trade-off, gap G11, rather than left undocumented. - Added
LICENSE(MIT). - Docs: README's two overlapping, partly stale intro blocks (a leftover
currently 1.1.3version line, a narrower duplicate usage example) collapsed into one accurate one.
1.3.1 - 2026-10-24
- Docs: gap G8 (
fsutil::mkdirsfollowing a planted symlink, RESEARCH) marked fixed, re-measured withmake -C audit/CVE-2021-30465 test(PASS); removed from COMPARISON's gaps list. The fix itself shipped in 1.3.0 as part of the security-review hardening; this corrects the docs to match.
1.3.0 - 2026-10-24
- Security review applied (review.md):
slirp4netns,pasta,newuidmapandnewgidmapare never searched onPATH; they exec via absolute paths with availability checked up front, and the helpers run with a scrubbedPATH. - Compat-directory mounts pin the parent through an
O_PATHfd so a symlink swap between check and use cannot happen (TOCTOU); symlinks whose target cannot be pinned are not recreated, fail closed instead. --i-understandis now required for--hardening relaxedand--net host; reduced sandboxing is also reported loudly at attach time.- Tests: the e2e suite covers all of the above (
passed=88 failed=0). Docs: RESEARCH, SPEC, README updated in the same change.
1.2.1 - 2026-10-23
scripts/release.sh: commit trailer model name corrected (no functional change).
1.2.0 - 2026-10-23
audit/: 10 more named, sourced CVEs (18 total): the overlayfs-in-unprivileged-userns family (CVE-2021-3493,CVE-2023-2640,CVE-2023-32629,CVE-2015-1328, directly doos's own mount on every attach),CVE-2022-0492(cgroup v1 release_agent; doos mounts no/sys),CVE-2022-27650(inheritable capabilities at container start),CVE-2019-16884andCVE-2023-28642(runc's/procmount-target handling, tested against doos's own/procmount),CVE-2018-12020(GnuPG SigSpoof, static check of the exactgpginvocation insrc/image.cpp),CVE-2020-7039(libslirp memory-safety cluster, version check againstslirp4netns --version).
1.1.5 - 2026-10-23
audit/: 8 named, sourced CVEs relevant to doos's own mechanisms (overlay writes, tar extraction, mount/directory creation, net namespace sharing, the mount-family seccomp denylist, kernel user-namespace exposure), each with its ownREADME.md,Makefileand non-destructivereproduce.shagainstbuild/doos.make auditruns them concurrently (-j8, recursive make);make -C audit list|reportalso available. Kernel memory-corruption CVEs (Dirty Pipe, Dirty COW,legacy_parse_param) are checked by kernel version only, no exploit code.- Found by the audit and disclosed:
fsutil::mkdirsfollows a symlink planted at a container's path, so a symlink under$DOOS_HOME/containers/<name>redirects where that container's state is written (low severity: needs write access to the caller's own$DOOS_HOME). Tracked as gap G8 in RESEARCH and in COMPARISON; not yet fixed. - Docs:
scripts/check-docs.shexcludesaudit/*.md(a separate, self-contained doc set);README.mdandAGENTS.mdlink toaudit/README.md.
1.1.4 - 2026-10-23
- Docs: COMPARISON section 6.1 answers whether doos is a security-wise Docker replacement (same class as rootless Podman, not for untrusted code), summarized in the README safety summary.
1.1.3 - 2026-10-23
- Charts: startup time, executable size and CPU limit as SVG (light and dark palettes, doos highlighted), embedded in COMPARISON and RESEARCH.
- Reproducible measurements:
scripts/bench.shwritesdocs/charts/bench.json;docs/charts/make_charts.pybuilds the charts and rewrites every generated number and table in the documents from it, so text, tables and charts cannot drift apart. Makefilewrapper (make help), expanded.gitignore.
1.1.2 - 2026-10-23
- Docs: new COMPARISON (doos against Docker, rootless Docker, Podman, bubblewrap, systemd-nspawn, LXC/Incus, Apptainer, Distrobox/Toolbx, gVisor, Kata/Firecracker) with sourced pros and cons, startup and disk measurements against Docker, Podman and bubblewrap on the same machine, a gaps list tied to code, and a conclusion.
- Docs: every document now has a navigation line and links to every other document.
scripts/check-docs.shenforces it (and that relative links resolve) and runs insidescripts/release.sh.
1.1.1 - 2026-10-23
doos apparmorprints a profile for the exact path of the running binary (own profile name per path, so several installs coexist). A start that fails because of AppArmor now prints the install command instead of onlymount bind /: Permission denied. Verified with a copy in~/.local/bin.apparmor/doos(packaging) covers more standard install paths.- Docs: Networking section with a verified example per mode (slirp, pasta, host, none), the inbound/loopback behavior of each, and the pasta port-detection delay.
- Tests: 86 checks (adds apparmor output,
none, slirp has no inbound path, pasta container to container).
1.1.0 - 2026-10-23
- Limits:
--memory,--pids,--cpus(cgroup v2; whole-container OOM kill; reports OOM kills and pid-limit hits). Later attaches run in their own cgroup leaf with the same limits. - Hardening (default): Docker's default capability set, a seccomp filter (arch check, x32 guard, clone3 ENOSYS, no nested user namespaces, no mounts/keyrings/bpf/perf/io_uring/...), host
/etcallowlist.--hardening relaxedturns it off per container. - Networking:
--net pasta(host-like reachability, private namespace and abstract sockets).--net hostnow prints a note. - Size cap: measured from inside the id map (counts other uids), paced by scan cost (2 s floor),
RLIMIT_FSIZEbounds single files. - Images: Debian in the catalog (
debian,debian-RELEASE); Alpine and Ubuntu signatures verified against pinned key fingerprints. - Fix: a failed
get_or_createno longer leaves an unreadable container directory behind. - Tests: 83 end-to-end checks.
1.0.0 - 2026-10-23
Breaking: state layout changed (private /etc, meta keys). Containers from 0.x must be deleted and recreated.
- Images:
doos image list|add|delete,--image NAMEonget_or_create/attach(fetched on demand). Catalog:alpine,ubuntu,ubuntu-VERSION; also https URL with--sha256, or a local tarball. sha256 verified before extraction. --size: cap for what a container writes (default 4g). Warns at 80%, freezes at 100% via cgroup v2, thaws below 95%.--ids: subuid mapping through newuidmap/newgidmap by default (chown, su and apt's_aptwork); falls back to one id.- Host mode fixes: directory skeleton so host-owned directories are writable, private copy of
/etc, pre-seeded/varand dpkg state.apt-get installnow completes. - Deleting trees with subuid-owned files works (runs inside the id map).
- Usage measurement counts hard links once.
- Tests: 56 end-to-end checks, including real image downloads, apt/apk installs and the size freeze.
0.1.3 - 2026-10-23
- Docs: field trial of apt and common tools, new gap G7 (host-owned lower layer), README limits section. No code change.
0.1.2 - 2026-10-23
- Docs: researched solutions for all known gaps (G1 to G6) in
docs/RESEARCH.md, with measurements. Nothing implemented yet.
0.1.1 - 2026-10-23
- Docs: AGENTS.md release workflow, ARCHITECTURE.md, expanded README, this changelog.
- Tooling:
scripts/release.sh(bump, build, test, commit, tag).
0.1.0 - 2026-10-23
- First release:
list,get_or_create,attach,delete. - overlayfs over host
/usr /etc /opt, user/mount/pid/uts/ipc/net namespaces. - Networking: slirp4netns (default),
host,none. - End-to-end test suite and AppArmor profile for Ubuntu 24.04+.