Pledge On Anoma OS

General Idea

pledge is an interesting tool from the openbsd world, it allows a program to pledge to operate in a restricted fashion. If those restrictions are violated in any ways, the underlying operating system will SIGABORT the violating process. This from a security point of view is quite nice, and having a similar tool to interact with a distributed operating system would be handy.

Terminology

Before I propose my ideas, I will define some terms:

  1. Operator :: A person or collective who control some application or shared knowledge base.
  2. Application :: A set of public resources, or database, or normal program that is under the operator’s control.
  3. gas :: Some computational payment to run public code.
    • NOTE: Not all public applications will charge users gas.

Concrete Ideas and Vision

I believe for the Anoma OS, we should be able to pledge to a variety of things

  1. The code executed only touches some restrict knowledge/resource set
  2. Certain pathways, namespaces, primitives, etc, can be barred from running.

If the code that pledged to the operation violates the pledge, then any gas consumed during the execution is forfeit, and the operation is rolled back, as if it never occurred.

For the Feature set:

  1. Operators decide what the application’s pledge environment is like, and can change it whenever they so wish
    • They can do this by vote if it’s a staked committee, or arbitrary if it’s under a single entities control
  2. Code sent in by users, can pledge to be in an even bigger restriction set inside some Application
    • If the application is some web operating environment, where users can submit extra functionality and applications, then a user calculator program may disable time calls or other such functions.

The API for pledges should be quite simple, and there should be tools built to visually see what applications have pledged to what, and tools made to see what any particular symbol/function may violate (for functions like eval, this would be potentially everything, but users can tag specific instances to directly tell the system rather than it infering it.)

1 Like

Something critical to the design and security of pledge/unveil is that it’s got a simple, non-“programmery” interface that can easily be used in every process.

Look at this example code (from OpenBSD resolvd, a daemon that manages /etc/resolv.conf, chosen arbitrarily for being very small (i.e., one process; larger daemons do not have more complicated pledge calls, just more of them)):

	if (unveil(_PATH_RESCONF, "rwc") == -1)
		lerr(1, "unveil " _PATH_RESCONF);
	if (unveil(_PATH_RESCONF_NEW, "rwc") == -1)
		lerr(1, "unveil " _PATH_RESCONF_NEW);
#ifndef SMALL
	if (unveil(_PATH_UNWIND_SOCKET, "w") == -1)
		lerr(1, "unveil " _PATH_UNWIND_SOCKET);
#endif

	if (pledge("stdio unix rpath wpath cpath", NULL) == -1)
		lerr(1, "pledge");

It doesn’t take exceptional effort, understanding of system calls or internals, &c. to add restrictions to any given daemon. The available pledges are in the man page, and it’s easy to select the types of functionality you intend to use (it’s also designed for privsep designs; different subprocesses may have different pledges). In this example, the daemon is allowed to access certain filesystem paths (the unveil calls) and allowed to use stdio, unix (unix domain sockets), rpath, wpath, and cpath (read, write, and create files, i.e., the /etc/resolv.conf file it is tasked with managing). (Note also that unveil takes, e.g., "rwc" for permitting the program to read/write/create that path.)

The equivalent functionality on Linux, seccomp, is incomprehensible to the point of parody and it would be importantly missing the point to compare to and criticize it here (it’s so awful that it would devolve into inane boggling at just how awful it is); suppose instead Linux had something vaguely plausible and akin to what I’d expect someone to come up first with if asked to design this feature, like enumerating a whitelist of syscalls. This would be a bad design; the granularity of individual syscalls is wrong compared to something like pledge("stdio rpath"), and people wouldn’t put it in things.