<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<title>sunfishcode&#x27;s blog</title>
	<subtitle>A blog by sunfishcode</subtitle>
	<link href="https://blog.sunfishcode.online/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="https://blog.sunfishcode.online"/>
	<generator uri="https://www.getzola.org/">Zola</generator>
	<updated>2025-03-11T00:00:00+00:00</updated>
	<id>https://blog.sunfishcode.online/atom.xml</id>
	<entry xml:lang="en">
		<title>Writing into uninitialized buffers in Rust</title>
		<published>2025-03-11T00:00:00+00:00</published>
		<updated>2025-03-11T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/writingintouninitializedbuffersinrust/" type="text/html"/>
		<id>https://blog.sunfishcode.online/writingintouninitializedbuffersinrust/</id>
		<content type="html">&lt;p&gt;Uninitialized buffers in Rust are a long-standing question, for example:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rfcs&#x2F;2930-read-buf.html&quot;&gt;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rfcs&#x2F;2930-read-buf.html&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;unstable-book&#x2F;library-features&#x2F;core-io-borrowed-buf.html&quot;&gt;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;unstable-book&#x2F;library-features&#x2F;core-io-borrowed-buf.html&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;uninit-read-write&#x2F;&quot;&gt;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;uninit-read-write&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;internals.rust-lang.org&#x2F;t&#x2F;reading-into-uninitialized-buffers-yet-again&#x2F;13282&#x2F;4&quot;&gt;https:&#x2F;&#x2F;internals.rust-lang.org&#x2F;t&#x2F;reading-into-uninitialized-buffers-yet-again&#x2F;13282&#x2F;4&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Recently, &lt;a href=&quot;https:&#x2F;&#x2F;notgull.net&#x2F;&quot;&gt;John Nunley&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;alexsaveau.dev&#x2F;blog&quot;&gt;Alex Saveau&lt;&#x2F;a&gt; came up with an idea for a new
approach, using a &lt;code&gt;Buffer&lt;&#x2F;code&gt; trait, which is now &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rustix&#x2F;1&#x2F;rustix&#x2F;buffer&#x2F;trait.Buffer.html&quot;&gt;in rustix 1.0&lt;&#x2F;a&gt;, which I&#x27;ll
describe in this post.&lt;&#x2F;p&gt;
&lt;p&gt;Update: This idea is now available in a standalone published library: &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;buffer-trait&quot;&gt;buffer-trait&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;introducing-the-buffer-trait&quot;&gt;Introducing the &lt;code&gt;Buffer&lt;&#x2F;code&gt; trait&lt;&#x2F;h2&gt;
&lt;p&gt;The POSIX &lt;code&gt;read&lt;&#x2F;code&gt; function reads bytes from a file descriptor into a buffer,
and it can read fewer bytes than requested. Using &lt;code&gt;Buffer&lt;&#x2F;code&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rustix&#x2F;1&#x2F;rustix&#x2F;io&#x2F;fn.read.html&quot;&gt;&lt;code&gt;read&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; in
rustix looks like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;Fd: AsFd, Buf: Buffer&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fd&lt;&#x2F;span&gt;&lt;span&gt;: Fd, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;: Buf) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Buf::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This uses the &lt;code&gt;Buffer&lt;&#x2F;code&gt; trait to describe the buffer argument. The &lt;code&gt;Buffer&lt;&#x2F;code&gt; trait
looks like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Buffer&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The type of the value returned by functions with `Buffer` arguments.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Return a raw pointer and length to the underlying buffer.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;parts_mut&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut&lt;&#x2F;span&gt;&lt;span&gt; T, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Assert that `len` elements were written to, and provide a return value.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;assume_init&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(And thanks to &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;&quot;&gt;Yoshua Wuyts&lt;&#x2F;a&gt; for feedback on this trait and encouragement
for the overall idea!)&lt;&#x2F;p&gt;
&lt;p&gt;(Rustix&#x27;s own &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rustix&#x2F;1&#x2F;rustix&#x2F;buffer&#x2F;trait.Buffer.html&quot;&gt;&lt;code&gt;Buffer&lt;&#x2F;code&gt; trait&lt;&#x2F;a&gt; is sealed and its functions are private, but
that&#x27;s just rustix choosing for now to reserve the ability to evolve the trait
without breaking compatibility, at the expense of not allowing users to use
&lt;code&gt;Buffer&lt;&#x2F;code&gt; for defining their own I&#x2F;O functions, for now.)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Buffer&lt;&#x2F;code&gt; is implemented for &lt;code&gt;&amp;amp;mut [T]&lt;&#x2F;code&gt;, so users can pass &lt;code&gt;read&lt;&#x2F;code&gt; a &lt;code&gt;&amp;amp;mut [u8]&lt;&#x2F;code&gt;
buffer to write into, and it&#x27;ll return a &lt;code&gt;Result&amp;lt;usize&amp;gt;&lt;&#x2F;code&gt;, where the &lt;code&gt;usize&lt;&#x2F;code&gt;
indicates how many bytes were actually read, on success. This matches how
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rustix&#x2F;0.38.44&#x2F;rustix&#x2F;io&#x2F;fn.read.html&quot;&gt;&lt;code&gt;read&lt;&#x2F;code&gt; in rustix used to work&lt;&#x2F;a&gt;. Using this looks like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buf = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; num_read = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(fd, &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buf)?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;buf[..num_read]);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;Buffer&lt;&#x2F;code&gt; is also implemented for &lt;code&gt;&amp;amp;mut [MaybeUninit&amp;lt;T&amp;gt;]&lt;&#x2F;code&gt;, so users can pass
&lt;code&gt;read&lt;&#x2F;code&gt; a &lt;code&gt;&amp;amp;mut [MaybeUninit&amp;lt;u8&amp;gt;]&lt;&#x2F;code&gt;, and in that case, they&#x27;ll get back a
&lt;code&gt;Result&amp;lt;(&amp;amp;mut [u8], &amp;amp;mut [MaybeUninit&amp;lt;u8&amp;gt;])&amp;gt;&lt;&#x2F;code&gt;. On success, that provides a pair
of slices which are subslices of the original buffer, containing the range
of bytes that data was read into, and the remaining bytes that remain
uninitialized. Rustix previously had a function called &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rustix&#x2F;0.38.44&#x2F;rustix&#x2F;io&#x2F;fn.read_uninit.html&quot;&gt;&lt;code&gt;read_uninit&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; that
worked this way, and in rustix 1.0 it&#x27;s replaced by this new &lt;code&gt;Buffer&lt;&#x2F;code&gt;-enabled
&lt;code&gt;read&lt;&#x2F;code&gt; function. Using this looks like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buf = [MaybeUninit::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;::uninit(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(init, uninit) = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(fd, &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buf)?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span&gt;(init);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This allows reading into uninitialized buffers with a safe API.&lt;&#x2F;p&gt;
&lt;p&gt;And, &lt;code&gt;Buffer&lt;&#x2F;code&gt; also supports a way to read into the spare capacity of a &lt;code&gt;Vec&lt;&#x2F;code&gt;.
The &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rustix&#x2F;1&#x2F;rustix&#x2F;buffer&#x2F;fn.spare_capacity.html&quot;&gt;&lt;code&gt;spare_capacity&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function takes a &lt;code&gt;&amp;amp;mut Vec&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; and returns a
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rustix&#x2F;1&#x2F;rustix&#x2F;buffer&#x2F;struct.SpareCapacity.html&quot;&gt;&lt;code&gt;SpareCapacity&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; newtype which implements &lt;code&gt;Buffer&lt;&#x2F;code&gt;, and it automatically
sets the length of the vector to include the number of initialized elements
after the &lt;code&gt;read&lt;&#x2F;code&gt;, encapsulating the unsafety of &lt;code&gt;Vec::set_len&lt;&#x2F;code&gt;. Using this looks like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buf = Vec::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;::with_capacity(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1024&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; num_read = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(fd, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spare_capacity&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buf))?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;buf);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In rustix, all functions that previously took &lt;code&gt;&amp;amp;mut [u8]&lt;&#x2F;code&gt; buffers to write into
now take &lt;code&gt;impl Buffer&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt; buffers, so they support writing into uninitialized
buffers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;under-the-covers&quot;&gt;Under the covers&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;read&lt;&#x2F;code&gt; is implemented &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rustix&#x2F;1&#x2F;src&#x2F;rustix&#x2F;io&#x2F;read_write.rs.html#39-44&quot;&gt;like this&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; len = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ backend::io::syscalls::read(fd.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_fd&lt;&#x2F;span&gt;&lt;span&gt;(), buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;parts_mut&lt;&#x2F;span&gt;&lt;span&gt;())? };
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Ok(buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;assume_init&lt;&#x2F;span&gt;&lt;span&gt;(len)) }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;First we call the underlying system call, and it returns the number of bytes it
read. We then pass that to &lt;code&gt;assume_init&lt;&#x2F;code&gt;, which computes the &lt;code&gt;Buffer::Output&lt;&#x2F;code&gt; to
return. The output may be just that number, or may be a pair of slices reflecting
that number.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-if-t-is-not-u8&quot;&gt;What if &lt;code&gt;T&lt;&#x2F;code&gt; is not &lt;code&gt;u8&lt;&#x2F;code&gt;?&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;Buffer&lt;&#x2F;code&gt; uses a type parameter &lt;code&gt;T&lt;&#x2F;code&gt; rather than hard-coding &lt;code&gt;u8&lt;&#x2F;code&gt;, so that it can be
used by functions like &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rustix&#x2F;1&#x2F;rustix&#x2F;event&#x2F;epoll&#x2F;fn.wait.html&quot;&gt;&lt;code&gt;epoll::wait&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rustix&#x2F;1&#x2F;x86_64-unknown-freebsd&#x2F;rustix&#x2F;event&#x2F;kqueue&#x2F;fn.kevent.html&quot;&gt;&lt;code&gt;kevent&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rustix&#x2F;1&#x2F;x86_64-unknown-illumos&#x2F;rustix&#x2F;event&#x2F;port&#x2F;fn.getn.html&quot;&gt;&lt;code&gt;port::get&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to return event
records instead of bytes. Using this can look like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; event_list = Vec::&amp;lt;epoll::Event&amp;gt;::with_capacity(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; _num = epoll::wait(&amp;amp;epoll, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spare_capacity&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; event_list), None)?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; event in event_list.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;drain&lt;&#x2F;span&gt;&lt;span&gt;(..) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;handle&lt;&#x2F;span&gt;&lt;span&gt;(event);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This drains the &lt;code&gt;Vec&lt;&#x2F;code&gt; with &lt;code&gt;drain&lt;&#x2F;code&gt; so that it&#x27;s empty before each &lt;code&gt;wait&lt;&#x2F;code&gt;, because
&lt;code&gt;spare_capacity&lt;&#x2F;code&gt; appends to the &lt;code&gt;Vec&lt;&#x2F;code&gt; rather than overwriting any elements.&lt;&#x2F;p&gt;
&lt;p&gt;There are no dynamic allocations inside the loop; &lt;code&gt;SpareCapacity&lt;&#x2F;code&gt; only uses the
existing spare capacity and only calls &lt;code&gt;set_len&lt;&#x2F;code&gt;, and not &lt;code&gt;resize&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Alternatively, because &lt;code&gt;Buffer&lt;&#x2F;code&gt; also works on slices, this code can be written
without using &lt;code&gt;Vec&lt;&#x2F;code&gt; at all:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; event_list = [MaybeUninit::&amp;lt;epoll::Event&amp;gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(init, _uninit) = epoll::wait(&amp;amp;epoll, &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; event_list, None)?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; event in init {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;handle&lt;&#x2F;span&gt;&lt;span&gt;(event);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;error-messages&quot;&gt;Error messages&lt;&#x2F;h2&gt;
&lt;p&gt;One downside of the &lt;code&gt;Buffer&lt;&#x2F;code&gt; trait approach is that it sometimes evokes error
messages from rustc which aren&#x27;t obvious. This happened enough that we now have
a &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rustix&#x2F;1&#x2F;rustix&#x2F;buffer&#x2F;trait.Buffer.html#guide-to-error-messages&quot;&gt;section&lt;&#x2F;a&gt; in rustix&#x27;s documentation about them, and an &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&#x2F;rustix&#x2F;blob&#x2F;main&#x2F;examples&#x2F;buffer_errors.rs&quot;&gt;example&lt;&#x2F;a&gt; showing examples
where they come up.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;using-buffer-safely&quot;&gt;Using &lt;code&gt;Buffer&lt;&#x2F;code&gt; safely&lt;&#x2F;h2&gt;
&lt;p&gt;Rust&#x27;s std currently contains an experimental API based on &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;io&#x2F;struct.BorrowedBuf.html&quot;&gt;&lt;code&gt;BorrowedBuf&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which
has the nice property of allowing users to use it without using &lt;code&gt;unsafe&lt;&#x2F;code&gt;, and without
doing anything hugely inefficient, such as initializing the full buffer. To
achieve this, &lt;code&gt;BorrowedBuf&lt;&#x2F;code&gt; uses a &amp;quot;double cursor&amp;quot; design to avoid re-initializing
memory that has already been initialized.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;Buffer&lt;&#x2F;code&gt; trait described here is simpler, avoiding the need for a &amp;quot;double cursor&amp;quot;,
however it does have an &lt;code&gt;unsafe&lt;&#x2F;code&gt; required method. Is there a way we could modify it
to support safe use?&lt;&#x2F;p&gt;
&lt;p&gt;A &lt;code&gt;Cursor&lt;&#x2F;code&gt; API like &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;io&#x2F;struct.BorrowedCursor.html&quot;&gt;&lt;code&gt;BorrowedCursor&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; could do it. That supports safely and
incrementally writing into an uninitialized buffer. And a key feature of
&lt;code&gt;BorrowedCursor&lt;&#x2F;code&gt; is that it never requires the full buffer to be eagerly
initialized.&lt;&#x2F;p&gt;
&lt;p&gt;With that, the &lt;code&gt;Buffer&lt;&#x2F;code&gt; trait might look like:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;pub trait Buffer&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &#x2F;&#x2F; ... existing contents
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &#x2F;&#x2F;&#x2F; An alternative to `parts_mut` for use with `init`.
&lt;&#x2F;span&gt;&lt;span&gt;    &#x2F;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &#x2F;&#x2F;&#x2F; Return a `Cursor`.
&lt;&#x2F;span&gt;&lt;span&gt;    fn cursor(&amp;amp;mut self) -&amp;gt; Cursor&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        Cursor::new(self)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;impl&amp;lt;T, B: Buffer&amp;lt;T&amp;gt;&amp;gt; Cursor&amp;lt;T, B&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &#x2F;&#x2F;&#x2F; ... cursor API
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    fn finish(self) -&amp;gt; B::Output {
&lt;&#x2F;span&gt;&lt;span&gt;        &#x2F;&#x2F; SAFETY: `Cursor` ensures that exactly `pos` bytes have been written.
&lt;&#x2F;span&gt;&lt;span&gt;        unsafe { self.b.assume_init(selff.pos) }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This way, a user could write their own functions that take &lt;code&gt;Buffer&lt;&#x2F;code&gt; arguments
and implement them using &lt;code&gt;cursor&lt;&#x2F;code&gt;, without using &lt;code&gt;unsafe&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-parts-mut-and-a-raw-pointer&quot;&gt;Why &lt;code&gt;parts_mut&lt;&#x2F;code&gt; and a raw pointer?&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;code&gt;parts_mut&lt;&#x2F;code&gt; function in the &lt;code&gt;Buffer&lt;&#x2F;code&gt; trait looks like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;parts_mut&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut&lt;&#x2F;span&gt;&lt;span&gt; T, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Why return a raw pointer and length, instead of a &lt;code&gt;&amp;amp;mut [MaybeUninit&amp;lt;T&amp;gt;]&lt;&#x2F;code&gt;? Because
a &lt;code&gt;&amp;amp;mut [MaybeUninit&amp;lt;T&amp;gt;]&lt;&#x2F;code&gt; would be unsound in a subtle way. We implement &lt;code&gt;Buffer&lt;&#x2F;code&gt;
for &lt;code&gt;&amp;amp;mut [T]&lt;&#x2F;code&gt;, which cannot contain any uninitialized elements, and exposing it
as a &lt;code&gt;&amp;amp;mut [MaybeUninit&amp;lt;T&amp;gt;]&lt;&#x2F;code&gt; would allow uninitialized elements to be written
into it.&lt;&#x2F;p&gt;
&lt;p&gt;With a raw pointer, we put the burden on the &lt;code&gt;assume_init&lt;&#x2F;code&gt; call to guarantee
that the buffer has been written to properly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;looking-forward&quot;&gt;Looking forward&lt;&#x2F;h2&gt;
&lt;p&gt;A limited version of this &lt;code&gt;Buffer&lt;&#x2F;code&gt; trait is now &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rustix&#x2F;1&#x2F;rustix&#x2F;buffer&#x2F;trait.Buffer.html&quot;&gt;in rustix 1.0&lt;&#x2F;a&gt;, so we&#x27;ll
see how it goes in practice.&lt;&#x2F;p&gt;
&lt;p&gt;This idea is now also available in a standalone published library: &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;buffer-trait&quot;&gt;buffer-trait&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If it works out well, I think this &lt;code&gt;Buffer&lt;&#x2F;code&gt; design is worth considering for
Rust&#x27;s std, as a replacement for &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;io&#x2F;struct.BorrowedBuf.html&quot;&gt;&lt;code&gt;BorrowedBuf&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; (which is currently unstable).
It&#x27;s simpler, as it avoids the &amp;quot;double cursor&amp;quot; pattern, and it has the fun
feature of supporting the &lt;code&gt;Vec&lt;&#x2F;code&gt; spare capacity use case and encapsulating
the unsafe &lt;code&gt;Vec::set_len&lt;&#x2F;code&gt; call.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Errors and Pipelines, a diversion</title>
		<published>2024-09-10T00:00:00+00:00</published>
		<updated>2024-09-10T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/diversion-errors-and-pipelines/" type="text/html"/>
		<id>https://blog.sunfishcode.online/diversion-errors-and-pipelines/</id>
		<content type="html">&lt;p&gt;Consider the following Unix shell command:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-shell &quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span&gt;$ a | b | c &amp;gt; d
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This runs program &lt;code&gt;a&lt;&#x2F;code&gt;, pipes the output to program &lt;code&gt;b&lt;&#x2F;code&gt;, pipes that output to
program &lt;code&gt;c&lt;&#x2F;code&gt;, and finally redirects that output to file &lt;code&gt;d&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If we think of the process tree, we could draw a diagram for it like this:&lt;&#x2F;p&gt;
&lt;pre&gt;
             a   b   c
             ↑   ↑   ↑
             └─shell─┘
&lt;&#x2F;pre&gt;
&lt;p&gt;The shell spawns processes for &lt;code&gt;a&lt;&#x2F;code&gt;, &lt;code&gt;b&lt;&#x2F;code&gt;, and &lt;code&gt;c&lt;&#x2F;code&gt;, wires up their file descriptors
to connect their I&#x2F;O in the desired way, and then waits for them to complete.&lt;&#x2F;p&gt;
&lt;p&gt;From another perspective, this is a kind of call graph, in which the shell &amp;quot;calls&amp;quot;
&lt;code&gt;a&lt;&#x2F;code&gt;, &lt;code&gt;b&lt;&#x2F;code&gt;, and &lt;code&gt;c&lt;&#x2F;code&gt;. They&#x27;re on separate stacks and have separate threads of control,
so they can coexist, but the shell waits for them to complete and collects their
&amp;quot;return values&amp;quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway. A very common question from newcomers in Unix is, &amp;quot;what&#x27;s the difference
between &lt;code&gt;|&lt;&#x2F;code&gt; and &lt;code&gt;&amp;gt;&lt;&#x2F;code&gt;?&amp;quot; It&#x27;s easy, we tell them. &lt;code&gt;|&lt;&#x2F;code&gt; pipes to a command, while &lt;code&gt;&amp;gt;&lt;&#x2F;code&gt;
redirects to a file. So easy, we say. But is it really easy?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-wild-error-appears&quot;&gt;A wild error appears&lt;&#x2F;h2&gt;
&lt;p&gt;First let&#x27;s consider the normal case. What happens if &lt;code&gt;b&lt;&#x2F;code&gt; encounters an error?&lt;&#x2F;p&gt;
&lt;pre&gt;
                 😱₀
             a   b   c
             ↑   ↑   ↑
             └─shell─┘
&lt;&#x2F;pre&gt;
&lt;p&gt;Well, each of these programs has been invoked by the shell, which is &lt;code&gt;wait&lt;&#x2F;code&gt;ing
for them to exit so that it can collect their error status. So &lt;code&gt;b&lt;&#x2F;code&gt; will exit with
an error code, back to the shell.&lt;&#x2F;p&gt;
&lt;p&gt;Unix shells will silently ignore such errors. Oops. So ok let&#x27;s back up and remember
that if we&#x27;re using Unix shell scripting for anything, we should
&lt;a href=&quot;https:&#x2F;&#x2F;wizardzines.com&#x2F;comics&#x2F;bash-errors&#x2F;&quot;&gt;add &lt;code&gt;set -euo pipefail&lt;&#x2F;code&gt; at the top of all our scripts&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now the shell will notice the error.&lt;&#x2F;p&gt;
&lt;p&gt;And then, the other commands in the pipeline will be terminated with &lt;code&gt;SIGPIPE&lt;&#x2F;code&gt;.
Or if they ignore the &lt;code&gt;SIGPIPE&lt;&#x2F;code&gt;, they will be given an &lt;code&gt;EPIPE&lt;&#x2F;code&gt; error next time
they try to write output, which tells them to exit quietly. So the error
propagates to the shell and &lt;code&gt;a&lt;&#x2F;code&gt; and &lt;code&gt;c&lt;&#x2F;code&gt; quietly exit:&lt;&#x2F;p&gt;
&lt;pre&gt;
            ❌  😱₀ ❌
            a   b   c
            ↑   ↑   ↑
            │   😱₁ │
            └─shell─┘
&lt;&#x2F;pre&gt;
&lt;p&gt;Great.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-wild-error-appears-somewhere-else&quot;&gt;A wild error appears &lt;em&gt;somewhere else&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;What happens if &lt;code&gt;d&lt;&#x2F;code&gt; fails?&lt;&#x2F;p&gt;
&lt;p&gt;Or wait, where even is &lt;code&gt;d&lt;&#x2F;code&gt; in that diagram?&lt;&#x2F;p&gt;
&lt;p&gt;Oh oh oh! That&#x27;s the wrong question! Remember, we used &lt;code&gt;&amp;gt;&lt;&#x2F;code&gt; for &lt;code&gt;d&lt;&#x2F;code&gt;, so it&#x27;s not
a program. It&#x27;s just a redirection to an output file. So it can&#x27;t fail!&lt;&#x2F;p&gt;
&lt;p&gt;Or wait, it kindof can? Filesystems can run out of space. Disks can have errors.
Things can happen. But in that case, why can&#x27;t these errors be reported in the
same way?&lt;&#x2F;p&gt;
&lt;p&gt;Oh that&#x27;s right. It&#x27;s because unlike the file descriptors for &lt;code&gt;a&lt;&#x2F;code&gt;&#x27;s and &lt;code&gt;b&lt;&#x2F;code&gt;&#x27;s
outputs, the thing on the other side of &lt;code&gt;c&lt;&#x2F;code&gt;&#x27;s file descriptor is just the operating
system.&lt;&#x2F;p&gt;
&lt;p&gt;And operating systems can&#x27;t fail. Or I should say, they can&#x27;t
report a failure back to the shell, because the shell isn&#x27;t thinking of the
OS as a process it&#x27;s managing. The operating system can&#x27;t push the error
directly to where it needs to go, so it instead pushes the error backwards
through the pipeline into &lt;code&gt;c&lt;&#x2F;code&gt;, and obliges &lt;code&gt;c&lt;&#x2F;code&gt; to report the problem to the
shell for it.&lt;&#x2F;p&gt;
&lt;pre&gt;
          ❌  ❌  😱₁  😱₀
          a   b   c   OS
          ↑   ↑   ↑
          │   │   😱₂
          └─shell─┘
&lt;&#x2F;pre&gt;
&lt;p&gt;It wasn&#x27;t &lt;code&gt;c&lt;&#x2F;code&gt;&#x27;s error. &lt;code&gt;c&lt;&#x2F;code&gt; is just a stream transformer and really shouldn&#x27;t
care about where the output is going or what ultimately happens to it, just like &lt;code&gt;a&lt;&#x2F;code&gt; and &lt;code&gt;b&lt;&#x2F;code&gt;.
But &lt;code&gt;c&lt;&#x2F;code&gt; is the unlucky one that happens to be at the end of the pipeline, so it
gets the error and the job of ensuring that the error makes it back to the shell.&lt;&#x2F;p&gt;
&lt;p&gt;So here&#x27;s a question. What would be different about this process if
we inserted what might seem like a no-op into our command line:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-shell &quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span&gt;$ a | b | c | cat &amp;gt; d
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;cat&lt;&#x2F;code&gt; defaults to reading from stdin and writing to stdout, so it&#x27;s just
a no-op passthrough here. But inserting it does subtly change how the error
handling works. With a &lt;code&gt;cat&lt;&#x2F;code&gt; in there, instead of the error being reported to
&lt;code&gt;c&lt;&#x2F;code&gt;, the error is reported to &lt;code&gt;cat&lt;&#x2F;code&gt;. That means that &lt;code&gt;c&lt;&#x2F;code&gt; can now be simply
terminated with &lt;code&gt;SIGPIPE&lt;&#x2F;code&gt; or told to exit quietly with &lt;code&gt;EPIPE&lt;&#x2F;code&gt; in exactly the same
way as &lt;code&gt;a&lt;&#x2F;code&gt; and &lt;code&gt;b&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre&gt;
         ❌  ❌  ❌   😱₁  😱₀
         a   b   c   cat  OS
         ↑   ↑   ↑   ↑
         │   │   │   😱₂
         └─shell─┴───┘
&lt;&#x2F;pre&gt;
&lt;p&gt;Which is kind of nice. And simple. It might look a little busier, but look closely
at what this says. &lt;code&gt;a&lt;&#x2F;code&gt;, &lt;code&gt;b&lt;&#x2F;code&gt;, and &lt;code&gt;c&lt;&#x2F;code&gt; are all handled in the same way. &lt;code&gt;c&lt;&#x2F;code&gt; is just a
stream transformer just like &lt;code&gt;a&lt;&#x2F;code&gt; and &lt;code&gt;b&lt;&#x2F;code&gt;. Because why should it be different?
Why should it have to know anything about error reporting for errors that happen elsewhere? It
doesn&#x27;t need that if it&#x27;s just writing to a pipe, because things like &lt;code&gt;SIGPIPE&lt;&#x2F;code&gt; or
&lt;code&gt;EPIPE&lt;&#x2F;code&gt; automatically handle it, just like in the others.&lt;&#x2F;p&gt;
&lt;p&gt;What if we built a system that always did that for programs in pipelines, so that they
don&#x27;t need to worry about doing this extra thing? Do what we already do for all the other
processes in a pipeline? And which would make it easier to write small programs
that do one thing and do it well.&lt;&#x2F;p&gt;
&lt;p&gt;But we wouldn&#x27;t want to always create an extra cat process. That would slow things down.
What we&#x27;d really want to do is design a system that just behaves like that without
needing an extra process. And perhaps such a system could explore making other things about
a pipeline more efficient as well. All those processes and context switching have a cost.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s it for now. I hope you enjoyed this diversion!&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Thinking about streams in WASI</title>
		<published>2024-09-10T00:00:00+00:00</published>
		<updated>2024-09-10T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/preview3-streams/" type="text/html"/>
		<id>https://blog.sunfishcode.online/preview3-streams/</id>
		<content type="html">&lt;p&gt;Streams are an essential feature of any large modular system. Whether they&#x27;re in
the form of channels, pipes, sockets, iterators, async coroutines, or other
things, streams represent sequences of data over time, and can connect two pieces
of software with minimal coordination.&lt;&#x2F;p&gt;
&lt;p&gt;WASI is being designed to support large modular systems, so WASI needs a
solid stream design. This is a blog post about streams in WASI.&lt;&#x2F;p&gt;
&lt;p&gt;WASIp2 has been out a while, so we can now look at some experience with it
in practice. WASIp3 is a ways in the future yet, so we have some time to think
about what we want to do differently. So let&#x27;s take a look!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wasip2-streams&quot;&gt;WASIp2 streams&lt;&#x2F;h2&gt;
&lt;p&gt;WASIp2 streams have overall worked fairly well, and are used in APIs like
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;wasi-filesystem&#x2F;&quot;&gt;wasi-filesystem&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;wasi-sockets&#x2F;&quot;&gt;wasi-sockets&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;wasi-http&#x2F;&quot;&gt;wasi-http&lt;&#x2F;a&gt;, providing a common
interface for streaming functionality. However, some of their big ideas
are limited in practice by the lack of integrated async.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;to-block-or-not-to-block&quot;&gt;To block or not to block&lt;&#x2F;h3&gt;
&lt;p&gt;WASIp2 has &lt;code&gt;input-stream&lt;&#x2F;code&gt; and &lt;code&gt;output-stream&lt;&#x2F;code&gt; types, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;wasi-io&#x2F;blob&#x2F;main&#x2F;wit&#x2F;streams.wit&quot;&gt;in wasi-io&lt;&#x2F;a&gt;.
These have pretty ordinary bytestream APIs, although they do do one thing
that&#x27;s different from what people may expect: Instead of being simply
blocking, or simply non-blocking, or even blocking-or-not depending on a
dynamic flag (&lt;code&gt;O_NONBLOCK&lt;&#x2F;code&gt;) as in POSIX, WASIp2 streams have separate
functions for doing blocking and nonblocking I&#x2F;O. The goal of this is to
fix the composition problem.&lt;&#x2F;p&gt;
&lt;p&gt;A lot of people have heard of the &lt;a href=&quot;https:&#x2F;&#x2F;journal.stuffwithstuff.com&#x2F;2015&#x2F;02&#x2F;01&#x2F;what-color-is-your-function&#x2F;&quot;&gt;&amp;quot;what color is your function?&amp;quot;&lt;&#x2F;a&gt;
blog post. In a sense, streams that are blocking or non-blocking also have
different &amp;quot;colors&amp;quot; which can present barriers to composition. Pass a
non-blocking stream in as the stdin of &lt;code&gt;grep&lt;&#x2F;code&gt; in Unix and you get this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;grep: (standard input): Resource temporarily unavailable
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So Unix&#x27;s &lt;code&gt;grep&lt;&#x2F;code&gt; needs a stream with the &amp;quot;blocking&amp;quot; color. Pass it the wrong
color and it doesn&#x27;t work.&lt;&#x2F;p&gt;
&lt;p&gt;The observation behind WASI&#x27;s streams is that one typically has to write
different code to work with using blocking versus non-blocking streams. It&#x27;s
not something that can be meaningfully switched at runtime based on a flag.
So WASI has separate API calls for blocking and non-blocking, so programmers
can just request what they want, and the stream can work in that way without
&amp;quot;color&amp;quot; being a property of the stream.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s a good idea in theory, though in WASIp2 it is somewhat hampered by two
issues. One is that the &lt;code&gt;output-stream&lt;&#x2F;code&gt; API ended up being a little more
cluttered than one might have wanted. The &lt;code&gt;flush&lt;&#x2F;code&gt; concept, in particular, is
something I hope we can improve in WASIp3.&lt;&#x2F;p&gt;
&lt;p&gt;The other issue is that composability in WASI for anything involving I&#x2F;O is
limited by WASI&#x27;s lack of &lt;code&gt;async&lt;&#x2F;code&gt; features. The &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;wasi-io&#x2F;blob&#x2F;main&#x2F;wit&#x2F;poll.wit&quot;&gt;&lt;code&gt;poll&lt;&#x2F;code&gt; function&lt;&#x2F;a&gt; needs to know
about all types of things that might be polled for, which means that virtualizing
any API that involves I&#x2F;O requires virtualizing the &lt;code&gt;poll&lt;&#x2F;code&gt; function, which then
requires virtualizing everything else that uses I&#x2F;O at the same time.&lt;&#x2F;p&gt;
&lt;p&gt;It is possible to virtualize things, and tools like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&#x2F;WASI-Virt&quot;&gt;WASI-virt&lt;&#x2F;a&gt; do so, but the
virtualization ends up having to completely wrap everything, rather than being
able to virtualize individual APIs individually.&lt;&#x2F;p&gt;
&lt;p&gt;And, &lt;code&gt;input-stream&lt;&#x2F;code&gt; is a different type from &lt;code&gt;output-stream&lt;&#x2F;code&gt;, so it&#x27;s not possible
to directly connect stream output from one place to stream input to another.
And the reason they have to be separate types is that WASIp2 has no way to suspend
the writer of a stream while the reader is reading. One can connect readers and
writers in various ways using custom code in the host, but it can&#x27;t be done
from within WASI.&lt;&#x2F;p&gt;
&lt;p&gt;Fixing all these issues properly really needs async features built into the platform.
Fortunately, it was already clear from the beginning that async features would be
critical for many use cases, so there&#x27;s already a plan to follow up WASIp2 with WASIp3
to add async as a headline feature. The idea is to replace &lt;code&gt;poll&lt;&#x2F;code&gt;, &lt;code&gt;input-stream&lt;&#x2F;code&gt;,
&lt;code&gt;output-stream&lt;&#x2F;code&gt;, and all the rest of wasi-io.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;streams-versus-files&quot;&gt;Streams versus files&lt;&#x2F;h3&gt;
&lt;p&gt;From a POSIX perspective, the other big difference between WASIp2 streams and
POSIX streams is they WASIp2 doesn&#x27;t have the &amp;quot;file is-a stream&amp;quot; property. Streams
are separate resources from files. You can request streams for reading from or
writing to files. And similar for sockets and other things. Libraries like libc
may hide this, but this is what&#x27;s happening at the WASI level.&lt;&#x2F;p&gt;
&lt;p&gt;I blogged about some of the reasons for doing this in &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;what-does-everything-is-a-file-do&#x2F;&quot;&gt;&amp;quot;What does everything is a file do?&amp;quot;&lt;&#x2F;a&gt;.
Long story short, decoupling streams from files means better composition because
we can compose anything that works in terms of stream types without worrying about
whether they actually need to be file streams.&lt;&#x2F;p&gt;
&lt;p&gt;These ideas will likely be more important in WASIp3, once we get more powerful
composition with async. Having them in WASIp2 has made things like supporting
libc more complex, and has made it less familiar to people familiar with POSIX.
At the same time, it has also been a step helping us get ready for WASIp3 where
these ideas will have more advantages.&lt;&#x2F;p&gt;
&lt;p&gt;Several people have observed that these changes aren&#x27;t particularly useful if
everyone is just going to use libc, which hides them. But the reason they make
sense for WASI is that in Wasm, not everything will want to use libc. In the &amp;quot;native&amp;quot; world, people
are often accustomed to thinking of C as being the only thing that really
matters, with all other languages simply being ways of producing the kinds of
programs that C could produce, and communicating with each other and the OS
as if they were C programs. But Wasm from the beginning has been on a path of
supporting other languages, including adding features like Garbage Collection
to the underlying platform. So to meet the needs of Wasm, WASI needs to address
languages that don&#x27;t use libc. That does make some things more complex for people
who only care about C, but the tradeoff is we get to aim for a more unified
ecosystem.&lt;&#x2F;p&gt;
&lt;p&gt;Also, even for C and C-like languages, WASI covers many areas not covered by
traditional libc APIs, such as &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;wasi-http&#x2F;&quot;&gt;HTTP&lt;&#x2F;a&gt;, and in these areas, users will more often
be using new APIs or new frameworks.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wasip3-streams&quot;&gt;WASIp3 streams&lt;&#x2F;h2&gt;
&lt;p&gt;The biggest feature of WASIp3 is expected to be the addition of &lt;strong&gt;async support&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?t=203&amp;amp;v=y3x4-nQeXxc&amp;amp;feature=youtu.be&quot;&gt;Luke Wagner&#x27;s talk on async in the Component Model&lt;&#x2F;a&gt; is a good introduction,
and discusses how WASI can fix the function coloring problem. Because Wasm VMs
are in control of the callstack, they&#x27;ll be able to do stack switching as needed to do
things like bridge between async code calling sync functions. And this is
also the way they&#x27;ll be able to bridge between blocking and non-blocking streams.
That talk goes into detail on a lot of material; here, I&#x27;ll just highlight a
few aspects of how it affects streams.&lt;&#x2F;p&gt;
&lt;p&gt;When async is a builtin feature of the platform, it enables a lot of different
possibilities. Imagine being able to link together code written in different
languages, in the same process on the same thread and using a single underlying
async event loop. That&#x27;s powerful. That&#x27;s where this is going.&lt;&#x2F;p&gt;
&lt;p&gt;With my standards hat on, none of what I&#x27;m describing here is in an official
proposal yet, but these general ideas are shared by several involved parties.
If you have thoughts or questions or concerns or suggestions, please reach out
and let&#x27;s talk!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-unified-stream-type&quot;&gt;A unified &lt;code&gt;stream&lt;&#x2F;code&gt; type&lt;&#x2F;h3&gt;
&lt;p&gt;Some of the ideas can look surprising at first, especially if you&#x27;re like me
and have an existing intuition based on existing platforms that are not designed
around async. For example, with async we can have a single &lt;code&gt;stream&lt;&#x2F;code&gt; type, rather
than having separate &lt;code&gt;input-stream&lt;&#x2F;code&gt; and &lt;code&gt;output-stream&lt;&#x2F;code&gt; types. It&#x27;s still
unidirectional, but it works as an input stream when it appears as a function
argument, and works as an output stream when it appears as a function return
value. In effect, &lt;code&gt;streams&lt;&#x2F;code&gt; are less like first-class handles that can be
passed around anywhere, and more like coroutine enables, that simply mediate
between a caller and a coroutine callee that coexist and have a stream of values
flowing between them.&lt;&#x2F;p&gt;
&lt;p&gt;For example, consider this signature for a hypothetical gzip function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;wit&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-wit &quot;&gt;&lt;code class=&quot;language-wit&quot; data-lang=&quot;wit&quot;&gt;&lt;span&gt;gzip: func(input: stream&amp;lt;u8&amp;gt;) -&amp;gt; stream&amp;lt;u8&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The argument is a &lt;code&gt;stream&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt;, which is a bytestream. Because it&#x27;s an argument,
it&#x27;s an input stream that the function can read from. The return type is
also &lt;code&gt;stream&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt;. Being a return value, it&#x27;s an output stream that the function
can create and write to.&lt;&#x2F;p&gt;
&lt;p&gt;Because it&#x27;s the same type on input and output , it could compose with other
functions using ordinary function composition. For example, if we also have this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;wit&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-wit &quot;&gt;&lt;code class=&quot;language-wit&quot; data-lang=&quot;wit&quot;&gt;&lt;span&gt;gunzip: func(input: stream&amp;lt;u8&amp;gt;) -&amp;gt; stream&amp;lt;u8&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then we could do compositions like &lt;code&gt;gzip(gunzip(data))&lt;&#x2F;code&gt; to decompress and
recompress the data (as a silly example).&lt;&#x2F;p&gt;
&lt;p&gt;These ideas aren&#x27;t new. For example, gRPC also has a single conceptual
&lt;code&gt;stream&lt;&#x2F;code&gt; type that works as input when it&#x27;s an argument and output when it&#x27;s
a return value.&lt;&#x2F;p&gt;
&lt;p&gt;Nevertheless, these ideas are things I&#x27;ve had to take time to understand, as I&#x27;m
more accustomed to thinking of input and output streams as being independent
handles (file descriptors) that can be passed around, and these kinds of streams
work in different ways. I&#x27;ve explored questions like
&lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;diversion-errors-and-pipelines&#x2F;&quot;&gt;how does error handling work&lt;&#x2F;a&gt;
and &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;errors-from-close&#x2F;&quot;&gt;should closing an output stream be allowed to fail?&lt;&#x2F;a&gt;
and &lt;a href=&quot;https:&#x2F;&#x2F;hachyderm.io&#x2F;@sunfish&#x2F;113081437290874884&quot;&gt;what happens if someone passed you an output-stream and then ...&lt;&#x2F;a&gt;
and &lt;a href=&quot;https:&#x2F;&#x2F;hachyderm.io&#x2F;@sunfish&#x2F;113108649700392973&quot;&gt;where do output-stream errors go?&lt;&#x2F;a&gt;.
One big-picture takeaway, every time I think &amp;quot;what if someone passes you an
output stream and then...&amp;quot;, I find that the answer is that I need to step
back a level and think about the system in a broader way.&lt;&#x2F;p&gt;
&lt;p&gt;My posts here are a start on exploring these topics, though clearly much
more will be needed as WASIp3 progresses. And WASI will need bridges to
connect with existing languages and libraries that work in terms of
channel-like concepts, or other streaming concepts.&lt;&#x2F;p&gt;
&lt;p&gt;But put all these pieces together, and we get the most plausible path
I&#x27;m aware of having been proposed to an ecosystem with a single &lt;code&gt;stream&lt;&#x2F;code&gt; type
that connects all the streaming things, which seems like a valuable goal
to pursue for WASI.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;stream-of-t&quot;&gt;Stream of &lt;code&gt;T&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Another advantage of being a builtin type is that the &lt;code&gt;stream&lt;&#x2F;code&gt; type can
more easily be parameterized on the data type. Bytestreams can do a lot,
but with a rich type system with things like resource handles, being
able to pass handles over a stream will be a powerful connecting primitive.&lt;&#x2F;p&gt;
&lt;p&gt;From a Unix perspective, streams-of-handles is much like passing file
descriptors over a Unix-domain socket, but hopefully with a much less
complex API.&lt;&#x2F;p&gt;
&lt;p&gt;From a higher-level language perspective, streams of typed values look
a lot like iterators.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;&#x2F;h2&gt;
&lt;p&gt;WASIp2 streams are here today. They are a transitional step between
WASIp1-style Unix streams and WASIp3&#x27;s coroutine-style streams.
But because WASIp2 lacks integrated async, they have some limitations.&lt;&#x2F;p&gt;
&lt;p&gt;WAISp3 will add integrated async, and make streams much more flexible
and powerful.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Errors from `close`</title>
		<published>2024-09-09T00:00:00+00:00</published>
		<updated>2024-09-09T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/errors-from-close/" type="text/html"/>
		<id>https://blog.sunfishcode.online/errors-from-close/</id>
		<content type="html">&lt;p&gt;A while ago I wrote a blog post about &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;bugs-in-hello-world&#x2F;&quot;&gt;&amp;quot;Bugs in Hello World&amp;quot;&lt;&#x2F;a&gt;, about how a lot
of programming languages&#x27; default way of printing to stdout silently swallow
errors.&lt;&#x2F;p&gt;
&lt;p&gt;This led to a &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;hello-world-vs-io-errors&quot;&gt;repo&lt;&#x2F;a&gt; for maintaining lists of languages that do and don&#x27;t have
this bug, and some examples of how to fix the bug. For example, in C, the
fixed Hello World looks like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;stdio.h&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;stdlib.h&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;printf&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Hello, World!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;fflush&lt;&#x2F;span&gt;&lt;span&gt;(stdout) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;|| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;ferror&lt;&#x2F;span&gt;&lt;span&gt;(stdout) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; EXIT_FAILURE;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; EXIT_SUCCESS;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s a little more verbose than the hello world code that&#x27;s usually presented
to newcomers, but still manageable.&lt;&#x2F;p&gt;
&lt;p&gt;So that&#x27;s it, right? Do we now have a &lt;em&gt;completely&lt;&#x2F;em&gt; bug-free version of Hello World?&lt;&#x2F;p&gt;
&lt;p&gt;Well for completeness, we might observe that this version doesn&#x27;t make any provision
for internationalization or accessibility. Not everyone will be able to read its output.
That&#x27;s worth thinking about. However the rest of this blog post is about a different
topic, let&#x27;s set this aside here.&lt;&#x2F;p&gt;
&lt;p&gt;And if we dig further, we notice that this version doesn&#x27;t call &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;functions&#x2F;fsync.html&quot;&gt;&lt;code&gt;fsync&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
That means that if its output is redirected to a file, and it runs, and exits, and reports
success, then data might still be lost. If the power goes out, then once power is restored
and the machine boots up again, users may log in to find corrupted or even entirely missing
output. Even though the program reported succeeding. Uh oh!&lt;&#x2F;p&gt;
&lt;p&gt;However, this is where we need to talk about &lt;em&gt;expectations&lt;&#x2F;em&gt;. Simple command-line
programs that just read from stdin and write to stdout aren&#x27;t &lt;em&gt;expected&lt;&#x2F;em&gt; to
&lt;code&gt;fsync&lt;&#x2F;code&gt; their output. The reason &lt;code&gt;fsync&lt;&#x2F;code&gt; exists in the first place is so that
applications can chose not to call it when they think they don&#x27;t need to, and
skip the overhead.&lt;&#x2F;p&gt;
&lt;p&gt;Simple command-line programs are often just one step of a larger logical program,
and it would add useless overhead if every program in a pipeline called &lt;code&gt;fsync&lt;&#x2F;code&gt;.
So the expectation is, programs only call &lt;code&gt;fsync&lt;&#x2F;code&gt; when they are operating at a
scope where they know it&#x27;s needed.&lt;&#x2F;p&gt;
&lt;p&gt;For example, something like &lt;code&gt;vim&lt;&#x2F;code&gt; does call &lt;code&gt;fsync&lt;&#x2F;code&gt; when saving a file. If the
power goes out, you really want that file you were editing to have all your edits.
But something like &lt;code&gt;grep&lt;&#x2F;code&gt; doesn&#x27;t call &lt;code&gt;fsync&lt;&#x2F;code&gt; when writing its output. If the
power goes out halfway through some script, it&#x27;ll take down the script too.
So you can often just rerun the whole script from the beginning. And if the
script&#x27;s output was really important, it can do a &lt;code&gt;sync&lt;&#x2F;code&gt; itself. So it all kind
of works out.&lt;&#x2F;p&gt;
&lt;p&gt;Our Hello World program here is a simple command-line program, so it isn&#x27;t expected
to call &lt;code&gt;fsync&lt;&#x2F;code&gt;. So we&#x27;ll say that&#x27;s not a bug.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ok-great-that-means-we-really-are-done-right&quot;&gt;Ok great. That means we really are done, right?&lt;&#x2F;h2&gt;
&lt;p&gt;Maybe.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what&quot;&gt;what&lt;&#x2F;h2&gt;
&lt;p&gt;There&#x27;s something of a longstanding debate.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;seriously&quot;&gt;seriously?&lt;&#x2F;h2&gt;
&lt;p&gt;So back in the day, when the Network File System (NFS) was first released, it was a triumph of
Unix design. The mighty filesystem could abstract over &lt;em&gt;everything&lt;&#x2F;em&gt;, even the network.&lt;&#x2F;p&gt;
&lt;p&gt;But back in the day back in the day, when Unix was being designed, even though disks and
tapes and things were slow, CPUs were also really slow. Moore&#x27;s law was still just getting
started. And the Internet didn&#x27;t exist yet. It would be decades before anyone would start thinking
about stuff like &lt;a href=&quot;http:&#x2F;&#x2F;www.kegel.com&#x2F;c10k.html&quot;&gt;C10K&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And in that environment, filesystem APIs were designed to have lots of simple operations that
each only did a small amount of work, and each operation blocked until the operation was complete.
This made everything very simple.&lt;&#x2F;p&gt;
&lt;p&gt;In the following decades, Unix systems would add various asynchronous I&#x2F;O APIs, and some of these things do
make some things better for some applications in some settings. But most regular applications
on Unix platforms continue to use synchronous APIs for most things.&lt;&#x2F;p&gt;
&lt;p&gt;Now, when NFS was introduced, all these little synchronous messages were going over the
network to a server, and applications were always waiting for the server to respond over
the network to each message before continuing. So NFS had a lot of waiting going on.&lt;&#x2F;p&gt;
&lt;p&gt;To speed things up, the NFS designers introduced an &amp;quot;async&amp;quot; mode. This mode still presents
the appearance of synchronous I&#x2F;O to applications, but under the covers it does some of the
work asynchronously. In particular, &lt;code&gt;write&lt;&#x2F;code&gt;s appear to succeed, before the actual I&#x2F;O is
completed on the server. This makes things faster, but also means that if an error occurs when
the data is sent, it&#x27;s too late to have the &lt;code&gt;write&lt;&#x2F;code&gt; fail with an error code. So write errors
end up getting deferred, and reported in later &lt;code&gt;write&lt;&#x2F;code&gt; or other calls. That&#x27;s different from
what applications previously expected, but in practice it&#x27;s close enough that most things
basically work.&lt;&#x2F;p&gt;
&lt;p&gt;And to be sure, we&#x27;re still not talking about use cases that should be doing &lt;code&gt;fsync&lt;&#x2F;code&gt; here.
It&#x27;s not about ensuring the data reaches the actual persistent storage on the server, so that
it&#x27;s safe from power failures. It&#x27;s just about ensuring that the data reached the server and
the server didn&#x27;t run out of storage space or quota, so that it&#x27;s safe from being corrupted
even when there isn&#x27;t a power failure.&lt;&#x2F;p&gt;
&lt;p&gt;But there is always one &lt;code&gt;write&lt;&#x2F;code&gt; that isn&#x27;t followed by another &lt;code&gt;write&lt;&#x2F;code&gt;: the last one. Errors
that happen during the last &lt;code&gt;write&lt;&#x2F;code&gt; on a stream would then be reported in the final &lt;code&gt;close&lt;&#x2F;code&gt;
call. From an OS perspective, this is fine. &lt;code&gt;close&lt;&#x2F;code&gt; is just a syscall that can fail, like any
other syscall.&lt;&#x2F;p&gt;
&lt;p&gt;However, despite it being nice and tidy from an OS perspective, userspace often doesn&#x27;t check
for errors from &lt;code&gt;close&lt;&#x2F;code&gt; in practice. For a lot of different reasons.&lt;&#x2F;p&gt;
&lt;p&gt;For example, if we look at the system calls performed by our Hello World program above, there isn&#x27;t
even a &lt;code&gt;close&lt;&#x2F;code&gt; call:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;write(1, &amp;quot;Hello, World!\n&amp;quot;, 14)         = 14
&lt;&#x2F;span&gt;&lt;span&gt;exit_group(0)                           = ?
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If the output of this application is redirected to a file on an NFS filesystem, then
that &lt;code&gt;14&lt;&#x2F;code&gt; returned from &lt;code&gt;write&lt;&#x2F;code&gt; might just be the NFS subsystem pretending everything is
synchronous, despite not having sent the data to the server yet. If the server runs out of
storage space, the user runs out of quota, the network gets overloaded, or
other failures happen, our hello world program will silently swallow the error. strace
won&#x27;t see it, because it&#x27;ll happen implicitly when the process exits and the OS cleans up
all its open file descriptors.&lt;&#x2F;p&gt;
&lt;p&gt;And to be &lt;em&gt;sure&lt;&#x2F;em&gt; sure, we&#x27;re still &lt;em&gt;still&lt;&#x2F;em&gt; not talking about applications that are expected
to &lt;code&gt;fsync&lt;&#x2F;code&gt; here. If you run out of storage space or quota, your output could be truncated,
and other applications could therefore see incorrect output, even if there isn&#x27;t a power
failure.&lt;&#x2F;p&gt;
&lt;p&gt;Is it a bug that we silently swallow errors here? Yes. Silently swallowing errors (unless
explicitly silenced) is &lt;a href=&quot;https:&#x2F;&#x2F;peps.python.org&#x2F;pep-0020&#x2F;#the-zen-of-python&quot;&gt;always a bug&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;But whose bug is it?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;who-will-it-be-who-will-it-be&quot;&gt;Who will it be? Who will it be?&lt;&#x2F;h2&gt;
&lt;p&gt;From the perspective we&#x27;ve approached it here, it first seems like this is the
application&#x27;s bug. Linux&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;close.2.html#NOTES&quot;&gt;&lt;code&gt;close&lt;&#x2F;code&gt; documentation&lt;&#x2F;a&gt; agrees, notably observing that
&amp;quot;careful programmers&amp;quot; should check for errors from &lt;code&gt;close&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Fingers pointed.&lt;&#x2F;p&gt;
&lt;p&gt;And it certainly is nice and tidy to just end the story there. The designers of Unix
intended for us to check errors from all syscalls, and &lt;code&gt;close&lt;&#x2F;code&gt; is a syscall, so we
should check errors from it. And in C, failing to check errors from a function is
associated with careless programmers, so it&#x27;s easy to just blame the programmers for
any problems that come up.&lt;&#x2F;p&gt;
&lt;p&gt;And there are some programs that do manage to do this. Notably GNU command-line utilities
like &lt;code&gt;grep&lt;&#x2F;code&gt; do close their stdio streams. So perhaps everyone should do this, if they
wish to think of themselves as &amp;quot;careful programmers&amp;quot;.&lt;&#x2F;p&gt;
&lt;p&gt;But it&#x27;s not so simple. &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;&quot;&gt;POSIX&#x27;s own &lt;code&gt;close&lt;&#x2F;code&gt; documentation&lt;&#x2F;a&gt; says that
&amp;quot;The close() operation itself need not block awaiting [...] I&#x2F;O completion&amp;quot;. So
programs written to the POSIX spec can&#x27;t rely on getting errors from &lt;code&gt;close&lt;&#x2F;code&gt; anyway.&lt;&#x2F;p&gt;
&lt;p&gt;And in the real world, lots of other real-world applications, written by careful
conscientious programmers, don&#x27;t check for errors from &lt;code&gt;close&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Furthermore, even in applications which do close &lt;code&gt;stdout&lt;&#x2F;code&gt;, it can cause problems. Some
debugging tools inject code that uses &lt;code&gt;stdout&lt;&#x2F;code&gt; for output, which can break if &lt;code&gt;stdout&lt;&#x2F;code&gt;
gets closed. Some C++ libraries use static destructors that produce output to &lt;code&gt;stdout&lt;&#x2F;code&gt;.
These are real-world concerns; for example, at one time, LLVM tools were made to close
&lt;code&gt;stdout&lt;&#x2F;code&gt;, to catch errors just as we&#x27;re discussing here, and it caused so many problems
that this code was eventually reverted, and they no longer do.&lt;&#x2F;p&gt;
&lt;p&gt;As an aside, sometimes when this topic is discussed, people bring up the idea that
instead of closing stdout, one could just &lt;code&gt;dup&lt;&#x2F;code&gt; it and then close the newly-created
file descriptor. However, this isn&#x27;t guaranteed to work, because file descriptions
are reference-counted, so a &lt;code&gt;close&lt;&#x2F;code&gt; of a &lt;code&gt;dup&lt;&#x2F;code&gt; may just decrement the reference
count without doing any extra work, so that doesn&#x27;t seem to be a reliable answer.&lt;&#x2F;p&gt;
&lt;p&gt;So not only do we not tell application programmers that they need to close stdout,
they face complicated problems when they do. Is it really their fault if they aren&#x27;t
doing it?&lt;&#x2F;p&gt;
&lt;p&gt;Maybe the real bug is in the design of the system that creates this situation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pointing-the-finger-elsewhere&quot;&gt;Pointing the finger elsewhere&lt;&#x2F;h2&gt;
&lt;p&gt;Perhaps we can blame the designers of NFS for inventing this &amp;quot;async&amp;quot; mode and not
fully implementing the expected local filesystem semantics. Or blame their users
who demanded faster NFS performance. Or blame the Unix designers for selling us on
the promise of &amp;quot;everything is a file&amp;quot; and encouraging the computing world to build
up an entire ecosystem of software around synchronous I&#x2F;O.&lt;&#x2F;p&gt;
&lt;p&gt;Or perhaps we can blame system administrators who choose to use NFS.&lt;&#x2F;p&gt;
&lt;p&gt;Or perhaps we can blame the causes of the I&#x2F;O errors. If a goat chews a network
cable, we blame the goat for any data loss that results. When a user uses too much
space, we blame the user for using too much space. If those things hadn&#x27;t happened,
none of this would have been a problem.&lt;&#x2F;p&gt;
&lt;p&gt;But as in so many things in life, it&#x27;s worthwhile to keep a question in mind: is the
goal just to find someone to blame? Or is the goal here to make systems more reliable?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fuse&quot;&gt;FUSE&lt;&#x2F;h2&gt;
&lt;p&gt;And besides, it&#x27;s not just NFS. Or other network filesystems that do similar things.&lt;&#x2F;p&gt;
&lt;p&gt;This problem of errors from &lt;code&gt;close&lt;&#x2F;code&gt; also comes up in FUSE filesystems too. The &lt;a href=&quot;https:&#x2F;&#x2F;libfuse.github.io&#x2F;doxygen&#x2F;structfuse__operations.html#a6bfecd61ddd58f74820953ee23b19ef3&quot;&gt;FUSE documentation&lt;&#x2F;a&gt; does
say that FUSE modules shouldn&#x27;t return errors from &lt;code&gt;close&lt;&#x2F;code&gt; if it&#x27;s important that
applications see them. And on some platforms, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;libfuse&#x2F;libfuse&#x2F;issues&#x2F;373&quot;&gt;these errors aren&#x27;t even reported&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;However nothing stops modules from ignoring this documentation, or in just ignoring
platforms other than Linux, so in theory they can also be having this problem.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-if-we-say-that-checking-for-errors-from-close-is-optional&quot;&gt;What if we say that checking for errors from close is optional?&lt;&#x2F;h2&gt;
&lt;p&gt;What if we said that it&#x27;s ok to ignore errors from close in general, and that applications
only have to do it if they have a special need to. If they&#x27;re handling sensitive data,
or if they&#x27;re talking to an unreliable filesystem, then they should check, but otherwise
they don&#x27;t have to?&lt;&#x2F;p&gt;
&lt;p&gt;But the problem is, most programs don&#x27;t know either of these things. Most programs don&#x27;t
know the context in which their users are using them. They don&#x27;t know what importance
their users assign to their data. And, while it&#x27;s possible to check for NFS, it&#x27;s not
possible to check for &amp;quot;is this an unreliable filesystem&amp;quot; in general.&lt;&#x2F;p&gt;
&lt;p&gt;Most applications don&#x27;t have any way to be aware of such things.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;who-should-be-responsible&quot;&gt;Who &lt;em&gt;should&lt;&#x2F;em&gt; be responsible?&lt;&#x2F;h2&gt;
&lt;p&gt;When I started this journey, I believed that applications were responsible. That&#x27;s what
major platforms say in their documentation, so it&#x27;s right by definition. Several years ago,
I was the one who made LLVM tools close &lt;code&gt;stdout&lt;&#x2F;code&gt; originally, and defended that code for
years as waves of reports of problems with it came in.&lt;&#x2F;p&gt;
&lt;p&gt;But eventually I stopped defending that code, and the problem reports kept coming in, and
the code was removed.&lt;&#x2F;p&gt;
&lt;p&gt;Partly as a result of this experience, I came to believe that the platform documentation
was misguided. It&#x27;s too easy. Platform developers can just hide behind the simple
stance that &lt;code&gt;close&lt;&#x2F;code&gt; is just another syscall that can fail, and pointedly document that
&amp;quot;&lt;em&gt;careful&lt;&#x2F;em&gt;&amp;quot; programmers will check for errors. If users have difficulty doing so, blame the
users.&lt;&#x2F;p&gt;
&lt;p&gt;Instead, I came to believe that we needed to renegotiate this relationship.
The responsibility should be with some combination of the people who chose to use NFS
or FUSE, and the causes of the I&#x2F;O errors. Users working with NFS &lt;em&gt;should&lt;&#x2F;em&gt; monitor their
free space. Administrators &lt;em&gt;should&lt;&#x2F;em&gt; be monitoring their networks and their hardware. And
everyone should watch out for goats. Because
so many applications don&#x27;t handle these errors gracefully, users and administrators should
be doing this anyway. Users using FUSE modules &lt;em&gt;should&lt;&#x2F;em&gt; be wary of modules that ignore the
FUSE API documentation&#x27;s recommendations. And if they&#x27;re doing those things anyway, from there,
it&#x27;s not a huge leap to say that users&#x27; &lt;em&gt;responsibility&lt;&#x2F;em&gt; to do them.&lt;&#x2F;p&gt;
&lt;p&gt;And besides, network filesystems like NFS are less popular today than they once were. Computer
labs have been disappearing in favor of bring-your-own-device. Data is increasingly stored in
the cloud rather than on departmental servers. NFS is still out there, but it&#x27;s far less
prevalent than it once was.&lt;&#x2F;p&gt;
&lt;p&gt;And besides besides, programming languages which make async programming more convenient
are becoming more popular. If more programs were written in a way that calling &lt;code&gt;write&lt;&#x2F;code&gt;
didn&#x27;t block them from doing other work, then this whole situation might be avoided entirely.&lt;&#x2F;p&gt;
&lt;p&gt;So these days, it&#x27;s difficult to justify taking a strong stance that programmers
everywhere need to take on all the burdens that come with calling &lt;code&gt;close&lt;&#x2F;code&gt; on stdout.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;so-where-are-we-now&quot;&gt;So where are we now?&lt;&#x2F;h2&gt;
&lt;p&gt;Platforms still blame applications for not checking errors from &lt;code&gt;close&lt;&#x2F;code&gt;. And these
days, platforms have decades of inertia to justify not making any major changes.&lt;&#x2F;p&gt;
&lt;p&gt;A great many applications don&#x27;t check for errors from &lt;code&gt;close&lt;&#x2F;code&gt;. And they also have
decades of inertia too.&lt;&#x2F;p&gt;
&lt;p&gt;Neither side can be easily fixed.&lt;&#x2F;p&gt;
&lt;p&gt;So mostly, this issue just persists through time. When problems in practice do happen,
there are usually other things around that can be blamed. I&#x27;m sorry your data got
silently corrupted. It&#x27;s those goats. Eating our network cables. You know how goats are 😉.&lt;&#x2F;p&gt;
&lt;p&gt;What I can say at this point is that I personally am not going to embark on a quest
to get application programmers to check for errors from &lt;code&gt;close&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And so, my conclusion here is that, no, our hello world program does not have a bug.
It&#x27;s fine. It&#x27;s just fine.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Capabilities and Filesystems</title>
		<published>2024-07-05T00:00:00+00:00</published>
		<updated>2024-07-05T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/capabilities-and-filesystems/" type="text/html"/>
		<id>https://blog.sunfishcode.online/capabilities-and-filesystems/</id>
		<content type="html">&lt;p&gt;When we first designed the filesystem API in WASI, we had a lot of questions.
When a Wasm module has an &lt;code&gt;import&lt;&#x2F;code&gt;, what does that mean? How are import names
resolved? What do we know about the state of the world outside of what the spec
calls the &amp;quot;store&amp;quot;? Capabilities are pretty cool; what&#x27;s the best way to
incorporate capabilities into filesystem APIs?&lt;&#x2F;p&gt;
&lt;p&gt;At the time, we mainly wanted to keep our options open and avoid hard-coding
ambient authority anywhere, because we knew from other systems that retrofitting
capability-based security onto an ecosystem designed without it can be
prohibitively difficult. So we followed the example of CloudABI, which in turn
draws a lot from Capsicum, which combine filesystem APIs and capabilities in
practical systems.&lt;&#x2F;p&gt;
&lt;p&gt;Today, we&#x27;ve learned a lot about how WASI is being used, and about what
imports are and how they&#x27;re resolved in the component model, and how the overall
security model of the component model works. And with this knowledge, it&#x27;s worth
taking a high-level look at WASI&#x27;s filesystem API to see if we can make something
that works with the tools we have today and fits with the way people want to use
it today.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wasi-s-current-design&quot;&gt;WASI&#x27;s current design&lt;&#x2F;h2&gt;
&lt;p&gt;In WASI&#x27;s current design, all filesystem API functions require a handle value to
be passed to them as an argument. Instead of having a plain &lt;code&gt;open&lt;&#x2F;code&gt; function which takes
a string and resolves it in some implied namespace, there&#x27;s just an &lt;code&gt;openat&lt;&#x2F;code&gt;-like method
in the descriptor resource, which takes a &lt;code&gt;descriptor&lt;&#x2F;code&gt; as its receiver parameter.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;wit&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-wit &quot;&gt;&lt;code class=&quot;language-wit&quot; data-lang=&quot;wit&quot;&gt;&lt;span&gt;    resource descriptor {
&lt;&#x2F;span&gt;&lt;span&gt;        ...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        open-at: func(
&lt;&#x2F;span&gt;&lt;span&gt;            &#x2F;&#x2F;&#x2F; Flags determining the method of how the path is resolved.
&lt;&#x2F;span&gt;&lt;span&gt;            path-flags: path-flags,
&lt;&#x2F;span&gt;&lt;span&gt;            &#x2F;&#x2F;&#x2F; The relative path of the object to open.
&lt;&#x2F;span&gt;&lt;span&gt;            path: string,
&lt;&#x2F;span&gt;&lt;span&gt;            &#x2F;&#x2F;&#x2F; The method by which to open the file.
&lt;&#x2F;span&gt;&lt;span&gt;            open-flags: open-flags,
&lt;&#x2F;span&gt;&lt;span&gt;            &#x2F;&#x2F;&#x2F; Flags to use for the resulting descriptor.
&lt;&#x2F;span&gt;&lt;span&gt;            %flags: descriptor-flags,
&lt;&#x2F;span&gt;&lt;span&gt;        ) -&amp;gt; result&amp;lt;descriptor, error-code&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        ...
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The implied &amp;quot;self&amp;quot; argument handle identifies a directory tree, and the &lt;code&gt;path&lt;&#x2F;code&gt;
string is resolved as a relative path within that tree. Programs are then given
an initial set of handles to work with via the &amp;quot;preopens&amp;quot; mechanism.&lt;&#x2F;p&gt;
&lt;p&gt;Unlike in POSIX, this &lt;code&gt;openat&lt;&#x2F;code&gt;-style function enforces sandboxing, preventing
absolute paths, or &lt;code&gt;..&lt;&#x2F;code&gt; or symlinks which would reference files or directories
outside of the handle&#x27;s namespace.&lt;&#x2F;p&gt;
&lt;p&gt;All these ideas come directly from &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;NuxiNL&#x2F;cloudabi&quot;&gt;CloudABI&lt;&#x2F;a&gt; and indirectly from &lt;a href=&quot;https:&#x2F;&#x2F;wiki.freebsd.org&#x2F;Capsicum&quot;&gt;Capsicum&lt;&#x2F;a&gt;,
and similar ideas were being &lt;a href=&quot;https:&#x2F;&#x2F;fuchsia.dev&#x2F;fuchsia-src&#x2F;concepts&#x2F;filesystems&#x2F;dotdot&quot;&gt;adopted in Google&#x27;s Fuchsia OS&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And to be sure, there are reasons why this approach makes sense, for security,
modularity, and portability. The areas around the roots of filesystems tend have
higher concentrations of security and portability hazards. Roots are where many &amp;quot;interesting&amp;quot;
directories like &lt;code&gt;&#x2F;etc&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;tmp&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;proc&lt;&#x2F;code&gt;, and &lt;code&gt;C:&#x2F;Windows&lt;&#x2F;code&gt; live. If we desire secure
and portable programs, we need to avoid them being especially aware of those directories.
Prohibiting absolute paths at the WASI level strongly resonates with that desire.&lt;&#x2F;p&gt;
&lt;p&gt;And while we knew that banning absolute paths would break a lot of things, we had the
idea to add compatibility back in, using the techniques of &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;musec&#x2F;libpreopen&quot;&gt;libpreopen&lt;&#x2F;a&gt;. The basic idea
is to emulate absolute paths in libc, while still avoiding them at the WASI level.&lt;&#x2F;p&gt;
&lt;p&gt;The cool thing about this approach is that, in theory, it achieves the best of both worlds.
We get compatibility for existing code and toolchains when we want that, and we also get
the option to have programs that don&#x27;t use those compatibility layers and in return get
stronger security guarantees.&lt;&#x2F;p&gt;
&lt;p&gt;Another theoretical win of this approach is that it avoids baking the concept of a &amp;quot;current working directory&amp;quot;
into the system. The current working directory is basically a file descriptor for a directory, except
that unlike normal file descriptors, this file descriptor is implicit. In Unix, this means it
needs its own special system calls like &lt;code&gt;chdir&lt;&#x2F;code&gt; to do what &lt;code&gt;open&lt;&#x2F;code&gt; does, and &lt;code&gt;fchdir&lt;&#x2F;code&gt; to do what &lt;code&gt;dup2&lt;&#x2F;code&gt;
does. So it has arbitrary restrictions, anywhere the specialized system calls don&#x27;t cover things that
the general system calls can do. And, this implied file descriptor is per-process, making it inflexible
for multi-threaded applications. So instead, we kept the current working directory concept out of WASI
and aimed for an approach of emulating it in libc instead.&lt;&#x2F;p&gt;
&lt;p&gt;This overall design means that Wasm toolchains and libraries can chose for themselves
whether to use the compatibility bridges if they need that functionality, or to lean
into the capability model and avoid having a filesystem root or current working directory
imposed on them if they don&#x27;t.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-it-s-going&quot;&gt;How it&#x27;s going&lt;&#x2F;h2&gt;
&lt;p&gt;This approach basically works, but it has several papercuts.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s less familiar. Practically everyone is familiar with traditional
filesystems and absolute paths and current working directories. And even though
Unix and Windows have concepts of directory handles, they&#x27;re not widely used, so
not everyone is familiar with them.&lt;&#x2F;p&gt;
&lt;p&gt;And it&#x27;s less compatible. Practically every source language has a standard
library with an &lt;code&gt;open&lt;&#x2F;code&gt; function that takes a string and opens a file in an
implied namespace. WASI&#x27;s current approach requires all source languages to use
libc, or to do their own emulation. And lots of programs end up depending on
absolute paths, or symlinks to absolute paths, or the ability to canonicalize
paths into absolute paths, and WASI&#x27;s current approach makes all that awkward.&lt;&#x2F;p&gt;
&lt;p&gt;And, there still are places where things don&#x27;t work quite right. In theory some
of these are fixable by doing more work in libc, but some are not.&lt;&#x2F;p&gt;
&lt;p&gt;And unlike on Unix where one can often get away by assuming that everyone will
be using libc, on Wasm, many toolchains are not using libc. And indeed, we don&#x27;t
&lt;em&gt;want&lt;&#x2F;em&gt; every toolchain to have to use libc.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;new-tools&quot;&gt;New tools&lt;&#x2F;h2&gt;
&lt;p&gt;When we started looking at capability-based security, one of the big ideas is to
avoid &lt;em&gt;ambient authority&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;But what we know now is, that there is no such thing as purely ambient authority.
Any system can be virtualized, such that any ambient authority can be sandboxed
and redirected. It&#x27;s not always cheap or easy to do so, but it&#x27;s always doable.
So fundamentally, ambient authority is always a question of degree and
granularity rather than being an absolute.&lt;&#x2F;p&gt;
&lt;p&gt;So instead of just saying &amp;quot;ambient authority bad&amp;quot;, we need to look at systems and
see the degree to which they achieve the Principle of Least Authority (PoLA) in
practice, and analyze what forces help or hinder it.&lt;&#x2F;p&gt;
&lt;p&gt;In Wasm, let&#x27;s imagine a component that imports a function named &lt;code&gt;do-stuff&lt;&#x2F;code&gt;, with no
arguments. This function has the appearance of using ambient authority, because it&#x27;s
just a function with no handle arguments. It would seem that anyone can call it
anywhere.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;wit&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-wit &quot;&gt;&lt;code class=&quot;language-wit&quot; data-lang=&quot;wit&quot;&gt;&lt;span&gt;   do-stuff: func();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However, Wasm components don&#x27;t have a global scope. It&#x27;s not true that anyone can
call it anywhere. It has to be linked to something, at link time. And it doesn&#x27;t
need to be linked to the same thing in every instance that needs it. So whoever
controls the linking process can chose to link this &lt;code&gt;do-stuff&lt;&#x2F;code&gt; import to a &lt;code&gt;do-stuff&lt;&#x2F;code&gt;
export of their choosing. They can even link it to a &lt;code&gt;do-stuff&lt;&#x2F;code&gt; wrapper around
another &lt;code&gt;do-stuff&lt;&#x2F;code&gt; implementation. That means it can be virtualized or attenuated
or refused entirely.&lt;&#x2F;p&gt;
&lt;p&gt;The fact that there are no handle values being passed in as arguments just means
that instead of a runtime capability, this &lt;code&gt;do-stuff&lt;&#x2F;code&gt; function provides a
&lt;em&gt;link-time&lt;&#x2F;em&gt; capability. That might have consequences for granularity, but it&#x27;ll
depend on how it gets used. So instead of calling it ambient authority and prohibiting
it, we can consider it, and think instead about how it&#x27;ll get used in practice.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;type-safety-and-granularity&quot;&gt;Type safety and granularity&lt;&#x2F;h2&gt;
&lt;p&gt;One of the reasons for wanting to avoid filesystem roots is that rooted
filesystem namespaces tend to bundle up many different logical resources
into a single namespace, which means the granularity of access granted
by that namespace is very coarse.&lt;&#x2F;p&gt;
&lt;p&gt;We could push for finer-grained filesystem capabilities, however there are
options at the conceptual level. Instead
of exposing new capabilities through filesystem APIs, we&#x27;d really rather be
exposing new capabilities through dedicated APIs using resources, because
that&#x27;s much easier to make fine-grained, typed, and robust.&lt;&#x2F;p&gt;
&lt;p&gt;So if we push toward more typed APIs, then we can let WASI&#x27;s filesystem API
just focus on providing access to files, and not be burdened with the
pressure to be finer-grained.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;link-time-versus-runtime-in-the-future&quot;&gt;Link-time versus runtime in the future&lt;&#x2F;h2&gt;
&lt;p&gt;And there&#x27;s one additional piece of this puzzle. What if make something like
&lt;code&gt;do-stuff&lt;&#x2F;code&gt; use link-time authority, and then some time in the future decide that
we really need it to use runtime authority? For example, suppose some program needs
to have the ability to call two different &lt;code&gt;do-stuff&lt;&#x2F;code&gt; backends, deciding between
them at runtime. If we were designing a new API, that&#x27;d be a use case for handles.
But if we didn&#x27;t use handles at the start, are we stuck, at least until we can
do a semver break?&lt;&#x2F;p&gt;
&lt;p&gt;This is likely a ways off in the future, but we now at least have an idea for
a future component-model feature, where we allow component instances to implement
resources. We could then have handles to component instances, and the instance exports
could satisfy the require methods of the resource type. If we had that feature,
then any interface with link-time authority functions could be converted into an
interface with runtime authority functions. This possible future path gives us
more confidence that we&#x27;ll be able to evolve in the future when we need to.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-does-this-look-like-in-wasi-filesystem&quot;&gt;What does this look like in wasi-filesystem?&lt;&#x2F;h2&gt;
&lt;p&gt;We could add a plain &lt;code&gt;open&lt;&#x2F;code&gt; function, which takes a path argument and resolves it relative
to a filesystem root that comes with the instance that the function is imported from.
That makes this &lt;code&gt;open&lt;&#x2F;code&gt; function use a link-time capability. It could support absolute
paths, symlinks to absolute paths, and all the rest. And, it could support a current
working directory concept.&lt;&#x2F;p&gt;
&lt;p&gt;And then, we could add similar non-&lt;code&gt;-at&lt;&#x2F;code&gt; versions of all the &lt;code&gt;-at&lt;&#x2F;code&gt; functions.&lt;&#x2F;p&gt;
&lt;p&gt;This new API could live in a new interface that could coexist with the current
interface.&lt;&#x2F;p&gt;
&lt;p&gt;Now, I believe we still don&#x27;t want to be defaulting to exposing the entire
host filesystem to WASI programs. So we&#x27;ll still want to have a simple VFS
system in Wasm engines, with roughly the same level of virtual &amp;quot;mounting&amp;quot;
that today&#x27;s preopens provide, just using a link-time authority namespace
instead of actual preopen handles.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-about-ghosts&quot;&gt;What about ghosts?&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;no-ghosts&#x2F;&quot;&gt;Ghosts&lt;&#x2F;a&gt; are when logical resources are identified by integers or strings
or similar things, across code boundaries, and &amp;quot;ghosts&amp;quot; conceptually relay
the resources needed to resolve the references. In the case of filesystem APIs,
ghosts are present in the form of filesystem paths being passed around, which
requires any code accepting such a path to have access to the same filesystem
namespace.&lt;&#x2F;p&gt;
&lt;p&gt;If a component ecosystem grows up where it&#x27;s common to use filesystem paths to
identify resources between components, rather than handles, the ecosystem becomes
less composable and, has weakened security properties, and requires more
expensive virtualization.&lt;&#x2F;p&gt;
&lt;p&gt;If we add an &lt;code&gt;open&lt;&#x2F;code&gt; function, there is a greater risk that the WASI ecosystem
will acquire some ghosts, in the form of components passing around filenames
and assuming a common filsystem namespace, making them more expensive and
complex to virtualize.&lt;&#x2F;p&gt;
&lt;p&gt;Now that we have resources though, we can see that they&#x27;re relatively easy to use,
which makes me more optimistic that we don&#x27;t have to worry as much about
people using filesystem paths in place of handles. This is something we can
continue to monitor as the ecosystem grows. For now, I think we can be
confident enough that we don&#x27;t need to preemptively worry about it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;With the new tools and understandings in Wasm components, I think we can
re-evaluate how wasi-filesystem works, to make it more familiar and more
compatible with existing tools, libraries, and applications.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Bridging between source languages, in Wasm</title>
		<published>2024-05-23T00:00:00+00:00</published>
		<updated>2024-05-23T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/bridging-language-divides-in-wasm/" type="text/html"/>
		<id>https://blog.sunfishcode.online/bridging-language-divides-in-wasm/</id>
		<content type="html">&lt;p&gt;One of the core design goals for Wasm is to support code compiled from many
different programming languages.&lt;&#x2F;p&gt;
&lt;p&gt;To this end, core Wasm&#x27;s type system is very low-level. It&#x27;s designed in view of
the fact that programming languages all have their own ways of doing things. Even
seemingly simple things like strings or dictionaries can have different semantics
or performance tradeoffs between different languages. Instead of imposing one
answer on every language, Wasm gives languages the flexibility to make their own
choices.&lt;&#x2F;p&gt;
&lt;p&gt;That also means that whenever we have a Wasm program written in one language, and
we want it to be able to talk to another Wasm program, or a host, written in another
language, we need a way to bridge between those different languages.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-are-the-options&quot;&gt;What are the options?&lt;&#x2F;h2&gt;
&lt;p&gt;Looking outside of Wasm at how other systems provide for cross-language
interfaces, there are roughly three different categories of approaches:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Point-to-point&lt;&#x2F;li&gt;
&lt;li&gt;Language-family&lt;&#x2F;li&gt;
&lt;li&gt;All-to-all&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;point-to-point&quot;&gt;Point-to-point&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;em&gt;Point-to-point&lt;&#x2F;em&gt; means connecting one specific language to another specific
language. For example, &lt;a href=&quot;https:&#x2F;&#x2F;pyo3.rs&quot;&gt;PyO3&lt;&#x2F;a&gt; is a system for connecting Rust and Python. With
PyO3, one might write Rust code, that talks to Python code, like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;pyo3::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Formats the sum of two numbers as string.
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pyfunction&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;sum_as_string&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; PyResult&amp;lt;String&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    Ok((a + b).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In point-to-point systems, at least one of the two sides &lt;em&gt;knows&lt;&#x2F;em&gt; what language
it&#x27;s talking to. With PyO3, it&#x27;s Rust code that knows it&#x27;s talking to Python code.
That Rust code wouldn&#x27;t be able to talk to any other language. The upside of that
tradeoff is that by being specialized to specific languages, point-to-point systems
can provide rich integration between languages. PyO3 can make much of the
expressivity of Python available to the Rust code, and it can do so efficiently.&lt;&#x2F;p&gt;
&lt;p&gt;But the downside from a Wasm perspective is that we specifically don&#x27;t want
interfaces where one side knows the source language of the other. The source language
of the guest shouldn&#x27;t have to be aware of the source language of the host.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;language-family&quot;&gt;Language-family&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;em&gt;Language-family&lt;&#x2F;em&gt; systems connect a family of languages that all share something in
common with each other. For example, on the Web, many different JavaScript-like languages
can talk to each other by having both sides pretend to be JavaScript. On Unix-like operating
systems, many different C-like languages can talk to each other by having both sides pretend
to be C. And so on.&lt;&#x2F;p&gt;
&lt;center&gt;
&lt;a title=&quot;Делфина, CC0, via Wikimedia Commons&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Sculpture_of_couple_with_masks,_Macedonian_National_Theater,_North_Macedonia.jpg&quot;&gt;&lt;img width=&quot;512&quot; alt=&quot;Sculpture of couple with masks, Macedonian National Theater, North Macedonia&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;a&#x2F;ac&#x2F;Sculpture_of_couple_with_masks%2C_Macedonian_National_Theater%2C_North_Macedonia.jpg&#x2F;512px-Sculpture_of_couple_with_masks%2C_Macedonian_National_Theater%2C_North_Macedonia.jpg&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;center&gt;
&lt;p&gt;Language-family systems tend to provide somewhat less rich integration than
point-to-point systems. You can&#x27;t access every feature of Python if you don&#x27;t
know that you&#x27;re talking to Python, for example. Any unique feature of any
language that isn&#x27;t common to the family as a whole tends to be hidden.&lt;&#x2F;p&gt;
&lt;p&gt;For example, ClojureScript code can talk to any JavaScript-family language by pretending
to be JavaScript. JavaScript doesn&#x27;t have the same types as ClojureScript, so
ClojureScript provides a function named &lt;code&gt;clj-&amp;gt;js&lt;&#x2F;code&gt; to convert ClojureScript values to
JavaScript values, and it&#x27;s lossy:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;clj&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-clj &quot;&gt;&lt;code class=&quot;language-clj&quot; data-lang=&quot;clj&quot;&gt;&lt;span&gt;(clj-&amp;gt;js [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;:red &lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;green&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; &amp;#39;blue])
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;;;=&amp;gt; #js [&amp;quot;red&amp;quot; &amp;quot;green&amp;quot; &amp;quot;blue&amp;quot;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This uses a feature of ClojureScript called symbols, which JavaScript doesn&#x27;t have. When
symbols get converted to JavaScript, they need to be converted into something JavaScript
does have, such as strings. This allows ClojureScript programs to talk to any other
language that thinks its talking to JavaScript. But, it means that ClojureScript can&#x27;t
expect other languages to pass it back symbols. There&#x27;s less integration.&lt;&#x2F;p&gt;
&lt;p&gt;And at the same time, languages that aren&#x27;t in the language family can&#x27;t fully
participate.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;all-to-all&quot;&gt;All-to-all&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;em&gt;All-to-all&lt;&#x2F;em&gt; systems are designed to connect any language to any other language.
Each side is completely unaware of the language of the other side. Often this
is done using an Interface Description Language (IDL), so that the interface between
languages can be described in a language-independent way.&lt;&#x2F;p&gt;
&lt;center&gt;
&lt;img width=&quot;256&quot; alt=&quot;A diagram of a fully-connected network&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;3&#x2F;3c&#x2F;NetworkTopology-FullyConnected.png&quot;&gt;
&lt;&#x2F;center&gt;
&lt;p&gt;All-to-all systems are common in RPC protocols, such as network protocols, where it&#x27;s
especially desirable to be able to implement clients and servers in different languages.&lt;&#x2F;p&gt;
&lt;p&gt;IDLs also have a lot of similarity with database schema languages. Both need to define
datatypes, and both typically have a strong need to keep the data independent of the
programming languages that will produce or consume the data. And, both have a need for
the data to be meaningful without existing within a particular address space or a GC
heap with an arbitrary reference graph.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-would-wasm-want&quot;&gt;What Would Wasm Want?&lt;&#x2F;h2&gt;
&lt;center&gt;
&lt;a title=&quot;Carlos Baraza, CC0, via Wikimedia Commons&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:WebAssembly_Logo.svg&quot;&gt;&lt;img width=&quot;256&quot; alt=&quot;WebAssembly Logo&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;1&#x2F;1f&#x2F;WebAssembly_Logo.svg&#x2F;256px-WebAssembly_Logo.svg.png&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;center&gt;
&lt;p&gt;First of all, there is no one answer that&#x27;s best for all situations. There are tradeoffs
in each of these three categories, so no single cross-language interface system will work
best for all situations. All three should, and can, coexist within the Wasm ecosystem.
C developers can use &lt;code&gt;.a&lt;&#x2F;code&gt; archives containing C code that links to other C code via C
ABIs. As Wasm GC matures, perhaps there will be conventional ways to link Java libraries
compiled to Wasm with other Java libraries, allowing any language in the Java language
family to be linked together with Java-level integration.&lt;&#x2F;p&gt;
&lt;p&gt;At the same time, there is a need for an over-arching all-to-all system. Point-to-point
and language-family approaches can be nested inside of the over-arching system to provide
greater integration where needed. The all-to-all approach is the only way to ensure that
every language can participate in the overall ecosystem, without having to be a member of
the right language family, without having a blessed language that every language has to
pretend to be.&lt;&#x2F;p&gt;
&lt;p&gt;This is one of the unique opportunities for Wasm. In contrast, Unix, the JVM, the CLR, and
JavaScript are all language-family platforms. They each start with their respective blessed
language, and oblige all other languages to talk to each other by pretending to be that
blessed language.&lt;&#x2F;p&gt;
&lt;p&gt;Wasm, on the other hand, doesn&#x27;t have an inherent blessed language.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ok-wait-wait-just-a-minute-everyone-knows-that-c-is-the-blessed-language&quot;&gt;Ok wait. Wait just a minute. Everyone knows that C is the blessed language&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;design&#x2F;blob&#x2F;main&#x2F;HighLevelGoals.md&quot;&gt;Wasm MVP&lt;&#x2F;a&gt; explicitly focused on C&#x2F;C++. Many people&#x27;s first introduction to Wasm
was filled with pointers and offsets and struct layouts. It gave a lot of people the
impression that Wasm was settling into its place within the grand Unix tradition of
using C as its blessed language of communication. Not everyone may be happy about
that, but a lot of people aren&#x27;t surprised by it. If you had asked me before I started
working on Wasm where it would go, C ABIs are what I would have guessed it would use.&lt;&#x2F;p&gt;
&lt;p&gt;And in many places in the computing world today; this was seen as inevitable, as C
is seen as the universal language. After all, some people observe, all information on a
computer is ultimately just bytes, and C pointers can point to any bytes in memory,
and that means C can talk to anything, in a way that most other languages cannot.
That makes C uniquely suited to be the universal glue between all languages.&lt;&#x2F;p&gt;
&lt;p&gt;Except that it isn&#x27;t.&lt;&#x2F;p&gt;
&lt;p&gt;😱&lt;&#x2F;p&gt;
&lt;p&gt;There are several wrinkles in that story when it comes to Wasm. One small wrinkle is
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;memory64&quot;&gt;memory64&lt;&#x2F;a&gt;, which is linear memory with 64-bit
pointers. So we don&#x27;t just have one C ABI; we have
at least two, because linear-memory addresses can be either 32-bit or 64-bit, and
programs compiled for one can&#x27;t directly interoperate with programs compile for the
other, even if they&#x27;re both pretending to be C.&lt;&#x2F;p&gt;
&lt;p&gt;But we also have a big wrinkle: Wasm GC.&lt;&#x2F;p&gt;
&lt;p&gt;This whole idea about how all data is just bytes doesn&#x27;t work in Wasm.&lt;&#x2F;p&gt;
&lt;p&gt;Wasm GC values are not accessible as just bytes. Wasm GC types &lt;em&gt;can&#x27;t&lt;&#x2F;em&gt; be pointed to by C
pointers. This means that C is not the fundamentally universal language on Wasm in the
way that it can be within the realm of Unix processes.&lt;&#x2F;p&gt;
&lt;p&gt;And even beyond that, there are more wrinkles, such as data lifetimes. Nothing prevents
the data indexed by a C pointer from dangling when data is deallocated. For decades, C
got away with saying that Undefined Behavior was unavoidable, but today, many users are
demanding different answers.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;clearly-gc-is-the-answer&quot;&gt;Clearly GC is the answer&lt;&#x2F;h3&gt;
&lt;p&gt;As obvious as it seems in some circles that C ABIs are the answer, it is equally obvious
in other spaces that some form of Wasm GC-based ABIs are the answer.&lt;&#x2F;p&gt;
&lt;p&gt;After all, if you look at the JVM, the CLR, or JavaScript, which are all very
popular platforms that run wide varieties of programming languages,
they all provide a set of GC types provided by the platform that everyone on
those platforms just uses. This is simple, efficient, and proven. And unlike C,
it doesn&#x27;t have scary memory safety hazards. So it might seem to be the obvious
answer for Wasm.&lt;&#x2F;p&gt;
&lt;p&gt;Except, there are winkles with that approach too.&lt;&#x2F;p&gt;
&lt;p&gt;😱&lt;&#x2F;p&gt;
&lt;p&gt;One is that even though C won&#x27;t be the blessed language, linear-memory languages
still do matter, and they can&#x27;t easily interop with GC types. GC types can&#x27;t easily
point to linear memory, and linear-memory languages can&#x27;t easily hold GC references,
so GC types aren&#x27;t universal either.&lt;&#x2F;p&gt;
&lt;p&gt;Another is that, in the spirit of Wasm as a whole, Wasm GC is being designed to be
as language-independent as possible, and this has led it away from attempting to
provide one-size-fits-all opinionated GC types for &amp;quot;string&amp;quot;, &amp;quot;list&amp;quot;, &amp;quot;dictionary&amp;quot;,
and so on. One person&#x27;s list is a growable array, while another&#x27;s is a cons list,
and another&#x27;s is a rope. In practice, programming languages have very different
needs, and Wasm instead aims to provide primitive constructs that programming
languages can use to build higher-level types.&lt;&#x2F;p&gt;
&lt;p&gt;Yet another is that when people are using systems that don&#x27;t need a GC, they often
don&#x27;t want to have to use a GC. If we make GC be the universal glue, then we
add GC dependencies in places that don&#x27;t want them.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;do-re-me-rpc&quot;&gt;Do re me, RPC&lt;&#x2F;h3&gt;
&lt;p&gt;Wasm isn&#x27;t the first place in computing to have a need to connect different
languages without having a single obvious blessed language. Networking protocols
in particular are an area where no single language took hold, in part because
most languages&#x27; type systems have things like pointers to mutable data, which
is awkward to share over a network. Popular network protocols have often turned
to IDLs, such as OpenAPI, Protobufs, or others, which make them all-to-all
systems.&lt;&#x2F;p&gt;
&lt;p&gt;Should Wasm use one of these existing RPC-based cross-language systems?&lt;&#x2F;p&gt;
&lt;p&gt;Just as language-family cross-language systems have a place in the Wasm
ecosystem, RPC systems do too. And just as before, there is also an over-arching
need in Wasm for a common system.&lt;&#x2F;p&gt;
&lt;p&gt;When we scale up software systems, they tend to become distributed systems,
so using an RPC protocol is tempting, as it would mean we&#x27;d be ready to go
distributed, out of the box. On the other hand though, one of the lessons from
CORBA is that making everything network-aware makes everything harder.&lt;&#x2F;p&gt;
&lt;p&gt;And, encoding calls into bytes and decoding them on the callee side has
overhead, and it&#x27;s overhead that would be difficult to optimize away in the
case where we have two components running on the same computer.&lt;&#x2F;p&gt;
&lt;p&gt;So what we&#x27;d ideally want is a system that uses an IDL to achieve the same kind
of all-to-all cross-language properties that RPC systems have, but which is
isn&#x27;t tied to either bytestream serialization or network awareness.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-wasm-component-model&quot;&gt;The Wasm component model&lt;&#x2F;h2&gt;
&lt;p&gt;The Wasm &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;component-model&quot;&gt;component model&lt;&#x2F;a&gt; is an all-to-all cross-language system. It has &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;component-model&#x2F;blob&#x2F;main&#x2F;design&#x2F;mvp&#x2F;WIT.md&quot;&gt;an IDL&lt;&#x2F;a&gt;,
and connects languages to each other without either side being aware of the other. And it
isn&#x27;t tied to bytestream serialization or network awareness.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a lot in the component model, but to get a taste of how it works, consider
a type like &lt;code&gt;string&lt;&#x2F;code&gt;. There is no &lt;code&gt;string&lt;&#x2F;code&gt; type in core Wasm, so &lt;code&gt;string&lt;&#x2F;code&gt; is just a
type in the &lt;em&gt;interface&lt;&#x2F;em&gt; type system. That means it doesn&#x27;t have a fixed representation
or even a fixed set of operations. It&#x27;s just a set of logical values, which for
&lt;code&gt;string&lt;&#x2F;code&gt; is the set of all sequences of Unicode Scalar Values.&lt;&#x2F;p&gt;
&lt;p&gt;Bindings for individual language work by encoding descriptions of how the Unicode
Scalar Values are represented within their languages. This avoids either side
of an interface knowing how the other side represents its values. And, it provides
enough information to linkers to insert whatever adaptation code is needed:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;If Wasm code is passing a string to the host, the host can just read
the string data straight from the Wasm code&#x27;s memory. No copying is needed
in many cases!&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;If Wasm code using UTF-8 strings is passing a string to Wasm code using
UTF-16 strings, the linking process can transparently insert UTF-8 to UTF-16
transcoding between then, so that strings can be passed without either side
knowing the encoding of the other side.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;If Wasm code is passing a string to Wasm code using the same encoding,
the data can be copied. A copy may sound expensive to some ears, but keep
in mind that this doesn&#x27;t happen between component and host, it only happens
between two components. And in today&#x27;s C-like ABIs, there isn&#x27;t a way to
link two modules at all, so this isn&#x27;t a regression of anything. And in GC land,
there are ideas for how even this copy could get optimized away in the future.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And because there is no serialization, and no object request brokers or network
awareness baked in, as compilers continue to optimize, component-model interfaces
will be able to be inlined, because everything compilers need to do inlining is
exposed up front.&lt;&#x2F;p&gt;
&lt;p&gt;So there&#x27;s a lot more to it than this, but hopefully this gives a taste of how
the system works.&lt;&#x2F;p&gt;
&lt;p&gt;For more information about using the component model, see the &lt;a href=&quot;https:&#x2F;&#x2F;component-model.bytecodealliance.org&#x2F;&quot;&gt;component model
documentation&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap up&lt;&#x2F;h2&gt;
&lt;p&gt;There&#x27;s a lot more to the component model, such as how the anticipated async
support avoids the function &amp;quot;coloring&amp;quot; problem, though see &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=y3x4-nQeXxc&amp;amp;t=203s&quot;&gt;here&lt;&#x2F;a&gt;
for a preview. This blog post is just about
the cross-language aspects of the design.&lt;&#x2F;p&gt;
&lt;p&gt;Wasm needs an over-arching cross-language interface system, if it&#x27;s to avoid
long-term language-based fragmentation. The component model works differently
from what people expecting it to be just C ABIs expect to find, and also different
from what people expecting just GC types expect to find, but it has the properties
that a unified ecosystem needs.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>WASI 0.2 Launched</title>
		<published>2024-01-25T00:00:00+00:00</published>
		<updated>2024-01-25T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/wasi-0-2/" type="text/html"/>
		<id>https://blog.sunfishcode.online/wasi-0-2/</id>
		<content type="html">&lt;p&gt;The WASI Subgroup has just voted to launch WASI 0.2, also known as WASI Preview 2 or WASIp2!
This blog post is a brief look at the present, past, and future of WASI.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-present&quot;&gt;The present&lt;&#x2F;h2&gt;
&lt;p&gt;The Subgroup voted to launch WASI 0.2!&lt;&#x2F;p&gt;
&lt;p&gt;This is a major milestone! We made it! At the same time, the journey is
only just beginning. But let&#x27;s talk this moment to step back and look at
what this means.&lt;&#x2F;p&gt;
&lt;p&gt;Most immediately, what this means is that the WASI Subgroup officially
says that the WASI 0.2 APIs are stable. There is still a lot more
to do, in writing more documentation, more tests, more toolchains, more
implementations, and there are a lot more features that we all want to add.
This vote today is a milestone along the way, rather than a destination in
itself.&lt;&#x2F;p&gt;
&lt;p&gt;It also means that WASI is now officially based on the Wasm &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;component-model&#x2F;&quot;&gt;component model&lt;&#x2F;a&gt;,
which makes it cross-language and virtualizable. Figuring out what a
component model even is, designing it, implementing it, and building APIs
using it has been a huge effort with involving many people, and it&#x27;s now
officially in WASI. Yay!&lt;&#x2F;p&gt;
&lt;p&gt;WASI 0.2 includes two &lt;em&gt;worlds&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;wasi-cli&lt;&#x2F;em&gt;, the &amp;quot;command-line interface&amp;quot; world, which roughly
corresponds to POSIX. Files, sockets, clocks, random numbers, etc.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;wasi-http&lt;&#x2F;em&gt;, an HTTP proxy world, organized around requests
and responses.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;There are more worlds in development, but for now, the important thing is
that we do have multiple worlds included. This means wasi-cli world isn&#x27;t
the only world, or even the primary world. It&#x27;s just one world, among
multiple.&lt;&#x2F;p&gt;
&lt;p&gt;One things I&#x27;m looking forward to that&#x27;s enabled by having multiple worlds is
&lt;a href=&quot;https:&#x2F;&#x2F;sunfishcode.github.io&#x2F;typed-main-wasi-presentation&#x2F;chapter_1.html&quot;&gt;Typed Main&lt;&#x2F;a&gt; (some details in that presentation are out of date by now, but
the big ideas still make sense), because we can have new worlds with new
entrypoints, with new signatures. It&#x27;s also a part of how we can grow WASI to
fit into new non-traditional computing environments. And this is just the
beginning.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;looking-back&quot;&gt;Looking back&lt;&#x2F;h2&gt;
&lt;p&gt;All the way back since the beginning of WebAssembly, people have been talking
about using it outside of browsers. Node.js had famously made JavaScript popular
on servers and more, and if it made sense for JavaScript, it was pretty natural to
imagine WebAssembly doing similar things. But beyond the basic outline, there
were a lot of questions, and a lot of ideas.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;How can we build a coherent ecosystem without fragmentation? And how do
we prevent an NPM-like situation with one company gaining control over the
ecosystem?&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;To some people, POSIX was the obvious place to start on a non-JS-based API.
POSIX is a C API, so how do we ensure that our C &lt;em&gt;ABI&lt;&#x2F;em&gt; is future-proof?
C ABIs tend to get baked in if one is not super careful, and bugs can
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Year_2038_problem&quot;&gt;take decades to fix&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;As much as POSIX was the obvious starting point for a lot of people, it was
just as much an obvious non-starter for a lot of other people. WASI being based
on POSIX made it &lt;em&gt;very&lt;&#x2F;em&gt; biased toward C, with raw pointers everywhere, implied
data structures, and so on. And would there need to be a &lt;code&gt;fork&lt;&#x2F;code&gt; function, with
all its ecosystem-wide implications? Building an ecosystem with C ABIs as its
primary connective tissue is very undesirable from a security perspective. Also,
what&#x27;s the plan when Wasm GC arrives?&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Should we always export linear memory, to ensure that we can pass pointers
around? But if we do that, we lose the benefit of the sandboxing that Wasm is
otherwise doing between modules—if you can corrupt a C program&#x27;s memory,
its game is over. But if we don&#x27;t export linear memory, how else do we pass
around complex data structures?&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Looking at use cases, there are the &amp;quot;port existing code&amp;quot; use cases, and the &amp;quot;do things
that other systems can already do, but do them &lt;em&gt;IN WASM&lt;&#x2F;em&gt;&amp;quot; use cases, and these are
important. But there are also new use cases that we can imagine Wasm can do, and we
wanted to be sure we didn&#x27;t define the system in terms of compatibility and exclude
these new use cases. One of the big themes that came up repeatedly was &lt;em&gt;virtualization&lt;&#x2F;em&gt;.
All I&#x2F;O in Wasm goes through its imports and exports, so we can completely virtualize a
Wasm module&#x27;s view of the outside just by controlling what the imports and exports are
linked to.&lt;&#x2F;p&gt;
&lt;p&gt;And, Wasm has a trusted stack, which is what makes it possible to call from
Wasm into JS and back within JS engines. In theory we should be able to use this
property to enable calling from Wasm into some other mutually untrusted Wasm.&lt;&#x2F;p&gt;
&lt;p&gt;Also, early on, some security-minded folks told us that we should look at something
called &amp;quot;capabilities&amp;quot;, which they said were really great. And avoiding global state
sounded like a good direction to go in. CloudABI combined capability-based security and
some impressive work to simplify the Unix platform down to a relatively small set of
carefully-designed primitives, which made it especially appealing. Consequently, much
of WASI 0.1 was closely derived from CloudABI.&lt;&#x2F;p&gt;
&lt;p&gt;That helped get us started, and helps us build systems that people could write
code with and get things working, but we still had all these open questions, and
big ideas to figure out.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;component-model-enters-the-chat&quot;&gt;Component Model enters the chat&lt;&#x2F;h3&gt;
&lt;p&gt;So while WASI 0.1 was out in the world, people were starting to think big
thoughts about how to answer all these big questions and how to fit all the
big ideas into a coherent design. There were these early proposals called
&amp;quot;interface types&amp;quot; and &amp;quot;module linking&amp;quot;, which seemed to be pointing toward
something, but had been through numerous iterations and hadn&#x27;t quite settled
in yet.&lt;&#x2F;p&gt;
&lt;p&gt;When I first heard about the idea for a component model, which would
subsume interface types and module linking, I didn&#x27;t know what a &amp;quot;component&amp;quot;
meant. My knowledge of COM was &amp;quot;that&#x27;s some Windows thing, right?&amp;quot;. And I knew
only slightly more about CORBA. Mostly, I knew just barely enough to react
&amp;quot;surely we don&#x27;t want to do &lt;em&gt;that&lt;&#x2F;em&gt;&amp;quot;. But as I got into it, I learned that
the Wasm component model was a chance to both learn from those existing systems
which had solved many of the problems we needed to solve, and also to learn
from those systems and do some things differently.&lt;&#x2F;p&gt;
&lt;p&gt;We didn&#x27;t want to force everyone to think about distributed computing just
to link libraries together. And we didn&#x27;t want to lose the advantage of Wasm
sandboxing each module independently. And when we looked at where that leaves
us, the common theme that remained was &lt;em&gt;composition&lt;&#x2F;em&gt;. It&#x27;s about building
things that can be easily put together to make larger things.&lt;&#x2F;p&gt;
&lt;p&gt;And then from there, composition ties together an entire family of ideas.
Even &lt;a href=&quot;http:&#x2F;&#x2F;www.erights.org&#x2F;talks&#x2F;thesis&#x2F;markm-thesis.pdf&quot;&gt;Mark Miller&#x27;s PhD thesis&lt;&#x2F;a&gt; about capability-based security is literally
titled &amp;quot;Robust Composition&amp;quot;. It&#x27;s right there. It&#x27;s what this is all about.
How do we put together parts to make a whole, without all kinds of complexities
creeping in?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Cross-language interop is needed to compose components written in
different languages.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Component isolation supports composition without the fear of components
having unexpected conflicts.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;No global namespace at runtime, so that composed components don&#x27;t
collide in or have differing requirements of the namespace.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Any interface can be virtualized, which is to say, composed with
any implementation of that interface.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;The output of linking two components is a component, so composition
can happen incrementally.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Capabilities are a way to compose two components together, in which
they share some parts of themselves with each other and not others.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;There&#x27;s a lot more to these topics, but this is hopefully enough to paint
the picture that there are some themes that all fit well with each other,
within the conceptual framework of composition.&lt;&#x2F;p&gt;
&lt;p&gt;And so, WASI 0.2 represents not just a new API, but a new approach to
APIs that gets us out of worrying about C ABI fragility, or C pointer hazards,
and that has reasonable paths forward for supporting many different
programming languages without hard fragmentation. It even allows us to not
worry so much about getting WASI 0.2 itself perfectly right for all time,
because we know we can virtualize WASI 0.2 itself in terms of future APIs.&lt;&#x2F;p&gt;
&lt;p&gt;This is why the Subgroup voting to launch WASI 0.2 is such a big deal.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;looking-ahead&quot;&gt;Looking ahead&lt;&#x2F;h2&gt;
&lt;p&gt;Ok, that&#x27;s a high-level view of how we got here. What&#x27;s next?&lt;&#x2F;p&gt;
&lt;p&gt;In terms of standards, there are two activities that people are already
looking forward to. With WASI 0.2.0 finalized, it&#x27;ll be time to start planning
for things we want to add in a WASI 0.2.1 soon after it. That&#x27;ll be another
milestone: the first update to WASI 0.2, which will establish how to do updates,
and set up the rhythm for doing incremental updates. WASI 0.2 is small still;
we had to scope down a number of features that people really wanted, so we&#x27;re
looking forward to doing many updates in 0.2.1 and beyond.&lt;&#x2F;p&gt;
&lt;p&gt;At the same time, work towards WASI 0.3 will be getting underway. The
major banner of WASI 0.3 is &lt;em&gt;async&lt;&#x2F;em&gt;, and adding the &lt;code&gt;future&lt;&#x2F;code&gt; and &lt;code&gt;stream&lt;&#x2F;code&gt; types
to Wit. And here again, the theme is &lt;em&gt;composability&lt;&#x2F;em&gt;. It&#x27;s one thing to do
async, it&#x27;s another to do &lt;em&gt;composable&lt;&#x2F;em&gt; async, where two components that are
async can be composed together without either event loop having to be nested
inside the other. Designing an async system flexible enough for Rust, C#,
JavaScript, Go, and many others, which all have their own perspectives on async,
will take some time, so while the design work is starting now, WASI 0.3
is expected to be at least a year away.&lt;&#x2F;p&gt;
&lt;p&gt;And when we do get there, the transition from WASI 0.2 to WASI 0.3 should be much smoother
than WASI 0.1 to WASI 0.2. The component model&#x27;s virtualizability means it
should be easier to polyfill WASI 0.2 in terms of WASI 0.3. And, it should be
easier for engines to support both WASI 0.2 and WASI 0.3 at the same time if
they wish to, because WASI 0.2 will essentially use a subset of WASI 0.3&#x27;s
language features.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrapping-it-up&quot;&gt;Wrapping it up&lt;&#x2F;h2&gt;
&lt;p&gt;WASI 0.2 is a major milestone that many people have contributed to, and
it&#x27;s now launched! It&#x27;s an API, but it also represents a new way to define
APIs for Wasm.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>(renamed)</title>
		<published>2024-01-25T00:00:00+00:00</published>
		<updated>2024-01-25T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/wasi-preview2/" type="text/html"/>
		<id>https://blog.sunfishcode.online/wasi-preview2/</id>
		<content type="html">&lt;p&gt;WASI Preview 2 is also known as WASI 0.2. and I&#x27;ve gotten feedback that that
name makes more sense to people, so I&#x27;ve renamed my post accordingly.
&lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;wasi-0-2&#x2F;&quot;&gt;Here&#x27;s the new URL for this page&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Eyra does the impossible</title>
		<published>2023-11-15T00:00:00+00:00</published>
		<updated>2023-11-15T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/eyra-does-the-impossible/" type="text/html"/>
		<id>https://blog.sunfishcode.online/eyra-does-the-impossible/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;eyra&quot;&gt;Eyra&lt;&#x2F;a&gt; is challenging ideas about what it means to be a libc. In doing so, it&#x27;s
doing a few things often considered to be... &lt;em&gt;impossible&lt;&#x2F;em&gt; 😉.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fixing-rust-s-set-var-unsoundness&quot;&gt;Fixing Rust&#x27;s &lt;code&gt;set_var&lt;&#x2F;code&gt; unsoundness&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;27970&quot;&gt;rust-lang&#x2F;rust#27970&lt;&#x2F;a&gt; is a soundness bug in Rust. It is a way that Rust programs
can segfault without using any &lt;code&gt;unsafe&lt;&#x2F;code&gt; code. The bug was opened 8 years ago,
and it&#x27;s widely believed to be impossible to fully fix.&lt;&#x2F;p&gt;
&lt;p&gt;One of the reasons it&#x27;s so difficult is that it isn&#x27;t enough to do locking,
even inside libc, because &lt;code&gt;getenv&lt;&#x2F;code&gt; returns pointers to memory that need to stay
valid after the &lt;code&gt;getenv&lt;&#x2F;code&gt; call returns. And, &lt;code&gt;getenv&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;setenv&lt;&#x2F;code&gt;&#x2F;etc. can be called
by arbitrary C code, so any scheme that relies on all callers of &lt;code&gt;getenv&lt;&#x2F;code&gt;
following a particular protocol isn&#x27;t reliable.&lt;&#x2F;p&gt;
&lt;p&gt;Eyra solves this by having &lt;code&gt;setenv&lt;&#x2F;code&gt; etc. just leak the old memory. That ensures
that it stays valid for as long as any thread needs it. Granted, leaking isn&#x27;t
great, and Eyra makes it configurable with the &amp;quot;threadsafe-setenv&amp;quot; cargo feature,
so it can be disabled in favor of the thread-unsafe implementation. However that
said, &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nomicon&#x2F;leaking.html&quot;&gt;leaking is not unsafe&lt;&#x2F;a&gt;, and for some use cases, it&#x27;ll be less bad than
the possibility of undefined behavior from dangling pointers.&lt;&#x2F;p&gt;
&lt;p&gt;Eyra currently only supports Linux, and has other limitations, so it isn&#x27;t a full
solution for all of Rust, but it does solve the problem within its range.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;full-host-nss-and-dns-support-without-dynamic-linking&quot;&gt;Full host NSS and DNS support without dynamic linking&lt;&#x2F;h2&gt;
&lt;p&gt;In glibc, a statically-linked binary, despite being statically linked,
heroically includes the ability to &lt;code&gt;dlopen&lt;&#x2F;code&gt; NSS libraries as needed in order
to implement the lookup rules defined in &amp;quot;&#x2F;etc&#x2F;nsswitch.conf&amp;quot;, and this means
that statically-linked binaries end up depending on the versions of the NSS
libraries that match the glibc version they were built with.&lt;&#x2F;p&gt;
&lt;p&gt;In musl, a statically-linked binary just hard-codes the basic NSS and DNS
resolution strategies. It knows how to read &amp;quot;&#x2F;etc&#x2F;passwd&amp;quot;, &amp;quot;&#x2F;etc&#x2F;resolv.conf&amp;quot;,
and other files, and do the main things that one does with those files, so it
doesn&#x27;t respect &amp;quot;&#x2F;etc&#x2F;nsswitch.conf&amp;quot; at all, and doesn&#x27;t use the same name
lookup logic as other programs on a glibc-based distribution.&lt;&#x2F;p&gt;
&lt;p&gt;These have long been the only options, but Eyra does something different.&lt;&#x2F;p&gt;
&lt;p&gt;In Eyra, NSS functions are implemented by executing the external &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man1&#x2F;getent.1.html&quot;&gt;&lt;code&gt;getent&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
program, and parsing its output. &lt;code&gt;getent&lt;&#x2F;code&gt; is present on both &lt;code&gt;glibc&lt;&#x2F;code&gt;-based
and &lt;code&gt;musl&lt;&#x2F;code&gt;-based Linux distributions, and has a stable command-line interface,
so Eyra programs do not depend on a specific version of libc being installed,
and it follows the system NSS and DNS configuration.&lt;&#x2F;p&gt;
&lt;p&gt;(And to be sure, using &lt;code&gt;getent&lt;&#x2F;code&gt; like this won&#x27;t work for &lt;em&gt;all&lt;&#x2F;em&gt; use cases, so
Eyra may add other options in the future.)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;compiling-whole-programs-with-a-single-cargo-build&quot;&gt;Compiling whole programs with a single &lt;code&gt;cargo build&lt;&#x2F;code&gt;.&lt;&#x2F;h2&gt;
&lt;p&gt;Eyra is not the only system capable of whole-program optimization, however to
my knowledge, it is the only system that can compile a whole program, entirely
from source, in a single &lt;code&gt;cargo build&lt;&#x2F;code&gt; invocation.&lt;&#x2F;p&gt;
&lt;p&gt;This is achieved by using cargo&#x27;s &lt;code&gt;-Z build-std&lt;&#x2F;code&gt; option, which builds libcore,
liballoc, libstd, and other Rust libraries from source, by using Eyra which
builds the libc implementation from source, and, for completeness, by disabling
Eyra&#x27;s &lt;code&gt;&amp;quot;use-compiler-builtins&amp;quot;&lt;&#x2F;code&gt; feature, which tells it to use its own
implementations of &lt;code&gt;memcpy&lt;&#x2F;code&gt; etc. instead of linking to Rust&#x27;s prebuilt
&lt;code&gt;compiler_builtins&lt;&#x2F;code&gt; library. Thay way, everything down to the OS boundary is
just a cargo dependency built from source. See &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;eyra&#x2F;tree&#x2F;main&#x2F;example-crates&#x2F;all-from-source&#x2F;#readme&quot;&gt;the all-from-source example&lt;&#x2F;a&gt;
for more details.&lt;&#x2F;p&gt;
&lt;p&gt;This may be useful for doing whole-program static analysis, for using
non-standard calling conventions, or anything else that requires that the whole
program be compiled together.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-eyra&quot;&gt;What&#x27;s Eyra?&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;eyra&quot;&gt;Eyra&lt;&#x2F;a&gt; is currently a side project that I&#x27;m building for fun. If you think it
sounds interesting, please reach out!&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Embrace the Kinda</title>
		<published>2023-05-31T00:00:00+00:00</published>
		<updated>2023-05-31T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/embrace-the-kinda/" type="text/html"/>
		<id>https://blog.sunfishcode.online/embrace-the-kinda/</id>
		<content type="html">&lt;p&gt;So yeah, what...&lt;&#x2F;p&gt;
&lt;p&gt;What &lt;em&gt;is&lt;&#x2F;em&gt; Wasm?&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;a title=&quot;Original: Martorell Vector:  Keymap9, CC BY-SA 4.0 &amp;lt;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by-sa&#x2F;4.0&amp;gt;, via Wikimedia Commons&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Decision_making.svg&quot;&gt;&lt;img width=&quot;128&quot; alt=&quot;Decision making&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;e&#x2F;e0&#x2F;Decision_making.svg&#x2F;128px-Decision_making.svg.png&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Well, I guess, one can find various one-sentence descriptions out there. The
&lt;a href=&quot;https:&#x2F;&#x2F;webassembly.org&quot;&gt;webassembly.org website&lt;&#x2F;a&gt; leads with:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;WebAssembly (abbreviated &lt;em&gt;Wasm&lt;&#x2F;em&gt;) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;WebAssembly&quot;&gt;Wikipedia&#x27;s WebAssembly article&lt;&#x2F;a&gt; leads with:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;WebAssembly (sometimes abbreviated Wasm) defines a portable binary-code format and a corresponding text format for executable programs as well as software interfaces for facilitating interactions between such programs and their host environment.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;wasm-reference-manual&#x2F;blob&#x2F;master&#x2F;WebAssembly.md&quot;&gt;WebAssembly reference manual&lt;&#x2F;a&gt;
I wrote a few years ago leads with:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;WebAssembly, or “Wasm”, is a general-purpose virtual ISA designed to be a compilation target for a wide variety of programming languages. Much of its distinct personality derives from its security, code compression, and decoding optimization features.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;And these are all like fine. But at the same time, these have all been out
there for years and here we are today and people are still trying to figure
out what this whole thing, just, like, &lt;em&gt;is&lt;&#x2F;em&gt; is.&lt;&#x2F;p&gt;
&lt;p&gt;Hang around Wasm spaces, and you may hear someone drop the quip:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;WebAssembly is neither Web nor Assembly!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It&#x27;s a scintillating one. It pops. It packs that irresistible combination
of classic meme ancestry, hot new subject, apparent absurdity, and a real kernel of
truth all in one scrumptiously crunchy package.&lt;&#x2F;p&gt;
&lt;p align=&quot;center&quot;&gt;&lt;a title=&quot;ESO&#x2F;A. Roquette, CC BY 3.0 &amp;lt;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by&#x2F;3.0&amp;gt;, via Wikimedia Commons&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Artist%E2%80%99s_impression_of_a_gamma-ray_burst.jpg&quot;&gt;&lt;img width=&quot;256&quot; alt=&quot;Artist’s impression of a gamma-ray burst&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;5&#x2F;55&#x2F;Artist%E2%80%99s_impression_of_a_gamma-ray_burst.jpg&#x2F;256px-Artist%E2%80%99s_impression_of_a_gamma-ray_burst.jpg&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;“Wasm is not Web”, the quote goes, “because it&#x27;s carefully factored so that nothing
in the core spec has any dependency on browsers. And we&#x27;re using it in servers
and embedded devices and stuff!” And it&#x27;s right!&lt;&#x2F;p&gt;
&lt;p&gt;At the same time, Wasm does come from a Web context, and many of the forces
shaping it have relationships with the Web. Wasm&#x27;s concept of program isolation,
with a trusted callstack enabling it to call out into code that it doesn&#x27;t trust
and doesn&#x27;t trust it, and its system of imports and exports, come from the need
to embed Wasm within very complex browser environments. Wasm has a standards body which is
a W3C Community Group. And in many ways, “the Web” itself has also
grown beyond its original scope, into an interconnected ecosystem of scopes,
which Wasm participates in in multiple ways. Is &lt;a href=&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;activitypub&#x2F;&quot;&gt;ActivityPub&lt;&#x2F;a&gt; Web? Well... yeah.
Is &lt;a href=&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;WoT&#x2F;&quot;&gt;Web of Things&lt;&#x2F;a&gt; Web? Still yeah. And of course, Wasm also does run in actual
browsers! So if we want to &lt;em&gt;fully&lt;&#x2F;em&gt; understand why Wasm works like it does, both
on a technological and social level, we can&#x27;t &lt;em&gt;ignore&lt;&#x2F;em&gt; the Web side of the story
either.&lt;&#x2F;p&gt;
&lt;p&gt;So is Wasm “Web”?&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps the shortest way to say it would be... well...&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;dict.org&#x2F;bin&#x2F;Dict?Form=Dict2&amp;amp;Database=*&amp;amp;Query=kinda&quot;&gt;Kinda&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;“...or Assembly”, the quote goes on, “because it has a lot of structure and a
type system”. And this is also true; assembly languages as we know them today
all basically look alike if you squint a little. Wasm looks distinctly
different.&lt;&#x2F;p&gt;
&lt;p&gt;But here too, Wasm&#x27;s instruction set is also very low-level, retaining many of the
design characteristics of a typical assembly language, like having a single
&lt;code&gt;i32&lt;&#x2F;code&gt; type that&#x27;s neither signed nor unsigned, leveraging the magic of two&#x27;s
complement, just like most machine ISAs do. And in some of the major compilers
that have been ported to target it, Wasm is emitted by the part of the compiler
that&#x27;s built to emit assembly code. It&#x27;s the “architecture”, in compiler parlance.
And this is one of the major forces behind Wasm&#x27;s overall design, so if we ignore
it, we aren&#x27;t seeing the whole picture.&lt;&#x2F;p&gt;
&lt;p&gt;So is Wasm “Assembly”?&lt;&#x2F;p&gt;
&lt;p&gt;Well...&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;a title=&quot;Xuan Zheng, CC BY-SA 2.0 &amp;lt;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by-sa&#x2F;2.0&amp;gt;, via Wikimedia Commons&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Thinking_woman.jpg&quot;&gt;&lt;img width=&quot;512&quot; alt=&quot;Thinking woman&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;2&#x2F;28&#x2F;Thinking_woman.jpg&#x2F;512px-Thinking_woman.jpg&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Kinda.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;kinda&quot;&gt;Kinda???&lt;&#x2F;h2&gt;
&lt;p&gt;Kinda! Our existing mental categories are important, because they&#x27;re how we
approach a new system, and they&#x27;re how we port existing code to new systems.
So we do talk about Wasm in terms of other systems, and we do build bridges
to enable concepts and code to be ported over.&lt;&#x2F;p&gt;
&lt;p&gt;At the same time, attempting to understand Wasm as categorically one existing
category or another will limit our potential to understand it and to take
advantage of its strengths.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cool-story&quot;&gt;Cool story&lt;&#x2F;h2&gt;
&lt;p&gt;Is a Wasm instance a &lt;em&gt;process&lt;&#x2F;em&gt;? Kinda. It can have an address space, like
a process does. And it has some forms of isolation from other instances,
somewhat like processes do from other processes. But it can also import its
entire address space from another instance, or not have an address space at
all! And it doesn&#x27;t carry around all the state that Unix attaches to its
processes. And the address space doesn&#x27;t contain things like the call stack
or the program&#x27;s executable code.&lt;&#x2F;p&gt;
&lt;p&gt;So we do sometimes use the word “process”, in contexts where that word fits.
We value compatibility with existing software, and existing software often
expects to have a process, so we do things to present the illusion that an
instance is such a process.&lt;&#x2F;p&gt;
&lt;p&gt;Sometimes we use the word “nanoprocess”, which highlights how Wasm processes
perform isolation without relying on heavyweight host process boundaries,
enabling it to scale to very many instances runnining on the same machine at
the same time, like little nanogears.&lt;&#x2F;p&gt;
&lt;p align=&quot;center&quot;&gt;&lt;a title=&quot;NASA, Public domain, via Wikimedia Commons&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Fullerene_Nanogears_-_GPN-2000-001535.jpg&quot;&gt;&lt;img width=&quot;400&quot; alt=&quot;Fullerene Nanogears - GPN-2000-001535&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;b&#x2F;b6&#x2F;Fullerene_Nanogears_-_GPN-2000-001535.jpg&#x2F;512px-Fullerene_Nanogears_-_GPN-2000-001535.jpg&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;But instances also have some superpowers that processes don&#x27;t have. Instances
can &lt;em&gt;call&lt;&#x2F;em&gt; each other. On the same callstack. This is difficult to even
contemplate if we limit ourselves to a Unix perspective, and it creates
interesting new opportunities for what Unix would call “Inter-Process
Communication”, but with very little ceremony. It&#x27;s just a call.
Compatibility is important. Taking full advantage of powerful new tools is
also part of the big picture here.&lt;&#x2F;p&gt;
&lt;p align=&quot;center&quot;&gt;&lt;a title=&quot;Grendelkhan, CC BY-SA 4.0 &amp;lt;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by-sa&#x2F;4.0&amp;gt;, via Wikimedia Commons&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Sciurus_carolinensis_performing_superhero_landing.jpg&quot;&gt;&lt;img width=&quot;512&quot; alt=&quot;Sciurus carolinensis performing superhero landing&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;1&#x2F;1c&#x2F;Sciurus_carolinensis_performing_superhero_landing.jpg&#x2F;512px-Sciurus_carolinensis_performing_superhero_landing.jpg&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;look-i-think-i-ve-got-a-pretty-good-picture&quot;&gt;Look I think I&#x27;ve got a pretty good picture&lt;&#x2F;h2&gt;
&lt;p&gt;Is WASI an OS? Kinda. It&#x27;s a framework for defining APIs, which could represent
an OS, and plays the role of an OS from the perspective of compatibility with
a lot of existing software.&lt;&#x2F;p&gt;
&lt;p&gt;But it doesn&#x27;t &lt;em&gt;have&lt;&#x2F;em&gt; to be an OS. WASI APIs could be implemented as an adapter
library on top of other APIs, WASI or otherwise, allowing a program written for
one environment to run in another. So it&#x27;s kinda?&lt;&#x2F;p&gt;
&lt;p&gt;Is Wasm a container? Kinda. It can perform isolation, protecting
the inside from the outside and vice versa, and it can be a single file that
contains everything needed to run a program. And as the tools mature I expect
it&#x27;ll be adding a lot of the features found in container systems. But at the
same time, it&#x27;s also kinda different. As in our discussion of processes above,
Wasm programs can straight-up call functions in other programs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;very-interesting-now-lets&quot;&gt;Very interesting now lets...&lt;&#x2F;h2&gt;
&lt;p&gt;Is Wasm a stack machine? Kinda. It has a stack-machine instruction encoding,
where most operands don&#x27;t need to be explicitly named, as they can be
implicitly “pushed” and “popped”, which compresses the binary encoding. But
it&#x27;s a heavily constrained stack machine. Wasm&#x27;s validation will check that
at every point in the code, the exact size of the stack, and the types of
everything on it, are known at compile time.&lt;&#x2F;p&gt;
&lt;p&gt;This enables optimizing Wasm engines to translate the stack machine into
a register-machine IR, with virtual registers that then get register-allocated.
And of all the Wasm producers I&#x27;ve seen, they all either internally work in
terms of registers, or an abstract syntax tree, and just translate into
pushes and pops at the last moment. So almost nothing in the overall ecosystem
actually operates at the pushes-and-pops abstraction level, except for the
binary encoding and a few tools that operate on it. So the stack-machine
personality is only a surface appearance.&lt;&#x2F;p&gt;
&lt;p&gt;Is Wasm a Reduced Instruction Set Computer (RISC)? Kinda. It does have
explicit load and store instructions, making it a load-store architecture,
and most of its arithmetic operations are very simple RISC-like instructions.
But it also does have fairly complex instructions like &lt;code&gt;call&lt;&#x2F;code&gt; and &lt;code&gt;memory.grow&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Is a Wasm component an executable, or a library? Kinda... both? In the
component model, those aren&#x27;t fundamentally different things. There are
components that can be used in the manner of commands, but these same
components can also be linked to like a library.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;can-we-wrap-this-up&quot;&gt;... can we wrap this up?&lt;&#x2F;h2&gt;
&lt;p&gt;Is Wasm a bytecode? Kinda. Or, well, yes. Yes it is. But the kinda here is
because if we reduce it down to &lt;em&gt;just&lt;&#x2F;em&gt; “a bytecode”, it&#x27;s easy to miss what
the big deal is. We already have multiple popular bytecode-based systems
out there. What makes Wasm different?&lt;&#x2F;p&gt;
&lt;p&gt;Wasm has a different approach to isolation, which makes it easier to embed
within existing systems and compose with itself without compromising its
security model. Wasm doesn&#x27;t have a single favorite source language,
and aims to be language-neutral from the beginning. And, Wasm isn&#x27;t strongly
associated with a single large corporation. It&#x27;s defined by a standards
body, and in practice it has active participation and meaningful consensus
process involving a wide variety of organizations.&lt;&#x2F;p&gt;
&lt;p&gt;Is Wasm a platform? Kinda? It&#x27;s kinda more like a substrate on which platforms
can be defined, along with a shared ecosystem that can be used on such
platforms. WASI has a concept of &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;what-is-a-world&#x2F;&quot;&gt;worlds&lt;&#x2F;a&gt; which are each like their own
platforms, defining all the APIs available to programs within them. And
embedders can define their own worlds, making their own platforms. So in a
sense, we&#x27;re building a meta-platform, plus a number of platforms inside.&lt;&#x2F;p&gt;
&lt;p&gt;But at the same time, with &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;phodPLY8zNE?t=1030&quot;&gt;virtual platform layering&lt;&#x2F;a&gt;, programs written for
one world can be adapted to run on another. And many ecosystem tools and
libraries will be able to be shared. So there is also a sense in which
all worlds are part of a single overarching meta-“platform”.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;maybe-stop-now&quot;&gt;Maybe stop now?&lt;&#x2F;h2&gt;
&lt;p&gt;Is Wasm a programming language? Kinda. It does have a type system, and a
syntax. And function calls with arguments and return values instead of a
“put things in certain registers and memories” calling convention. Tail
calls have to be built in rather than being just compiler cleverness. It even
has an &lt;code&gt;if&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;else&lt;&#x2F;code&gt; construct and eschews &lt;code&gt;goto&lt;&#x2F;code&gt;. But it&#x27;s also too
low-level to be really written by hand on a regular basis.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ok-ok-here-is-wasm-a-lisp&quot;&gt;Ok, ok. Here. Is Wasm a Lisp?&lt;&#x2F;h2&gt;
&lt;p&gt;Well... ok, fine. You got me there. One could try to make the case for Wasm being
a Lisp with the S-expression text syntax, and like, being Turing-complete?
And it&#x27;s gaining tail calls and GC, and it &lt;em&gt;is&lt;&#x2F;em&gt; getting increasingly interesting
to compile Lisp-family languages to. But ultimately, it&#x27;s not recognizably a
Lisp.  There are no builtin concepts of &lt;code&gt;cons&lt;&#x2F;code&gt; lists, &lt;code&gt;eval&lt;&#x2F;code&gt;, macros, and so on.&lt;&#x2F;p&gt;
&lt;p&gt;But here we are. A sea of kindas. And we can, and do, simplify them into the
familiar concepts and categories that people know and that existing programming
languages and existing code is often assuming. Giving people onramps and
compiling existing code and running existing applications are all critically
important for Wasm to succeed.&lt;&#x2F;p&gt;
&lt;p&gt;At the same time,&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s have fun, and embrace the kinda!&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>The Filesystem Namespace</title>
		<published>2023-04-17T00:00:00+00:00</published>
		<updated>2023-04-17T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/the-filesystem-namespace/" type="text/html"/>
		<id>https://blog.sunfishcode.online/the-filesystem-namespace/</id>
		<content type="html">&lt;p&gt;This post is in a series about &amp;quot;Everything Is A File&amp;quot;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;is-everything-a-file&quot;&gt;Is Everything A File?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;measuring-system-interface-complexity&#x2F;&quot;&gt;Measuring System Interface Complexity&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;what-does-everything-is-a-file-do&#x2F;&quot;&gt;What does Everything Is A File do?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;The Filesystem Namespace (this post)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Blog post content coming soon!&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>What does Everything Is A File do?</title>
		<published>2023-04-13T00:00:00+00:00</published>
		<updated>2023-04-13T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/what-does-everything-is-a-file-do/" type="text/html"/>
		<id>https://blog.sunfishcode.online/what-does-everything-is-a-file-do/</id>
		<content type="html">&lt;p&gt;This post is in a series about &amp;quot;Everything Is A File&amp;quot;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;is-everything-a-file&quot;&gt;Is Everything A File?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;measuring-system-interface-complexity&#x2F;&quot;&gt;Measuring System Interface Complexity&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;What does Everything Is A File do? (this post)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;the-filesystem-namespace&quot;&gt;The Filesystem Namespace&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;In particular, this post is looking at the &amp;quot;Everything is a file &lt;em&gt;descriptor&lt;&#x2F;em&gt;&amp;quot;
meaning.&lt;&#x2F;p&gt;
&lt;p&gt;To see how the Everything Is A File approach works in practice, let&#x27;s look at
three kinds of classic resources that have been a part of Unix and the
Everything Is A File tradition for a long time.&lt;&#x2F;p&gt;
&lt;p&gt;First, actual files.&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;a title=&quot;Vijay Verma, CC0, via Wikimedia Commons&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:File-text-dynamic-color.png&quot;&gt;&lt;img width=&quot;256&quot; alt=&quot;File-text-dynamic-color&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;6&#x2F;6f&#x2F;File-text-dynamic-color.png&#x2F;256px-File-text-dynamic-color.png&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Files are resizable arrays. They support random access to their data. Streaming
access patterns are implemented on top of this, using a &amp;quot;current position&amp;quot;
cursor.&lt;&#x2F;p&gt;
&lt;p&gt;Next, serial ports.&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;a title=&quot;Jud McCranie, CC BY-SA 4.0 &amp;lt;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by-sa&#x2F;4.0&amp;gt;, via Wikimedia Commons&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Serial_port_(9-pin).jpg&quot;&gt;&lt;img width=&quot;256&quot; alt=&quot;Serial port (9-pin)&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;b&#x2F;b3&#x2F;Serial_port_%289-pin%29.jpg&#x2F;256px-Serial_port_%289-pin%29.jpg&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Serial ports can transmit and receive bytes. There are many protocols that can
be used with serial ports, but here, we&#x27;re talking about Everything Is A File,
so we&#x27;re going to look at what you get when you talk directly to a serial-port
device file, such as &lt;code&gt;&#x2F;dev&#x2F;ttyS0&lt;&#x2F;code&gt; on a Unix system. This is a higher-level
interface than the hardware wires, but only by a little.&lt;&#x2F;p&gt;
&lt;p&gt;And third, TCP sockets.&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;a title=&quot;Someone&amp;#039;s Moving Castle, CC BY-SA 3.0 &amp;lt;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by-sa&#x2F;3.0&amp;gt;, via Wikimedia Commons&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Ethernet_Connection.jpg&quot;&gt;&lt;img width=&quot;256&quot; alt=&quot;Ethernet Connection&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;1&#x2F;11&#x2F;Ethernet_Connection.jpg&#x2F;256px-Ethernet_Connection.jpg&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;TCP sockets are multiple abstraction layers removed from the hardware wires.
They can also transmit and receive bytes, but they also have higher-level
functionality, such as addressing that allows connections to be routed
between many different wires.&lt;&#x2F;p&gt;
&lt;p&gt;On their own, each of these three things has a set of functions that it
naturally supports, like these:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;EIAF-files-serial-ports-sockets.png&quot; alt=&quot;Operations on files, serial ports, and sockets&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;These sets represent something inherent about each of these resources. Files
have a &amp;quot;current position&amp;quot; cursor that can be moved with an &amp;quot;lseek&amp;quot; operation,
but sockets and serial ports don&#x27;t. TCP sockets have connections and one can
query the IP address of the remote end, but files and serial ports don&#x27;t.
Files, serial ports, and TCP sockets are three different things, that support
three different sets of operations.&lt;&#x2F;p&gt;
&lt;p&gt;But, the Everything Is A File approach says to treat them all as files. How
does that work?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;read-and-write&quot;&gt;Read and Write&lt;&#x2F;h2&gt;
&lt;p&gt;The first thing to notice here is that all three of these resources support
&lt;code&gt;read&lt;&#x2F;code&gt; and &lt;code&gt;write&lt;&#x2F;code&gt;. And, &lt;code&gt;read&lt;&#x2F;code&gt; and &lt;code&gt;write&lt;&#x2F;code&gt; are the only operations that show
up in all three of these resources.&lt;&#x2F;p&gt;
&lt;p&gt;One of the big reasons Everything Is A File works as well as it does is that
a lot of use cases only need &lt;code&gt;read&lt;&#x2F;code&gt; or &lt;code&gt;write&lt;&#x2F;code&gt;. As long as you
stick to one of those two operations, the Everything Is A File abstraction works
pretty well. Serial ports and TCP sockets can be thought of as infinite-length
files.&lt;&#x2F;p&gt;
&lt;p&gt;But, things get tricky. We said &lt;code&gt;read&lt;&#x2F;code&gt; &lt;em&gt;or&lt;&#x2F;em&gt; &lt;code&gt;write&lt;&#x2F;code&gt; above, but
what if you &lt;code&gt;read&lt;&#x2F;code&gt; &lt;em&gt;and&lt;&#x2F;em&gt; &lt;code&gt;write&lt;&#x2F;code&gt;? Serial ports and TCP sockets are both
&lt;em&gt;interactive&lt;&#x2F;em&gt;. It&#x27;s common to write some bytes, and then read the response.
However, files aren&#x27;t interactive. If you write some bytes and then do a read,
you&#x27;ll read bytes from the array starting at the byte after the one you just
wrote to.&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;img width=&quot;512&quot; alt=&quot;Read some bytes, then write some points starting where the read stopped, then read some bytes after that, and so on&quot; src=&quot;&#x2F;ReadWriteReadWrite.svg&quot;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;On serial ports and TCP sockets, interleaving reads and writes like this is
very common. In files, it takes a lot of creativity to even imagine why one
would ever want to do this.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;unix-everything-is-a-file-serialport-tcpsocket-etc&quot;&gt;Unix: Everything Is A File-SerialPort-TCPSocket-etc.&lt;&#x2F;h2&gt;
&lt;p&gt;What happens if you try to call a file operation, like &lt;code&gt;lseek&lt;&#x2F;code&gt;, which seeks
the &amp;quot;current position&amp;quot; of a file to a different location, on a resource like
a serial port or a TCP socket, which doesn&#x27;t have a concept of a &amp;quot;current position&amp;quot;?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Open the serial device &amp;quot;file&amp;quot;.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; fd = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;dev&#x2F;ttyUSB0&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, O_RDWR);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Attempt to seek to byte-offset 8.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;lseek&lt;&#x2F;span&gt;&lt;span&gt;(fd, SEEK_SET, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Fails with `ESPIPE`, &amp;quot;Invalid seek&amp;quot;.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Unix lets you to attempt this, and the operation fails at runtime. This is
effectively dynamic typing; the file descriptor refers to a resource with a
dynamic type, which in this case is &amp;quot;serial port&amp;quot;. The &lt;code&gt;lseek&lt;&#x2F;code&gt; call does a
dynamic type check, and if dynamic type isn&#x27;t &amp;quot;regular file&amp;quot;, then the &lt;code&gt;lseek&lt;&#x2F;code&gt;
call fails.&lt;&#x2F;p&gt;
&lt;p&gt;So Everything Is A File doesn&#x27;t mean that everything is &lt;em&gt;really&lt;&#x2F;em&gt; a file. There&#x27;s
still a distinct &amp;quot;serial port&amp;quot; &lt;em&gt;type&lt;&#x2F;em&gt;. Everything Is A File just means that you
can use file APIs at compile time, and the types aren&#x27;t checked until runtime.&lt;&#x2F;p&gt;
&lt;p&gt;And even though Unix invented the concept, Unix doesn&#x27;t fully realize
Everything Is A File. When Unix added sockets, it didn&#x27;t insist on using only
operations in the file API. Instead, it added a bunch of new functions. So in
practice, it has one big combined API with all the functions that it supports
available on all resources:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;EIAF-everything-is-an-everything.png&quot; alt=&quot;All functions of all APIs concatenated into a single list&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;All these new functions fail at runtime if you pass them a file descriptor for
something that isn&#x27;t actually a socket.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;plan-9-everything-is-a-file-convention-at-runtime&quot;&gt;Plan 9: Everything Is A ~~File~~Convention at Runtime&lt;&#x2F;h2&gt;
&lt;p&gt;Unix didn&#x27;t insist on rigidly following Everything Is A File when it came to
sockets, but Plan 9 did. As we saw in
&lt;a href=&quot;&#x2F;measuring-system-interface-complexity&#x2F;&quot;&gt;Measuring System Interface Complexity&lt;&#x2F;a&gt;,
Plan 9&#x27;s way of adding resource-specific functions while staying within the file
API is to dynamically serialize requests as data, which can be written through
the file API.&lt;&#x2F;p&gt;
&lt;p&gt;For example, for sockets, Plan 9 uses ASCII strings to encode commands like
&amp;quot;connect&amp;quot; and &amp;quot;accept&amp;quot; and send them to the network driver, which then parses
the ASCII strings and then calls the appropriate code inside the driver. This
way it can nominally use only the File API, since it&#x27;s just using &lt;code&gt;write&lt;&#x2F;code&gt;, but
it can still make arbitrary function calls.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;EIAF-dynamic-protocols.png&quot; alt=&quot;Everything uses the File API with non-file operations encoded on top&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Unix&#x27;s &lt;code&gt;ioctl&lt;&#x2F;code&gt; is another form of this pattern, where dynamic values determine
the callee. The same values can even have different meanings, depending on what
type of resource they&#x27;re being used with.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;abstractions-that-don-t-abstract&quot;&gt;Abstractions that don&#x27;t abstract&lt;&#x2F;h2&gt;
&lt;p&gt;Even though Everything Is A File is about using the file API in a very abstract
way, it doesn&#x27;t end up providing much actual &lt;em&gt;abstraction&lt;&#x2F;em&gt;. It doesn&#x27;t usually
let user code written to work with files automatically work with things that
aren&#x27;t files, unless it&#x27;s just using &lt;code&gt;read&lt;&#x2F;code&gt; or just using &lt;code&gt;write&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Whether it&#x27;s the Unix approach of having lots of functions that fail at runtime
if the dynamic type is wrong, or the Plan 9 approach of serializing lots of
functions into data that can be smuggled through the file API, user code still
has to know what the dynamic type is in order to make meaningful use of it.&lt;&#x2F;p&gt;
&lt;p&gt;In all, Everything Is A File is often given credit for abstracting over widely
diverse resources. However it&#x27;s really just &lt;code&gt;read&lt;&#x2F;code&gt; and &lt;code&gt;write&lt;&#x2F;code&gt; doing all the
abstracting. The rest of the file API doesn&#x27;t enable reuse of logic across
different types.&lt;&#x2F;p&gt;
&lt;p&gt;So the real abstraction here is just &lt;em&gt;Lots Of Things Are Streams&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;a title=&quot;Sciencia58, CC BY-SA 4.0 &amp;lt;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by-sa&#x2F;4.0&amp;gt;, via Wikimedia Commons&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Bach_Isenach.jpg&quot;&gt;&lt;img width=&quot;256&quot; alt=&quot;Bach Isenach&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;4&#x2F;4b&#x2F;Bach_Isenach.jpg&#x2F;256px-Bach_Isenach.jpg&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-big-picture&quot;&gt;The big picture&lt;&#x2F;h2&gt;
&lt;p&gt;Other than the stream-style abstraction with &lt;code&gt;read&lt;&#x2F;code&gt; and &lt;code&gt;write&lt;&#x2F;code&gt;, a recurring theme in
Everything Is A File is deferring things which might otherwise be compile-time or link-time
concerns into runtime concerns. Type checks happen at runtime. And if we go all-in on
Everything Is A File, even function dispatch happens at runtime.&lt;&#x2F;p&gt;
&lt;p&gt;Doing all these things at runtime has many implications. One is that it opens up the
possibility that core parts of program behavior could be influenced by malicious data.
If function names are encoded as strings like &amp;quot;accept&amp;quot; or &amp;quot;connect&amp;quot;, it&#x27;s harder to
ensure Control Flow Integrity (CFI) because it opens up opportunities for malicious
code to cause other strings to be used instead, redirecting control flow to other
functions.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly, authorization becomes more complex because every single operation an
application does is something which could dynamically represent something it shouldn&#x27;t
be permitted to do, so the platorm has to be continually performing authorization.&lt;&#x2F;p&gt;
&lt;p&gt;Another implication is that doing things at runtime makes it harder to understand
programs without running them. If you want to know what resources a program will
access, which functions it will use to do the access, the only way to be sure is
to be there as it happens at runtime. This makes it harder to
write interposition or virtualization layers, harder to know what resources an
application will need ahead of time, and harder to figure out what&#x27;s wrong when
the application&#x27;s assumptions of its environment aren&#x27;t met.&lt;&#x2F;p&gt;
&lt;p&gt;So, if Everything Is A File has downsides, why do it?&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s more to say about the hierarchical namespace side of Everything Is A File in
future posts, but here we&#x27;re just looking at the file-descriptor meaning. And the main
thing this meaning does is:&lt;&#x2F;p&gt;
&lt;p&gt;It works around the problem that adding new functions in Unix is hard.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hard&quot;&gt;Hard&lt;&#x2F;h2&gt;
&lt;p&gt;Sometimes adding new functions in Unix is hard because you have to touch a lot
of things. You probably need to touch multiple places in the kernel. You probably
have touch touch the libc header files. You probably have to touch libc itself.
And you probably have to teach source languages that have C FFI layers about the
new function.&lt;&#x2F;p&gt;
&lt;p&gt;And sometimes these things are made harder by organizational reasons. When someone
is writing a driver, and they often can&#x27;t conveniently make changes to the core
OS kernel or libc. Adding new functions in Unix and libc is often expected to be
done with central coordination.&lt;&#x2F;p&gt;
&lt;p&gt;And sometimes adding new functions in Unix is hard because interfaces are described
using C header files, and C header files don&#x27;t contain enough information to
auto-generate intermediaries, such as tracing tools, filtering tools, RPC protocols,
bindings in languages other than C, and many other things. When you see a pointer,
you don&#x27;t know if it&#x27;s a pointer to a single element or an array, and if it&#x27;s an
array, what the array length is. And either way you don&#x27;t know if the memory is used
for just the duration of the call, retained after the call, or freed by the call. C is
accustomed to passing all of these concerns off to its users, but this means that it
takes a lot of manual work when adding new functions to update everything.&lt;&#x2F;p&gt;
&lt;p&gt;And sometimes adding new functions in Unix is hard because new functions come with
the expectation of long-term stability. The C ABI approach means that ABI details
get baked into everything that interfaces with them. If you ever change the signature
of a function, except in very specialized ways, you cause silent corruption for all
users. And if you ever remove a function, you have to all the work you did to add the
function in inverse. So in practice, you don&#x27;t add new functions, unless you&#x27;re
really ready to commit to them for the long term.&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;a title=&quot;Gary Todd, CC0, via Wikimedia Commons&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Sumerian_Cuneiform_Stone_Tablet_AO_3866.jpg&quot;&gt;&lt;img width=&quot;256&quot; alt=&quot;Sumerian Cuneiform Stone Tablet AO 3866&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;3&#x2F;3b&#x2F;Sumerian_Cuneiform_Stone_Tablet_AO_3866.jpg&#x2F;256px-Sumerian_Cuneiform_Stone_Tablet_AO_3866.jpg&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;So the big advantage of this meaning of Everything Is A File is that you can add
new logical functions while avoiding the difficulties of adding new actual
functions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-9p-protocol&quot;&gt;The 9p protocol&lt;&#x2F;h2&gt;
&lt;p&gt;Plan 9 has an additional consideration: It has a protocol, called 9p, which
encodes a kind of file API. This ends up being another arena where adding new
functions is hard.&lt;&#x2F;p&gt;
&lt;p&gt;A network protocol needs a specification, and 9p has one, but it&#x27;s kind of an
anti-specification. It defines just enough functionality to work with a hierarchical
namespace and files, and excludes everything else. It deliberately doesn&#x27;t define the
rest of the protocol, pushing everything else out to dynamic conventions, like
&lt;a href=&quot;&#x2F;measuring-system-interface-complexity&#x2F;&quot;&gt;String OS&lt;&#x2F;a&gt;. This is very convenient for a
spec, because specs take a lot of work to maintain.&lt;&#x2F;p&gt;
&lt;p&gt;In a spec, adding new functions is hard.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-if&quot;&gt;What if...&lt;&#x2F;h2&gt;
&lt;p&gt;The constraints that make adding new functions in Unix and other domains hard
have been with us for a long time, such that we don&#x27;t always realize when it&#x27;s
there, shaping the way the systems around us work, and even shaping the way
we think about new systems.&lt;&#x2F;p&gt;
&lt;p&gt;Everything Is A File bundles up a wide range of assumptions in a way that aren&#x27;t
always easy to see. If we unpack those assumptions, it helps us ask the question:&lt;&#x2F;p&gt;
&lt;p&gt;What if we designed systems differently?&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Mustang update</title>
		<published>2023-03-31T00:00:00+00:00</published>
		<updated>2023-03-31T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/mustang-update/" type="text/html"/>
		<id>https://blog.sunfishcode.online/mustang-update/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&quot;&gt;Mustang&lt;&#x2F;a&gt; gained lots of new features recently. It&#x27;s now complete enough to run
lots of real-world Rust programs, with no libc:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;tide&#x2F;tree&#x2F;mustang&quot;&gt;Tide&#x27;s hello web server example&lt;&#x2F;a&gt; (epoll and async!)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;tokio&#x2F;&quot;&gt;Tokio&#x27;s tinyhttp web server example&lt;&#x2F;a&gt; (more epoll and async!)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;coreutils&#x2F;&quot;&gt;Most of coreutils&lt;&#x2F;a&gt; (lots of stuff!)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;ripgrep&quot;&gt;Ripgrep&lt;&#x2F;a&gt; (threads!)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang#usage&quot;&gt;See here&lt;&#x2F;a&gt; for instructions on how to port programs to mustang. And if
you give it a try, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;issues&#x2F;22&quot;&gt;post about your experience here&lt;&#x2F;a&gt;, whether it works or not!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;looking-ahead&quot;&gt;Looking ahead&lt;&#x2F;h2&gt;
&lt;p&gt;Currently mustang requires programs be modified to include
&lt;code&gt;mustang::can_run_this!()&lt;&#x2F;code&gt; in their main source file, which is very inconvenient.
The only way I currently know how to fix that is to teach the Rust toolchain about
mustang. Is that the next step?&lt;&#x2F;p&gt;
&lt;p&gt;On one hand, mustang is cool and fun. But a lot of other things are cool and fun
too. An official Rust toolchain would involve a lot of work from a lot of people
who have a lot of other important things to work on. And for the most obvious use
cases, one of the Musl targets would be a better choice, being more featureful
and stable and so on.&lt;&#x2F;p&gt;
&lt;p&gt;So mustang is kind of waiting for a sign.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Measuring System Interface Complexity</title>
		<published>2022-11-29T00:00:00+00:00</published>
		<updated>2022-11-29T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/measuring-system-interface-complexity/" type="text/html"/>
		<id>https://blog.sunfishcode.online/measuring-system-interface-complexity/</id>
		<content type="html">&lt;p&gt;This post is in a series about &amp;quot;Everything Is A File&amp;quot;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;is-everything-a-file&#x2F;&quot;&gt;Is Everything A File?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Measuring System Interface Complexity (this post)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;what-does-everything-is-a-file-do&#x2F;&quot;&gt;What does Everything Is A File do?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;the-filesystem-namespace&quot;&gt;The Filesystem Namespace&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;One of the most easily quantifiable ways to measure the &amp;quot;simplicity&amp;quot; or &amp;quot;elegance&amp;quot; or an operating system this is to count the number of functions in its system interface, or &amp;quot;syscalls&amp;quot;. Linux has over 300. That&#x27;s lot! For comparison, Plan 9 has around 30. It would seem that Plan 9 is, like, &lt;em&gt;10x&lt;&#x2F;em&gt; more elegant than Linux.&lt;&#x2F;p&gt;
&lt;p&gt;Ok, so listen to this. That&#x27;s cool. But guess what.&lt;&#x2F;p&gt;
&lt;p&gt;I have a design for an OS which is &lt;strong&gt;30x&lt;&#x2F;strong&gt; more elegant than even Plan 9. It&#x27;s &lt;em&gt;300x&lt;&#x2F;em&gt; more elegant than Linux!&lt;&#x2F;p&gt;
&lt;p&gt;Introducing &amp;quot;String OS&amp;quot;.&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;img width=&quot;350&quot; alt=&quot;String OS logo, very garish&quot; src=&quot;&#x2F;StringOS.png&quot;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;What is the secret to String OS&#x27; amazing simplicity and elegance? I&#x27;ll tell you.&lt;&#x2F;p&gt;
&lt;p&gt;It has only one syscall!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;the_syscall&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;arg&lt;&#x2F;span&gt;&lt;span&gt;: String) -&amp;gt; String;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s it! That&#x27;s the entire interface.&lt;&#x2F;p&gt;
&lt;p&gt;The way it works is, you describe requests you want to make in strings, and you call &lt;code&gt;the_syscall&lt;&#x2F;code&gt; and pass them in. You get back a string, which describes the result. That&#x27;s it.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s trivial to interface with from any programming language; all you need is a string type and the ability to call functions!&lt;&#x2F;p&gt;
&lt;p&gt;And it&#x27;s fully serializable, loggable, extensible, interposable, replayable, remotable, and network-transparent.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;big&gt;🤯&lt;&#x2F;big&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Other operating systems have &amp;quot;shells&amp;quot; to provide interactive experiences. String OS doesn&#x27;t hide behind a shell. You can type commands straight into the OS.&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;img width=&quot;212&quot; alt=&quot;No Shells! (image of cockle shells with a no symbol over them)&quot; src=&quot;&#x2F;NoShells.svg&quot;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;What&#x27;s that you say? You want to know the list of commands?&lt;&#x2F;p&gt;
&lt;p&gt;...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;seriously-though&quot;&gt;Seriously though&lt;&#x2F;h2&gt;
&lt;p&gt;String OS is a made-up example, but the real world sometimes isn&#x27;t that far off. Consider Unix&#x27;s &lt;code&gt;ioctl&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;ioctl&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fd&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsigned long &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;request&lt;&#x2F;span&gt;&lt;span&gt;, ...);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, instead of a string, we&#x27;re passing an integer, but it&#x27;s not that different. The way &lt;code&gt;ioctl&lt;&#x2F;code&gt; is implemented, it does a big switch on the &lt;code&gt;request&lt;&#x2F;code&gt; argument, and dispatches to one of hundreds of different functions, depending on the values of its arguments. When OS&#x27;s do this kind of thing, it fools our little &amp;quot;number of syscalls&amp;quot; metric.&lt;&#x2F;p&gt;
&lt;p&gt;But perhaps there&#x27;s a way we can fix the metric by looking a little closer. Perhaps instead of looking at the literal number of system calls, we count the number of underlying implementation functions you can reach. We can look through the big &lt;code&gt;switch&lt;&#x2F;code&gt;. Or for String OS, we can look through the parsing and dispatch code. If we did that for Linux, we&#x27;d add over a thousand more syscalls. Yeah, there&#x27;s a &lt;em&gt;lot&lt;&#x2F;em&gt; of &lt;code&gt;ioctl&lt;&#x2F;code&gt; codes.&lt;&#x2F;p&gt;
&lt;p&gt;Is this Plan 9&#x27;s cue to take the stage? Shall we sound the fanfare? After all, Plan 9 famously doesn&#x27;t even &lt;em&gt;have&lt;&#x2F;em&gt; an &lt;code&gt;ioctl&lt;&#x2F;code&gt; function. It avoids &lt;code&gt;ioctl&lt;&#x2F;code&gt; &lt;em&gt;entirely&lt;&#x2F;em&gt;. So elegant!&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;a title=&quot;Phildonnia at English Wikipedia, CC BY-SA 3.0 &amp;lt;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by-sa&#x2F;3.0&amp;gt;, via Wikimedia Commons&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Pythagorean_proof_(1).svg&quot;&gt;&lt;img width=&quot;400&quot; alt=&quot;Pythagorean proof (1), as an example of extreme elegance&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;9&#x2F;9a&#x2F;Pythagorean_proof_%281%29.svg&#x2F;512px-Pythagorean_proof_%281%29.svg.png&quot;&gt;&lt;&#x2F;a&gt;
&lt;p&gt;(this picture illustrates an elegant mathematical proof; have we reached this level of elegance in system interface design yet?)&lt;&#x2F;p&gt;
&lt;p&gt;Or does it?&lt;&#x2F;p&gt;
&lt;p&gt;Now, come to think of it, how...&lt;&#x2F;p&gt;
&lt;p&gt;er, how...&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a title=&quot;Notas de prensa, CC BY-SA 2.5 &amp;lt;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by-sa&#x2F;2.5&amp;gt;, via Wikimedia Commons&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Confused_man.jpg&quot;&gt;&lt;img width=&quot;128&quot; alt=&quot;Confused man&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;5&#x2F;59&#x2F;Confused_man.jpg&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;How can Plan 9 have only 30 syscalls? How does it work?&lt;&#x2F;p&gt;
&lt;p&gt;It turns out, Plan 9 has a thing called a &lt;a href=&quot;http:&#x2F;&#x2F;doc.cat-v.org&#x2F;plan_9&#x2F;4th_edition&#x2F;papers&#x2F;net&#x2F;&quot;&gt;&amp;quot;ctl file&amp;quot;&lt;&#x2F;a&gt;. Plan 9 file descriptors can have a special file associated with them named &amp;quot;ctl&amp;quot;. The way you use it is, you open that file, and write a specially-formatted ASCII string into it, containing a command and parameters to pass to it. From the link:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Writing the string &lt;code&gt;connect 2048&lt;&#x2F;code&gt; to the ctl file sets the packet type to 2048 and configures the connection to receive all IP packets sent to the machine.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This means that we&#x27;re using the existing &lt;code&gt;write&lt;&#x2F;code&gt; system call to send a serialized message, which effectively encodes independent system calls and their parameters. We&#x27;ve avoided an &lt;code&gt;ioctl&lt;&#x2F;code&gt; system call, but we&#x27;ve effectively just re-introduced new logical syscalls using dynamic dispatch within the &amp;quot;ctl&amp;quot; file driver.&lt;&#x2F;p&gt;
&lt;p&gt;So while Plan 9 has a very small number of direct system calls in its system interface, part of how it achieves this is by hiding logical functions behind a string parsing and dynamic dispatch layer.&lt;&#x2F;p&gt;
&lt;p&gt;In short, it works like String OS!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;and-more&quot;&gt;And more&lt;&#x2F;h2&gt;
&lt;p&gt;Even when they aren&#x27;t literally serializing commands into strings, Unix&#x27;s and Plan 9&#x27;s
pervasive use of filesystem namespaces means that the system calls they do have are
very string-oriented. Strings identify resources in the namespaces.&lt;&#x2F;p&gt;
&lt;p&gt;And more broadly, the Everything Is A File design focuses everything on a relatively
small set of file-like operations, where features that don&#x27;t fit into file-like usage
patterns get accessed through integer or string values and dynamic dispatch.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;so-what&quot;&gt;So what?&lt;&#x2F;h2&gt;
&lt;p&gt;So a few things.&lt;&#x2F;p&gt;
&lt;p&gt;First, counting the number of direct syscalls is a &lt;em&gt;very&lt;&#x2F;em&gt; unreliable way to measure OS design elegance.&lt;&#x2F;p&gt;
&lt;p&gt;Second, is String OS a good way to design system interfaces? I&#x27;ll write more about this in a future post. As a sneak preview, using strings to identify resources is a sign that &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;no-ghosts&#x2F;&quot;&gt;there may be ghosts present&lt;&#x2F;a&gt;, but there&#x27;s more to say 😃.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>What is a Capability?</title>
		<published>2022-11-21T00:00:00+00:00</published>
		<updated>2022-11-21T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/what-is-a-capability/" type="text/html"/>
		<id>https://blog.sunfishcode.online/what-is-a-capability/</id>
		<content type="html">&lt;p&gt;This blog post aims to provide a simple answer to the question: What is a
Capability? I answer this question from my own perspective, as someone who
didn&#x27;t previously know anything about component models.&lt;&#x2F;p&gt;
&lt;p&gt;This post is forward-looking; not all of the pieces described here are usable yet. It&#x27;s a look at what&#x27;s coming.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;preliminaries&quot;&gt;Preliminaries&lt;&#x2F;h2&gt;
&lt;p&gt;When I say &amp;quot;capabilities&amp;quot;, I&#x27;m talking about capabilities in the context of the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;component-model&quot;&gt;Wasm component model&lt;&#x2F;a&gt;. These are capabilities in the sense of
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Capability-based_security&quot;&gt;&lt;em&gt;capability-based security&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There is a relationship with the term &amp;quot;object capabilities&amp;quot;, or &amp;quot;ocap&amp;quot;, however
that terminology involves some nuance and I&#x27;m aiming for a simple intuitive
description here.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m not talking about &lt;a href=&quot;https:&#x2F;&#x2F;wasmcloud.dev&#x2F;reference&#x2F;host-runtime&#x2F;capabilities&#x2F;&quot;&gt;wasmCloud &amp;quot;capabilities&amp;quot;&lt;&#x2F;a&gt;
or &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man7&#x2F;capabilities.7.html&quot;&gt;Linux &amp;quot;capabilities&amp;quot;&lt;&#x2F;a&gt;.
Similarly, there are connections that could be drawn here, but I&#x27;m aiming to keep
things simple.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ok-let-s-go&quot;&gt;Ok, Let&#x27;s go!&lt;&#x2F;h2&gt;
&lt;p&gt;One of the great things about Wasm is that it can&#x27;t do anything.&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;img alt=&quot;An anthropormorphized Wasm component with no arms.&quot; src=&quot;&#x2F;WasmNothing.jpg&quot;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Wasm has no syscall instructions. It has no I&#x2F;O ports. All it can do is compute.
And it can import functions from the outside and call them, and export functions
to the outside and have them be called.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;link-time-capabilities&quot;&gt;Link-time capabilities&lt;&#x2F;h2&gt;
&lt;p&gt;So the way to let a Wasm component &lt;em&gt;do&lt;&#x2F;em&gt; something outside of itself is to give
it functions it can import that do things, or conversely, to call its exports
from functions that do things when they return.&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;img alt=&quot;An anthropormorphized Wasm component *with* arms.&quot; src=&quot;&#x2F;WasmArms.jpg&quot;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;And that&#x27;s great, because it means the Wasm program can do what the things
we provided it can do, and nothing else.&lt;&#x2F;p&gt;
&lt;p&gt;Imports and exports are supplied at link time, so we call these
&lt;em&gt;link-time capabilities&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;capabilities-with-too-much-authority&quot;&gt;Capabilities with too much authority&lt;&#x2F;h2&gt;
&lt;p&gt;Link-time capabilities are useful, but often they&#x27;re &lt;em&gt;too&lt;&#x2F;em&gt; useful. As a
simple example, the following interface describes a link-time capability:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;wit&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-wit &quot;&gt;&lt;code class=&quot;language-wit&quot; data-lang=&quot;wit&quot;&gt;&lt;span&gt;&#x2F;&#x2F;&#x2F; Execute the command described in the provided
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&#x2F;&#x2F; `command` string.
&lt;&#x2F;span&gt;&lt;span&gt;do-command: func(command: string) -&amp;gt; string
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Imagine this is a function that passes the string argument to some command
interpreter, that can execute arbitrary commands. This can potentially be
a &lt;em&gt;very&lt;&#x2F;em&gt; powerful API, capable of doing almost anything.&lt;&#x2F;p&gt;
&lt;p&gt;Imagine I have a large codebase, and I want to pass around a reference
to some variable within in the command interpreter. The only way to do it
with this &lt;code&gt;do-command&lt;&#x2F;code&gt; API is to pass around the string name.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Set `x` to 2 within the command interpreter.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;do_command&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;x = 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Set the variable named in `some_dynamic_string` to 2.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;do_command&lt;&#x2F;span&gt;&lt;span&gt;(format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt; = 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, some_dynamic_string));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With this, it can be very difficult to answer questions like &amp;quot;what are all
the places in the code that use this variable?&amp;quot; or, looking at a particular
callsite, &amp;quot;what are all the variables this callsite could access?&amp;quot;. Strings
can originate from many places at runtime, potentially even untrusted places
like attacker-controlled inputs, so it&#x27;s very difficult to make any kind of
comprehensive guarantees with an API like this.&lt;&#x2F;p&gt;
&lt;p&gt;In systems where command strings are computed from other strings, it&#x27;s
also notoriously difficult to prevent quoting and whitespace bugs, leading
to bugs like &lt;a href=&quot;https:&#x2F;&#x2F;owasp.org&#x2F;www-community&#x2F;attacks&#x2F;SQL_Injection&quot;&gt;SQL Injection&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And when we look at modular systems, when a string is passed from one
component to another, it often means that there&#x27;s an assumption that the
two sides are implicitly sharing a namespace,
&lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;no-ghosts&quot;&gt;as if a ghost were connecting the two&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;no-ghosts&quot;&gt;&lt;p style=&quot;text-align:center&quot;&gt;&lt;img width=&quot;512&quot; alt=&quot;A Ghost!&quot; src=&quot;&#x2F;Ghost.jpg&quot;&gt;&lt;&#x2F;p&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Furthermore, APIs like this &lt;code&gt;do-command&lt;&#x2F;code&gt; are awkward to virtualize, for sandboxing,
logging, testing, or other purposes. They require intermediaries to always
parse the command string, even when they&#x27;re only interested in specific kinds
of requests.&lt;&#x2F;p&gt;
&lt;p&gt;Ultimately, APIs like this combine too many authorities into a single capability.
Capabilities like this are called &lt;em&gt;coarse-grained&lt;&#x2F;em&gt;, since an individual capability
exposes access to many distinct logical resources.&lt;&#x2F;p&gt;
&lt;p&gt;Traditional Filesystem and IP networking APIs tend to be coarse-grained, with
functions like &lt;code&gt;open&lt;&#x2F;code&gt; or &lt;code&gt;connect&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;wit&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-wit &quot;&gt;&lt;code class=&quot;language-wit&quot; data-lang=&quot;wit&quot;&gt;&lt;span&gt;open: func(path: string) -&amp;gt; file
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;connect: func(hostname: string) -&amp;gt; socket
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Filesystems and network namespaces both often contain many different logical
resources, often with differing security considerations. The code that calls
&lt;code&gt;open&lt;&#x2F;code&gt; or &lt;code&gt;connect&lt;&#x2F;code&gt; can open any file or host in the namespace, identified only
by some runtime string value. And sandboxing such APIs can be tricky,
because resources can often have multiple names, with links or aliases, which
can appear anywhere in the namespace.&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;img alt=&quot;An anthropormorphized Wasm component with a filesystem, offering to trade a file for a string.&quot; src=&quot;&#x2F;WasmAmbient.jpg&quot;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;One of the great properties of link-time capabilities is that one can find
all the places that use them at link time. But this advantage is negated if the
capabilities they represent are coarse-grained and you can&#x27;t tell which specific
resources are being accessed until runtime anyway.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;runtime-capabilities&quot;&gt;Runtime capabilities&lt;&#x2F;h2&gt;
&lt;p&gt;To avoid these problems, we need &lt;em&gt;runtime capabilities&lt;&#x2F;em&gt;. The Wasm component
model provides this with &lt;em&gt;handles&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;img alt=&quot;An anthropormorphized Wasm component with a filesystem, offering to trade a file for a magic token.&quot; src=&quot;&#x2F;WasmHandle.jpg&quot;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Handles are references to &lt;em&gt;resources&lt;&#x2F;em&gt;, and are values which can be passed
around as arguments and return values between components. And unlike other
values, handles are &lt;em&gt;unforgeable&lt;&#x2F;em&gt;. The only way to construct a handle to a
resource is to be the implementor of the resource. The only components that
can obtain a handle are components it&#x27;s been explicitly passed to.&lt;&#x2F;p&gt;
&lt;p&gt;Handles are similar to file descriptors in Unix. They&#x27;re references to
external things, where the &lt;em&gt;access&lt;&#x2F;em&gt; to the thing is represented by the
reference itself. And like file descriptors, they may be represented in
source languages as &lt;code&gt;i32&lt;&#x2F;code&gt; values or similar, where those &lt;code&gt;i32&lt;&#x2F;code&gt; values are
indices into a table of the actual unforgeable handle values.&lt;&#x2F;p&gt;
&lt;p&gt;Revisiting the filesystem and networking APIs above, we can make them
more fine-grained by adding handles arguments, such as a directory in which
to open files, or an address pool with which to initiate a network connection:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;wit&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-wit &quot;&gt;&lt;code class=&quot;language-wit&quot; data-lang=&quot;wit&quot;&gt;&lt;span&gt;open-at: func(dir: directory, path: string) -&amp;gt; file
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;connect-in: func(pool: address-pool, hostname: string) -&amp;gt; socket
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This way, instead of having an API which can reference any resource in an
implicitly shared namespace, conveyed as if by &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;no-ghosts&quot;&gt;ghost&lt;&#x2F;a&gt;, we have an API where
the namespace to use is explicitly communicated as an explicit argument.
This gives the caller, or an intermediary, the opportunity to be selective
about what resources are passed to the callee, without needing to configure
an external sandbox.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap up&lt;&#x2F;h2&gt;
&lt;p&gt;To do anything, Wasm components need capabilities. These can be provided at
link time, via imports and exports, which is sometimes useful, but can
easily be too coarse-grained. The Wasm component model also includes
&lt;em&gt;handles&lt;&#x2F;em&gt;, which identify capabilities at runtime.&lt;&#x2F;p&gt;
&lt;p&gt;Interfaces that expose access to logically distinct resources should represent
them as distinct capabilities.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Is Everything A File?</title>
		<published>2022-11-17T00:00:00+00:00</published>
		<updated>2022-11-17T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/is-everything-a-file/" type="text/html"/>
		<id>https://blog.sunfishcode.online/is-everything-a-file/</id>
		<content type="html">&lt;p&gt;This post is the first in a series about &amp;quot;Everything Is A File&amp;quot;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Is Everything A File? (this post)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;measuring-system-interface-complexity&#x2F;&quot;&gt;Measuring System Interface Complexity&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;what-does-everything-is-a-file-do&#x2F;&quot;&gt;What does Everything Is A File do?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;the-filesystem-namespace&quot;&gt;The Filesystem Namespace&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&amp;quot;Everything Is A File&amp;quot; is one of the most fundamental and widely influential
pillars of Unix design philosophy.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s one of the major sources of &lt;em&gt;simplicity&lt;&#x2F;em&gt; that propelled Unix beyond its
predecessor Multics, and helped it achieve widespread popularity. It enabled a
small set of simple tools to operate on data from a wide variety of sources.&lt;&#x2F;p&gt;
&lt;p&gt;At the same time, it&#x27;s also become a major source of &lt;em&gt;complexity&lt;&#x2F;em&gt; in modern
computing. And it&#x27;s been so pervasive for so many decades at this point, that
we often don&#x27;t recognize it as such.&lt;&#x2F;p&gt;
&lt;p&gt;&amp;quot;Everything Is A File&amp;quot; itself has at least three different meanings:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Everything has a name in a hierarchical namespace&lt;&#x2F;li&gt;
&lt;li&gt;Everything is a file &lt;em&gt;descriptor&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Everything is byte sequences&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Strictly speaking, Unix itself doesn&#x27;t perfectly conform to any of these, but
it does follow them enough in enough places that they&#x27;re recognizable and
influential. And then there&#x27;s Plan 9 which took some of these ideas further.&lt;&#x2F;p&gt;
&lt;p&gt;So there&#x27;s a lot to explore here. This is the first of a series of blog posts
exploring different aspects of Everything Is A File, with an overall focus on
&lt;em&gt;system interface design&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To get things started, here&#x27;s a quick exploration of one small but illustrative
quirk of Unix.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-tale-of-two-file-descriptors&quot;&gt;A tale of two file descriptors&lt;&#x2F;h2&gt;
&lt;p&gt;Unix&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;functions&#x2F;dup.html&quot;&gt;&lt;code&gt;dup&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function returns a new file descriptor referring to the same
resource as an existing file descriptor. The new file descriptor is independent
if the old one; we can &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;functions&#x2F;close.html&quot;&gt;&lt;code&gt;close&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; either one and the other remains open.&lt;&#x2F;p&gt;
&lt;p&gt;When file descriptors refer to files, they keep track of a &amp;quot;current position&amp;quot;
that tells &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;functions&#x2F;read.html&quot;&gt;&lt;code&gt;read&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;functions&#x2F;write.html&quot;&gt;&lt;code&gt;write&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; where in the file to read and write. Since the
file descriptors are independent of each other, one might think that each file
descriptor would have its own file position, like this:&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;img width=&quot;212&quot; alt=&quot;Two file descriptors pointing to one file, each with their own file position&quot; src=&quot;&#x2F;EIAF-two-positions.svg&quot;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;But what actually happens in Unix is that the file position is shared between
the two file descriptors, like this:&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;img width=&quot;212&quot; alt=&quot;Two file descriptors pointing to one file, sharing a file position&quot; src=&quot;&#x2F;EIAF-one-position.svg&quot;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If we do an &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;functions&#x2F;lseek.html&quot;&gt;&lt;code&gt;lseek&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to change the position of one, it changes the position
on the other one at the same time. Users of each have to be aware that the way
they use one file descriptor might affect the other. And if they have this level
of coordination, why did they need to call &lt;code&gt;dup&lt;&#x2F;code&gt; in the first place?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;everything-is-a-file&quot;&gt;Everything Is A File&lt;&#x2F;h2&gt;
&lt;p&gt;Pipes aren&#x27;t files, but Everything Is A File wants to treat everything in a
uniform way, and it would be expensive to make pipes work like files. Files
are random-access, and pipes aren&#x27;t.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s not that expensive to make files work like pipes though. All it takes
is adding this &amp;quot;file position&amp;quot; to open file descriptors. In this way, Unix&#x27;s
&lt;code&gt;read&lt;&#x2F;code&gt; can read from a file just as it can read from a pipe.&lt;&#x2F;p&gt;
&lt;p&gt;But then, we might ask, how should &lt;code&gt;dup&lt;&#x2F;code&gt; work? If we do &lt;code&gt;dup&lt;&#x2F;code&gt; in the natural
way for files, each file descriptor would have its own current position. But
the equivalent of that for pipes would be expensive to implement; it&#x27;d require
storing a copy of all data sent through the pipe. So Unix instead says that
&lt;code&gt;dup&lt;&#x2F;code&gt;&#x27;d file descriptors act like they do on pipes, which means they share a
current position.&lt;&#x2F;p&gt;
&lt;p&gt;It makes sense from that perspective. But if we go back and look at it from
the perspective of &lt;code&gt;lseek&lt;&#x2F;code&gt;, it doesn&#x27;t make sense again. &lt;code&gt;lseek&lt;&#x2F;code&gt; doesn&#x27;t even
work on pipes, so why are pipes the thing that determine how &lt;code&gt;lseek&lt;&#x2F;code&gt; has
to work?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;so-what-if&quot;&gt;So, what if...&lt;&#x2F;h2&gt;
&lt;p&gt;Underneath this is an &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Is-a&quot;&gt;&amp;quot;Is A&amp;quot;&lt;&#x2F;a&gt; relationship. Everything &lt;em&gt;Is A&lt;&#x2F;em&gt; file, and an
open file &lt;em&gt;Is A&lt;&#x2F;em&gt; stream.&lt;&#x2F;p&gt;
&lt;p&gt;What if we split out a &lt;em&gt;streaming view&lt;&#x2F;em&gt; as a separate entity?&lt;&#x2F;p&gt;
&lt;p&gt;An open file would continue to support all the essential file operations, like
&lt;code&gt;fsync&lt;&#x2F;code&gt;, &lt;code&gt;pread&lt;&#x2F;code&gt;, &lt;code&gt;pwrite&lt;&#x2F;code&gt;, and so on, but not &lt;code&gt;read&lt;&#x2F;code&gt; or &lt;code&gt;write&lt;&#x2F;code&gt;. A streaming
view would support &lt;code&gt;read&lt;&#x2F;code&gt; and&#x2F;or &lt;code&gt;write&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;d then add a new function, which takes an open file and an offset, and
returns a streaming view of the file at that offset.&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;img width=&quot;212&quot; alt=&quot;Two file descriptors pointing to one file; one is a stream with a position, and the other is a plain open file&quot; src=&quot;&#x2F;StreamView.svg&quot;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If we had a system like that, the &lt;code&gt;lseek&lt;&#x2F;code&gt; function wouldn&#x27;t be needed, and we&#x27;d
avoid this whole question of how &lt;code&gt;lseek&lt;&#x2F;code&gt; and &lt;code&gt;dup&lt;&#x2F;code&gt; interact in surprising ways.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s more we could say here about ergonomics and efficiency, but for now,
this gives a glimpse of a shape for a simpler and more orthogonal system, where
files just do one thing and do it well: hold arrays of data, and streams do one
thing and do it well: stream data.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap up&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;re just getting started here.&lt;&#x2F;p&gt;
&lt;p&gt;Everything Is A File conveys some underlying truths. Being able to write programs
that can automatically read from files, pipes, sockets, and more is really powerful.
But Everything Is A File also distracts us by pointing us toward the &amp;quot;file&amp;quot;
concept as the vehicle for achieving this.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s lot&#x27;s more to explore. Follow along for future explorations!&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Fork versus Elegance</title>
		<published>2022-11-10T00:00:00+00:00</published>
		<updated>2022-11-10T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/fork-versus-elegance/" type="text/html"/>
		<id>https://blog.sunfishcode.online/fork-versus-elegance/</id>
		<content type="html">&lt;p&gt;The research paper &lt;a href=&quot;https:&#x2F;&#x2F;www.microsoft.com&#x2F;en-us&#x2F;research&#x2F;publication&#x2F;a-fork-in-the-road&#x2F;&quot;&gt;A Fork in The Road&lt;&#x2F;a&gt; contains a good summary of the problems
with the &lt;code&gt;fork&lt;&#x2F;code&gt; call in Unix.&lt;&#x2F;p&gt;
&lt;p&gt;As the paper points out, &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;functions&#x2F;posix_spawn.html&quot;&gt;&lt;code&gt;posix_spawn&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; provides an alternative to &lt;code&gt;fork&lt;&#x2F;code&gt; which
solves some of the performance problems. However, if we set aside the performance
side for the moment, &lt;code&gt;posix_spawn&lt;&#x2F;code&gt;&#x27;s API kind of gives an impression that, if
that&#x27;s the alternative, perhaps we should reconsider.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;posix_spawn&lt;&#x2F;code&gt; needs a whole flock of &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;basedefs&#x2F;spawn.h.html&quot;&gt;&lt;code&gt;posix_spawn_*&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; helper functions, which
provide ways to configure various aspects of the child process:&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;img width=&quot;678&quot; height=696&quot; alt=&quot;the posix_spawn helper function API&quot; src=&quot;&#x2F;posix-spawn-helpers.png&quot;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This is inelegant,
because POSIX already has functions for doing all these things, except that they
only work on the parent process. So &lt;code&gt;posix_spawn&lt;&#x2F;code&gt; has alternate versions of all
these things, that operate on the child instead of the parent. And even with all
the features made available this way, it still doesn&#x27;t turn out to cover
everything that people want to do.&lt;&#x2F;p&gt;
&lt;p&gt;In all, &lt;code&gt;posix_spawn&lt;&#x2F;code&gt; just doesn&#x27;t feel &amp;quot;Unixy&amp;quot;.&lt;&#x2F;p&gt;
&lt;p&gt;In contrast, &lt;code&gt;fork&lt;&#x2F;code&gt; allows the child to be configured with the same APIs as the
parent. It can do &lt;em&gt;everything&lt;&#x2F;em&gt;, with no API duplication. Does this mean that
maybe &lt;code&gt;fork&lt;&#x2F;code&gt; is an elegant way to design systems after all?&lt;&#x2F;p&gt;
&lt;p&gt;Not necessarily.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-different-perspective&quot;&gt;A different perspective&lt;&#x2F;h2&gt;
&lt;p&gt;One reason why &lt;code&gt;posix_spawn&lt;&#x2F;code&gt; is simultaneously complex and insufficient is
that Unix has a lot of resources implicitly associated with processes, that
then need to be configured.&lt;&#x2F;p&gt;
&lt;p&gt;One such resource is the current directory. It acts a lot like a file descriptor
for a directory, except that the OS implicitly holds onto to it on behalf of
the process.&lt;&#x2F;p&gt;
&lt;p&gt;There isn&#x27;t any fundamental reason why userspace couldn&#x27;t hold onto this file
descriptor itself. If a current directory handle were passed into a process
alongside stdin, stdout, and stderr, userspace could use it and manage it
explicitly, and there&#x27;d be no need for a dedicated &lt;code&gt;chdir&lt;&#x2F;code&gt; system call.
And in a &lt;code&gt;posix_spawn&lt;&#x2F;code&gt; situation, the parent could pass any file descriptor to
be the child&#x27;s current directory, using the same mechanism as passing other
file descriptors.&lt;&#x2F;p&gt;
&lt;p&gt;So, what if we had an OS that took this even further? What if we moved even
more state out of the process, and into resources that would be explicitly
managed via file descriptors?&lt;&#x2F;p&gt;
&lt;p&gt;That would let parent processes easily configure resources for their children
processes without needing special APIs. All they&#x27;d have to do is use the
regular system calls to set up file descriptors they want their child processes
to have.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;but-wait-there-s-more&quot;&gt;But wait, there&#x27;s more&lt;&#x2F;h2&gt;
&lt;p&gt;If we managed Linux namespaces with file descriptors, we could avoid having a
bunch of flags on &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;clone.2.html&quot;&gt;&lt;code&gt;clone&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to say what parts of the parent get copied to the
child. And we could give userspace more control over how it wants to share
things.&lt;&#x2F;p&gt;
&lt;p&gt;To be sure, at this point we&#x27;re talking about a fair number of file descriptors.
A design like this would likely also want better ways to manage and pass
around file descriptors. As the paper above points out, the &lt;code&gt;fork&lt;&#x2F;code&gt;+&lt;code&gt;exec&lt;&#x2F;code&gt; way
of having children inherit file descriptors from the parent (with &lt;code&gt;O_CLOEXEC&lt;&#x2F;code&gt; as
an awkward opt-out) already isn&#x27;t great. Perhaps what we&#x27;d want is a way to
pass file descriptors to the child explicitly, rather than relying on children
implicitly inheriting them. At this point though, I&#x27;ll leave that for future
possible blog posts.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-does-it-all-mean&quot;&gt;What does it all mean?&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;fork&lt;&#x2F;code&gt;&#x27;s apparent simplicity is built on an underlying complex system, which
attaches a lot of implicit resources to processes.&lt;&#x2F;p&gt;
&lt;p&gt;A new OS that doesn&#x27;t attach as many implicit resources to processes wouldn&#x27;t 
necessarily need either &lt;code&gt;fork&lt;&#x2F;code&gt; or &lt;code&gt;posix_spawn&lt;&#x2F;code&gt;&#x27;s flock of helpers as
primitives.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>What is a World?</title>
		<published>2022-11-03T00:00:00+00:00</published>
		<updated>2022-11-03T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/what-is-a-world/" type="text/html"/>
		<id>https://blog.sunfishcode.online/what-is-a-world/</id>
		<content type="html">&lt;p&gt;&lt;em&gt;Worlds&lt;&#x2F;em&gt; have emerged as an important tool for WASI.&lt;&#x2F;p&gt;
&lt;p&gt;Luke Wagner&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=phodPLY8zNE&quot;&gt;The Path to Components&lt;&#x2F;a&gt; talk gives a great introduction to
Worlds, with the story to how we got here, and the path ahead.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;wasi-kv-store&#x2F;pull&#x2F;2&quot;&gt;WebAssembly&#x2F;wasi-kv-store#2&lt;&#x2F;a&gt; is a PR to the wasi-kv-store showing a concrete
example of Worlds, and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;component-model&#x2F;pull&#x2F;83&quot;&gt;WebAssembly&#x2F;component-model#83&lt;&#x2F;a&gt; is a PR to the
component-model spec with a lot of detailed information.&lt;&#x2F;p&gt;
&lt;p&gt;This blog post aims to provide a simple answer to the question: What is a World?
I answer this question from my own perspective, as someone who didn&#x27;t
previously know anything about component models.&lt;&#x2F;p&gt;
&lt;p&gt;This post is forward-looking; not all of the pieces described here are usable yet. It&#x27;s a look at what&#x27;s coming.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-a-world&quot;&gt;What is a World?&lt;&#x2F;h2&gt;
&lt;p&gt;A World is a &lt;em&gt;virtual&lt;&#x2F;em&gt; &lt;em&gt;environment&lt;&#x2F;em&gt; for a &lt;em&gt;component&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This packs a lot of meaning into a few words, so let&#x27;s unpack!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;for-a-component&quot;&gt;For a Component&lt;&#x2F;h3&gt;
&lt;p&gt;A Wasm &lt;em&gt;component&lt;&#x2F;em&gt; is a &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;what-is-a-wasm-component&#x2F;&quot;&gt;&lt;em&gt;deployable&lt;&#x2F;em&gt; &lt;em&gt;unit&lt;&#x2F;em&gt; of &lt;em&gt;software&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;an-environment&quot;&gt;An Environment&lt;&#x2F;h3&gt;
&lt;p&gt;An &lt;em&gt;environment&lt;&#x2F;em&gt; here is the surroundings that a Wasm component can run in. It
contains &lt;em&gt;imports&lt;&#x2F;em&gt; and &lt;em&gt;exports&lt;&#x2F;em&gt; that a component&#x27;s exports and imports can
link to. Wasm components are isolated, so this is the only way they can
interact with the outside.&lt;&#x2F;p&gt;
&lt;p&gt;A World is a description of what an environment contains. A component can be
built to run in a particular World, and then any environment that implements
that World can run it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;that-s-virtual&quot;&gt;That&#x27;s Virtual&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;em&gt;Virtual&lt;&#x2F;em&gt; here means that Worlds aren&#x27;t tied to concrete implementations.&lt;&#x2F;p&gt;
&lt;p&gt;A database API might be implemented using a remote database in a production
environment, and using a local-file database in a testing environment. A logging
API might write log messages to a local file, a remote log service a console,
or a chat channel.&lt;&#x2F;p&gt;
&lt;p&gt;The implementation of a World may be provided by native host code, by other
Wasm components, or a mix of both.&lt;&#x2F;p&gt;
&lt;p&gt;The strong isolation properties of Wasm components means that components can&#x27;t
simply &amp;quot;look around&amp;quot; and see what&#x27;s happening on the system around them. For
example, if a logging API doesn&#x27;t say where the log output is going, and the
World doesn&#x27;t include filesystem access, the component can&#x27;t look around and
see whether the output is going to a file. The output could go somewhere else
entirely, and the component will still work.&lt;&#x2F;p&gt;
&lt;p&gt;Virtualization enables testing with mocked dependencies, adapting components
written for one environment to run in another, polyfilling older versions of
APIs for backwards compatibility, and more.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap up&lt;&#x2F;h2&gt;
&lt;p&gt;A World is a &lt;em&gt;virtual&lt;&#x2F;em&gt; &lt;em&gt;environment&lt;&#x2F;em&gt; for a &lt;em&gt;component&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The WASI Subgroup is expected to define some standard Worlds, which environments
may chose to implement, allowing developers to produce components that run in
many different environments. Hosts may also chose to define their own bespoke
Worlds, either by extending or combining standard Worlds, or by describing new
Worlds from scratch.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a lot more that can be said about Wasm components and Worlds; check out
the links in the intro, and follow me for future explorations!&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>What is a Wasm component?</title>
		<published>2022-08-10T00:00:00+00:00</published>
		<updated>2022-08-10T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/what-is-a-wasm-component/" type="text/html"/>
		<id>https://blog.sunfishcode.online/what-is-a-wasm-component/</id>
		<content type="html">&lt;p&gt;When I first heard people in the Wasm world talking about these things called
&amp;quot;components&amp;quot; for Wasm, I had no idea what they were talking about.&lt;&#x2F;p&gt;
&lt;p&gt;Other people have now written about what a Wasm component is, such as
&lt;a href=&quot;https:&#x2F;&#x2F;www.fermyon.com&#x2F;blog&#x2F;webassembly-component-model&quot;&gt;this blog post from Fermyon&lt;&#x2F;a&gt; which makes an analogy relating Wasm concepts to
native code and OS concepts, and &lt;a href=&quot;https:&#x2F;&#x2F;www.infoq.com&#x2F;podcasts&#x2F;web-assembly-component-model&#x2F;&quot;&gt;this podcast with Lin Clark&lt;&#x2F;a&gt; which makes an
analogy between Wasm components and Lego blocks. And the Wasm component model
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;component-model&quot;&gt;proposal repo&lt;&#x2F;a&gt; has documentation about its &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;component-model&#x2F;blob&#x2F;main&#x2F;design&#x2F;high-level&#x2F;Goals.md&quot;&gt;goals&lt;&#x2F;a&gt;, intended &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;component-model&#x2F;blob&#x2F;main&#x2F;design&#x2F;high-level&#x2F;UseCases.md&quot;&gt;use cases&lt;&#x2F;a&gt;, and
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;component-model&#x2F;blob&#x2F;main&#x2F;design&#x2F;high-level&#x2F;Choices.md&quot;&gt;design choices&lt;&#x2F;a&gt;, and an &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;component-model&#x2F;blob&#x2F;main&#x2F;design&#x2F;high-level&#x2F;FAQ.md&quot;&gt;FAQ&lt;&#x2F;a&gt;. These are all great resources, and I recommend
them.&lt;&#x2F;p&gt;
&lt;p&gt;This blog post aims to provide a simple answer to the question: What is a Wasm component?
I answer this question from my own perspective, as someone who didn&#x27;t
previously know anything about component models.&lt;&#x2F;p&gt;
&lt;p&gt;This post is forward-looking; not all of the pieces described here are usable
yet. It&#x27;s a look at what&#x27;s coming.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-a-wasm-component&quot;&gt;What is a Wasm component?&lt;&#x2F;h2&gt;
&lt;p&gt;A Wasm component is a &lt;em&gt;deployable&lt;&#x2F;em&gt; &lt;em&gt;unit&lt;&#x2F;em&gt; of &lt;em&gt;software&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This packs a lot of meaning into a few words, so let&#x27;s unpack!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-unit&quot;&gt;A Unit&lt;&#x2F;h3&gt;
&lt;p&gt;A Wasm component is a self-contained unit. It doesn&#x27;t need wrappers, glue,
header files, or build artifacts, to be usable. It may have dependencies,
but its dependencies are on declared and self-describing APIs, rather than
on specific artifacts.&lt;&#x2F;p&gt;
&lt;p&gt;In comparison, Wasm &lt;em&gt;modules&lt;&#x2F;em&gt; often have implicit contracts with the outside
world. When a Wasm module passes around an &lt;code&gt;i32&lt;&#x2F;code&gt; value, it might be a number,
which might be signed or unsigned, or it might be a set of flags, a function
pointer, or a data pointer. If it&#x27;s a data pointer, the pointer is expected
to be used with a particular linear memory address space, where it points to
a region of memory with a layout, a lifetime, and other conventions.&lt;&#x2F;p&gt;
&lt;p&gt;This means that Wasm modules have the flexibility to represent many different
kinds of source languages. But it also means that many source-language
assumptions aren&#x27;t represented in a Wasm module&#x27;s type system. Anyone using
a module needs to share those assumptions. This means a Wasm module
conceptually acts as a slice of a larger whole.&lt;&#x2F;p&gt;
&lt;p&gt;A Wasm &lt;em&gt;component&lt;&#x2F;em&gt; is a whole. It may still be used as a dependency within
a larger conceptual program, but it doesn&#x27;t depend on being used that way.
Components just have APIs which can be used wherever they&#x27;re relevant.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;deployable&quot;&gt;Deployable&lt;&#x2F;h3&gt;
&lt;p&gt;Wasm&#x27;s high level of deterministic behavior and isolation provides very
consistent behavior, even across diverse environments.&lt;&#x2F;p&gt;
&lt;p&gt;Wasm components build on that. They add features supporting capability-based
security, which allows them to share I&#x2F;O facilities with other components
without sharing namespaces or user identity. And they don&#x27;t use a
globally-shared linear memory, which protects against cross-component
memory-safety hazards.&lt;&#x2F;p&gt;
&lt;p&gt;Wasm components also add explicit linking features. Linking works the same
way whether it&#x27;s performed at development time, or just before the program is
run. The output of linking components is a new component. This new component
can then be optimized, including with inlining, dead code elimination, and
other optimizations that can then cross the original component boundaries.&lt;&#x2F;p&gt;
&lt;p&gt;This enables the ability to take a collection of Wasm components and either
run them as a collection, or link them into a single optimized easy-to-deploy
component.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;software&quot;&gt;Software&lt;&#x2F;h3&gt;
&lt;p&gt;Wasm components are &amp;quot;software&amp;quot;, rather than &amp;quot;Python software&amp;quot;,
&amp;quot;Haskell software&amp;quot;, or any other specific source language&#x27;s software. The
source language a Wasm component is implemented in is not exposed in the API
of a component.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s not to say that Wasm components have to always be implemented in
software. Components encapsulate their implementation, so component APIs
can also be implemented by host environments, including using special
hardware. But from the outside, the API behaves the same as if it were
software.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap up&lt;&#x2F;h2&gt;
&lt;p&gt;A Wasm component is a &lt;em&gt;deployable&lt;&#x2F;em&gt; &lt;em&gt;unit&lt;&#x2F;em&gt; of &lt;em&gt;software&lt;&#x2F;em&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a lot more that can be said about components; check out the links
in the intro, and follow me for future explorations!&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>No Ghosts!</title>
		<published>2022-03-15T00:00:00+00:00</published>
		<updated>2022-03-15T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/no-ghosts/" type="text/html"/>
		<id>https://blog.sunfishcode.online/no-ghosts/</id>
		<content type="html">&lt;p&gt;This post proposes and explores a design principle for components in complex
software systems:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;No Ghosts!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The ideas in this post aren&#x27;t new; they come from papers and blog posts such as
&lt;a href=&quot;http:&#x2F;&#x2F;erights.org&#x2F;talks&#x2F;thesis&#x2F;markm-thesis.pdf&quot;&gt;Robust Composition&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.cs.cmu.edu&#x2F;%7Ealdrich&#x2F;papers&#x2F;effects-icfem2018.pdf&quot;&gt;Capabilities: Effects for Free&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;lexi-lambda.github.io&#x2F;blog&#x2F;2019&#x2F;11&#x2F;05&#x2F;parse-don-t-validate&#x2F;&quot;&gt;Parse, don&#x27;t validate&lt;&#x2F;a&gt;,
the &lt;a href=&quot;https:&#x2F;&#x2F;bytecodealliance.org&#x2F;articles&#x2F;1-year-update&quot;&gt;nanoprocess model&lt;&#x2F;a&gt;, and the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;component-model&#x2F;blob&#x2F;main&#x2F;design&#x2F;high-level&#x2F;Choices.md&quot;&gt;design choices in the Wasm component model&lt;&#x2F;a&gt;, which
itself incorporates ideas from Erlang, OCaml, Rust, COM, and many others. This post
is an attempt to articulate what I see as one of the themes that runs through all of
these. It&#x27;s not any kind of official position, and it certainly won&#x27;t be the last
word on any of these topics.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;d also be very interested in feedback on what makes sense here, what doesn&#x27;t, and
what&#x27;s missing: &lt;a href=&quot;https:&#x2F;&#x2F;hachyderm.io&#x2F;@sunfish&quot;&gt;mastodon&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;bytecodealliance.zulipchat.com&#x2F;#narrow&#x2F;pm-with&#x2F;254083-user254083&quot;&gt;zulip&lt;&#x2F;a&gt;,
&lt;a href=&quot;mailto:blog-feedback@sunfishcode.online&quot;&gt;email&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This is motivated by WASI and Wasm components, however the core ideas generalize
to any complex software system, including those using libraries, daemons,
containers, VMs, microservices, or a combination.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;One of the main ways we can make complex systems manageable is to make them
&lt;em&gt;modular&lt;&#x2F;em&gt;. This means being able to add, remove, change, or understand individual
components (or whatever a system is composed of) without needing to consider the
system around them.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s common for systems with large numbers of components to have problems with
unexpected interactions between components. A common response to these kinds of
problems is to impose a level of modularity by introducing &lt;em&gt;heavyweight barriers&lt;&#x2F;em&gt;,
such as sandboxes, process boundaries, firewalls, or service meshes. These
comprehensively block many of the avenues for components to interact. Then,
since components still do need to communicate, it&#x27;s common to effectively poke
small holes in the barriers, such as allowing specific HTTP connections to pass
through.&lt;&#x2F;p&gt;
&lt;p&gt;However, while the barriers-and-pinholes approach fixes the immediate problems,
barriers are sometimes &lt;em&gt;too&lt;&#x2F;em&gt; comprehensive. They get in the way of connecting
things that we &lt;em&gt;do&lt;&#x2F;em&gt; want to connect. This then leads us to do more things
through the pinholes, or poke more pinholes, which then increases the risks of
unexpected interactions again.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;2044&#x2F;&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;imgs.xkcd.com&#x2F;comics&#x2F;sandboxing_cycle.png&quot; alt=&quot;XKCD 2044: Sandboxing Cycle&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;There are many reasons why we get stuck on this path, but one is that
heavyweight barriers tend to focus us on limiting the &lt;em&gt;mechanisms&lt;&#x2F;em&gt; that let
components interact, such as which components a component can directly talk to,
and what kinds of messages it can send. However, the more fundamental problems
are often in the &lt;em&gt;relationships&lt;&#x2F;em&gt; between components. One of the things we can
do to avoid these problems, and promote modularity in a sustainable way, is to
design component APIs that avoid &lt;em&gt;ghosts&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;👻? 😱!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ghosts&quot;&gt;Ghosts?&lt;&#x2F;h2&gt;
&lt;p&gt;By “ghost” here, I mean any situation where resources are referenced by
&lt;em&gt;plain data&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And by “plain data” here, I mean strings, integers, or any other data where
independently produced copies of the data are interchangeable. For example, two
completely independent parts of a system may create a string with the value
&lt;code&gt;&amp;quot;Purple&amp;quot;&lt;&#x2F;code&gt;, and the two strings will be interchangeable.&lt;&#x2F;p&gt;
&lt;p&gt;Plain data can contain filenames, network addresses, usernames, or other forms
of data which effectively &lt;em&gt;reference&lt;&#x2F;em&gt; resources.&lt;&#x2F;p&gt;
&lt;p&gt;For example, when we say that a particular string contains a filesystem path, we
mean that it &lt;em&gt;refers to&lt;&#x2F;em&gt; an entity in a filesystem namespace. Filesystem namespaces
are not explicitly passed as arguments in the APIs of many popular systems, so
from the perspective of an API, while paths are explicit string parameters, the
additional information &lt;em&gt;referenced&lt;&#x2F;em&gt; by those paths is not. In this post, we&#x27;ll
say this additional information is being carried by a “ghost”:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; We&amp;#39;re explicitly passing a path, but implicitly
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; passing the namespace to resolve it in.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;do_stuff&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;tmp&#x2F;data.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;By passing a filename, the caller here is requiring that the callee have a
specific filesystem namespace, in order to interpret that filename. This is
an example of a &lt;em&gt;relationship&lt;&#x2F;em&gt; between components that&#x27;s difficult to control
with heavyweight barriers focused on &lt;em&gt;mechanisms&lt;&#x2F;em&gt;. The actual message is
just a string, which could be communicated through practically any pinhole.
And once the caller can send filenames through, it can depend on the callee
having a particular namespace and being able to resolve those filenames, and
we have the potential to get complex relationships between caller and callee,
despite whatever barriers we put between them.&lt;&#x2F;p&gt;
&lt;p&gt;As another example, suppose one part of a system sets an environment variable,
and another part of the system reads it.&lt;&#x2F;p&gt;
&lt;p&gt;⬅ In one place:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;export &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;TIMEOUT&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;30
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;➡ In another:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char &lt;&#x2F;span&gt;&lt;span&gt;*timeout = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;getenv&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;TIMEOUT&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, two independent parts of the system both use the string &lt;code&gt;&amp;quot;TIMEOUT&amp;quot;&lt;&#x2F;code&gt; as
an identifier to send a message between them. As far as these specific parts of
the code know, it&#x27;s as if the content of the message is carried by a ghost,
from one part to the other.&lt;&#x2F;p&gt;
&lt;p&gt;IP addresses are another example of plain data that references other
resources. If one part of a system listens on a socket and sends the
IP address to other parts of the system for them to connect to, the address
is a plain-data list of integers, while the interpretation of those integers
depends on a particular network view.&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;img width=&quot;512&quot; alt=&quot;Ghosts can occur in filesystems, networks, and more&quot; src=&quot;&#x2F;Ghosts.svg&quot;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Ghosts can also occur within key-value stores, registries, brokers, buses, and
many other things where the identifiers are plain data. There are situations
where plain-data identifiers are the only option, such as when working with
external resources. But when designing component APIs, we should seek to avoid
ghosts where we can, and seek to identify and encapsulate ghosts where we can&#x27;t.&lt;&#x2F;p&gt;
&lt;p&gt;Granted, the way all these things work isn&#x27;t &lt;em&gt;literally&lt;&#x2F;em&gt; supernatural. We
can figure out how filesystem namespaces, environment-variable dictionaries,
networks, and other things make our resources available if we know some
things about the surrounding system. However, that goes against our goal of
modularity. We specifically don&#x27;t want individual components knowing about
the system around them.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-trouble-with-ghosts&quot;&gt;The trouble with ghosts&lt;&#x2F;h3&gt;
&lt;p&gt;Ghosts are often &lt;em&gt;convenient&lt;&#x2F;em&gt;, in the way that duct tape is convenient. They
can quickly connect two things, even in a large system, without extensive
changes. And on small scales, they sometimes work well. But like duct tape,
they aren&#x27;t a material one wants to build complex structures from.&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;a title=&quot;1sfoerster, CC BY-SA 3.0 &amp;lt;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by-sa&#x2F;3.0&amp;gt;, via Wikimedia Commons&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:DuctTape.jpg&quot;&gt;&lt;img width=&quot;512&quot; alt=&quot;a boat made from cardboard and duct tape&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;0&#x2F;0f&#x2F;DuctTape.jpg&#x2F;512px-DuctTape.jpg&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Ghosts have four distinct problems as systems scale up in complexity:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Ghosts don&#x27;t always go to the places we want them to 👻➡😞. When we pass
plain-data references around, they depend on the ghosts going to the same
places. If our references go somewhere that the ghosts don&#x27;t go, attempting
to resolve them may fail, or may resolve to something unintended. An example
of this is &lt;a href=&quot;https:&#x2F;&#x2F;cwe.mitre.org&#x2F;data&#x2F;definitions&#x2F;706.html&quot;&gt;CWE-706&lt;&#x2F;a&gt; “Use of Incorrectly-Resolved Name or Reference”.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ul&gt;
&lt;li&gt;Ghosts may go places we don&#x27;t want them to 👻➡😲. For example, environment
variable values are propagated to all child processes, even those that
don&#x27;t need them, and some programs log the contents of their environment for
diagnostic purposes. If our variables contain sensitive information, it may
get exposed. Similarly, ghosts may also persist for longer than we want them
to, because cleaning them up can lead to dangling or even aliasing
references. Examples of this include &lt;a href=&quot;https:&#x2F;&#x2F;cwe.mitre.org&#x2F;data&#x2F;definitions&#x2F;532.html&quot;&gt;CWE-532&lt;&#x2F;a&gt; “Insertion of Sensitive
Information into Log File” and &lt;a href=&quot;https:&#x2F;&#x2F;cwe.mitre.org&#x2F;data&#x2F;definitions&#x2F;386.html&quot;&gt;CWE-386&lt;&#x2F;a&gt; “Symbolic Name not Mapping to
Correct Object”.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ul&gt;
&lt;li&gt;Ghosts may collide with other ghosts 👻➡💥⬅👻. In a complex system,
the same name can end up getting used in multiple places. Naming
conventions can help, but aren&#x27;t enough if there are multiple instances of
the same component within the larger system. In the case of filesystem
namespaces, sometimes two different parts of a system need different versions
of a resource, but they both expect it to be at the same path. An example of
this is &lt;a href=&quot;https:&#x2F;&#x2F;cwe.mitre.org&#x2F;data&#x2F;definitions&#x2F;435.html&quot;&gt;CWE-435&lt;&#x2F;a&gt; “Improper Interaction Between Multiple Correctly-Behaving
Entities”.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ul&gt;
&lt;li&gt;And sometimes, ghosts &lt;em&gt;come from&lt;&#x2F;em&gt; places they&#x27;re not expected to ❓➡👻.
When plain data can reference resources, any plain data within a system
could potentially be representing a reference. Plain data may also be
influenced by attackers. Examples of this are &lt;a href=&quot;https:&#x2F;&#x2F;cwe.mitre.org&#x2F;data&#x2F;definitions&#x2F;22.html&quot;&gt;CWE-22&lt;&#x2F;a&gt;
“Improper Limitation of a Pathname to a Restricted Directory
(&#x27;Path Traversal&#x27;)” and &lt;a href=&quot;https:&#x2F;&#x2F;cwe.mitre.org&#x2F;data&#x2F;definitions&#x2F;73.html&quot;&gt;CWE-73&lt;&#x2F;a&gt; “External Control of File Name or Path”.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Systems which use ghost patterns often face several challenges:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;ghosts-complicate-static-analysis&quot;&gt;Ghosts complicate static analysis&lt;&#x2F;h4&gt;
&lt;p&gt;Being unable to know where ghosts are going and where they&#x27;re coming from makes
it difficult and often impossible to answer questions such as:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;“I have sensitive data flowing through part of the system. Where are
all the places that might be able to access it?”&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;“If I change the behavior of something, what are all the things I
need to update?”&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;“If there&#x27;s a bug in something, what parts of the system could be affected?”&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;“If an attacker can control certain input data, what are all the things
which they might be able to influence?”&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;ghosts-complicate-debugging&quot;&gt;Ghosts complicate debugging&lt;&#x2F;h4&gt;
&lt;p&gt;A common way to debug complex systems is to isolate parts of the system and
study how they behave independently. Ghosts create situations where components
work differently when run independently than when they&#x27;re run together, or
work differently in different environments, making this kind of debugging more
difficult.&lt;&#x2F;p&gt;
&lt;p&gt;Ghosts create hidden cause-and-effect relationships, making it harder to
understand the system&#x27;s behavior.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;ghosts-are-often-a-sign-of-over-sharing&quot;&gt;Ghosts are often a sign of over-sharing&lt;&#x2F;h4&gt;
&lt;p&gt;Over-sharing happens when a component is given access to resources that it
doesn&#x27;t need. This often happens in namespace-oriented systems because it&#x27;s
difficult to precisely configure namespaces to be fine-grained and share only
what&#x27;s needed to each component. Even with features such as bind mounts on Linux,
it can be tricky to make sure that every part of a complex system has access to
all the things it needs, at the paths it expects them to be at, and nothing it
doesn&#x27;t need. As a result, programs are often run with more filesystem access
than they strictly need.&lt;&#x2F;p&gt;
&lt;p&gt;This makes it difficult to follow the &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Principle_of_least_privilege&quot;&gt;Principle of Least Authority&lt;&#x2F;a&gt; (PoLA).&lt;&#x2F;p&gt;
&lt;h4 id=&quot;ghosts-can-contribute-to-confused-deputies&quot;&gt;Ghosts can contribute to confused deputies&lt;&#x2F;h4&gt;
&lt;p&gt;A common pattern in complex systems composed of multiple privilege levels
is that some components are considered to run on behalf of specific users,
which determine their privilege level. We can call components that work this
way &lt;em&gt;deputies&lt;&#x2F;em&gt; of the users that own them.&lt;&#x2F;p&gt;
&lt;p&gt;When components send plain-data requests to components running as different
users, senders may be able to reference resources they shouldn&#x27;t be able to
access. In such situations, receivers perform &lt;em&gt;access control&lt;&#x2F;em&gt;, explicitly
checking requests to see whether the sender has the appropriate privileges.
This is often tricky, especially when an API has a complex surface area.
Receivers may get &lt;em&gt;confused&lt;&#x2F;em&gt; into doing things they shouldn&#x27;t allow senders
to ask them to do.&lt;&#x2F;p&gt;
&lt;p&gt;This is a form of the &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Confused_deputy_problem&quot;&gt;confused deputy problem&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-different-kind-of-relationship&quot;&gt;A different kind of relationship&lt;&#x2F;h3&gt;
&lt;p&gt;Systems which have a concept of &lt;em&gt;handles&lt;&#x2F;em&gt;—values which can be passed between
components, but which are not &lt;em&gt;plain data&lt;&#x2F;em&gt;—can use them to avoid ghosts.
Handles provide a way to make specific resources accessible across a component
boundary without requiring any other relationship.&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;a title=&quot;User:Mateus2019, CC BY 2.0 DE &amp;lt;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by&#x2F;2.0&#x2F;de&#x2F;deed.en&amp;gt;, via Wikimedia Commons&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:GER-BY-RO-Wasserburg_am_Inn_-_Brucktor_(mechanische_T%C3%BCrglocken_au%C3%9Fen).jpg&quot;&gt;&lt;img width=&quot;256&quot; alt=&quot;GER-BY-RO-Wasserburg am Inn - Brucktor (mechanische Türglocken außen)&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;7&#x2F;75&#x2F;GER-BY-RO-Wasserburg_am_Inn_-_Brucktor_%28mechanische_T%C3%BCrglocken_au%C3%9Fen%29.jpg&#x2F;256px-GER-BY-RO-Wasserburg_am_Inn_-_Brucktor_%28mechanische_T%C3%BCrglocken_au%C3%9Fen%29.jpg&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Handles make cause-and-effect relationships clear, since they are explicitly
passed between components. And, receivers can assume that any handle they are
passed represents a resource that the sender is allowed to ask them to
operate on. That way, receivers need less authority of their own, which
reduces the risk of them accidentally misusing their authority.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ghosts-can-hide-inside-explicit-sharing&quot;&gt;Ghosts can hide inside explicit sharing&lt;&#x2F;h2&gt;
&lt;p&gt;One of the tricky things about ghosts is that they&#x27;re about &lt;em&gt;relationships&lt;&#x2F;em&gt;
rather than specific &lt;em&gt;mechanisms&lt;&#x2F;em&gt;. Mechanisms tend to be easy to understand,
and to sandbox. But, relationships that permit ghosts can pass through even
the most restrictive sandboxes.&lt;&#x2F;p&gt;
&lt;p&gt;This blog post talks a lot about implicitly shared resources, however that&#x27;s
not the only place ghosts can hide. For example, consider our example above of
caller and callee implicitly sharing a filesystem namespace, and passing
strings representing paths:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;do_stuff&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;tmp&#x2F;data.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a ghost pattern, with a string carrying a reference to an implicitly
shared namespace. A simple way we might try to eliminate such a ghost is to
replace the use of an implicit namespace with an explicit filesystem root
parameter:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;do_stuff_in_root&lt;&#x2F;span&gt;&lt;span&gt;(root_handle, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;tmp&#x2F;file.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This might be tempting, as it means that most of our code doesn&#x27;t need to
fundamentally change. It&#x27;s a mostly mechanical change to just add root
parameters in places where they&#x27;re needed, and everything else about our
code can stay the same.&lt;&#x2F;p&gt;
&lt;p&gt;We might then be tempted to claim that we&#x27;ve eliminated our ghosts here, because
we now do the sharing via explicit communication rather than an implicitly
shared resource. And we might indeed find that this code does afford us some
added flexibility.&lt;&#x2F;p&gt;
&lt;p&gt;The problem is that this doesn&#x27;t change the &lt;em&gt;relationship&lt;&#x2F;em&gt;. We&#x27;re still using
strings to identify specific resources within the filesystem root we&#x27;re
passing around. And that means we still have resources being referenced by
plain data.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s effectively a ghost, hiding &lt;em&gt;inside&lt;&#x2F;em&gt; the resource.&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;&lt;a title=&quot;gamene, CC BY 2.0 &amp;lt;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by&#x2F;2.0&amp;gt;, via Wikimedia Commons&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Ghost_onigiri_bento_(4039012309).jpg&quot;&gt;&lt;img width=&quot;512&quot; alt=&quot;onigiri bento with a ghost inside (4039012309)&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;a&#x2F;a5&#x2F;Ghost_onigiri_bento_%284039012309%29.jpg&#x2F;512px-Ghost_onigiri_bento_%284039012309%29.jpg&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;One way to think about it is in terms of granularity. While passing around
handles to “root”, “world”, “namespace” or “registry” resources is better
than implicit sharing, those kinds of resources tend to be coarse-grained.
They can end up having ghosts hiding inside them. Plain-data references to
specific items within coarse-grained resources can still have dynamic
cause-and-effect relationships, and can still dangle, collide, or be
influenced by attackers.&lt;&#x2F;p&gt;
&lt;p&gt;To avoid ghosts, it&#x27;s not enough to change the mechanisms. To change the
relationships, we need to switch from coarse-grained sharing to fine-grained
sharing with handles. Instead of whole filesystems, we should ideally
reference specific directories or even individual files, such as like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Open the file using our own privileges.
&lt;&#x2F;span&gt;&lt;span&gt;    file_handle = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(root_handle, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;tmp&#x2F;file.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Instead of passing root_handle and a path, pass
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; *just* the one file handle to the other component.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;process_open_file&lt;&#x2F;span&gt;&lt;span&gt;(file_handle);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;how-to-smell-a-ghost&quot;&gt;How to smell a ghost&lt;&#x2F;h2&gt;
&lt;p&gt;There are some common signs that a ghost may be present.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;String parameters which don&#x27;t represent user data&lt;&#x2F;em&gt;. String types in
programming languages can hold many different kinds of things, such
as names or text fields. And when a program is talking to the outside
world, strings may also contain external identifiers such as filenames,
network addresses, or URLs. But when software is talking to
other software, resources should ideally be identified by handles,
rather than by string identifiers. And as a bonus, this also helps
minimize exposure to &lt;a href=&quot;https:&#x2F;&#x2F;eev.ee&#x2F;blog&#x2F;2015&#x2F;09&#x2F;12&#x2F;dark-corners-of-unicode&#x2F;&quot;&gt;Unicode subtleties&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;cwe.mitre.org&#x2F;data&#x2F;definitions&#x2F;149.html&quot;&gt;quoting subtleties&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Heuristic: “Strings are for humans” 🌟&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;The word “the”&lt;&#x2F;em&gt;. Whenever we find ourselves thinking about &lt;em&gt;the&lt;&#x2F;em&gt;
filesystem, &lt;em&gt;the&lt;&#x2F;em&gt; network, &lt;em&gt;the&lt;&#x2F;em&gt; process, &lt;em&gt;the&lt;&#x2F;em&gt; host, &lt;em&gt;the&lt;&#x2F;em&gt; OS,
or &lt;em&gt;the&lt;&#x2F;em&gt; computer, it often means we&#x27;re making assumptions about state
that might be shared between parts of a larger system. Wherever possible,
components should not be aware of “the host”, or any entities associated
with it, as nouns.&lt;&#x2F;p&gt;
&lt;p&gt;Heuristic: “Components should be hostless” 🌟&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;User identity outside the user interface&lt;&#x2F;em&gt;. While there&#x27;s a place for
user-facing software to maintain an explicit knowledge of who they&#x27;re
acting on behalf of, components interfacing with other components should eagerly
resolve that user authority to obtain finer-grained handles which can then
be passed to other components. That way, those other components don&#x27;t need
the full access of the user, and will be less likely to make assumptions about
shared state associated with the user.&lt;&#x2F;p&gt;
&lt;p&gt;Heuristic: “Handles are permissions” 🌟&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;wrapping-it-up&quot;&gt;Wrapping it up&lt;&#x2F;h2&gt;
&lt;p&gt;An important property for complex software systems is that they be modular,
where parts can be isolated from the whole. Ghosts, or resources referenced by
plain data, create implicit relationships which must be considered when we add,
remove, change, or understand individual components. They impede modularity,
making complex systems less manageable.&lt;&#x2F;p&gt;
&lt;p&gt;This leads to a design principle for components in complex software systems:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;No Ghosts!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;👻? 🚫!&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Bugs in Hello World</title>
		<published>2022-03-08T00:00:00+00:00</published>
		<updated>2022-03-08T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/bugs-in-hello-world/" type="text/html"/>
		<id>https://blog.sunfishcode.online/bugs-in-hello-world/</id>
		<content type="html">&lt;p&gt;Hello World might be the most frequently written computer program. For decades,
it&#x27;s been the first program many people write, when getting started in a new
programming language.&lt;&#x2F;p&gt;
&lt;p&gt;Surely, this humble starting-point program should be bug free, right?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.monkeyuser.com&#x2F;2019&#x2F;bug-free&#x2F;&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.monkeyuser.com&#x2F;2019&#x2F;bug-free&#x2F;131-bug-free.png&quot; alt=&quot;&amp;quot;Bug Free&amp;quot; comic at monkeyuser.com&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;After all, hello world programs only do one thing. How could there be a bug?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hello-world-in-c&quot;&gt;Hello world in C&lt;&#x2F;h2&gt;
&lt;p&gt;There are a lot of different ways to write hello world in C. There&#x27;s
the &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;%22Hello,_World!%22_program#C&quot;&gt;Wikipedia version&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;riptutorial.com&#x2F;c&#x2F;example&#x2F;3675&#x2F;original--hello--world---in-k-r-c&quot;&gt;the hello world in the K&amp;amp;R book&lt;&#x2F;a&gt;, and there&#x27;s
even &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;%22Hello,_World!%22_program#History&quot;&gt;the oldest known C hello world program from 1974&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a title=&quot;Brian Kernighan, CC BY-SA 3.0 &amp;lt;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by-sa&#x2F;3.0&amp;gt;, via Wikimedia Commons&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Hello_World_Brian_Kernighan_1978.jpg&quot;&gt;&lt;img width=&quot;512&quot; alt=&quot;Hello World Brian Kernighan 1978&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;thumb&#x2F;2&#x2F;21&#x2F;Hello_World_Brian_Kernighan_1978.jpg&#x2F;512px-Hello_World_Brian_Kernighan_1978.jpg&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s another, this one &lt;a href=&quot;http:&#x2F;&#x2F;helloworldcollection.de&#x2F;#C%C2%A0(ANSI)&quot;&gt;in &amp;quot;ANSI C&amp;quot;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* Hello World in C, Ansi-style *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;stdio.h&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;stdlib.h&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;puts&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Hello World!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; EXIT_SUCCESS;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the most careful version of the bunch. It uses &lt;code&gt;(void)&lt;&#x2F;code&gt; to ensure that
&lt;code&gt;main&lt;&#x2F;code&gt; is a new-style declaration. It uses the &lt;code&gt;EXIT_SUCCESS&lt;&#x2F;code&gt; macro instead
of just assuming that the platform uses 0 to indicate success, which isn&#x27;t
necessary, according to the C standard, but we&#x27;re not taking any chances here.
And it uses the appropriate headers to avoid implicitly declaring &lt;code&gt;puts&lt;&#x2F;code&gt;. This
version attempts to do &lt;em&gt;everything&lt;&#x2F;em&gt; right.&lt;&#x2F;p&gt;
&lt;p&gt;And yet, it still has a bug.&lt;&#x2F;p&gt;
&lt;p&gt;All the versions linked above have a bug.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-bug&quot;&gt;A bug?&lt;&#x2F;h2&gt;
&lt;p&gt;Linux has this fun device file called &amp;quot;&#x2F;dev&#x2F;full&amp;quot;, which is like its more
famous cousin &amp;quot;&#x2F;dev&#x2F;null&amp;quot;, but when you write to &amp;quot;&#x2F;dev&#x2F;full&amp;quot;, instead of
throwing away the data, it fails. It acts like a file on a filesystem that
has just run out of space:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; echo &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Hello World!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; &amp;gt; &#x2F;dev&#x2F;full
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;bash:&lt;&#x2F;span&gt;&lt;span&gt; echo: write error: No space left on device
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; echo $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a great little tool for testing that programs handle I&#x2F;O errors
correctly. It&#x27;s inconvenient to create actual filesystems with no
space left, or disks that actually fail, but it&#x27;s really easy to ask a
program to write its output to &amp;quot;&#x2F;dev&#x2F;full&amp;quot; and see what happens.&lt;&#x2F;p&gt;
&lt;p&gt;So let&#x27;s test the C example above:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; gcc hello.c&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -o&lt;&#x2F;span&gt;&lt;span&gt; hello
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; .&#x2F;hello &amp;gt; &#x2F;dev&#x2F;full
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; echo $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Unlike when we used &lt;code&gt;echo&lt;&#x2F;code&gt; in the shell above, here, we got no output, and
the exit status was zero. That means the &lt;code&gt;hello&lt;&#x2F;code&gt; program reported successful
execution. However, it didn&#x27;t actually succeed. We can confirm that it
encounters a failure using &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man1&#x2F;strace.1.html&quot;&gt;strace&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; strace&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -etrace&lt;&#x2F;span&gt;&lt;span&gt;=write .&#x2F;hello &amp;gt; &#x2F;dev&#x2F;full
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(1, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Hello World!\n&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, 13)          = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;-1&lt;&#x2F;span&gt;&lt;span&gt; ENOSPC (No space left on device)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;+++&lt;&#x2F;span&gt;&lt;span&gt; exited with 0 +++
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There&#x27;s our &amp;quot;No space&amp;quot; error getting reported by the OS, but no matter,
the program silently swallows it and returns 0, the code for success. That&#x27;s
a bug!&lt;&#x2F;p&gt;
&lt;p&gt;How severe is this bug? Arguably, hello world isn&#x27;t going to be safety-critical
anywhere. However, hello world does do something that programs in the real
world do: print to standard output, which might be redirected to a file. And
files in the real world can run out of space. If a program doesn&#x27;t detect this
kind of error and report it through its return code, its parent process won&#x27;t
know that the child failed, and will continue running as if nothing was wrong,
even though the output it expected to have been produced has silently lost data.&lt;&#x2F;p&gt;
&lt;p&gt;For example, consider a program that prints a &lt;a href=&quot;https:&#x2F;&#x2F;yaml.org&#x2F;&quot;&gt;yaml&lt;&#x2F;a&gt; file to standard output.
If standard output runs out of space, the output may be truncated at some
arbitrary point, though it &lt;a href=&quot;https:&#x2F;&#x2F;www.sqlservercentral.com&#x2F;editorials&#x2F;do-you-have-all-the-yaml&quot;&gt;may still be valid yaml&lt;&#x2F;a&gt;. So we should expect
programs to detect and report this kind of situation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-about-other-languages&quot;&gt;What about other languages?&lt;&#x2F;h2&gt;
&lt;p&gt;We looked at bash and C above; what about Python, which tells us that
&lt;a href=&quot;https:&#x2F;&#x2F;www.python.org&#x2F;dev&#x2F;peps&#x2F;pep-0020&#x2F;#id2&quot;&gt;&amp;quot;Errors should never pass silently&amp;quot;&lt;&#x2F;a&gt;? Here&#x27;s Python 2:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; python2 hello.py &amp;gt; &#x2F;dev&#x2F;full
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;close&lt;&#x2F;span&gt;&lt;span&gt; failed in file object destructor:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;sys.excepthook&lt;&#x2F;span&gt;&lt;span&gt; is missing
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;lost&lt;&#x2F;span&gt;&lt;span&gt; sys.stderr
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; echo $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It did print a message to stderr, though it&#x27;s a confusing message. However, it
also returned 0, which means it&#x27;s telling whoever ran it that it exited
succeesfully.&lt;&#x2F;p&gt;
&lt;p&gt;Fortunately, Python 3 properly reports the error, and prints a nicer
error message too:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; python3 hello.py &amp;gt; &#x2F;dev&#x2F;full
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Exception&lt;&#x2F;span&gt;&lt;span&gt; ignored in: &amp;lt;_io.TextIOWrapper name=&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&amp;lt;stdout&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39; mode=&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;w&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39; encoding=&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;utf-8&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;OSError: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Errno 28&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt; No space left on device
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; echo $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;120
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using hello world programs from common tutorial sites in a few languages that
I happened to try, here are the results:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Language&lt;&#x2F;th&gt;&lt;th align=&quot;center&quot;&gt;Has the bug&lt;&#x2F;th&gt;&lt;th&gt;Versions tested&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;C&lt;&#x2F;td&gt;&lt;td align=&quot;center&quot;&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;(all)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;C++&lt;&#x2F;td&gt;&lt;td align=&quot;center&quot;&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;(all)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Python 2&lt;&#x2F;td&gt;&lt;td align=&quot;center&quot;&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Python 2.7.18&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Ruby&lt;&#x2F;td&gt;&lt;td align=&quot;center&quot;&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-linux-gnu]&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Java&lt;&#x2F;td&gt;&lt;td align=&quot;center&quot;&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;openjdk 11.0.11 2021-04-20&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Node.js&lt;&#x2F;td&gt;&lt;td align=&quot;center&quot;&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;v12.21.0&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Haskell&lt;&#x2F;td&gt;&lt;td align=&quot;center&quot;&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;The Glorious Glasgow Haskell Compilation System, version 8.8.4&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;td align=&quot;center&quot;&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Rust&lt;&#x2F;td&gt;&lt;td align=&quot;center&quot;&gt;No&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rustc 1.59.0 (9d1b2106e 2022-02-23)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Python 3&lt;&#x2F;td&gt;&lt;td align=&quot;center&quot;&gt;No&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Python 3.9.5&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Perl&lt;&#x2F;td&gt;&lt;td align=&quot;center&quot;&gt;No&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;perl 5, version 32, subversion 1 (v5.32.1) built for x86_64-linux-gnu-thread-multi (with 46 registered patches...)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Perl 6&lt;&#x2F;td&gt;&lt;td align=&quot;center&quot;&gt;No&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;v2020.12&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Bash&lt;&#x2F;td&gt;&lt;td align=&quot;center&quot;&gt;No&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;GNU bash, version 5.1.4(1)-release (x86_64-pc-linux-gnu)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Awk&lt;&#x2F;td&gt;&lt;td align=&quot;center&quot;&gt;No&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;GNU Awk 5.1.0, API: 3.0 (GNU MPFR 4.1.0, GNU MP 6.2.1)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;OCaml&lt;&#x2F;td&gt;&lt;td align=&quot;center&quot;&gt;No&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;4.08.1&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Tcl&lt;&#x2F;td&gt;&lt;td align=&quot;center&quot;&gt;No&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;8.6.11&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;C#&lt;&#x2F;td&gt;&lt;td align=&quot;center&quot;&gt;No&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Mono JIT compiler version 6.8.0.105&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;A more complete and current list is maintained &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;hello-world-vs-io-errors&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Porting Rust&#x27;s std to rustix</title>
		<published>2022-01-04T00:00:00+00:00</published>
		<updated>2022-01-04T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/port-std-to-rustix/" type="text/html"/>
		<id>https://blog.sunfishcode.online/port-std-to-rustix/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;rustix&quot;&gt;Rustix&lt;&#x2F;a&gt; is a system-call wrapper library with multiple backends. It has a raw
Linux syscalls backend, as well as a libc backend, and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&#x2F;rustix&#x2F;tree&#x2F;wasi&#x2F;src&#x2F;imp&#x2F;wasi&quot;&gt;other backends&lt;&#x2F;a&gt; are in
development. Rustix is designed for memory safety, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;blob&#x2F;master&#x2F;text&#x2F;3128-io-safety.md&quot;&gt;I&#x2F;O safety&lt;&#x2F;a&gt;, and
performance.&lt;&#x2F;p&gt;
&lt;p&gt;And &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;rust&#x2F;tree&#x2F;rustix&quot;&gt;&lt;em&gt;this&lt;&#x2F;em&gt;&lt;&#x2F;a&gt; is a branch of Rust&#x27;s std partially ported to use rustix in
place of direct libc calls. Read on for why this is cool, and stay for the
benchmarks!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;factoring-out-unsafe-error-handling-and-raw-pointers&quot;&gt;Factoring out &lt;code&gt;unsafe&lt;&#x2F;code&gt;, error handling, and raw pointers&lt;&#x2F;h2&gt;
&lt;p&gt;The first reason that porting std to rustix is cool is that rustix factors out
a lot of &lt;code&gt;unsafe&lt;&#x2F;code&gt; blocks from std. Talking to the OS still requires &lt;code&gt;unsafe&lt;&#x2F;code&gt;, but
with rustix the &lt;code&gt;unsafe&lt;&#x2F;code&gt; blocks are focused on individual syscalls. That way, the
&lt;code&gt;unsafe&lt;&#x2F;code&gt; blocks that remain in std are the interesting ones, where std itself is
doing something interesting that needs &lt;code&gt;unsafe&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Rustix also provides idiomatic &lt;code&gt;Result&lt;&#x2F;code&gt; error handling for system calls. And
it uses Rust references and slices instead of raw pointers. These make it
easier to read std&#x27;s code and focus on the important semantics of the system
calls, without the distractions of libc API mechanics.&lt;&#x2F;p&gt;
&lt;p&gt;And, rustix simplifies some minor infelicities in syscall APIs related to
C integer type sizes.&lt;&#x2F;p&gt;
&lt;p&gt;Putting these all together in an example, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;rust&#x2F;commit&#x2F;74ec948f644d2a4a63e21587450d271e01f4fb32#diff-a5c25e0262199413ba7e001ae7067353d4b6833039cb1a25ff556b5b0a040f5aL646&quot;&gt;this code&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; len = cmp::min(buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(), &amp;lt;wrlen_t&amp;gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX &lt;&#x2F;span&gt;&lt;span&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;wrlen_t&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; ret = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;cvt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;       c::send(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_raw&lt;&#x2F;span&gt;&lt;span&gt;(), buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_ptr&lt;&#x2F;span&gt;&lt;span&gt;() as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const c_void&lt;&#x2F;span&gt;&lt;span&gt;, len, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MSG_NOSIGNAL&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;   })?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;becomes &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;rust&#x2F;commit&#x2F;74ec948f644d2a4a63e21587450d271e01f4fb32#diff-a5c25e0262199413ba7e001ae7067353d4b6833039cb1a25ff556b5b0a040f5aR647&quot;&gt;this&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; ret = rustix::net::send(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner, buf, SendFlags::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;NOSIGNAL&lt;&#x2F;span&gt;&lt;span&gt;)?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This puts the focus on the &lt;code&gt;send&lt;&#x2F;code&gt; operation, without the distractions of
&lt;code&gt;unsafe&lt;&#x2F;code&gt;, raw pointers, &lt;code&gt;wrlen_t&lt;&#x2F;code&gt; types, and &lt;code&gt;cvt&lt;&#x2F;code&gt; error handling.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-path-to-a-rust-on-linux-without-libc&quot;&gt;A path to a Rust on Linux without libc&lt;&#x2F;h2&gt;
&lt;p&gt;A second reason this is cool is that it&#x27;s a step towards a Rust toolchain
on Linux that doesn&#x27;t depend on libc.&lt;&#x2F;p&gt;
&lt;p&gt;Rustix is able to make direct Linux syscalls from Rust code. And &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;tree&#x2F;main&#x2F;origin#origin&quot;&gt;origin&lt;&#x2F;a&gt; is a
Rust library which is able to startup and shutdown processes and threads
(comparable to crt1.o and libpthread).&lt;&#x2F;p&gt;
&lt;p&gt;With these, we have all the things needed to run Rust programs on Linux. And
it turns out there are two different ways to do this. The first way is &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;rust-programs-entirely-in-rust&#x2F;&quot;&gt;mustang&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Mustang is uses a library called &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;tree&#x2F;main&#x2F;c-scape#c-scape&quot;&gt;c-scape&lt;&#x2F;a&gt;, which wraps rustix with libc-compatible
APIs, allowing std to use rustix without modifications, including
&lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;implementing-threads&#x2F;&quot;&gt;threading support&lt;&#x2F;a&gt;. This has gotten a lot of functionality up and running;
mustang can run a lot of real-world code now. And mustang helps test rustix and
origin. And beyond that, the c-scape libc compatibility layer has several additional
uses. But, mustang in its currrent form looks like it would be awkward to upstream
into Rust.&lt;&#x2F;p&gt;
&lt;p&gt;Fortunately, mustang&#x27;s architecture of keeping c-scape as a separate layer on top
of rustix and origin, with rustix and origin providing idiomatic Rust APIs, means
that another way is possible as well. This blog post is about starting to port std
to rustix directly. In addition to not using libc code, this path doesn&#x27;t use libc
APIs either.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;performance&quot;&gt;Performance&lt;&#x2F;h2&gt;
&lt;p&gt;And another reason this is cool is that rustix-enabled std also brings several
modest speedups, compared to std in upstream Rust. On machines I&#x27;ve tested it on:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;std::fs::metadata&lt;&#x2F;code&gt; is about 3% faster&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;std::fs::File::open&lt;&#x2F;code&gt; is about 5% faster&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;std::fs::read_to_string&lt;&#x2F;code&gt; is about 3% faster &lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;std::time::Instant::now&lt;&#x2F;code&gt; ranges from 1% to 10% faster on Linux&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;See &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;rustix-bench&quot;&gt;the benchmark source code&lt;&#x2F;a&gt; to see what&#x27;s being measured.&lt;&#x2F;p&gt;
&lt;p&gt;Rustix makes &lt;code&gt;metadata&lt;&#x2F;code&gt;, &lt;code&gt;open&lt;&#x2F;code&gt;, and other filesystem path operations faster by
avoiding a dynamic allocation when converting from Rust strings into
NUL-terminated C strings. Rustix uses stack-allocated memory for strings up
to a reasonable size, which is much faster.&lt;&#x2F;p&gt;
&lt;p&gt;Rustix makes &lt;code&gt;Instant::new&lt;&#x2F;code&gt; faster on Linux by simplifying error handling,
since we know that reading the system monotonic clock never fails (and as in
current std, it still does panic if a failure ever does occur).&lt;&#x2F;p&gt;
&lt;p&gt;And rustix contains a number of other optimizations, such as using inline
system calls and avoiding the TLS &lt;code&gt;errno&lt;&#x2F;code&gt; variable on Linux, but so far
benchmarks confirm the common wisdom that these aren&#x27;t usually very
significant compared to the cost of the actual syscalls.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;looking-forward&quot;&gt;Looking forward&lt;&#x2F;h2&gt;
&lt;p&gt;A goal for this port of std to rustix is to eventually propose it to be merged
into upstream Rust. I&#x27;m hoping this blog post will start some conversations
about what this should eventually look like.&lt;&#x2F;p&gt;
&lt;p&gt;With rustix&#x27;s libc backend, std can continue to support all the libc-using
platforms that Rust currently supports. And with either backend, rustix brings
the advantages of factoring out &lt;code&gt;unsafe&lt;&#x2F;code&gt;, error handling, and raw pointers,
and its optimizations for converting to C-style strings.&lt;&#x2F;p&gt;
&lt;p&gt;This project promotes several other goals as well, such as promoting
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;blob&#x2F;master&#x2F;text&#x2F;3128-io-safety.md&quot;&gt;I&#x2F;O safety&lt;&#x2F;a&gt; concepts and APIs, helping test some of the infrastructure used
by &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&#x2F;cap-std&quot;&gt;cap-std&lt;&#x2F;a&gt;, and helping set the stage for future projects related to
sandboxing, WASI, &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;nameless&quot;&gt;nameless&lt;&#x2F;a&gt;, and other areas.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;thanks&quot;&gt;Thanks!&lt;&#x2F;h2&gt;
&lt;p&gt;Thanks to @nivkner for implementing support for child processes, to
@Urgau for adding arm support and implementing several features in rustix,
@cole-miller for implementing &lt;code&gt;getcwd&lt;&#x2F;code&gt; and &lt;code&gt;chdir&lt;&#x2F;code&gt; in mustang, and @jplatte
and @ratmice and others for contributing useful patches, and @tshepang in
particular for bringing up &lt;code&gt;ripgrep&lt;&#x2F;code&gt; as a testcase (and it &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;issues&#x2F;22#issuecomment-964653423&quot;&gt;almost works&lt;&#x2F;a&gt;
now!).&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Context Brainstorming</title>
		<published>2021-12-23T00:00:00+00:00</published>
		<updated>2021-12-23T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/context-brainstorming/" type="text/html"/>
		<id>https://blog.sunfishcode.online/context-brainstorming/</id>
		<content type="html">&lt;p&gt;This is a blog post brainstorming about &lt;a href=&quot;https:&#x2F;&#x2F;tmandry.gitlab.io&#x2F;blog&#x2F;posts&#x2F;2021-12-21-context-capabilities&#x2F;&quot;&gt;contexts&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ll us the term &lt;em&gt;contexts&lt;&#x2F;em&gt; here, as &lt;a href=&quot;https:&#x2F;&#x2F;internals.rust-lang.org&#x2F;t&#x2F;blog-post-contexts-and-capabilities-in-rust&#x2F;15833&#x2F;28&quot;&gt;tmandry is leaning to&lt;&#x2F;a&gt;, since it seems to
make sense to keep capabilities distinct concepts. Idiomatic capability-based
code and the Principle of Least Authority prefer &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;the-spectrum-from-namespaces-to-values&#x2F;&quot;&gt;fine-grained access to resources&lt;&#x2F;a&gt;,
which contexts don&#x27;t seem like a good fit for. So let&#x27;s keep these concepts distinct
for now.&lt;&#x2F;p&gt;
&lt;p&gt;yoshuawuyts showed me there is way we might use something like contexts to
retrofit an awareness of ambient authority into Rust. Here&#x27;s an attempt to sketch
up more of what that might look like.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;automatic-contexts&quot;&gt;Automatic contexts&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s extend the contexts proposal with a concept of &lt;em&gt;automatic&lt;&#x2F;em&gt; contexts, that
functions would implement by default. Just like how Rust has automatic trait impls.
Like automatic trait impls, you can opt out, with negative with-declarations,
using &lt;code&gt;!&lt;&#x2F;code&gt; syntax.&lt;&#x2F;p&gt;
&lt;p&gt;And let&#x27;s introduce the concept of supercontexts, which are contexts that imply
other contexts. Much like supertraits in Rust. This isn&#x27;t strictly necessary,
but it helps with granularity.&lt;&#x2F;p&gt;
&lt;p&gt;With those, and the observation that contexts are a way of &lt;a href=&quot;https:&#x2F;&#x2F;jam1.re&#x2F;blog&#x2F;thoughts-on-contexts-and-capabilities-in-rust&quot;&gt;coloring functions&lt;&#x2F;a&gt;,
let&#x27;s introduce some hypothetical automatic contexts:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;global_allocator&lt;&#x2F;code&gt;, the ability to use the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;alloc&#x2F;index.html#the-global_allocator-attribute&quot;&gt;Rust global allocator&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ambient_authority&lt;&#x2F;code&gt;. Similar to &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;ambient-authority&#x2F;latest&#x2F;ambient_authority&#x2F;struct.AmbientAuthority.html&quot;&gt;this &lt;code&gt;AmbientAuthority&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, but
as a context, so it can be more. This would be a supercontext which includes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;fs&lt;&#x2F;code&gt; - the current process&#x27; filesystem namespace&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;net&lt;&#x2F;code&gt; - the current process&#x27; network namespace&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;time&lt;&#x2F;code&gt; - the current process&#x27; time namespace. Preventing code from
observing time entirely is hard, especially if there can be multiple
threads, so maybe this &lt;code&gt;time&lt;&#x2F;code&gt; would just be about the explicit time
APIs rather than blocking all potential time sources.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;stdio&lt;&#x2F;code&gt; - access to the ambient stdin, stdout, and stderr&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;process&lt;&#x2F;code&gt; - the ability to spawn arbitrary child processes&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;mutable_static&lt;&#x2F;code&gt; - write to &lt;em&gt;or&lt;&#x2F;em&gt; read from statically-allocated mutable
&lt;em&gt;and&lt;&#x2F;em&gt; interior-mutable state in the process. There are use cases where
statically-allocated state is useful, but since we have contexts here, for
maximal modularity, these cases should ideally use contexts instead of
implicitly associating state with the whole process.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;and others. OS&#x27;s attach a lot of miscellaneous authorities to processes.
Ideally we&#x27;d make sure we have everything covered.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These being automatic is kind of a way to retroactively reinterpret existing
Rust code. All code now defaults to having these contexts, and we can then
opt out of them, like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;useless&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;with
&lt;&#x2F;span&gt;&lt;span&gt;    !ambient_authority 
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, we can know immediately that this &lt;code&gt;useless&lt;&#x2F;code&gt; is a useless function just by looking
at its signature. It has no return value, no arguments, no ambient authority. All
it could do is return, panic, or infloop.&lt;&#x2F;p&gt;
&lt;p&gt;Panic could unwind, and it&#x27;d be nice to add a context for that too:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;unwind&lt;&#x2F;code&gt; - the ability to unwind the stack&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;then &lt;code&gt;!unwind&lt;&#x2F;code&gt; could be used for functions that can&#x27;t unwind. Maybe this
could even be connected to &lt;a href=&quot;https:&#x2F;&#x2F;llvm.org&#x2F;docs&#x2F;LangRef.html#function-attributes&quot;&gt;LLVM&#x27;s &lt;code&gt;nounwind&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Anyway, with &lt;code&gt;!unwind&lt;&#x2F;code&gt;, we could
write code like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;totally_pure&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;A) -&amp;gt; B
&lt;&#x2F;span&gt;&lt;span&gt;with
&lt;&#x2F;span&gt;&lt;span&gt;    !ambient_authority +
&lt;&#x2F;span&gt;&lt;span&gt;    !unwind
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; lots of interesting stuff
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I think someone told me once that the Rust compiler can know whether
types have interior mutability. Let&#x27;s assume it can, and that this includes
&lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;first-class-io&#x2F;&quot;&gt;types that hold I&#x2F;O handles&lt;&#x2F;a&gt;. In theory, if &lt;code&gt;A&lt;&#x2F;code&gt; here has no interior mutability,
this should allow Rust to annotate functions like this with optimizer attributes
like &lt;a href=&quot;https:&#x2F;&#x2F;llvm.org&#x2F;docs&#x2F;LangRef.html#function-attributes&quot;&gt;LLVM&#x27;s &lt;code&gt;readonly&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, meaning calls to it could be redundant-code-eliminated.&lt;&#x2F;p&gt;
&lt;p&gt;Beyond just LLVM though, this could enable MIR-level redundant-code elimination
of calls, even pre-monomorphization. No need to do complex alias analysis or
escape analysis, because the type system just tells you what you need to know
up front!&lt;&#x2F;p&gt;
&lt;p&gt;But it wouldn&#x27;t get dead-code elimination, because of the possibility of
inflooping. More on that later.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pure-except-where-indicated-otherwise&quot;&gt;Pure, except where indicated otherwise&lt;&#x2F;h3&gt;
&lt;p&gt;By the way, if one of the arguments has a type that does have an I&#x2F;O handle,
including a filesystem handle, then the function can always do I&#x2F;O. The &lt;code&gt;fs&lt;&#x2F;code&gt;
context is about the process&#x27; filesystem namespace. So with
&lt;code&gt;!fs&lt;&#x2F;code&gt;, you can&#x27;t do &lt;code&gt;File::open&lt;&#x2F;code&gt;, but you can use a &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;cap-std&#x2F;latest&#x2F;cap_std&#x2F;fs&#x2F;struct.Dir.html&quot;&gt;&lt;code&gt;Dir&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; you&#x27;ve been given
as an argument to do &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;cap-std&#x2F;latest&#x2F;cap_std&#x2F;fs&#x2F;struct.Dir.html#method.open&quot;&gt;&lt;code&gt;Dir::open&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, because it&#x27;s resolved relative to a directory
you have an explicit handle to, rather than the process&#x27; filesystem namespace.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly, passing a &lt;code&gt;&amp;amp;mut&lt;&#x2F;code&gt; reference into a function marked this way requires
no special ceremony. Unlike &amp;quot;pure&amp;quot; keywords in languages where purity is all
or nothing, the rule here is, if the signature has a &lt;code&gt;&amp;amp;mut&lt;&#x2F;code&gt;, the callee can
access it as a &lt;code&gt;&amp;amp;mut&lt;&#x2F;code&gt;, including mutating it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;pure_except_as_obvious&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;A, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;m&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; M, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;File) -&amp;gt; B
&lt;&#x2F;span&gt;&lt;span&gt;with
&lt;&#x2F;span&gt;&lt;span&gt;    !ambient_authority +
&lt;&#x2F;span&gt;&lt;span&gt;    !unwind
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; lots of interesting stuff, including mutating `*m` and writing to `*f`.
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;See &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;first-class-io&#x2F;&quot;&gt;First-class I&#x2F;O&lt;&#x2F;a&gt; for more discussion of this.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;security&quot;&gt;Security&lt;&#x2F;h2&gt;
&lt;p&gt;It may be surprising that that I haven&#x27;t talked about security in this post yet. It
turns out that capability-based security really is just a special case of a
deeper capability-based design philosophy. It&#x27;s similar to how Rust&#x27;s borrow
checker is, on its face, a memory-management strategy, but also much deeper,
with things to say about such seemingly unrelated areas as thread safety, pointer
aliasing, iterator invalidation, and refactoring. There&#x27;s a lot going on here.&lt;&#x2F;p&gt;
&lt;p&gt;It also turns out that security for untrusted or compromised-supply-chain
code is complex. For example, if we want to completely sandbox a piece of Rust
code with language mechanisms, we need to make sure it can&#x27;t use &lt;code&gt;unsafe&lt;&#x2F;code&gt; blocks,
since unsafe Rust could trivially escape any sandbox. Security exploits are ok
relying on UB if it works with enough probability in practice.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;getting-closer-unsafe&quot;&gt;Getting closer: unsafe&lt;&#x2F;h3&gt;
&lt;p&gt;This post is all about contexts though, so let&#x27;s see if we can use them to fix
that problem too:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new_unsafe&lt;&#x2F;code&gt; - an automatic context representing the ability to introduce
new unsafe contexts. This corresponds to the ability to write &lt;code&gt;unsafe { ... }&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;unsafe&lt;&#x2F;code&gt; - a retroactive reinterpretation of what &lt;code&gt;unsafe fn&lt;&#x2F;code&gt; desugars to.
Includes &lt;code&gt;new_unsafe&lt;&#x2F;code&gt; as a subcontext, or doesn&#x27;t, depending on how
&lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rfcs&#x2F;2585-unsafe-block-in-unsafe-fn.html&quot;&gt;unsafe blocks in unsafe functions&lt;&#x2F;a&gt; goes.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;As an aside, contexts would also be a path for libraries to define unsafe-like
concepts for their own invariants, which is something I occasionally see people
asking for in Rust.&lt;&#x2F;p&gt;
&lt;p&gt;With &lt;code&gt;new_unsafe&lt;&#x2F;code&gt;, we could write:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;untrusted_code&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;X, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;y&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; Y) -&amp;gt; Z
&lt;&#x2F;span&gt;&lt;span&gt;with
&lt;&#x2F;span&gt;&lt;span&gt;    !ambient_authority +
&lt;&#x2F;span&gt;&lt;span&gt;    !new_unsafe
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; untrusted code here?
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Would this be a secure sandbox? Not yet; one problem is that even if we
know &lt;code&gt;X&lt;&#x2F;code&gt; has no interior mutability or I&#x2F;O handles, this code still
exposes the &lt;em&gt;address&lt;&#x2F;em&gt; of &lt;code&gt;x&lt;&#x2F;code&gt; or &lt;code&gt;y&lt;&#x2F;code&gt; to untrusted code, because converting a
reference to a raw pointer doesn&#x27;t require &lt;code&gt;unsafe&lt;&#x2F;code&gt; in Rust. The address
might tell an attacker something about the &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Address_space_layout_randomization&quot;&gt;ASLR&lt;&#x2F;a&gt; in the process, which
might make other attacks more powerful.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;still-getting-closer-raw-pointers&quot;&gt;Still getting closer: raw pointers&lt;&#x2F;h3&gt;
&lt;p&gt;When all you&#x27;re doing is writing a blog post about contexts, everything
looks like a problem to be solved by adding a new automatic context.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;raw_pointers&lt;&#x2F;code&gt; - the ability to convert references into raw pointers.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In addition to solving this ALSR problem, this attribute has some
interesting possibilities. It&#x27;s awkward how Rust allows APIs with reference
arguments to observe whether two references have the same address, when
this usually isn&#x27;t part of the conceptual API. &lt;code&gt;!raw_pointers&lt;&#x2F;code&gt; would be
a way to declare that a function doesn&#x27;t do that.&lt;&#x2F;p&gt;
&lt;p&gt;Further, with &lt;code&gt;!raw_pointers&lt;&#x2F;code&gt;, it&#x27;d be possible to have Rust code that
doesn&#x27;t depend on a byte-addressed address space. There&#x27;d be no alignment or
endianness visible. Objects could be moved at any time, just like in a
moving GC. Threads could be migrated to different stacks. This might even
open up a path to Rust being able to use Wasm reference types, which Rust
can&#x27;t otherwise hold directly since they&#x27;re opaque and can&#x27;t have their
representation exposed.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;are-we-secure-yet&quot;&gt;Are we secure yet?&lt;&#x2F;h3&gt;
&lt;p&gt;No. But, to keep this blog post scoped, let&#x27;s ignore side-channel attacks like
Spectre, hardware attacks like Rowhammer, crypto miners, and denial-of-service
attacks. And let&#x27;s ignore attacks which change the behavior of the code without
breaking the sandbox, such as changing an encryption implementation to emit
syntactically valid but insecure data. That&#x27;s a lot to ignore in reality, but
the solutions to those would require radically different mechanisms, so let&#x27;s
put those aside for now.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ok-now-are-we-done-yet&quot;&gt;Ok, &lt;em&gt;now&lt;&#x2F;em&gt; are we done yet?&lt;&#x2F;h3&gt;
&lt;p&gt;What about global variables? We included &lt;code&gt;mutate_static&lt;&#x2F;code&gt; in &lt;code&gt;ambient_authority&lt;&#x2F;code&gt;
above, so they won&#x27;t be mutated, but is it a problem if the untrusted code
reads any of the program&#x27;s global immutable state? Could it find authentication
secrets? To answer this, we&#x27;d need to start getting more specific about the
threat model. But to keep things simple, let&#x27;s say the program doesn&#x27;t have
anything sensitive in immutable global state. It&#x27;s best to keep sensitive
things like authorization credentials as scoped as possible in general anyway.&lt;&#x2F;p&gt;
&lt;p&gt;Along those lines, what about &lt;code&gt;std::env::vars&lt;&#x2F;code&gt;, &lt;code&gt;std::env::args&lt;&#x2F;code&gt;, &lt;code&gt;std::env::home_dir&lt;&#x2F;code&gt;
and others? They might contain sensitive information, or even just your username.
Let&#x27;s say these are disallowed by &lt;code&gt;!mutable_static&lt;&#x2F;code&gt; by virtue of being mutable
through libc APIs. Or, if needed, we could also add a new context to cover these.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;will-it-ever-stop&quot;&gt;Will it ever stop&lt;&#x2F;h3&gt;
&lt;p&gt;This is just a brainstorming post, and it&#x27;s possible things are missing, but
it&#x27;s likely any such things can be covered by adding more contexts. For the sake
of making a finite blog post, let&#x27;s assume we can cover everything.&lt;&#x2F;p&gt;
&lt;p&gt;So can we say then, that we now, assuming all of our assumptions, &lt;em&gt;finally&lt;&#x2F;em&gt; have
a secure hypothetical sandbox here?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;untrusted_code&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;X) -&amp;gt; Y
&lt;&#x2F;span&gt;&lt;span&gt;with
&lt;&#x2F;span&gt;&lt;span&gt;    !ambient_authority +
&lt;&#x2F;span&gt;&lt;span&gt;    !new_unsafe +
&lt;&#x2F;span&gt;&lt;span&gt;    !raw_pointers
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; untrusted code here!
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Yes.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;beat&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In theory.&lt;&#x2F;p&gt;
&lt;p&gt;In practice, the Rust compiler isn&#x27;t currently designed or intended to be used
as a security surface in this way. And it&#x27;s not necessarily worth it for it to
try to be one. There&#x27;d be work involved, and for this to actually make sense,
we&#x27;d need to look at real-world use cases and attack vectors, and we wouldn&#x27;t
be able to ignore any of the things we ignored above.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;capability-based-programming&quot;&gt;Capability-based programming&lt;&#x2F;h2&gt;
&lt;p&gt;However, even if we don&#x27;t look to &lt;code&gt;!ambient_authority&lt;&#x2F;code&gt; to be the basis of an
actual sandbox, and even if the performance impacts of the aliasing, escaping,
and side effect knowledge isn&#x27;t compelling, this overall technique might still
be useful.&lt;&#x2F;p&gt;
&lt;p&gt;For people reviewing code, &lt;code&gt;!ambient_authority&lt;&#x2F;code&gt; could reduce the
&lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2017&#x2F;03&#x2F;02&#x2F;lang-ergonomics.html&quot;&gt;reasoning footprint&lt;&#x2F;a&gt;, because they&#x27;d be able to make more local assumptions
about the side effects of calling functions.&lt;&#x2F;p&gt;
&lt;p&gt;And for people building large complex applications, it could give them more
tools to help ensure that two parts of the application don&#x27;t have unintended
interactions, as explored &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;the-spectrum-from-namespaces-to-values&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And for people building &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;component-model&quot;&gt;wasm components&lt;&#x2F;a&gt;, it could give them more tools to
ensure that they&#x27;re only using APIs which compose cleanly with other
components.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;potential-downsides&quot;&gt;Potential downsides&lt;&#x2F;h2&gt;
&lt;p&gt;With all these colors, and with users having the ability to define their
own colors, we could end up with a lot of colors.&lt;&#x2F;p&gt;
&lt;p&gt;Will having an ecosystem where everyone can use all these colors to enforce
their requirements with extraordinary precision increase or decrease overall
usability of Rust? Will it lead programmers to waste time pursuing every
possible dimension of theoretical purity, regardless of what really matters
in practice?&lt;&#x2F;p&gt;
&lt;p&gt;Will these new colors and automatic contexts prompt new rounds of users
going through all their dependencies and insisting that they support new
colors? If so, will it cause ecosystem churn and&#x2F;or awkward workarounds,
or even ecosystem fragmentation, like &lt;code&gt;#![no_std]&lt;&#x2F;code&gt; sometimes does, and is
that worth it?&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t know.&lt;&#x2F;p&gt;
&lt;p&gt;What I do know is, in a vacuum, it sure is fun to think up new colors.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tangent-pretty-colors&quot;&gt;Tangent: Pretty colors&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s think about one more possible context, for fun:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;turing_complete&lt;&#x2F;code&gt; - the ability to have loops (or tail
recursion, if Rust adds that), that can&#x27;t be proved to terminate.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The halting problem gets talked about a lot. However, how often does one
actually write &lt;code&gt;loop&lt;&#x2F;code&gt;, as opposed to just using &lt;code&gt;for&lt;&#x2F;code&gt;? If we also had a way
to assert that iterator implementations don&#x27;t repeat themselves, a lot of
real-world code might be able to be compatible with &lt;code&gt;!turing_complete&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;One of the tricky issues for iterators would be linked lists, which would need
to be guaranteed to be acyclic. But it&#x27;s interesting to note that in Rust,
creating a circularly linked list actually requires &lt;code&gt;unsafe&lt;&#x2F;code&gt; anyway. So maybe
there&#x27;s something we could do here.&lt;&#x2F;p&gt;
&lt;p&gt;This would also address the &amp;quot;or infloop&amp;quot; case mentioned above, so we could
also get dead-code-elimination of calls.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>The Spectrum from Namespaces to Values</title>
		<published>2021-12-22T00:00:00+00:00</published>
		<updated>2021-12-22T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/the-spectrum-from-namespaces-to-values/" type="text/html"/>
		<id>https://blog.sunfishcode.online/the-spectrum-from-namespaces-to-values/</id>
		<content type="html">&lt;p&gt;In order to make large applications modular, we need to think about
resources and sharing. One axis for thinking about this is the spectrum
of granularity. It&#x27;s a spectrum, but we can identify several notable
levels:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Level 0: &lt;code&gt;File::open&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Level 1: &lt;code&gt;with root: &amp;amp;Dir&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Level 2: &lt;code&gt;dir.open&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Level 3: &lt;code&gt;thing: &amp;amp;File&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Level 4: &lt;code&gt;thing: &amp;amp;StreamReader&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This post describes each of these levels and considers the impact on
application modularity of moving up through each of the levels.&lt;&#x2F;p&gt;
&lt;p&gt;As a caveat, in this post, I&#x27;ll be discussing &lt;em&gt;trusted&lt;&#x2F;em&gt; code. It&#x27;s about
modularity and flexibility. Specifically, I&#x27;m ignoring the concerns of
&lt;em&gt;untrusted&lt;&#x2F;em&gt; code here. If there&#x27;s code in the system which is actively
attempting to break out, it requires additional mechanisms to securely
contain it. The concepts discussed here can be used as part of a sandbox
for untrusted code, but a proper sandbox involves many additional concerns
that I&#x27;m not covering here.&lt;&#x2F;p&gt;
&lt;p&gt;Usually when someone writes a post about capabilities and the Principle
of Least Authority, they&#x27;re talking about security. However, this post
is about how these concepts are relevant to programming in the large
in general.&lt;&#x2F;p&gt;
&lt;p&gt;With that in mind, let&#x27;s start at the bottom and work our way up :-).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;level-0-file-open&quot;&gt;Level 0: &lt;code&gt;File::open&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Level 0 is how most application code today uses filesystems:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; thing = File::open(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;path&#x2F;to&#x2F;some&#x2F;dir&#x2F;thing&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There&#x27;s a filesystem namespace implicitly associated with the program, and
filesystem paths are resolved in it. Lots of code works this way to day, and
it works. But, traditional OS isolation mechanisms are not sufficient for many
popular use cases today, so many use cases end up using &lt;em&gt;containers&lt;&#x2F;em&gt;. A
container provides a little world for an application to run in, where it can
pretend it&#x27;s running on a &amp;quot;normal computer&amp;quot; built specifically for it.&lt;&#x2F;p&gt;
&lt;p&gt;However, containers are coarse-grained. One typically needs to run an entire
application within the same container. Or if applications are split into
parts that run in different containers, the parts usually need to communicate
over invasive RPC mechanisms. By climbing up to the next level of granularity,
we can gain more options.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;level-1-with-root-dir&quot;&gt;Level 1: &lt;code&gt;with root: &amp;amp;Dir&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Using a mechanism such as cap-std&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;cap-std&#x2F;latest&#x2F;cap_std&#x2F;fs&#x2F;struct.Dir.html&quot;&gt;&lt;code&gt;Dir&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; type, we could arrange to pass
in a &amp;quot;root filesystem&amp;quot; as a parameter rather than using a namespace implicitly
attached to the program:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;root&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;Dir) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; thing = dir.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;path&#x2F;to&#x2F;some&#x2F;dir&#x2F;thing&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And if we write a lot of code like that, we might find a recent blog post
about &lt;a href=&quot;https:&#x2F;&#x2F;tmandry.gitlab.io&#x2F;blog&#x2F;posts&#x2F;2021-12-21-context-capabilities&#x2F;&quot;&gt;context capabilities&lt;&#x2F;a&gt; useful. That would allow us to write the above
code like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;with
&lt;&#x2F;span&gt;&lt;span&gt;    root: &amp;amp;Dir
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; thing = File::open(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;path&#x2F;to&#x2F;some&#x2F;dir&#x2F;thing&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Unlike the standard-library &lt;code&gt;File::open&lt;&#x2F;code&gt;, this would use a &lt;code&gt;File::open&lt;&#x2F;code&gt; that
also uses context capabilities, so it would also have a &lt;code&gt;with root: &amp;amp;Dir&lt;&#x2F;code&gt;, and
it&#x27;d automatically get passed the root in which to resolve the path.&lt;&#x2F;p&gt;
&lt;p&gt;This approach has the appealing property that the body of the code is the exact
same as it is in level 0. It would be easy to convert existing code to use this
style, because it just requires changes at the high-level scopes.&lt;&#x2F;p&gt;
&lt;p&gt;Going from 0 to 1 means that an application could have the ability to create
little dedicated filesystem worlds, and run parts of itself in these little
worlds, with each part having its own root filesystem. It wouldn&#x27;t have to
completely split into multiple containers.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s a step up. However, creating dedicated filesystems is still complex and
potentially inefficient. How do we know what those little worlds need to
contain?  It requires us to know the set of strings that the code might
dynamically pass to an &lt;code&gt;open&lt;&#x2F;code&gt; function. Sometimes we can get a pretty good idea
of code code needs by studying it. And sometimes we resort to running code and
just dynamically recording what things it needs.&lt;&#x2F;p&gt;
&lt;p&gt;And, if two parts of an application want to communicate, we still have to figure
out if they need to run in the same little world, or if they can run in different
worlds. And if they are in the same world, to share data through it, we then need
to somehow make sure they don&#x27;t collide in unintended ways in other parts of
their shared filesystem, such as needing different versions of a dependency
installed at the same path.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;level-2-dir-open&quot;&gt;Level 2: &lt;code&gt;dir.open&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The next step up is to break up the monolithic &amp;quot;world&amp;quot; into more fine-grained
handles. cap-std&#x27;s &lt;code&gt;Dir&lt;&#x2F;code&gt; type makes it easy to have first-class directory
handles, so we can just pass those around.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;dir&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;Dir) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; thing = dir.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;thing&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We could use the above-mentioned context capabilities for these. However that
syntax is less valuable once we start getting more fine-grained, as we do here
at level 2. When we&#x27;re talking about a whole filesystem, it&#x27;s common for code
to want to treat it like an ambiently present resource, and context capabilities
approximate that. But once we can talk about specific directories, it&#x27;s more
natural for code to be aware of the specific directories it needs, and take those
directories as explicit parameters. It&#x27;s no longer about &amp;quot;here&#x27;s a world to
operate in&amp;quot;, it&#x27;s about &amp;quot;here&#x27;s the directory you asked for&amp;quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Passing individual directories is a step up from level 1. With this, when
an application is split into parts, we don&#x27;t need to create whole filesystem
views for each part. We just need to give each part its own &lt;code&gt;dir&lt;&#x2F;code&gt; directory.
And if they do need to share, they just share those directories, and we don&#x27;t
have to worry about them colliding in other areas of their filesystems.&lt;&#x2F;p&gt;
&lt;p&gt;But if the only thing &lt;code&gt;foo&lt;&#x2F;code&gt; needs is one file in that directory, passing
it a whole directory is still more complex than we need. How can we know when
two parts of an application need to share a directory? As above, the only way
to know how they interact is to look at the set of strings they dynamically
pass into &lt;code&gt;open&lt;&#x2F;code&gt; functions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;level-3-thing-file&quot;&gt;Level 3: &lt;code&gt;thing: &amp;amp;File&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;If &lt;code&gt;foo&lt;&#x2F;code&gt; just needs a single file, it can be passed just that file:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;thing&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;File) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ...
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This way, an application can be split into parts, and the parts can freely
operate on different files. The application doesn&#x27;t need to worry about
whether it needs to separate those files into separate directories. Even if
the files all live in the same directory, the parts of an application
accessing individual files won&#x27;t collide, because they only have their
&lt;code&gt;&amp;amp;File&lt;&#x2F;code&gt;, not the whole directory.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;level-4-thing-streamreader&quot;&gt;Level 4: &lt;code&gt;thing: &amp;amp;StreamReader&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The next level up is to observe that most applications don&#x27;t need an actual
&lt;code&gt;File&lt;&#x2F;code&gt; as such. Even though Unix told us that &amp;quot;everything is a file&amp;quot;, pipes
and sockets aren&#x27;t really files, in that they don&#x27;t always have filenames, and
don&#x27;t support all of the &lt;code&gt;File&lt;&#x2F;code&gt; operations. However, in a lot of use cases,
applications would ultimately be ok reading from a pipe or a socket just as
well as an actual file. In some cases, we may want them to simply read data
from a buffer in memory. The thing that most application code needs is
just a source of data to read from.&lt;&#x2F;p&gt;
&lt;p&gt;This could be &lt;code&gt;impl Read&lt;&#x2F;code&gt;, &lt;code&gt;Box&amp;lt;Read&amp;gt;&lt;&#x2F;code&gt;, or the io-stream crate&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-streams&#x2F;latest&#x2F;io_streams&#x2F;struct.StreamReader.html&quot;&gt;&lt;code&gt;StreamReader&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
Or the async versions of any of those. But that&#x27;s getting into the mechanics
of how the I&#x2F;O is done. It&#x27;s an interesting topic, but not the focus of this post.&lt;&#x2F;p&gt;
&lt;p&gt;The important part for this blog post is that level 4 is where we reduce a piece
of code&#x27;s requirements down to just an input stream, so it can be connected to
other pieces of code without having to think about what other resources
that might cause them to implicitly share. Input streams can be streamed
across networks. They can be buffered, or stored and replayed. If we can write
code that works in terms of streams instead of files, we have a lot of flexibility,
because we don&#x27;t need to worry about the code implicitly depending on file-specific
semantics.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;and-beyond&quot;&gt;And beyond&lt;&#x2F;h2&gt;
&lt;p&gt;The next step up from byte streams would be typed streams, iterators, or
generators. A big sequence of &lt;code&gt;u8&lt;&#x2F;code&gt;s requires the producers and consumers of
the data to have some implicit agreement about how the bytes are interpreted.
An API providing a sequence of values of some type &lt;code&gt;T&lt;&#x2F;code&gt; would allow producers
and consumers to be self-describing. The mechanics of these APIs are another
interesting topic, and also not the focus of this post :-).&lt;&#x2F;p&gt;
&lt;p&gt;The focus is that once we have an abstraction level where bodies of code can
communicate typed values, these bodies of code can communicate precisely what
they need, without incompatibilities among things they implicitly share.&lt;&#x2F;p&gt;
&lt;p&gt;At each step up, we got closer to &amp;quot;what does the code actually need?&amp;quot;, and
found ways to give it what it needed, while reducing the amount it implicitly
shares with other parts. This reduced the potential for conflicts with other
code, and simplified the task of breaking up applications into parts.&lt;&#x2F;p&gt;
&lt;p&gt;An analogous concept in computing is &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;False_sharing&quot;&gt;false sharing&lt;&#x2F;a&gt;, except here, instead of
performance and sharing parts of cache lines that we don&#x27;t need, it&#x27;s about
modularity and sharing parts of monolithic resources that we don&#x27;t need.&lt;&#x2F;p&gt;
&lt;p&gt;By applying the Principle of Least Authority, and passing around fine-grained
resources to code that advertises specific needs, we improve modularity.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Thread support in Mustang</title>
		<published>2021-10-14T00:00:00+00:00</published>
		<updated>2021-10-14T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/implementing-threads/" type="text/html"/>
		<id>https://blog.sunfishcode.online/implementing-threads/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&quot;&gt;Mustang&lt;&#x2F;a&gt;, a system for running Rust programs entirely written in Rust, has
make a lot of progress since the last blog post:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;New targets: riscv64 and arm, joining x86_64, aarch64, and x86;
thanks to @Urgau for arm support in rustix!&lt;&#x2F;li&gt;
&lt;li&gt;Threading support, including TLS, TLS destructors, and detaching&lt;&#x2F;li&gt;
&lt;li&gt;Panic and unwind support, thanks to the &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;unwinding&quot;&gt;unwinding&lt;&#x2F;a&gt; crate!&lt;&#x2F;li&gt;
&lt;li&gt;Math library support, thanks to the &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;libm&quot;&gt;libm&lt;&#x2F;a&gt; crate!&lt;&#x2F;li&gt;
&lt;li&gt;A proper allocator, thanks to the &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;dlmalloc&quot;&gt;dlmalloc&lt;&#x2F;a&gt; crate!&lt;&#x2F;li&gt;
&lt;li&gt;No more debugging messages on stderr by default&lt;&#x2F;li&gt;
&lt;li&gt;DNS (&lt;code&gt;ToSocketAddrs&lt;&#x2F;code&gt;) support&lt;&#x2F;li&gt;
&lt;li&gt;Much smaller code size&lt;&#x2F;li&gt;
&lt;li&gt;Lots more test coverage&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Mustang&#x27;s thread library is a chance to explore the role of a thread library,
the special syscalls and registers that only a thread library uses, and the
interaction between a thread library and other system calls. The rest of
this blog post takes a closer look.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;d like to thank &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;japaric&#x2F;steed&#x2F;blob&#x2F;master&#x2F;src&#x2F;libc&#x2F;mod.rs&quot;&gt;Steed&#x27;s pthread implementation&lt;&#x2F;a&gt; for the initial
inspiration here, and demonstrating how to use &lt;code&gt;clone&lt;&#x2F;code&gt;, &lt;code&gt;futex&lt;&#x2F;code&gt;, and the
platform thread register.&lt;&#x2F;p&gt;
&lt;p&gt;So, what does a thread library do?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;create-threads&quot;&gt;Create threads&lt;&#x2F;h2&gt;
&lt;p&gt;First, what is a thread?&lt;&#x2F;p&gt;
&lt;p&gt;A thread consists of an OS thread, which on Linux is just a special kind of
process, and some data: metadata, user TLS data, stack memory, and a stack
guard. Creating a thread involves allocating memory for the data, and then
creating an OS thread configured to use them.&lt;&#x2F;p&gt;
&lt;p&gt;Mustang&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;tree&#x2F;main&#x2F;origin&quot;&gt;origin&lt;&#x2F;a&gt; crate allocates all the memory for a thread in a single
contiguous anonymous &lt;code&gt;mmap&lt;&#x2F;code&gt; allocation. Most platforms have a special
&amp;quot;Thread Pointer&amp;quot; register which is used to point to thread-specific data,
&lt;code&gt;%fs&lt;&#x2F;code&gt; on x86_64, &lt;code&gt;%gs&lt;&#x2F;code&gt; on x86, &lt;code&gt;tpidr_el0&lt;&#x2F;code&gt; on aarch64, &lt;code&gt;tp&lt;&#x2F;code&gt; on RISC-V, and
so on, and we use this to point to this allocation. Compiled code uses this
register to locate TLS data, and origin uses this register to locate its
metadata.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;..&#x2F;ThreadLayout.svg&quot; alt=&quot;Thread Layout&quot; title=&quot;Thread memory layout&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The specific layout &lt;a href=&quot;https:&#x2F;&#x2F;www.akkadia.org&#x2F;drepper&#x2F;tls.pdf&quot;&gt;differs between architectures&lt;&#x2F;a&gt;, for example with the
metadata being located before or after the user TLS data. And things would be
much more involved if we were talking about dynamic linking. But this covers
the basics.&lt;&#x2F;p&gt;
&lt;p&gt;Once the data is allocated and initialized, it&#x27;s time to create the OS thread.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-clone-system-call&quot;&gt;The &lt;code&gt;clone&lt;&#x2F;code&gt; system call&lt;&#x2F;h3&gt;
&lt;p&gt;Origin creates an OS thread using the &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;clone.2.html&quot;&gt;&lt;code&gt;clone&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; system call. Linux considers
this to be similar to &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;fork.2.html&quot;&gt;&lt;code&gt;fork&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which creates new processes, but with more
options. A new thread is a new execution context, with its own CPU register
state, similar to a new process. The main thing that makes it a thread instead
of a process is that it happens to use the same virtual address space and other
parts as its parent.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;..&#x2F;ForkClone.svg&quot; alt=&quot;Fork vs. Clone&quot; title=&quot;Fork vs. Clone, illustrated&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Like &lt;code&gt;fork&lt;&#x2F;code&gt;, &lt;code&gt;clone&lt;&#x2F;code&gt; is invoked by one execution context, and when it returns
there are two execution contexts, one for the parent and one for the child.&lt;&#x2F;p&gt;
&lt;p&gt;Unlike &lt;code&gt;fork&lt;&#x2F;code&gt; though, when the child shares virtual memory with the parent, it
can&#x27;t continue on the same stack, so we pass &lt;code&gt;clone&lt;&#x2F;code&gt; the pointer to the stack
we allocated above for the child to run on.&lt;&#x2F;p&gt;
&lt;p&gt;The child starts execution by returning from the &lt;code&gt;clone&lt;&#x2F;code&gt; call, and the return
value of the &lt;code&gt;clone&lt;&#x2F;code&gt; call is 0 in the child, and the child&#x27;s thread id in the
parent, so the code after the &lt;code&gt;clone&lt;&#x2F;code&gt; call can test whether it&#x27;s running in
the child or the parent.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;clone&lt;&#x2F;code&gt; system call doesn&#x27;t have a built-in way of passing any arguments to
the child to tell is what to do. To do that, we place additional arguments in
registers that we know the system call doesn&#x27;t clobber, effectively &amp;quot;passing&amp;quot;
them to the child.&lt;&#x2F;p&gt;
&lt;p&gt;To illustrate, here&#x27;s an illustrated version of the RISC-V code for this. Other
architectures do equivalent things, though eg. x86 has more ABI details in
play.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Place syscall arguments in a0, a1, ...,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; and `__NR_clone` in a7.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; And place the function pointer for the child to call, and
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; the argument to pass to it, in a8 and a9, which are not
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; used by the syscall, but not clobbered either.
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;ecall                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Do the `clone` system call.
&lt;&#x2F;span&gt;&lt;span&gt;bnez a0, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;f          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; If we&amp;#39;re in the parent, branch to 0:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; We&amp;#39;re in the child! Move the argument and function
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; pointer into calling-convention registers for the call to
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `entry`.
&lt;&#x2F;span&gt;&lt;span&gt;mv a0, a8            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `arg`
&lt;&#x2F;span&gt;&lt;span&gt;mv a1, a9            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `fn_`
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Zero out the frame address and return address. The call
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; below will never return.
&lt;&#x2F;span&gt;&lt;span&gt;mv fp, zero
&lt;&#x2F;span&gt;&lt;span&gt;mv ra, zero
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Call into our Rust code which will call the callee,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; passing it the argument. The Rust code will terminate
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; the thread and not return here.
&lt;&#x2F;span&gt;&lt;span&gt;tail &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;entry
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; We&amp;#39;re in the parent! Return from the system call in the
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; normal way.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;origin&#x27;s philosophy is to do as little as possible in assembly, so this code
just sets the frame pointer and return address to null, to ensure that we never
try to return back to our little assembly fragment, moves the arguments into
place for the platform calling-convention argument registers, and calls into
Rust code, specifically the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;blob&#x2F;75cbca7ffdf968db597071366843fde9c3ccd46f&#x2F;origin&#x2F;src&#x2F;threads.rs#L21&quot;&gt;&lt;code&gt;threads::entry&lt;&#x2F;code&gt; function&lt;&#x2F;a&gt;, to do the rest.&lt;&#x2F;p&gt;
&lt;p&gt;As an aside, this is very similar to the code origin uses for the start of
the process, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;blob&#x2F;75cbca7ffdf968db597071366843fde9c3ccd46f&#x2F;origin&#x2F;src&#x2F;lib.rs#L37&quot;&gt;&lt;code&gt;_start&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which calls &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;blob&#x2F;75cbca7ffdf968db597071366843fde9c3ccd46f&#x2F;origin&#x2F;src&#x2F;program.rs#L15&quot;&gt;&lt;code&gt;program::entry&lt;&#x2F;code&gt; function&lt;&#x2F;a&gt;. The OS
doesn&#x27;t start a process in a manner compatible with the platform
calling-convention, so we use a minimal amount of assembly to set up a call
into Rust code, also including setting the return address and frame pointer
to null.&lt;&#x2F;p&gt;
&lt;p&gt;In both threads and processes, we always exit by calling the &lt;code&gt;exit&lt;&#x2F;code&gt;
(for threads) or &lt;code&gt;exit_group&lt;&#x2F;code&gt; (for the process) system calls, and never by
returning to assembly code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;join-threads&quot;&gt;Join threads&lt;&#x2F;h2&gt;
&lt;p&gt;When one thread wants to wait for another to exit, it performs a &amp;quot;join&amp;quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Once the other thread exits, the joining thread is woken up, and it frees
any resources associated with the other thread, and collects the return
values (though Rust&#x27;s &lt;code&gt;std::thread&lt;&#x2F;code&gt; implementation doesn&#x27;t use thread return
values as such, so the return value part isn&#x27;t implemented in Mustang yet).&lt;&#x2F;p&gt;
&lt;p&gt;In the &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;clone.2.html&quot;&gt;&lt;code&gt;clone&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; system call that we called in &lt;code&gt;create_thread&lt;&#x2F;code&gt; above, one of the
flags we pass is &lt;code&gt;CLONE_CHILD_CLEARTID&lt;&#x2F;code&gt;. This tells Linux to clear the child thread
id and wake up any futexes that are waiting on that memory location when the
child exits. It&#x27;s important that it does both, so that the parent&#x27;s futex call
can avoid waiting if the child has exited first.&lt;&#x2F;p&gt;
&lt;p&gt;If the child hasn&#x27;t exited yet, &lt;code&gt;join_thread&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;futex&lt;&#x2F;code&gt; call waits until the
child exits and Linux wakes it up. If the thread wasn&#x27;t detached (more on that
below), joining then frees the thread&#x27;s memory—its stack, TLS data, and
metadata.&lt;&#x2F;p&gt;
&lt;p&gt;In the code, this is &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;blob&#x2F;75cbca7ffdf968db597071366843fde9c3ccd46f&#x2F;origin&#x2F;src&#x2F;threads.rs#L624&quot;&gt;&lt;code&gt;join_thread&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which calls &lt;code&gt;wait_for_thread_exit&lt;&#x2F;code&gt;, and
then &lt;code&gt;free_thread_memory&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;run-thread-destructors-registered-with-cxa-thread-atexit-impl&quot;&gt;Run thread destructors (registered with &lt;code&gt;__cxa_thread_atexit_impl&lt;&#x2F;code&gt;)&lt;&#x2F;h2&gt;
&lt;p&gt;Variables declared with the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;macro.thread_local.html&quot;&gt;&lt;code&gt;thread_local&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; macro can have &lt;code&gt;Drop&lt;&#x2F;code&gt;
implementations, and those &lt;code&gt;drop&lt;&#x2F;code&gt; functions are called on a thread&#x27;s copy
of the data when the thread exits.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;__cxa_thread_atexit_impl&lt;&#x2F;code&gt; is the C ABI function to register a cleanup
function to call when a thread exits. It simply pushes the function onto
a &lt;code&gt;Vec&lt;&#x2F;code&gt;, and then the thread exits, it &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;blob&#x2F;75cbca7ffdf968db597071366843fde9c3ccd46f&#x2F;origin&#x2F;src&#x2F;threads.rs#L252&quot;&gt;calls &lt;code&gt;call_thread_dtors&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to
call the functions in the &lt;code&gt;Vec&lt;&#x2F;code&gt;, in reverse order of their registration,
to ensure that object initializations and finalizations are nested.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;detach-threads&quot;&gt;Detach threads&lt;&#x2F;h2&gt;
&lt;p&gt;&amp;quot;Detaching&amp;quot; a thread declares that it will never be &amp;quot;joined&amp;quot; by any other
thread, so it needs to release its resources on its own when it exits.&lt;&#x2F;p&gt;
&lt;p&gt;This is a fairly straightforward matter of just doing bookkeeping to
keep track of whether a thread is in the detached state, and freeing resources
when it exits if it is, but there are a few catches.&lt;&#x2F;p&gt;
&lt;p&gt;One is that we create threads with &lt;code&gt;clone&lt;&#x2F;code&gt; with the &lt;code&gt;CLONE_CHILD_CLEARTID&lt;&#x2F;code&gt;
flag, which tells Linux to zero out our tid field when the child exits.
That helps &lt;code&gt;join_thread&lt;&#x2F;code&gt;, but for detached threads, it means that if we free
our memory before we exit, the kernel will still think it needs to clear the
tid field. Something else in the program could reuse our free&#x27;d memory, and
it could get corrupted if Linux clears out what is no longer our tid field.
So when a thread is marked detached, we call the &lt;code&gt;set_tid_address&lt;&#x2F;code&gt; system
call, passing it a null pointer, which effectively disables the
&lt;code&gt;CLONE_CHILD_CLEARTID&lt;&#x2F;code&gt; for the thread.&lt;&#x2F;p&gt;
&lt;p&gt;The other is that a thread&#x27;s memory is freed by an &lt;code&gt;munmap&lt;&#x2F;code&gt; system call, but
if we call the usual &lt;code&gt;munmap&lt;&#x2F;code&gt; function that wraps the system call, it will
free the current thread, including the stack we&#x27;re running on out from
underneath us. The &lt;code&gt;munmap&lt;&#x2F;code&gt; wrapper will then access freed memory trying to
read its return address for the return jump.&lt;&#x2F;p&gt;
&lt;p&gt;To fix this, we need more assembly code. We need a special code
sequence to make a &lt;code&gt;munmap&lt;&#x2F;code&gt; system call, and then make an &lt;code&gt;exit&lt;&#x2F;code&gt; system
call to exit the thread, without touching the stack after the &lt;code&gt;munmap&lt;&#x2F;code&gt;.
Fortunately, this can be done in &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;blob&#x2F;75cbca7ffdf968db597071366843fde9c3ccd46f&#x2F;origin&#x2F;src&#x2F;arch-x86_64.rs#L72&quot;&gt;just a handful of instructions&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Note that on 32-bit x86, we normally don&#x27;t make syscalls directly, because
the usual &lt;code&gt;int 0x80&lt;&#x2F;code&gt; mechanism is very slow, and Linux provides a much
faster way to make syscalls through &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man7&#x2F;vdso.7.html&quot;&gt;the vDSO&lt;&#x2F;a&gt;. However, we can&#x27;t use that
here because the vdso is effectively another syscall wrapper that
expects to store a return address on the stack. So we use &lt;code&gt;int 0x80&lt;&#x2F;code&gt;
so that we can completely prevent touching the stack. Fortunately,
threads don&#x27;t exit all that often, so the performance loss here isn&#x27;t
that important.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;synchronize-threads&quot;&gt;Synchronize threads&lt;&#x2F;h2&gt;
&lt;p&gt;It&#x27;s common for threading libraries to provide synchronization primitives
such as mutexes and reader-writer locks.&lt;&#x2F;p&gt;
&lt;p&gt;Mustang&#x27;s main strategy is to use &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;parking_lot&#x2F;&quot;&gt;&lt;code&gt;parking_lot&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to implement these, since
&lt;code&gt;parking_lot&lt;&#x2F;code&gt; is a widely-used library, and there&#x27;s not a lot to add here.&lt;&#x2F;p&gt;
&lt;p&gt;Except there&#x27;s one place Mustang can&#x27;t yet use &lt;code&gt;parking_lot&lt;&#x2F;code&gt;: the Rust global
allocator uses a &lt;code&gt;Mutex&lt;&#x2F;code&gt;, because it&#x27;s allocating memory for multiple threads
from a shared heap. But the twist for Mustang is, &lt;code&gt;parking_lot&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;Mutex&lt;&#x2F;code&gt;
does global allocation.&lt;&#x2F;p&gt;
&lt;p&gt;Uh oh.&lt;&#x2F;p&gt;
&lt;p&gt;Allocator tries to acquire a lock, which tries to perform an allocation,
which tries to acquire a lock, which tries to perform an allocation...&lt;&#x2F;p&gt;
&lt;p&gt;💥&lt;&#x2F;p&gt;
&lt;p&gt;So what do we do? For now, Mustang has &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;blob&#x2F;75cbca7ffdf968db597071366843fde9c3ccd46f&#x2F;c-scape&#x2F;src&#x2F;raw_mutex.rs&quot;&gt;its own Mutex implementation&lt;&#x2F;a&gt;, built
on top of atomics and Linux&#x27;s &lt;code&gt;futex&lt;&#x2F;code&gt;. It&#x27;s nothing fancy, it&#x27;s unfair,
it&#x27;s inefficient in a bunch of ways, and it&#x27;s certainly not proven correct.
But it&#x27;s pretty simple and it passes all the tests! This is your regular
reminder that simply implementing everything in Rust does not make anything
automatically safer. Mustang is still experimental at this point, with lots
of &lt;code&gt;unsafe&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;but-not-cancellation&quot;&gt;But not cancellation&lt;&#x2F;h2&gt;
&lt;p&gt;The other really big piece of functionality that a libpthread would provide is
&lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man3&#x2F;pthread_cancel.3.html&quot;&gt;cancellation&lt;&#x2F;a&gt;. Cancellation is very complex, and requires hooks in libc and
very special handling of many system calls. However, Rust doesn&#x27;t support
cancellation, and it&#x27;s relatively rare even in C code, so origin and mustang
don&#x27;t implement it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mustang-organization&quot;&gt;Mustang organization&lt;&#x2F;h2&gt;
&lt;p&gt;The origin crate provides low-level but still somewhat Rust-idiomatic
interfaces to process startup and shutdown, and now also threads. This
accompanies the &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;rustix&quot;&gt;rustix&lt;&#x2F;a&gt; crate which provides Rust-idiomatic interfaces to
system calls.&lt;&#x2F;p&gt;
&lt;p&gt;The c-scape crate provides libc and libpthread ABIs as wrappers around
rustix and origin. Right now, this allows existing code, such as Rust&#x27;s
&lt;code&gt;std&lt;&#x2F;code&gt; to run on origin and rustix without any extra porting work.&lt;&#x2F;p&gt;
&lt;p&gt;But also, code that wants to can bypass the c-scape compatibility layer,
and call into rustix and origin directly. This eliminates some overhead,
but more importantly, it offers greater safety and simplicity, because there
are fewer raw pointers, raw file descriptors, and raw error return values.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;and-beyond&quot;&gt;And beyond!&lt;&#x2F;h2&gt;
&lt;p&gt;Of course, even rustix and origin are still very low-level. Most users should of
course continue to use &lt;code&gt;std&lt;&#x2F;code&gt;, and high-level libraries such as
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&#x2F;cap-std&#x2F;&quot;&gt;cap-std&lt;&#x2F;a&gt;. But perhaps someday
there could be a way of &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&#x2F;rustix&#x2F;issues&#x2F;76&quot;&gt;using rustix in std&lt;&#x2F;a&gt;, simplifying the code by factoring
out raw pointers, raw file descriptors, and raw error handling.&lt;&#x2F;p&gt;
&lt;p&gt;And perhaps someday, one could even imagine, an &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;issues&#x2F;39&quot;&gt;official Rust target&lt;&#x2F;a&gt; for
Rust programs built entirely in Rust, with I&#x2F;O safety &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;rustix-and-io-safety&#x2F;&quot;&gt;down to the syscalls&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Rust programs written entirely in Rust</title>
		<published>2021-09-07T00:00:00+00:00</published>
		<updated>2021-09-07T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/rust-programs-entirely-in-rust/" type="text/html"/>
		<id>https://blog.sunfishcode.online/rust-programs-entirely-in-rust/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&quot;&gt;&lt;code&gt;mustang&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is a system for writing Rust programs entirely in Rust, meaning
they don&#x27;t use &lt;code&gt;libc&lt;&#x2F;code&gt;, &lt;code&gt;crt1.o&lt;&#x2F;code&gt;, or any C code. It&#x27;s experimental, but it&#x27;s
complete enough to run a &lt;code&gt;std&lt;&#x2F;code&gt;-using Hello World and other simple programs
on Linux on x86-64, x86, and aarch64.&lt;&#x2F;p&gt;
&lt;p&gt;See &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;blob&#x2F;main&#x2F;README.md&quot;&gt;&lt;code&gt;mustang&lt;&#x2F;code&gt;&#x27;s README&lt;&#x2F;a&gt; for information on how to use it. This post walks
through the major steps leading to this point.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;system-calls&quot;&gt;System calls&lt;&#x2F;h2&gt;
&lt;p&gt;The first building block for &lt;code&gt;mustang&lt;&#x2F;code&gt; was &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;rustix&quot;&gt;&lt;code&gt;rustix&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, a crate providing a
syscall-like API, but which can be configured to use different backends,
currently either libc or raw Linux syscalls. &lt;code&gt;rustix&lt;&#x2F;code&gt; has been a place to
help prototype the &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;io-lifetimes&quot;&gt;&lt;code&gt;io-lifetimes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate and I&#x2F;O safety feature, support
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&#x2F;wasmtime&quot;&gt;Wasmtime&lt;&#x2F;a&gt;&#x27;s WASI implementation, support &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&#x2F;cap-std&quot;&gt;cap-std&lt;&#x2F;a&gt;&#x27;s filesystem sandbox
implementation, and to &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;rustix-and-io-safety&#x2F;&quot;&gt;push the boundaries&lt;&#x2F;a&gt; of low-level performance
while maintaining safe and relatively idiomatic Rust APIs.&lt;&#x2F;p&gt;
&lt;p&gt;These continue to be the main motivators for &lt;code&gt;rustix&lt;&#x2F;code&gt;, and that&#x27;s an
important point: while &lt;code&gt;mustang&lt;&#x2F;code&gt; isn&#x27;t particularly practical, it isn&#x27;t all a
one-off effort. Some of the major pieces have real-world practical use cases.&lt;&#x2F;p&gt;
&lt;p&gt;The first part of the inspiration for &lt;code&gt;mustang&lt;&#x2F;code&gt; was the realization that &lt;code&gt;rustix&lt;&#x2F;code&gt;
could be used in this way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;process-startup&quot;&gt;Process startup&lt;&#x2F;h2&gt;
&lt;p&gt;crt1.o and process startup has always had an aura of mystery about it, at least
to me. There are parts implemented in assembly, parts that use obscure C
compiler features, parts that are heavily conditionalized with ifdefs, and
support for dynamic linking requires several particularly tricky features.&lt;&#x2F;p&gt;
&lt;p&gt;The other part of the inspiration for &lt;code&gt;mustang&lt;&#x2F;code&gt; was the realization that simple
Rust programs don&#x27;t need most of what goes into crt1.o and libc startup code
The minimum needed is just a &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;blob&#x2F;main&#x2F;origin&#x2F;src&#x2F;lib.rs#L19&quot;&gt;little bit of assembly&lt;&#x2F;a&gt; to translate from the
initial process state that the OS sets up into the Rust calling convention.
Once Rust code is running, it just needs to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;blob&#x2F;main&#x2F;origin&#x2F;src&#x2F;lib.rs#L108&quot;&gt;compute argc, argv, and envp&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;blob&#x2F;main&#x2F;origin&#x2F;src&#x2F;lib.rs#L118&quot;&gt;call any &lt;code&gt;.init_array&lt;&#x2F;code&gt; functions&lt;&#x2F;a&gt;, and then &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;blob&#x2F;main&#x2F;origin&#x2F;src&#x2F;lib.rs#L132&quot;&gt;call &lt;code&gt;main&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This code is in mustang&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;blob&#x2F;main&#x2F;origin&#x2F;&quot;&gt;&lt;code&gt;origin&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate; it&#x27;s very small.&lt;&#x2F;p&gt;
&lt;p&gt;To tell the linker to avoid linking in crt1.o so that it uses &lt;code&gt;origin&lt;&#x2F;code&gt;&#x27;s startup
code instead, &lt;code&gt;mustang&lt;&#x2F;code&gt; defines &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;tree&#x2F;main&#x2F;specs&quot;&gt;custom targets&lt;&#x2F;a&gt; named &lt;code&gt;*-mustang&lt;&#x2F;code&gt;. These primarily
add &lt;code&gt;-nostdlib&lt;&#x2F;code&gt; to the link command so that &lt;code&gt;crt1.o&lt;&#x2F;code&gt; is not linked in.&lt;&#x2F;p&gt;
&lt;p&gt;Cargo&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;cargo&#x2F;reference&#x2F;unstable.html#build-std&quot;&gt;build-std&lt;&#x2F;a&gt; mode allows &lt;code&gt;mustang&lt;&#x2F;code&gt; to easily compile the standard
library with its custom targets, so it doesn&#x27;t need to make any upstream
standard library changes (for now...).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;c-scape&quot;&gt;C-scape&lt;&#x2F;h2&gt;
&lt;p&gt;If we can start a process with Rust code, and make system calls with Rust code,
what&#x27;s left that&#x27;s not Rust?&lt;&#x2F;p&gt;
&lt;p&gt;As a practical matter, Rust&#x27;s standard library depends on &lt;code&gt;libc&lt;&#x2F;code&gt; and uses many
libc APIs. One option would be to build a runtime library that runs on
&lt;code&gt;no_std&lt;&#x2F;code&gt;. However, in the limit, that would essentially require a
reimplementation of &lt;code&gt;std&lt;&#x2F;code&gt;, which would be a lot of work, and a huge burden to
maintain.&lt;&#x2F;p&gt;
&lt;p&gt;So &lt;code&gt;mustang&lt;&#x2F;code&gt; instead defines &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;tree&#x2F;main&#x2F;c-scape&quot;&gt;C-compatible ABIs&lt;&#x2F;a&gt; providing functions like &lt;code&gt;write&lt;&#x2F;code&gt;,
&lt;code&gt;strlen&lt;&#x2F;code&gt;, &lt;code&gt;memcpy&lt;&#x2F;code&gt;, &lt;code&gt;mmap&lt;&#x2F;code&gt;, and other things used by Rust&#x27;s standard library,
using &lt;code&gt;rustix&lt;&#x2F;code&gt; internally to do actual system calls. These implementations are
currently very minimal, but they are enough to support Hello World, running
with &lt;code&gt;std&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And going forward, it should be relatively straightforward to add additional
&lt;code&gt;libc&lt;&#x2F;code&gt; APIs as needed by &lt;code&gt;std&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;That said, the goal here is to just implement enough of libc to get &lt;code&gt;std&lt;&#x2F;code&gt;
working on top of it. &lt;code&gt;Mustang&lt;&#x2F;code&gt; doesn&#x27;t need to implement a whole new libc,
which would be a lot more work, and much of it wouldn&#x27;t be needed in Rust
programs.&lt;&#x2F;p&gt;
&lt;p&gt;This code is in mustang&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;tree&#x2F;main&#x2F;c-scape&quot;&gt;&lt;code&gt;c-scape&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-global-allocator&quot;&gt;The &lt;code&gt;global_allocator&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Rust allows users to configure their global allocator with the
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;alloc&#x2F;index.html#the-global_allocator-attribute&quot;&gt;&lt;code&gt;global_allocator&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; attribute. The default global allocator ultimately
uses libc &lt;code&gt;malloc&lt;&#x2F;code&gt;. Writing a new &lt;code&gt;malloc&lt;&#x2F;code&gt; is a lot more work that I was
looking to do here, so the question here was, is there a nice Rust allocator
crate that can be used with &lt;code&gt;#[global_allocator]&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
&lt;p&gt;It turns out, there are a few options, but one which turned out to be
particularly easy to integrate was &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;wee_alloc&quot;&gt;&lt;code&gt;wee_alloc&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Built for reducing code size
on WebAssembly, &lt;code&gt;wee_alloc&lt;&#x2F;code&gt; doesn&#x27;t do fancy optimizations, but it does plug
directly into &lt;code&gt;#[global_alloctor]&lt;&#x2F;code&gt; with no additional hassle, and it is
portable, so it was very easy to set up. And it only uses a few things from
&lt;code&gt;libc&lt;&#x2F;code&gt; which &lt;code&gt;c-scape&lt;&#x2F;code&gt; is easily able to support.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;putting-it-all-together&quot;&gt;Putting it all together&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;code&gt;mustang&lt;&#x2F;code&gt; crate pulls all these pieces together to make it easy to use
them all at once. But note that since &lt;code&gt;mustang&lt;&#x2F;code&gt; is aiming at supporting
regular &lt;code&gt;std&lt;&#x2F;code&gt;-using Rust code, it isn&#x27;t something you explicitly call
yourself. As such, it currently needs an &lt;code&gt;extern crate mustang&lt;&#x2F;code&gt; to link it
into the program.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-note-about-safety-and-a-lack-thereof&quot;&gt;A note about safety (and a lack thereof)&lt;&#x2F;h2&gt;
&lt;p&gt;There is often a temptation whenever one is working with C code to
Rewrite It In Rust, however it&#x27;s not always a good idea. In &lt;code&gt;mustang&lt;&#x2F;code&gt;&#x27;s case,
existing libc implementations are mature, robust, and well optimized. Libc
interfaces are relatively portable, and on some operating systems, libc
interfaces are the only stable interfaces to operating system functionality.
There&#x27;s no urgency to stop using libc or to rewrite it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;mustang&lt;&#x2F;code&gt; is inspired by the realization that some of the major pieces were
already available, and the remaining pieces to get basic examples working could
be written with a relatively quick effort. It&#x27;s new code, it&#x27;s experimental, it
has a lot of &lt;code&gt;unsafe&lt;&#x2F;code&gt; code, it lacks important optimizations, it&#x27;s overall
far less safe to use than just using libc, and it would take a lot of work to
change this. But, it&#x27;s fun, and educational.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s also possible that in the future, &lt;code&gt;mustang&lt;&#x2F;code&gt; could be part of a path to
designing new low-level system features like command-line arguments, environment
variables, or OS error codes are handled with more safety or other ideas such as
&lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;first-class-io&#x2F;&quot;&gt;first-class I&#x2F;O&lt;&#x2F;a&gt;. This is also part of why the goal isn&#x27;t to just build a Rust
implementation of libc: many libc APIs consist of a small amount of code behind
a function signature that uses raw pointers; just putting Rust behind those
kinds of APIs isn&#x27;t going to make them significantly safer. But that&#x27;s another
post; for now...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hello-world&quot;&gt;Hello, World!&lt;&#x2F;h2&gt;
&lt;p&gt;See &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;blob&#x2F;main&#x2F;README.md&quot;&gt;&lt;code&gt;mustang&lt;&#x2F;code&gt;&#x27;s README&lt;&#x2F;a&gt; for step-by-step instructions for how to build an
run &lt;code&gt;mustang&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re interested in following the story, helping out, or even just asking
questions, come say hi in &lt;a href=&quot;https:&#x2F;&#x2F;bytecodealliance.zulipchat.com&#x2F;#narrow&#x2F;stream&#x2F;217126-wasmtime&quot;&gt;the chat channel&lt;&#x2F;a&gt;, or &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;mustang&#x2F;issues&quot;&gt;file an issue&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Broken Encapsulation</title>
		<published>2021-09-02T00:00:00+00:00</published>
		<updated>2021-09-02T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/broken-encapsulation/" type="text/html"/>
		<id>https://blog.sunfishcode.online/broken-encapsulation/</id>
		<content type="html">&lt;p&gt;What kinds of bugs should &lt;em&gt;safety&lt;&#x2F;em&gt; in Rust protect against?&lt;&#x2F;p&gt;
&lt;p&gt;Rust clearly wants to say that safety is about protecting programs against some
kinds of bugs, but not &lt;em&gt;all possible&lt;&#x2F;em&gt; bugs. Where should the boundary be?&lt;&#x2F;p&gt;
&lt;p&gt;Safety should at the very least mean protection against memory corruption through
dangling and out-of-bounds pointers. To do that, it&#x27;s necessary to protect
against all Undefined Behavior, because if behavior of a program is undefined,
anything could happen, including arbitrary memory corruption.&lt;&#x2F;p&gt;
&lt;p&gt;There are also categories of bugs that we don&#x27;t expect Rust&#x27;s safety to protect
against. For example, &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;cmp&#x2F;trait.Eq.html&quot;&gt;&lt;code&gt;Eq&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; implementations must be reflexive, symmetric, and
transitive, however it would likely be impractical to enforce all the invariants
of all such APIs. Fortunately, violating these invariants doesn&#x27;t cause
Undefined Behavior; it just causes some algorithms to do the wrong thing.&lt;&#x2F;p&gt;
&lt;p&gt;So, Undefined Behavior is a very practical place to put the boundary.&lt;&#x2F;p&gt;
&lt;p&gt;However, there are several potential situations which do not necessarily involve
Undefined Behavior, but which are still arguably within the spirit of
Rust&#x27;s safety:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;blob&#x2F;master&#x2F;text&#x2F;3128-io-safety.md&quot;&gt;I&#x2F;O safety&lt;&#x2F;a&gt;: Raw file descriptors have the same fundamental properties that
make raw pointers unsafe: They can dangle and they can be be forged. One
crate operating on a dangling or forged file descriptor can end up doing I&#x2F;O
on file descriptors held in other unrelated crates. Without I&#x2F;O safety,
it&#x27;s impossible to characterize the I&#x2F;O of a crate without considering the
behavior of all other crates it might be linked with.&lt;&#x2F;p&gt;
&lt;p&gt;(I&#x2F;O safety does intersect with memory safety through &lt;code&gt;mmap&lt;&#x2F;code&gt;, but using &lt;code&gt;mmap&lt;&#x2F;code&gt;
safely is non-trivial in any case, and this is not the only motivation for
I&#x2F;O safety.)&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;POSIX&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;functions&#x2F;munlock.html&quot;&gt;&lt;code&gt;munlock&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function: This function takes a raw pointer and length, but it&#x27;s
defined to fail gracefully if given invalid pointers. It doesn&#x27;t mutate any memory,
or cause any subsequent memory access to behave differently with respect to Rust
language semantics, so it arguably never causes Undefined Behavior. However, if a
crate is internally using locked memory to protect sensitive data, exposing &lt;code&gt;munlock&lt;&#x2F;code&gt;
as a safe function would mean that a wayward &lt;code&gt;munlock&lt;&#x2F;code&gt; call in another crate could
bypass the first crate&#x27;s encapsulation and &lt;code&gt;munlock&lt;&#x2F;code&gt; the memory, compromising the
sensitive data.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;POSIX&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;functions&#x2F;write.html&quot;&gt;&lt;code&gt;write&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function: this function also takes a raw pointer and a length, and
also guarantees to not segfault or mutate any memory. POSIX isn&#x27;t clear on whether
&lt;code&gt;write&lt;&#x2F;code&gt; has Undefined Behavior in the presence of data races or provenance violations
or other infelicities with its buffer, but for the sake of this post, let&#x27;s assume
it doesn&#x27;t. The memory is read by the OS, which one could argue isn&#x27;t bound by the
same rules as userspace. In that case, one can argue that &lt;code&gt;write&lt;&#x2F;code&gt; never has Undefined
Behavior. But making it safe would mean safe code in any crate could read encapsulated
memory in any other crate, which seems outside the spirit.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So, instead of &lt;em&gt;Undefined Behavior&lt;&#x2F;em&gt;, a slightly more expanded concept that covers
these cases might be described as &lt;em&gt;Broken Encapsulation&lt;&#x2F;em&gt;. This is a superset of
Undefined Behavior, because anything that causes Undefined Behavior can break any
language-level encapsulation boundary. And like Undefined Behavior, it still excludes
things like &lt;code&gt;Eq&lt;&#x2F;code&gt;&#x27;s invariants.&lt;&#x2F;p&gt;
&lt;p&gt;Language-level encapsulation boundaries help in maintaining
&lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2017&#x2F;03&#x2F;02&#x2F;lang-ergonomics.html&quot;&gt;Reasoning Footprints&lt;&#x2F;a&gt;, especially in programs that contain many crates. It&#x27;s what
lets us look at an individual crate and understand its behavior in isolation,
without having to think about whether any other crate in the program could
accidentally observe the crate&#x27;s internal data, do I&#x2F;O on its internal file
descriptors, or cause its internal secrets to be swapped out of memory and
potentially compromised.&lt;&#x2F;p&gt;
&lt;p&gt;In practice, thinking about Broken Encapsulation is only slightly different from
thinking about Undefined Behavior, but it also reflects a broader observation:
Guarding against Undefined Behavior is about ensuring that certain kinds of
bugs don&#x27;t happen, while guarding against Broken Encapsulation is also about
helping users build large programs out of smaller parts.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>(renamed)</title>
		<published>2021-07-12T00:00:00+00:00</published>
		<updated>2021-07-12T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/posish-and-io-safety/" type="text/html"/>
		<id>https://blog.sunfishcode.online/posish-and-io-safety/</id>
		<content type="html">&lt;p&gt;Posish has been renamed to Rustix. &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;rustix-and-io-safety&#x2F;&quot;&gt;Here&#x27;s the new URL for this page&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>(renamed)</title>
		<published>2021-07-12T00:00:00+00:00</published>
		<updated>2021-07-12T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/rsix-and-io-safety/" type="text/html"/>
		<id>https://blog.sunfishcode.online/rsix-and-io-safety/</id>
		<content type="html">&lt;p&gt;Rsix has been renamed to Rustix. &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;rustix-and-io-safety&#x2F;&quot;&gt;Here&#x27;s the new URL for this page&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>I&#x2F;O safety and speed: Why not both?</title>
		<published>2021-07-12T00:00:00+00:00</published>
		<updated>2021-07-12T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/rustix-and-io-safety/" type="text/html"/>
		<id>https://blog.sunfishcode.online/rustix-and-io-safety/</id>
		<content type="html">&lt;h2 id=&quot;rustix-i-o-safety-in-practice&quot;&gt;Rustix: I&#x2F;O Safety in practice&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;blob&#x2F;master&#x2F;text&#x2F;3128-io-safety.md&quot;&gt;I&#x2F;O Safety RFC&lt;&#x2F;a&gt; is now merged! But it&#x27;s all fairly abstract, so what will
this look like in practice with real APIs?&lt;&#x2F;p&gt;
&lt;p&gt;One of the ways is rustix, the fastest POSIX-ish, Unix-ish, Linux-ish, and
libc-ish API for Rust!&lt;&#x2F;p&gt;
&lt;p&gt;And it&#x27;s also I&#x2F;O-safe! And memory-safe! These are actually the bigger
motivators for this crate, and it helped guide the development of the I&#x2F;O
safety APIs. But it&#x27;s also fast, which is fun, and shows that Rust&#x27;s
&lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2015&#x2F;05&#x2F;11&#x2F;traits.html&quot;&gt;&amp;quot;abstraction without overhead&amp;quot;&lt;&#x2F;a&gt; is preserved. More on that later though.
First, what&#x27;s all this about safety, you say? I&#x27;m glad you asked 😉!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;safety&quot;&gt;Safety&lt;&#x2F;h2&gt;
&lt;p&gt;Memory safety is of course an established concept for Rust. Memory-safe
abstractions for POSIX&#x2F;libc functions is a well-established idea, with Rust
references, slices and return values in place of raw pointers, and rustix
provides all this as well.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x2F;O safety is a &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;3128&quot;&gt;newly-introduced concept&lt;&#x2F;a&gt; and is about treating file
descriptors similar to pointers, with concepts of &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-lifetimes&#x2F;*&#x2F;io_lifetimes&#x2F;struct.OwnedFd.html&quot;&gt;ownership&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-lifetimes&#x2F;*&#x2F;io_lifetimes&#x2F;struct.BorrowedFd.html&quot;&gt;borrowing&lt;&#x2F;a&gt;.
See the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;blob&#x2F;master&#x2F;text&#x2F;3128-io-safety.md&quot;&gt;I&#x2F;O Safety RFC&lt;&#x2F;a&gt; and the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;io-lifetimes&quot;&gt;io-lifetimes crate&lt;&#x2F;a&gt; for details. Rustix uses
io-lifetimes types for all its APIs that work with file descriptors.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-tour-of-a-function-in-rustix&quot;&gt;A tour of a function in rustix&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s take a quick look at the &lt;code&gt;openat&lt;&#x2F;code&gt; function, which demonstrates several
of the things rustix does.&lt;&#x2F;p&gt;
&lt;p&gt;The libc version of &lt;code&gt;openat&lt;&#x2F;code&gt; looks &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;libc&#x2F;*&#x2F;libc&#x2F;fn.openat.html&quot;&gt;like this&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub unsafe extern &lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;C&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;openat&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;dirfd&lt;&#x2F;span&gt;&lt;span&gt;: c_int,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pathname&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const&lt;&#x2F;span&gt;&lt;span&gt; c_char,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;flags&lt;&#x2F;span&gt;&lt;span&gt;: c_int,
&lt;&#x2F;span&gt;&lt;span&gt;         ...
&lt;&#x2F;span&gt;&lt;span&gt;    ) -&amp;gt; c_int
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Rustix&#x27;s looks &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;libc&#x2F;*&#x2F;libc&#x2F;fn.openat.html&quot;&gt;like this&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;openat&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;P: Arg, Fd: AsFd&amp;gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;dirfd&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;Fd,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: P,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;oflags&lt;&#x2F;span&gt;&lt;span&gt;: OFlags,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;create_mode&lt;&#x2F;span&gt;&lt;span&gt;: Mode
&lt;&#x2F;span&gt;&lt;span&gt;    ) -&amp;gt; Result&amp;lt;OwnedFd&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here&#x27;s a breakdown of the differences:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;
    pub fn openat&amp;lt;P: Arg, &lt;span style=&quot;color:purple&quot;&gt;Fd: AsFd&lt;&#x2F;span&gt;&amp;gt;(
        &lt;span style=&quot;color:purple&quot;&gt;dirfd: &amp;Fd&lt;&#x2F;span&gt;,
        path: P,
        oflags: OFlags,
        create_mode: Mode
    ) -&gt; Result&amp;lt;OwnedFd&amp;gt;
&lt;&#x2F;pre&gt;&lt;&#x2F;code&gt;
&lt;p&gt;Rustix&#x27;s &lt;code&gt;dirfd&lt;&#x2F;code&gt; accepts any type which implements the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-lifetimes&#x2F;*&#x2F;io_lifetimes&#x2F;trait.AsFd.html&quot;&gt;&lt;code&gt;AsFd&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; trait, so you
can pass in a &lt;code&gt;&amp;amp;File&lt;&#x2F;code&gt; or &lt;code&gt;&amp;amp;TcpStream&lt;&#x2F;code&gt; or other things conveniently and safely
instead of having to call &lt;code&gt;.as_raw_fd()&lt;&#x2F;code&gt; and pass in the result. &lt;code&gt;AsFd&lt;&#x2F;code&gt;
works like a borrow, and similar to Rust references, it&#x27;s prevented from
escaping and dangling.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-lifetimes&#x2F;*&#x2F;io_lifetimes&#x2F;trait.AsFd.html&quot;&gt;&lt;code&gt;AsFd&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is similar to &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;os&#x2F;unix&#x2F;io&#x2F;trait.AsRawFd.html&quot;&gt;&lt;code&gt;AsRawFd&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, except that &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-lifetimes&#x2F;*&#x2F;io_lifetimes&#x2F;trait.AsFd.html#tymethod.as_fd&quot;&gt;&lt;code&gt;AsFd::as_fd&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; returns a
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-lifetimes&#x2F;*&#x2F;io_lifetimes&#x2F;struct.BorrowedFd.html&quot;&gt;&lt;code&gt;BorrowedFd&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; instead of &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;os&#x2F;unix&#x2F;io&#x2F;trait.AsRawFd.html#tymethod.as_raw_fd&quot;&gt;&lt;code&gt;AsRawFd::as_raw_fd&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;os&#x2F;unix&#x2F;io&#x2F;type.RawFd.html&quot;&gt;&lt;code&gt;RawFd&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which is an
integer, it returns a &lt;code&gt;BorrowedFd&lt;&#x2F;code&gt;, which is a special type scoped to the
lifetime of the borrow.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;
    pub fn openat&amp;lt;&lt;span style=&quot;color:purple&quot;&gt;P: Arg&lt;&#x2F;span&gt;, Fd: AsFd&amp;gt;(
        dirfd: &amp;Fd,
        &lt;span style=&quot;color:purple&quot;&gt;path: P&lt;&#x2F;span&gt;,
        oflags: OFlags,
        create_mode: Mode
    ) -&gt; Result&amp;lt;OwnedFd&amp;gt;
&lt;&#x2F;pre&gt;&lt;&#x2F;code&gt;
&lt;p&gt;Similar to &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;nix&quot;&gt;nix&lt;&#x2F;a&gt;, rustix&#x27;s &lt;code&gt;path&lt;&#x2F;code&gt; is also generic and accepts any type of
string that implements the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rustix&#x2F;*&#x2F;rustix&#x2F;path&#x2F;trait.Arg.html&quot;&gt;&lt;code&gt;Arg&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; trait, which includes &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt;, &lt;code&gt;&amp;amp;Path&lt;&#x2F;code&gt;,
&lt;code&gt;&amp;amp;CStr&lt;&#x2F;code&gt;, &lt;code&gt;&amp;amp;OsStr&lt;&#x2F;code&gt;, and other string-like types in Rust&#x27;s standard library.
Actual POSIX-ish system calls expect NUL-terminated strings, so there are
optimized paths that avoid dynamic allocation in most cases where you pass
in something other than a &lt;code&gt;&amp;amp;CStr&lt;&#x2F;code&gt;. And rustix avoids making any assumptions
about &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;libc&#x2F;*&#x2F;libc&#x2F;constant.PATH_MAX.html&quot;&gt;&lt;code&gt;PATH_MAX&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, so the lengths of strings you can use is between you and
the individual syscalls.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;
    pub fn openat&amp;lt;P: Arg, Fd: AsFd&amp;gt;(
        dirfd: &amp;Fd,
        path: P,
        &lt;span style=&quot;color:purple&quot;&gt;oflags: OFlags&lt;&#x2F;span&gt;,
        &lt;span style=&quot;color:purple&quot;&gt;create_mode: Mode&lt;&#x2F;span&gt;
    ) -&gt; &lt;span style=&quot;color:purple&quot;&gt;Result&lt;&#x2F;span&gt;&amp;lt;OwnedFd&amp;gt;
&lt;&#x2F;pre&gt;&lt;&#x2F;code&gt;
&lt;p&gt;Similar to other libc-wrapping creates, rustix&#x27;s &lt;code&gt;oflags&lt;&#x2F;code&gt; argument takes an
&lt;code&gt;OFlags&lt;&#x2F;code&gt;, which uses the &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;bitflags&quot;&gt;&lt;code&gt;bitflags&lt;&#x2F;code&gt; crate&lt;&#x2F;a&gt; to create a type-checked flags
type instead of a raw integer type. Rustix uses an explicit &lt;code&gt;create_mode&lt;&#x2F;code&gt;
argument instead of &lt;code&gt;...&lt;&#x2F;code&gt; so it avoids the unsafety of varargs. And rustix
reports errors via a &lt;code&gt;Result&lt;&#x2F;code&gt; instead of a plain &lt;code&gt;c_int&lt;&#x2F;code&gt;, and returns a
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rustix&#x2F;*&#x2F;rustix&#x2F;io&#x2F;struct.Error.html&quot;&gt;&lt;code&gt;Error&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; inside the &lt;code&gt;Result&lt;&#x2F;code&gt; instead of setting &lt;code&gt;errno&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;
    pub fn openat&amp;lt;P: Arg, Fd: AsFd&amp;gt;(
        dirfd: &amp;Fd,
        path: P,
        oflags: OFlags,
        create_mode: Mode
    ) -&gt; Result&amp;lt;&lt;span style=&quot;color:purple&quot;&gt;OwnedFd&lt;&#x2F;span&gt;&amp;gt;
&lt;&#x2F;pre&gt;&lt;&#x2F;code&gt;
&lt;p&gt;On success, rustix returns an &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-lifetimes&#x2F;*&#x2F;io_lifetimes&#x2F;struct.OwnedFd.html&quot;&gt;&lt;code&gt;OwnedFd&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; instead of a raw file descriptor,
modeling the file descriptor&#x27;s lifetime in the type system, so similar to
a Rust &lt;code&gt;Box&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; or other owning type, it&#x27;s prevented from dangling.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;OwnedFd&lt;&#x2F;code&gt; is very similar to &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;fs&#x2F;struct.File.html&quot;&gt;&lt;code&gt;std::fs::File&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. From a user perspective, the
main difference between &lt;code&gt;OwnedFd&lt;&#x2F;code&gt; and &lt;code&gt;File&lt;&#x2F;code&gt; is that &lt;code&gt;OwnedFd&lt;&#x2F;code&gt; doesn&#x27;t suggest
any file-like purpose or behavior, it&#x27;s just a generic owned file descriptor
for any kind of resource. Most use cases will likely want to wrap &lt;code&gt;OwnedFd&lt;&#x2F;code&gt; in
higher-level types. When &lt;code&gt;OwnedFd&lt;&#x2F;code&gt; is added to the standard library, I expect
&lt;code&gt;File&lt;&#x2F;code&gt; itself will be implemented in terms of &lt;code&gt;OwnedFd&lt;&#x2F;code&gt; in this way as well.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;
    &lt;span style=&quot;color:purple&quot;&gt;pub fn&lt;&#x2F;span&gt; openat&amp;lt;P: Arg, Fd: AsFd&amp;gt;(
        dirfd: &amp;Fd,
        path: P,
        oflags: OFlags,
        create_mode: Mode
    ) -&gt; Result&amp;lt;OwnedFd&amp;gt;
&lt;&#x2F;pre&gt;&lt;&#x2F;code&gt;
&lt;p&gt;And finally, the &lt;code&gt;openat&lt;&#x2F;code&gt; system call itself is &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;functions&#x2F;open.html&quot;&gt;documented&lt;&#x2F;a&gt; to not have any
other side effects, so it has &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;first-class-io&quot;&gt;first-class I&#x2F;O&lt;&#x2F;a&gt;, though at a fairly coarse
granularity since the &lt;code&gt;path&lt;&#x2F;code&gt; can contain &lt;code&gt;..&lt;&#x2F;code&gt; components and can thereby
reference any path in the filesystem (if you&#x27;re worried about that kind of
thing, see &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&#x2F;cap-std&#x2F;&quot;&gt;cap-std&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;So with all these together, rustix&#x27;s &lt;code&gt;openat&lt;&#x2F;code&gt; is a safe function, both in
memory safety and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;3128&quot;&gt;I&#x2F;O safety&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cool-cool-what-about-speed-though&quot;&gt;Cool cool what about speed though?&lt;&#x2F;h3&gt;
&lt;p&gt;On Linux on x86-64, x86, and aarch64, rustix uses avoids &lt;code&gt;libc&lt;&#x2F;code&gt; entirely,
avoiding &lt;code&gt;errno&lt;&#x2F;code&gt; and pthread cancellation checking. On stable Rust it uses
out-of-line asm to perform syscalls; on Rust nightly, it uses inline asm and,
since it adds very little code itself, it can fully inline the syscall
instructions into the user callsites. On all other platforms, it currently
uses &lt;code&gt;libc&lt;&#x2F;code&gt; and &lt;code&gt;errno&lt;&#x2F;code&gt;, but it&#x27;s factored to facilitate additional backend
implementations in the future.&lt;&#x2F;p&gt;
&lt;p&gt;It also uses an optimized error type and the string argument optimization
mentioned above. In microbenchmarks, at this moment in time, filesystem
syscalls with string path arguments are about 15% faster than nix, and about
3% faster than libc with allocating temporary &lt;code&gt;CString&lt;&#x2F;code&gt;s. And it uses the
&lt;code&gt;vDSO&lt;&#x2F;code&gt; to make &lt;code&gt;clock_gettime&lt;&#x2F;code&gt; really fast on Linux (and to avoid using the
super-slow &lt;code&gt;int 0x80&lt;&#x2F;code&gt; mechanism on x86), just like Linux libc implementations
do, but without depending on libc.&lt;&#x2F;p&gt;
&lt;p&gt;That said, the bigger picture is that most of the time for syscalls is spent in
the OS itself, and rustix makes most syscalls only a few percentage points
faster at most. But these days, with system calls often getting slower, it&#x27;s
still fun to have some gains in performance in this space, even if they are
relatively small. And it demonstrates that the new abstraction of I&#x2F;O safety
doesn&#x27;t entail new overhead.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;is-that-all&quot;&gt;Is that all?&lt;&#x2F;h3&gt;
&lt;p&gt;Rustix provides a few additional niceties, including:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;It always uses 64-bit file offsets, so users don&#x27;t need to juggle &lt;code&gt;off64_t&lt;&#x2F;code&gt;
vs. &lt;code&gt;off_t&lt;&#x2F;code&gt;, or remember to pass &lt;code&gt;O_LARGEFILE&lt;&#x2F;code&gt; when needed.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;On 32-bit Linux platforms that use direct Linux syscalls, it uses a 64-bit
&lt;code&gt;time_t&lt;&#x2F;code&gt; type when the underlying kernel supports it, so clocks won&#x27;t wrap
around &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Year_2038_problem&quot;&gt;in the year 2038&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;And as a fun bonus, some names have been made more human-friendly and less
historic-accidental, with names such as &lt;code&gt;accept_with&lt;&#x2F;code&gt; and &lt;code&gt;dup2_with&lt;&#x2F;code&gt; to
take extra flags arguments instead of &lt;code&gt;accept4&lt;&#x2F;code&gt; and &lt;code&gt;dup3&lt;&#x2F;code&gt;, and &lt;code&gt;seek&lt;&#x2F;code&gt;
instead of &lt;code&gt;lseek&lt;&#x2F;code&gt;. The code also uses &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;rustdoc&#x2F;advanced-features.html#add-aliases-for-an-item-in-documentation-search&quot;&gt;doc aliases&lt;&#x2F;a&gt; so that you can still
find things via the traditional C names.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;what-about-portability&quot;&gt;What about portability?&lt;&#x2F;h3&gt;
&lt;p&gt;Rustix isn&#x27;t a fully-fledged portability layer; it doesn&#x27;t support Windows and
some of its APIs are OS-specific, and even OS-version-specific. Rustix doesn&#x27;t
do non-trivial emulation of features, and prefers to let higher-level layers
provide that kind of portability when needed.&lt;&#x2F;p&gt;
&lt;p&gt;Many POSIX-ish APIs are very low-level, and not a suitable abstraction layer
for efficiently implementing on different kinds of platforms. See Rust&#x27;s
standard library for an illustration of this: For example,
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;fs&#x2F;struct.Metadata.html&quot;&gt;&lt;code&gt;std::fs::Metadata&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is more abstract than &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;libc&#x2F;*&#x2F;libc&#x2F;struct.stat.html&quot;&gt;&lt;code&gt;struct stat&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and this gives
platforms more options when implementing functions like
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;fs&#x2F;fn.metadata.html&quot;&gt;&lt;code&gt;std::fs::File::metadata&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Other interesting cases are &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man7&#x2F;epoll.7.html&quot;&gt;&lt;code&gt;epoll&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;810414&#x2F;&quot;&gt;&lt;code&gt;io_uring&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Rustix doesn&#x27;t yet have
APIs for these, and it&#x27;s an open question whether it&#x27;s worth it. These APIs are
very low-level, they have complex file descriptor ownership, and they are most
often wrapped in higher-level APIs. It&#x27;s not yet clear whether I&#x2F;O safety makes
sense at the abstraction level of these APIs, or whether they should just
continue to use &lt;code&gt;RawFd&lt;&#x2F;code&gt; and introduce safety at higher levels of abstraction.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-about-close&quot;&gt;What about &lt;code&gt;close&lt;&#x2F;code&gt;?&lt;&#x2F;h3&gt;
&lt;p&gt;It&#x27;s called &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;mem&#x2F;fn.drop.html&quot;&gt;&lt;code&gt;drop&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; 😃.&lt;&#x2F;p&gt;
&lt;p&gt;Rustix doesn&#x27;t currently have a &lt;code&gt;close&lt;&#x2F;code&gt; function in its public API. It would be
straight-forward to add it, and the signature would either have an &lt;code&gt;OwnedFd&lt;&#x2F;code&gt;
argument or a &lt;code&gt;T: IntoFd&lt;&#x2F;code&gt; generic argument, to express that the file
descriptor ownership is being consumed. However it&#x27;d also be redundant for most
users. &lt;code&gt;OwnedFd&lt;&#x2F;code&gt; calls &lt;code&gt;close&lt;&#x2F;code&gt; in its &lt;code&gt;Drop&lt;&#x2F;code&gt; implementation, so in most cases,
the way to close a file descriptor is to simply drop it.&lt;&#x2F;p&gt;
&lt;p&gt;(&lt;code&gt;Drop&lt;&#x2F;code&gt; doesn&#x27;t have a way to report errors, so this may not be the last word
on this subject, but this is a separate and much more complex topic involving
things like NFS in async mode.)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;how-complete-is-rustix&quot;&gt;How complete is rustix?&lt;&#x2F;h3&gt;
&lt;p&gt;It has everything that &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&#x2F;cap-std&#x2F;&quot;&gt;cap-std&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&#x2F;wasmtime&quot;&gt;wasmtime&lt;&#x2F;a&gt;&#x27;s WASI implementation need,
as well as a few other projects, though it doesn&#x27;t have everything. If you find
it&#x27;s missing something you need, please file an issue!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;where-does-i-o-safety-go-from-here&quot;&gt;Where does I&#x2F;O safety go from here?&lt;&#x2F;h3&gt;
&lt;p&gt;Now that the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;blob&#x2F;master&#x2F;text&#x2F;3128-io-safety.md&quot;&gt;I&#x2F;O Safety RFC&lt;&#x2F;a&gt; is merged, my next step in this wing of the story
is to prepare a PR adding &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-lifetimes&#x2F;*&#x2F;io_lifetimes&#x2F;struct.OwnedFd.html&quot;&gt;&lt;code&gt;OwnedFd&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-lifetimes&#x2F;*&#x2F;io_lifetimes&#x2F;struct.BorrowedFd.html&quot;&gt;&lt;code&gt;BorrowedFd&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and friends to the Rust
standard library. Once that&#x27;s done, I&#x27;ll update the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;io-lifetimes&quot;&gt;io-lifetimes crate&lt;&#x2F;a&gt; to use
the new standard library types and traits instead of defining them itself.&lt;&#x2F;p&gt;
&lt;p&gt;io-lifetimes defines more functionality than will be in the initial standard
library PR, such as &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-lifetimes&#x2F;*&#x2F;io_lifetimes&#x2F;views&#x2F;index.html&quot;&gt;views&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-lifetimes&#x2F;*&#x2F;io_lifetimes&#x2F;trait.FromFd.html#method.from_into_fd&quot;&gt;&lt;code&gt;from_into_fd&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-lifetimes&#x2F;*&#x2F;io_lifetimes&#x2F;trait.AsFilelike.html&quot;&gt;&lt;code&gt;AsFilelike&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&#x2F;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-lifetimes&#x2F;*&#x2F;io_lifetimes&#x2F;trait.AsSocketlike.html&quot;&gt;&lt;code&gt;AsSocketlike&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; Windows&#x2F;Unix portability layer, so it&#x27;ll remain
useful for some time, but it&#x27;ll get thinner as the standard library takes over
more functionality.&lt;&#x2F;p&gt;
&lt;p&gt;And for the Rust ecosystem as a whole, the I&#x2F;O safety RFC outlines
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;blob&#x2F;master&#x2F;text&#x2F;3128-io-safety.md#gradual-adoption&quot;&gt;the path forward&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Introducing cap-std, a capability-based version of the Rust standard library</title>
		<published>2021-06-14T00:00:00+00:00</published>
		<updated>2021-06-14T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/introducing-cap-std/" type="text/html"/>
		<id>https://blog.sunfishcode.online/introducing-cap-std/</id>
		<content type="html">&lt;h2 id=&quot;introducing-cap-std&quot;&gt;Introducing &lt;code&gt;cap-std&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;cap-std&lt;&#x2F;code&gt; is a project to create capability-based versions of Rust standard
library and related APIs.&lt;&#x2F;p&gt;
&lt;p&gt;Capability-based here means that the APIs don&#x27;t access files, directories,
network addresses, clocks, or other external resources implicitly, but instead
operate on handles that are explicitly passed in. This helps programs that work
with potentially malicious content avoid accidentally accessing resources other
than they intend, and does so without the need of a traditional process-wide
sandbox, so it can be easily embedded in larger applications.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;background&quot;&gt;Background&lt;&#x2F;h2&gt;
&lt;p&gt;Some of the most devious software bugs are those where the code looks like it
does one thing, and usually does that thing in practice, but sometimes, under
special circumstances, does something else. Here&#x27;s a simple example using
Rust&#x27;s filesystem APIs:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;Path) -&amp;gt; Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; tmp = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;tempdir&lt;&#x2F;span&gt;&lt;span&gt;()?;
&lt;&#x2F;span&gt;&lt;span&gt;        fs::write(tmp.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(name), &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello world&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The expected behavior of this function is to write &amp;quot;hello world&amp;quot; to a file within
a temporary directory. The code looks like it will do this. And indeed, it will
&lt;em&gt;usually&lt;&#x2F;em&gt; do this. But if the path passed in is &lt;code&gt;..&#x2F;..&#x2F;home&#x2F;me&#x2F;.ssh&#x2F;id_dsa.pub&lt;&#x2F;code&gt;,
then the behavior of this function could be to corrupt the user&#x27;s ssh public key 😲.
That&#x27;s... not remotely within what we said the expected behavior is. It usually
doesn&#x27;t do that, but under the right circumstances, it could.&lt;&#x2F;p&gt;
&lt;p&gt;And since &lt;code&gt;name&lt;&#x2F;code&gt; is just a string, if the string is computed in a way that could
be influenced by an attacker, the right circumstances could easily be made to
occur in practice.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&#x2F;cap-std&#x2F;&quot;&gt;&lt;code&gt;cap-std&lt;&#x2F;code&gt; project&lt;&#x2F;a&gt; provides Rust crates with lightweight ways to avoid such
problems. In particular, the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;cap-std&quot;&gt;&lt;code&gt;cap-std&lt;&#x2F;code&gt; crate&lt;&#x2F;a&gt;&#x27;s &lt;code&gt;Dir&lt;&#x2F;code&gt; type represents a
directory, with &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;cap-std&#x2F;latest&#x2F;cap_std&#x2F;fs&#x2F;struct.Dir.html#impl&quot;&gt;methods&lt;&#x2F;a&gt; corresponding to Rust&#x27;s &lt;code&gt;std::fs&lt;&#x2F;code&gt; functions, for
opening and working with files within the directory, that ensure that all paths
stay within that directory. For networking, the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;cap-std&#x2F;latest&#x2F;cap_std&#x2F;net&#x2F;struct.Pool.html&quot;&gt;&lt;code&gt;Pool&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; type represents a set of
network addresses, ensuring that all network accesses made through the API
are to addresses in the pool.&lt;&#x2F;p&gt;
&lt;p&gt;In contrast to conventional sandboxing, &lt;code&gt;cap-std&lt;&#x2F;code&gt; doesn&#x27;t have any global state,
so using it in one part of an application doesn&#x27;t require using it in the rest of
the application. Library crates can use &lt;code&gt;cap-std&lt;&#x2F;code&gt; internally without imposing any
sandboxing constraints on their users.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-can-dir-do&quot;&gt;What can &lt;code&gt;Dir&lt;&#x2F;code&gt; do?&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;cap_std&lt;&#x2F;code&gt; is just a library, so by itself, it isn&#x27;t a sandbox for arbitrary
Rust code—it can&#x27;t prevent arbitrary Rust code from using &lt;code&gt;std::fs&lt;&#x2F;code&gt;&#x27;s
path-oriented APIs. Instead, it protects against malicious &lt;em&gt;content&lt;&#x2F;em&gt;, when
filesystem paths can be influenced by untrusted inputs, and malicious
&lt;em&gt;concurrent modifications&lt;&#x2F;em&gt;, when another program running at the same time
has the ability to remove, rename, or create files, directories, symlinks,
or hard links in ways that could cause a program to inadvertently access
unintended resources.&lt;&#x2F;p&gt;
&lt;p&gt;Revisiting our example above, with &lt;code&gt;cap-std&lt;&#x2F;code&gt; we might write:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;Path, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tmp&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;Dir) -&amp;gt; Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        tmp.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(name, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello world&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this code, if the passed-in path uses &lt;code&gt;..&lt;&#x2F;code&gt; to access directories outside of
the one passed in, &lt;code&gt;tmp.write&lt;&#x2F;code&gt; returns an error.&lt;&#x2F;p&gt;
&lt;p&gt;One key difference from before is that instead of creating the temporary
directory itself, this function requests a directory be passed in. The &lt;code&gt;Dir&lt;&#x2F;code&gt;
type here serves as a &amp;quot;vocabulary&amp;quot; type, allowing the function to declare that
it wants a directory to be passed in, and that it intends to access resources
within that directory, rather than accessing arbitrary locations in the
filesystem. These kinds of declarations can help reduce the
&lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2017&#x2F;03&#x2F;02&#x2F;lang-ergonomics.html&quot;&gt;reasoning footprint&lt;&#x2F;a&gt; of a function call.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;Dir&lt;&#x2F;code&gt; crate also makes it much easier to write this code robustly. There&#x27;s
no need to think about &lt;code&gt;..&lt;&#x2F;code&gt; or absolute paths at the application level, and no
need to handle symlinks specially, which with the Rust standard library today
isn&#x27;t even possible to do robustly without &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;os&#x2F;unix&#x2F;fs&#x2F;trait.OpenOptionsExt.html#examples-1&quot;&gt;platform-specific code&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;It also gives callers increased control. The caller gets to choose how and
where to create the directory, and when to remove it. Callers could choose to use
something like &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;cap-tempfile&quot;&gt;&lt;code&gt;cap-tempfile&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&#x27;s &lt;code&gt;tempdir&lt;&#x2F;code&gt; function to easily create a
temporary directory in a conventional location and automatically remove it
afterwords, however they could also opt to create the directory somewhere
else and manage it manually.&lt;&#x2F;p&gt;
&lt;p&gt;Note that &lt;code&gt;Dir&lt;&#x2F;code&gt; is passed by immutable reference, even though it&#x27;s being used
to mutate external filesystem state. This follows Rust&#x27;s conventions, for
example in &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;fs&#x2F;struct.File.html#method.set_len&quot;&gt;&lt;code&gt;std::fs::File::set_len&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and it reflects an underlying truth
about filesystems. &lt;code&gt;&amp;amp;mut&lt;&#x2F;code&gt; in Rust is sometimes called an &amp;quot;exclusive&amp;quot; reference,
because when someone has a &lt;code&gt;&amp;amp;mut&lt;&#x2F;code&gt;, they&#x27;re the only one which can access the
underlying object. However, this is generally not a safe assumption when
working with filesystem objects, because other programs could concurrently
access or even mutate files or directories without Rust&#x27;s type system having
any say in the matter. Consequently, it makes sense to think of filesystem
state as being external to the program, with &lt;code&gt;File&lt;&#x2F;code&gt; and &lt;code&gt;Dir&lt;&#x2F;code&gt; objects being
just handles that are themselves typically immutable.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Dir&lt;&#x2F;code&gt; can also be combined with other security techniques. In a project which is
written to carefully avoid using untrusted paths, it can add an extra layer of
defense in depth.&lt;&#x2F;p&gt;
&lt;p&gt;And in the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&#x2F;wasmtime&#x2F;&quot;&gt;Wasmtime&lt;&#x2F;a&gt; project, the next step we &lt;a href=&quot;https:&#x2F;&#x2F;bytecodealliance.org&#x2F;articles&#x2F;1-year-update&quot;&gt;described earlier&lt;&#x2F;a&gt; is now
finished, and we&#x27;re &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&#x2F;wasmtime&#x2F;pull&#x2F;2487&quot;&gt;now using cap-std&lt;&#x2F;a&gt; in combination with with our WebAssembly
sandbox to implement WASI, providing sandboxed access to system resources.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-simple-example&quot;&gt;A simple example&lt;&#x2F;h2&gt;
&lt;p&gt;The main pattern for filesystem operations using the &lt;code&gt;cap-std&lt;&#x2F;code&gt; crate is to
obtain a &lt;code&gt;Dir&lt;&#x2F;code&gt; and use methods on it, which closely resemble the functions in
&lt;code&gt;std::fs&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;One of the ways to obtain a &lt;code&gt;Dir&lt;&#x2F;code&gt; is to use the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;cap-directories&quot;&gt;&lt;code&gt;cap-directories&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
crate to request a &lt;code&gt;Dir&lt;&#x2F;code&gt; for a standard directory (similar to the
&lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;directories-next&quot;&gt;&lt;code&gt;directories-next&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate, but returns a &lt;code&gt;Dir&lt;&#x2F;code&gt; instead of a &lt;code&gt;Path&lt;&#x2F;code&gt;).
For example, to obtain the data directory for an example program:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; project_dirs =
&lt;&#x2F;span&gt;&lt;span&gt;        cap_directories::ProjectDirs::from(
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;com.example&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;,
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Example Organization&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;,
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;`cap-std` Key-Value CLI Example&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;,
&lt;&#x2F;span&gt;&lt;span&gt;            cap_directories::ambient_authority()
&lt;&#x2F;span&gt;&lt;span&gt;        )
&lt;&#x2F;span&gt;&lt;span&gt;    };
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; data_dir = project_dirs.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;data_dir&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then in place of &lt;code&gt;fs::read&lt;&#x2F;code&gt; and &lt;code&gt;fs::write&lt;&#x2F;code&gt; to read and write files, one
can use &lt;code&gt;data_dir&lt;&#x2F;code&gt; here to do &lt;code&gt;data_dir.read(key)&lt;&#x2F;code&gt; and
&lt;code&gt;data_dir.write(file_name, value)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Note the use of the &lt;code&gt;ambient_authority()&lt;&#x2F;code&gt; function here, which is a no-op that
returns an instance of the opaque &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;ambient-authority&#x2F;0.0.0&#x2F;ambient_authority&#x2F;struct.AmbientAuthority.html&quot;&gt;&lt;code&gt;AmbientAuthority&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; type, and serves to mark a
place in the code where ambient authority is being invoked. &lt;code&gt;cap-directories&lt;&#x2F;code&gt;,
and related crates have an overall invariant that functions don&#x27;t create their
own absolute filesystem paths, and always rely on resources being passed in as
handles. Functions which don&#x27;t uphold this invariant, such as
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;cap-directories&#x2F;latest&#x2F;cap_directories&#x2F;struct.ProjectDirs.html#method.from&quot;&gt;&lt;code&gt;cap_directories::ProjectDirs::from&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, take an &lt;code&gt;AmbientAuthority&lt;&#x2F;code&gt; argument to
advertise their ability to open resources given only a string.&lt;&#x2F;p&gt;
&lt;p&gt;This makes it easy to search a codebase to find all the places where a
non-sandboxed cap-std API is being used. It can also be scanned for with
Clippy using a &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;ambient-authority&#x2F;blob&#x2F;main&#x2F;clippy.toml&quot;&gt;clippy configuration file&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To see all this put together in a complete example, see
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&#x2F;cap-std&#x2F;blob&#x2F;main&#x2F;examples&#x2F;kv-cli.rs&quot;&gt;the kv-cli example&lt;&#x2F;a&gt;
in the &lt;code&gt;cap-std&lt;&#x2F;code&gt; repository. This program implements a simple key-value store,
using filesystem paths as keys, and using &lt;code&gt;cap-std&lt;&#x2F;code&gt; ensures that it only
accesses paths within its own data directory. Attempts to escape the directory
with &lt;code&gt;..&lt;&#x2F;code&gt; fail gracefully. This is true even if a concurrently running program
renames directories on the path or changes symlinks—something that&#x27;s very hard
to get right using &lt;code&gt;std::fs&lt;&#x2F;code&gt; APIs.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; cargo run&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; --quiet --example&lt;&#x2F;span&gt;&lt;span&gt; kv-cli color green
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; cargo run&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; --quiet --example&lt;&#x2F;span&gt;&lt;span&gt; kv-cli color
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;green
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; cargo run&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; --quiet --example&lt;&#x2F;span&gt;&lt;span&gt; kv-cli temperature cold
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; cargo run&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; --quiet --example&lt;&#x2F;span&gt;&lt;span&gt; kv-cli temperature
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cold
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; cargo run&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; --quiet --example&lt;&#x2F;span&gt;&lt;span&gt; kv-cli color
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;green
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; cargo run&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; --quiet --example&lt;&#x2F;span&gt;&lt;span&gt; kv-cli &#x2F;etc&#x2F;passwd
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Error:&lt;&#x2F;span&gt;&lt;span&gt; a path led outside of the filesystem
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; cargo run&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; --quiet --example&lt;&#x2F;span&gt;&lt;span&gt; kv-cli ..&#x2F;..&#x2F;..&#x2F;secret_cookie_recipe.txt
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Error:&lt;&#x2F;span&gt;&lt;span&gt; a path led outside of the filesystem
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Another useful crate is &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;cap-tempfile&quot;&gt;&lt;code&gt;cap-tempfile&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which creates temporary directories
and provides a &lt;code&gt;Dir&lt;&#x2F;code&gt; to access them.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s also possible to create a &lt;code&gt;Dir&lt;&#x2F;code&gt; by opening a raw path, using
&lt;code&gt;Dir::open_ambient_dir&lt;&#x2F;code&gt;. Note that this function takes an &lt;code&gt;AmbientAuthority&lt;&#x2F;code&gt;
since it does not uphold the sandboxing invariant that the rest of the API
does.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-real-world-example&quot;&gt;A real-world example&lt;&#x2F;h2&gt;
&lt;p&gt;Web servers often need to serve files from a given directory, and it&#x27;d be nice
to have a guarantee that they don&#x27;t accidentally stray outside that directory.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;tide-naive-static-files&#x2F;&quot;&gt;tide-native-static-files&lt;&#x2F;a&gt; is a fork of a real-world Web server project built
on the Tide framework, ported to use cap-std instead of directory paths.&lt;&#x2F;p&gt;
&lt;p&gt;The port is very straightforward, mostly consisting of passing around a &lt;code&gt;Dir&lt;&#x2F;code&gt;
instead of a string holding a base directory name. And in many cases, working
with a &lt;code&gt;Dir&lt;&#x2F;code&gt; is actually simpler than working with a string. The complete set
of changes needed for this port can be seen &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;eignnx&#x2F;tide-naive-static-files&#x2F;compare&#x2F;master...sunfishcode:main&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;implementation-landscape&quot;&gt;Implementation Landscape&lt;&#x2F;h2&gt;
&lt;p&gt;One of the reasons that Rust doesn&#x27;t already have a &lt;code&gt;Dir&lt;&#x2F;code&gt; type, when it does have a
&lt;code&gt;File&lt;&#x2F;code&gt; type, is that popular OS filesystem APIs don&#x27;t make this as efficient
or idiomatic as just using paths to name directories. However, this is changing.&lt;&#x2F;p&gt;
&lt;p&gt;One of the inspirations for &lt;code&gt;cap-std&lt;&#x2F;code&gt; is the &lt;a href=&quot;https:&#x2F;&#x2F;cloudabi.org&#x2F;&quot;&gt;CloudABI project&lt;&#x2F;a&gt;, which among
other things developed a technique of using a sequence of &lt;code&gt;openat&lt;&#x2F;code&gt; calls to
emulate path lookup in userspace in a way that&#x27;s robust in the face of concurrent
renames. &lt;code&gt;cap-std&lt;&#x2F;code&gt; uses a variant of this technique, optimized to use fewer
intermediate system calls, to implement a portable sandboxed path lookup algorithm.&lt;&#x2F;p&gt;
&lt;p&gt;And, Linux &lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;816213&#x2F;&quot;&gt;recently&lt;&#x2F;a&gt; added a system call, &lt;code&gt;openat2&lt;&#x2F;code&gt;, which has the ability to
&lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;796868&#x2F;&quot;&gt;restrict path lookup&lt;&#x2F;a&gt; so that it stays within a given directory, which is exactly
the behavior we want here. It doesn&#x27;t require a process-wide mode, and it avoids
the overhead of doing multiple system calls. &lt;code&gt;cap-std&lt;&#x2F;code&gt; uses this in place of its
portable algorithm whenever it can. On systems which support &lt;code&gt;openat2&lt;&#x2F;code&gt;, most
functions in the API perform only one or two system calls.&lt;&#x2F;p&gt;
&lt;p&gt;Linux and other operating systems are also exploring adding more such features,
and as these features become available, it will become increasingly practical to
not just implement a &lt;code&gt;Dir&lt;&#x2F;code&gt; type, but to implement it with WASI-style sandboxing
protections built in.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;philosophy&quot;&gt;Philosophy&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;cap-std&lt;&#x2F;code&gt; came about because we were looking to generalize the filesystem
sandboxing techniques we were using in Wasmtime&#x27;s WASI implementation to make
them more broadly applicable, and we were particularly inspired by
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;async-rs&#x2F;async-std#philosophy&quot;&gt;&lt;code&gt;async-std&lt;&#x2F;code&gt;&#x27;s philosophy&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;the best API is the one you already know.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Rust already has a standard library API. It&#x27;s very good overall, and a lot of
care has gone into ensuring that it&#x27;s implementable on many platforms. It&#x27;s
used by a lot of code, and well known to a lot of developers.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;cap-std&lt;&#x2F;code&gt; is an approach that takes advantage of this. Developers who know &lt;code&gt;std&lt;&#x2F;code&gt;
can easily learn &lt;code&gt;cap-std&lt;&#x2F;code&gt;. Applications using &lt;code&gt;std&lt;&#x2F;code&gt; can be ported to &lt;code&gt;cap-std&lt;&#x2F;code&gt;, with
the main concern being about how to ensure that directory handles are available
to all the places that need them, rather than with dealing with differences
in the API or in filesystem behavior.&lt;&#x2F;p&gt;
&lt;p&gt;The close alignment between &lt;code&gt;cap-std&lt;&#x2F;code&gt; and &lt;code&gt;std&lt;&#x2F;code&gt;, combined with the close
alignment between &lt;a href=&quot;https:&#x2F;&#x2F;async.rs&#x2F;&quot;&gt;&lt;code&gt;async-std&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;code&gt;std&lt;&#x2F;code&gt;, also make it straightforward to do
both at the same time, producing &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;cap-async-std&quot;&gt;&lt;code&gt;cap-async-std&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re familiar with using &lt;code&gt;std::fs&lt;&#x2F;code&gt;, you should be familiar with &lt;code&gt;cap-std&lt;&#x2F;code&gt;&#x27;s
APIs without any surprises. Similarly, if you&#x27;re familiar with &lt;code&gt;async-std&lt;&#x2F;code&gt;,
&lt;code&gt;cap-async-std&lt;&#x2F;code&gt;&#x27;s APIs should work as expected.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;current-status&quot;&gt;Current status&lt;&#x2F;h2&gt;
&lt;p&gt;Cap-std works on Linux, macOS, FreeBSD, Windows, and more, with stable Rust. On
Linux, &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;cap-std&#x2F;latest&#x2F;cap_std&#x2F;fs&#x2F;index.html&quot;&gt;&lt;code&gt;cap_std::fs&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is optimized to use new system calls including &lt;code&gt;openat2&lt;&#x2F;code&gt;,
when available, which significantly reduces the sandboxing overhead.&lt;&#x2F;p&gt;
&lt;p&gt;Support for compiling to WASI is under active development.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;speaking-of-wasi&quot;&gt;Speaking of WASI...&lt;&#x2F;h2&gt;
&lt;p&gt;The sandboxing performed by &lt;code&gt;cap-std&lt;&#x2F;code&gt; is the same as what&#x27;s provided by WASI APIs.&lt;&#x2F;p&gt;
&lt;p&gt;While &lt;code&gt;cap-std&lt;&#x2F;code&gt; is designed so that it can be used as a library within otherwise
unsandboxed native applications, WASI applies the same kind of sandboxing to all
filesystem accesses, so that it serves as an extension to the core WebAssembly
sandbox.&lt;&#x2F;p&gt;
&lt;p&gt;This means that when the &lt;code&gt;cap-std&lt;&#x2F;code&gt; library is compiled for the WASI platform, it
will be able to bypass its own sandboxing techniques and simply call into the WASI
system calls directly, achieving smaller code size and tighter integration with
the underlying WASI platform.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-future&quot;&gt;The Future!&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;re continuing to add more testing, fuzzing, and optimization. A port to WASI
is underway.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;re also starting to think about extending the capability-based model to more
parts of Rust&#x27;s API. The most obvious next step is &lt;code&gt;std::net&lt;&#x2F;code&gt;, which is in a very
early state right now, but this is a space we&#x27;re thinking about for the future! Other
areas that may be interesting include &lt;code&gt;std::env&lt;&#x2F;code&gt; for information passed in by the
host environment, &lt;code&gt;std::process&lt;&#x2F;code&gt; for launching sandboxed processes, and anything else
that allows programs to interact with the outside world.&lt;&#x2F;p&gt;
&lt;p&gt;And as we&#x27;re doing with &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;cap-directories&quot;&gt;&lt;code&gt;cap-directories&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;cap-tempfile&quot;&gt;&lt;code&gt;cap-tempfile&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, we&#x27;re also interested
in ways that we can do more than just translate the standard library API into a
capability-based model, but also make the capability-based model easy to use.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>First-Class I&#x2F;O</title>
		<published>2021-04-06T00:00:00+00:00</published>
		<updated>2021-04-06T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/first-class-io/" type="text/html"/>
		<id>https://blog.sunfishcode.online/first-class-io/</id>
		<content type="html">&lt;p&gt;@withoutBoats makes this observation about Rust in &lt;a href=&quot;https:&#x2F;&#x2F;without.boats&#x2F;blog&#x2F;notes-on-a-smaller-rust&#x2F;&quot;&gt;&amp;quot;Notes on a smaller Rust&amp;quot;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Pure functional programming is an ingenious trick to show you can code
without mutation, but Rust is an even cleverer trick to show you can just
have mutation.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;A particular aspect I&#x27;d like to explore here is: Can we apply this
observation to I&#x2F;O?&lt;&#x2F;p&gt;
&lt;p&gt;Haskell also has an ingenious trick to do first-class I&#x2F;O without mutation. So,
can we have first-class I&#x2F;O in Rust that just uses mutation?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-first-class-i-o&quot;&gt;What is First-Class I&#x2F;O?&lt;&#x2F;h2&gt;
&lt;p&gt;As in Haskell, first-class I&#x2F;O in Rust would mean functions that do I&#x2F;O would
do so through values which can be passed around the program as arguments or
return values:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_some_io&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;File) -&amp;gt; io::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    ...
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;File&lt;&#x2F;code&gt; here is an example of a first-class value which represents a resource
that supports I&#x2F;O. But unlike Haskell, instead of using monads, &lt;code&gt;File&lt;&#x2F;code&gt; here just
has side-effecting operations like &lt;code&gt;read&lt;&#x2F;code&gt; and &lt;code&gt;write&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Of course, Rust already has lots of these kinds of types, including in the
standard library with types like &lt;code&gt;File&lt;&#x2F;code&gt; and &lt;code&gt;TcpStream&lt;&#x2F;code&gt;. And a lot of Rust
code already follows this pattern. Strictly speaking, many of the operations
don&#x27;t take &lt;code&gt;&amp;amp;mut&lt;&#x2F;code&gt; references, but these types conceptually use
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;interior-mutability.html&quot;&gt;interior mutability&lt;&#x2F;a&gt;, which isn&#x27;t unique to I&#x2F;O.&lt;&#x2F;p&gt;
&lt;p&gt;The remaining piece that Haskell has that Rust doesn&#x27;t here is that in Haskell,
&lt;em&gt;all&lt;&#x2F;em&gt; I&#x2F;O is done through values which are passed around through the program.
Any function which does I&#x2F;O says so in its signature. In Rust, when a function
has a &lt;code&gt;File&lt;&#x2F;code&gt; argument in its signature, you know it&#x27;s going to do I&#x2F;O using that
&lt;code&gt;File&lt;&#x2F;code&gt;, but a function which doesn&#x27;t have &lt;code&gt;File&lt;&#x2F;code&gt; or any other I&#x2F;O type might
still access files.&lt;&#x2F;p&gt;
&lt;p&gt;Of course, monads in Haskell have many other uses too. This blog post is just
looking at I&#x2F;O operations in function signatures, which has implications for how
two otherwise unrelated pieces of code interact, as well as for one piece of
code can redirect the I&#x2F;O of another.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;example-stdout&quot;&gt;Example: Stdout&lt;&#x2F;h2&gt;
&lt;p&gt;An example in Rust of code that uses global I&#x2F;O is &lt;code&gt;std::io::stdout&lt;&#x2F;code&gt;. Any
code can call this and obtain a &lt;code&gt;Stdout&lt;&#x2F;code&gt; value that can do I&#x2F;O without having
any mention of it in the surrounding function&#x27;s signature. &lt;code&gt;Stdout&lt;&#x2F;code&gt; uses a
builtin mutex, even though many use cases don&#x27;t need that, and is a common
performance pitfall. Diligent users can of course use &lt;code&gt;StdoutLock&lt;&#x2F;code&gt; to reduce
the performance impact in some cases, but what if we could eliminate the
builtin mutex altogether?&lt;&#x2F;p&gt;
&lt;p&gt;What if stdout was a value that a program would acquire once, and then pass
around to all functions that want to print to it? Using Rust&#x27;s usual ownership
and borrowing rules, it wouldn&#x27;t need a mutex for many use cases. And users
could of course still explicitly wrap it in a &lt;code&gt;Mutex&lt;&#x2F;code&gt; or similar in cases where
they really want shared access to it, just like anything else in Rust.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;io-streams&quot;&gt;&lt;code&gt;io-streams&lt;&#x2F;code&gt; crate&lt;&#x2F;a&gt; has an implementation of this. The
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-streams&#x2F;latest&#x2F;io_streams&#x2F;struct.StreamWriter.html#method.stdout&quot;&gt;&lt;code&gt;StreamWriter::stdout&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function returns an output stream which writes to
the process&#x27; standard output. It implements the standard &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;io&#x2F;trait.Write.html&quot;&gt;&lt;code&gt;Write&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; trait
so it&#x27;s easy to use, and it conceptually owns its resource, so it doesn&#x27;t
need a builtin mutex.&lt;&#x2F;p&gt;
&lt;p&gt;Behind the scenes, this function actually acquires a &lt;code&gt;StdoutLock&lt;&#x2F;code&gt; to prevent
accidental mixing of &lt;code&gt;std::io::stdout&lt;&#x2F;code&gt; usage with &lt;code&gt;StreamWriter::stdout&lt;&#x2F;code&gt;
usage, to uphold its exclusive ownership assumption.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;example-files&quot;&gt;Example: Files&lt;&#x2F;h2&gt;
&lt;p&gt;As another example, any code can do &lt;code&gt;File::open(...)&lt;&#x2F;code&gt; and pass it a string,
to open any file in the process&#x27; filesystem namespace, without declaring it
in a function signature.&lt;&#x2F;p&gt;
&lt;p&gt;This means that if you want to run piece of code that does this in a different
directory, the only way to do so is to create a new process, with a new
filesystem namespace. This is a very heavy-weight operation, both in terms of
performance and memory usage, but also in terms of portability and complexity.&lt;&#x2F;p&gt;
&lt;p&gt;Some codebases have a convention of having a &amp;quot;root&amp;quot; path that is passed in
that everything is relative to, which helps, but doesn&#x27;t enforce that all
paths are relative to the root, or that paths don&#x27;t lead outside the root
using &lt;code&gt;..&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;cap-std&quot;&gt;&lt;code&gt;cap-std&lt;&#x2F;code&gt; crate&lt;&#x2F;a&gt; has a &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;cap-std&#x2F;latest&#x2F;cap_std&#x2F;fs&#x2F;struct.Dir.html&quot;&gt;&lt;code&gt;Dir&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; type, which represents a directory,
which can make filesystem access a first-class part of a function&#x27;s signature,
and allow callers to specify a different directory for the I&#x2F;O to happen in.
And, it also performs sandboxing, ensuring that paths relative to the &lt;code&gt;Dir&lt;&#x2F;code&gt;
stay within the &lt;code&gt;Dir&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Filesystems are effectively pools of aliased mutable state, and with relatively
weak synchronization primitives. While &lt;code&gt;cap-std&lt;&#x2F;code&gt; doesn&#x27;t address all the
problems that can arise from this, it can be one tool for helping manage
this state with standard Rust idioms.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tangent-rethinking-pure-functions&quot;&gt;Tangent: Rethinking &amp;quot;pure&amp;quot; functions&lt;&#x2F;h2&gt;
&lt;p&gt;Rust doesn&#x27;t have a way to declare functions as &amp;quot;pure&amp;quot;, having no side effects.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;this_is_pure&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;y&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;   x + y
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(As an aside, this function could panic on overflow; in what follows, I assume
&amp;quot;pure&amp;quot; permits panics.)&lt;&#x2F;p&gt;
&lt;p&gt;Features to enable this have been &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;issues&#x2F;1631&quot;&gt;proposed&lt;&#x2F;a&gt; a few times, but they haven&#x27;t been
added to the language, in part because the need for such features tends to be
lower in Rust than other languages. From an optimizer perspective, this
property can often be inferred, at least in simple cases.&lt;&#x2F;p&gt;
&lt;p&gt;And from a programmer perspective, programmers don&#x27;t need &amp;quot;pure&amp;quot; to know whether
arguments are mutated or not, because in Rust, these things are already
declared, reliably, in the signature. The presence or absence of &lt;code&gt;&amp;amp;mut&lt;&#x2F;code&gt; or
types with interior mutability tells you everything you need to know about
which arguments could be mutated. As such, much of what &amp;quot;pure&amp;quot; would mean would
be redundant with information which is already there:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Can you guess which state this function mutates?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;increment&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut i32&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; You&amp;#39;re right!
&lt;&#x2F;span&gt;&lt;span&gt;   *x += &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The things that aren&#x27;t covered by the signature are global mutable state and
I&#x2F;O. Global mutable state tends to be less important in Rust than other
languages because Rust pretty strongly discourages global mutable state.&lt;&#x2F;p&gt;
&lt;p&gt;However, Rust doesn&#x27;t outright prohibit global mutable state, and doesn&#x27;t
really discourage global I&#x2F;O, which is present even in the standard library.&lt;&#x2F;p&gt;
&lt;p&gt;So instead of a &amp;quot;pure&amp;quot;, that prohibits all mutations, the more interesting
property would be what I&#x27;ll call &amp;quot;explicit&amp;quot;, which would mean &amp;quot;no global
mutable state or I&#x2F;O&amp;quot;. When used on a function with no &lt;code&gt;&amp;amp;mut&lt;&#x2F;code&gt; or
interior-mutable types in the signature, &amp;quot;explicit&amp;quot; would be the same as
&amp;quot;pure&amp;quot;, and could be declared as &amp;quot;pure&amp;quot; to optimizers. However, &amp;quot;explicit&amp;quot;
could be used in functions that do have mutable arguments too, where it
would indicate that those are the only things that are mutated.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; All mutations and I&#x2F;O are accounted for!
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;this_is_explicit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;File, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut i32&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; io::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    writeln!(f, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello world&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;    *x += &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &amp;quot;explicit&amp;quot; property would also serve to indicate a lack of
&lt;em&gt;ambient authority&lt;&#x2F;em&gt;, from a &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Capability-based_security&quot;&gt;capability-oriented security&lt;&#x2F;a&gt; perspective.&lt;&#x2F;p&gt;
&lt;p&gt;Would it make sense to add an &amp;quot;explicit&amp;quot; keyword to Rust then? Probably not
as such; it&#x27;s likely that the majority of functions in Rust would qualify as
&amp;quot;explicit&amp;quot;, so adding it as a function attribute would add a lot of clutter.
A more ergonomic approach might be to give crates a way to declare that all
their functions are explicit, with a way to opt out for individual functions.&lt;&#x2F;p&gt;
&lt;p&gt;A possible direction for future exploration would be to use the
&lt;a href=&quot;https:&#x2F;&#x2F;rustc-dev-guide.rust-lang.org&#x2F;rustc-driver.html&quot;&gt;rustc driver API&lt;&#x2F;a&gt; to create a custom static analysis tool that could recognize
some form of syntax for this and then check that &amp;quot;explicit&amp;quot; functions don&#x27;t
accidentally call &amp;quot;non-explicit&amp;quot; functions without explicit overrides, much
like &lt;code&gt;unsafe&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;First-class I&#x2F;O points to a way of thinking about software where &amp;quot;the machine&amp;quot;
it&#x27;s running on or &amp;quot;the process&amp;quot; it&#x27;s running in aren&#x27;t the focus. Instead of
ad-hoc conventions for coordinating access to a shared filesystem namespace or
other process-associated resources, code using first-class I&#x2F;O can pass values
around to manage its I&#x2F;O resources similar to how it already manages other
program resources.&lt;&#x2F;p&gt;
&lt;p&gt;First-class I&#x2F;O can be a useful concept to apply broadly, such as how
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Capability-based_security&quot;&gt;capability-oriented security&lt;&#x2F;a&gt; helps enable &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;interface-types&#x2F;blob&#x2F;master&#x2F;proposals&#x2F;interface-types&#x2F;Explainer.md#creating-maximally-reusable-modules&quot;&gt;shared-nothing linking&lt;&#x2F;a&gt;. It can
also be useful to apply incrementally, such as how the &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;io-streams&quot;&gt;&lt;code&gt;io-streams&lt;&#x2F;code&gt; crate&lt;&#x2F;a&gt;
or the &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;cap-std&quot;&gt;&lt;code&gt;cap-std&lt;&#x2F;code&gt; crate&lt;&#x2F;a&gt; can help parts of a program cooperate with each other
efficiently and idiomatically.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pchickey&quot;&gt;Pat Hickey&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;lukewagner&quot;&gt;Luke Wagner&lt;&#x2F;a&gt; for feedback on this post!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Canonicalization</title>
		<published>2018-10-22T00:00:00+00:00</published>
		<updated>2018-10-22T00:00:00+00:00</updated>
		<link href="https://blog.sunfishcode.online/canonicalization/" type="text/html"/>
		<id>https://blog.sunfishcode.online/canonicalization/</id>
		<content type="html">&lt;p&gt;Canonicalization and canonical forms are one dimension of organizing the
work of an optimizing compiler.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;intro&quot;&gt;Intro&lt;&#x2F;h2&gt;
&lt;p&gt;A lot of code constructs can be written in multiple ways. For example:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;   x + 4
&lt;&#x2F;span&gt;&lt;span&gt;   4 + x
&lt;&#x2F;span&gt;&lt;span&gt;   (x + 2) + 2
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Canonicalization&lt;&#x2F;em&gt; means picking one of these forms to
be the &lt;em&gt;canonical form&lt;&#x2F;em&gt;, and then going through the program and
rewriting all constructs which are equivalent to the canonical
form into the canonical form.&lt;&#x2F;p&gt;
&lt;p&gt;In the case of add, it&#x27;s common to pick the form that has a constant
on the right side, so we&#x27;d rewrite all
these constructs to &lt;code&gt;x + 4&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;why-is-canonicalization-useful&quot;&gt;Why is canonicalization useful?&lt;&#x2F;h3&gt;
&lt;p&gt;The goal of canonicalization is &lt;em&gt;to make subsequent optimizations more
effective&lt;&#x2F;em&gt;. This is a key point, and we&#x27;ll get into some of the subtleties
below. But there are a lot of cases where it&#x27;s just obviously a good thing
to do. It means that subsequent optimizations that look for specific patterns of code
only have to look for the canonical forms, rather than all forms.&lt;&#x2F;p&gt;
&lt;p&gt;Another way of saying this is, having a canonicalization pass is a
way of factoring out the parts in a compiler that know all the different
forms &lt;code&gt;x + 4&lt;&#x2F;code&gt; could take, so that most optimization passes don&#x27;t have
to worry about this. They don&#x27;t have to look for &lt;code&gt;4 + x&lt;&#x2F;code&gt;, because they
can assume that looking for &lt;code&gt;x + 4&lt;&#x2F;code&gt; covers that. Handy!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;how-do-we-choose-a-canonical-form&quot;&gt;How do we choose a canonical form?&lt;&#x2F;h3&gt;
&lt;p&gt;Sometimes it&#x27;s easy. The canonical form for &lt;code&gt;2 + 3&lt;&#x2F;code&gt; is &lt;code&gt;5&lt;&#x2F;code&gt;, because
that&#x27;s clearly simpler in every possible way.&lt;&#x2F;p&gt;
&lt;p&gt;Sometimes it&#x27;s an arbitrary choice. It often doesn&#x27;t matter than much
whether one picks &lt;code&gt;4 + x&lt;&#x2F;code&gt; over &lt;code&gt;x + 4&lt;&#x2F;code&gt;, but it is helpful to pick one
or the other, so sometimes it&#x27;s just human aesthetics.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s tempting to pick whatever form would be fastest, or &lt;em&gt;optimal&lt;&#x2F;em&gt;, on
the target machine. And indeed, sometimes what&#x27;s fastest aligns with what&#x27;s
simplest. &lt;code&gt;2 + 3&lt;&#x2F;code&gt; canonicalizing &lt;code&gt;5&lt;&#x2F;code&gt; is typically such a case. But
sometimes it doesn&#x27;t.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;yeah-so-what-about-x-2&quot;&gt;Yeah so what about &lt;code&gt;x * 2&lt;&#x2F;code&gt;...&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;x * 2&lt;&#x2F;code&gt; is equivalent to &lt;code&gt;x + x&lt;&#x2F;code&gt;; which of these should be
the canonical form? It might seem like we might want to say: pick whatever&#x27;s
optimal for the target architecture. Addition is generally
faster than multiplication, so that would suggest we pick &lt;code&gt;x + x&lt;&#x2F;code&gt; as
the canonical form.&lt;&#x2F;p&gt;
&lt;p&gt;But, &lt;code&gt;x + x&lt;&#x2F;code&gt; can actually make things harder for subsequent
optimizations, because it means that now &lt;code&gt;x&lt;&#x2F;code&gt; has multiple uses. Having multiple uses
makes some optimizations more complex -- in terms of the dependence graph,
this is a DAG rather than a tree, and trees are generally simpler to
work with. So maybe &lt;code&gt;x * 2&lt;&#x2F;code&gt; is actually a better canonical form, even if it&#x27;s a worse optimal form.&lt;&#x2F;p&gt;
&lt;p&gt;That said, we might consider canonicalizing this to &lt;code&gt;x &amp;lt;&amp;lt; 1&lt;&#x2F;code&gt;, which has only one use of &lt;code&gt;x&lt;&#x2F;code&gt;,
and has the nice property of making it as obvious as
possible that the least significant bit of the result is zero. That way,
we don&#x27;t have to have as much random knowledge of multiplication by
powers of two strewn throughout the compiler.&lt;&#x2F;p&gt;
&lt;p&gt;Efficiency on the target machine still matters, but we can defer thinking
about that until codegen, where it&#x27;s no longer as important to enable
subsequent optimizations. At that point, we&#x27;re going to start caring about picking between &lt;code&gt;+&lt;&#x2F;code&gt;,
&lt;code&gt;*&lt;&#x2F;code&gt;, and &lt;code&gt;&amp;lt;&amp;lt;&lt;&#x2F;code&gt; based on which one executes fastest.&lt;&#x2F;p&gt;
&lt;p&gt;The basic philosophy
of canonicalization says that canonical forms should be translated into
optimal forms toward the back of the compiler, after all mid-level
optimizations which benefit from canonical form are done. It&#x27;s also
worth noting that codegen itself benefits from having the
code coming into it be in canonical form, so that it doesn&#x27;t have to
recognize all the ways to write &lt;code&gt;x &amp;lt;&amp;lt; 1&lt;&#x2F;code&gt;, and can just recognize one
pattern for that and emit the optimal code for it.&lt;&#x2F;p&gt;
&lt;p&gt;This is often a source of confusion: Is canonicalization
the same as optimization? It&#x27;s often done as part of the &amp;quot;optimizer&amp;quot;, and
many of the things it does produce more optimal code directly. But
ultimately, in its purest form, canonicalization just focuses on
removing unnecessary variation so that subsequent optimizations can
be simpler.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Canonical form, canonical form&lt;br&gt;
Canonical form hates optimal form&lt;br&gt;
They have a fight, canonical wins&lt;br&gt;
Canonical form…&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;(sung to the tune of &amp;quot;Particle Man&amp;quot; by They Might Be Giants)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sometimes-it-s-ambiguous-redundancy-elimination&quot;&gt;Sometimes it&#x27;s ambiguous: redundancy elimination&lt;&#x2F;h3&gt;
&lt;p&gt;Is redundancy elimination a canonicalization or an optimization?&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s certainly simpler to compute a given value once and reuse the value, rather than compute it twice.
But does that aid subsequent optimizations? It depends.&lt;&#x2F;p&gt;
&lt;p&gt;A case where it does aid subsequent optimizations is when it eliminates redundant memory accesses.
That way, it&#x27;s essentially saying that no later passes have to even ask what the dependencies are
for a given memory access, because the memory access has been eliminated.&lt;&#x2F;p&gt;
&lt;p&gt;A case where it doesn&#x27;t is where it can take expression trees where everything has a single use and
give some values multiple uses. Some kinds of optimization passes are harder to do on DAGs than on
trees, so this can result in pessimizations in some cases, depending on what kinds of things the
rest of the compiler is doing.&lt;&#x2F;p&gt;
&lt;p&gt;However, we typically do think of redundancy elimination as being a canonicalization.
It&#x27;s trivial to convert multiple-use values into single-use values by duplicating code,
while going the other direction requires some analysis.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;even-more-ambiguous-inlining&quot;&gt;Even more ambiguous: inlining&lt;&#x2F;h3&gt;
&lt;p&gt;Inlining can act like canonicalization, especially in cases where the inlined function body can
be optimized away. However, thinking of inlining in terms of canonicalization doesn&#x27;t lead to a natural threshold. Should we maximally
inline everything as far as possible? Or should we do the reverse and maximally outline and deduplicate
outlined functions? Neither extreme is particularly practical, so most compilers use heuristics in
practice rather than having a rigid definition of canonical form relative to calls.&lt;&#x2F;p&gt;
&lt;p&gt;That said, even though there&#x27;s no clear boundary, we can imagine a rough guideline.
Think of old-school C code, written at a time when &amp;quot;C is a portable assembly language&amp;quot;
was more true than it is today, where calls that were important to inline were
written as macros. In many ways, one of the jobs of compilers for higher-level languages
is to compile them down to roughly this level, so that they can be optimized using
optimization techniques which work well at this level. In theory, we could define the
task of a canonicalizing inliner to just be to inline code down to what it would have
looked like if that same code had been written in old-school C (at least with
respect to inlining). That&#x27;s not very pure, and it&#x27;s difficult to precisely describe,
but it&#x27;s an intuitive and relatively practical compromise between extremes.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;canonical-form-isn-t-just-for-arithmetic-expressions&quot;&gt;Canonical form isn&#x27;t just for arithmetic expressions!&lt;&#x2F;h3&gt;
&lt;p&gt;Everything in an IR may be subjected to canonicalization.&lt;&#x2F;p&gt;
&lt;p&gt;For example, a control flow canonicalization might involve sorting the
basic blocks of a program into Reverse Post-Order (RPO). Doing this is
a simple way to ensure that the code is optimized the same regardless
of how the user organizes the code inside their functions.&lt;&#x2F;p&gt;
&lt;p&gt;Dead code elimination is also a kind of canonicalization. The canonical
form for dead code is no code.&lt;&#x2F;p&gt;
&lt;p&gt;In aggressive loop-transforming compilers, another form of canonicalization
is to maximally fission loops into as many parts as possible, and then
assume subsequent passes will fuse them back together into optimal
loops that effectively utilize available registers and cache space.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;canonicalization-as-compression&quot;&gt;Canonicalization as compression&lt;&#x2F;h3&gt;
&lt;p&gt;It&#x27;s often the case that smaller forms are preferred over longer
forms, so canonicalization tends to make code smaller, making it a
form of compression. Also, since it effectively reduces non-essential
entropy, it can make subsequent general-purpose compression more
effective as well.&lt;&#x2F;p&gt;
&lt;p&gt;If we could conceptually perform all theoretically possible
canonicalizations on a program, we&#x27;d end up with something related to
its &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Kolmogorov_complexity&quot;&gt;Kolmogorov Complexity&lt;&#x2F;a&gt;
(it may not be identical, since canonicalization puts the needs of
subsequent optimizations first, rather than absolute compression).
Maximal canonicalization is frequently impossible in practice, because
of the halting problem, but also because even in cases where it&#x27;s
theoretically possible, it can require impractical amounts of computation.&lt;&#x2F;p&gt;
&lt;p&gt;That said, it is pretty fun to think that for any given program, there
is a theoretical &amp;quot;maximally canonical form&amp;quot; for that program, that
all equivalent ways of writing that program could be reduced to. It
is tempting to think of this as a kind of pure essence of the program.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;excessive-canonicalization&quot;&gt;Excessive canonicalization&lt;&#x2F;h3&gt;
&lt;p&gt;Canonicalization discards inessential information.
However, sometimes that information can be useful to preserve.&lt;&#x2F;p&gt;
&lt;p&gt;An example arises in instruction scheduling: Say a user writes code like&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;  x = a + b;
&lt;&#x2F;span&gt;&lt;span&gt;  y = c * d;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Assuming there&#x27;s no aliasing going on here, there&#x27;s no reason why
one of these statements has to be ordered before the other. Their
order in the user&#x27;s source code is inessential information.
&amp;quot;Sea of nodes&amp;quot; style compilers may canonicalize to the point where
there is no inherent ordering between these two statements.&lt;&#x2F;p&gt;
&lt;p&gt;The compiler backend ultimately has to produce machine code, which
on conventional architectures requires the compiler to pick &lt;em&gt;some&lt;&#x2F;em&gt;
ordering. Compilers can be pretty smart, and can take into
consideration many things, such as available execution resources
before and after these statements to know what order a 
CPU would prefer to see them in. However, as smart as they can be,
compilers can&#x27;t always find the optimal answers. Optimal instruction
scheduling is NP complete, but also, it may come down to runtime
factors that ahead-of-time compilers don&#x27;t have. And 
CPU hardware performance characteristics aren&#x27;t always fully
documented.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;do-no-harm&quot;&gt;&amp;quot;Do No Harm&amp;quot;?&lt;&#x2F;h4&gt;
&lt;p&gt;Most software has no idea how it&#x27;ll be mapped on to CPU pipelines.
But some does. And it&#x27;s these cases where getting the mapping right is
most important.&lt;&#x2F;p&gt;
&lt;p&gt;On such software, optimizations that make actual improvements are fine, however it can be
important that compilers not make anything &lt;em&gt;worse&lt;&#x2F;em&gt; than if they
had translated the code naively. Aggressively canonicalizing compilers
have a risk that they will throw away information and at the end
reconstruct a form which is worse than if they had just simply translated the code as it was written.&lt;&#x2F;p&gt;
&lt;p&gt;This, along with the ambiguous cases above, suggests that canonicalization
be used in practical rather than rigid ways.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;the-theoretical-shape-of-optimization&quot;&gt;The theoretical shape of optimization.&lt;&#x2F;h2&gt;
&lt;p&gt;A compiler typically starts with human-written source code.&lt;&#x2F;p&gt;
&lt;p&gt;Typical human-written code
follows various human-oriented sensibilities. Different humans may have different aesthetic sensibilities,
and this can lead to writing the same code in different ways. But of
course this isn&#x27;t interesting to optimizers.&lt;&#x2F;p&gt;
&lt;p&gt;So the first then we typically do when the code hits the optimizers is
to start canonicalizing. Throw away useless fluff that humans
imbue their code with.&lt;&#x2F;p&gt;
&lt;p&gt;Canonicalizing optimizations are cascading; often doing one canonicalization
will enable more. Folding an expression to a constant may allow other
expressions to be folded to constants. Replacing a load by forwarding a value
through a prior store may create a direct edge between two expression trees
and introduce opportunities to simplify further.&lt;&#x2F;p&gt;
&lt;p&gt;So ignoring the practical concerns we mentioned above, we can imagine a
theoretical compiler that does all the canonicalization it knows how to do
up front. And while we don&#x27;t realistically approach Kolmogorov Complexity
levels, we do lift the program closer to what we might think of as its
essence, the simplest form that does what it needs to do.&lt;&#x2F;p&gt;
&lt;p&gt;And then, the compiler can begin to optimize, rewriting canonical forms into
optimal forms, as it lowers the code all the way down to assembly code.&lt;&#x2F;p&gt;
&lt;p&gt;For practical reasons, it isn&#x27;t always possible to build compilers in terms
of a purely canonicalizing phase and a purely optimizing phase, however this
can be a useful reference point for understanding compilers in practice.&lt;&#x2F;p&gt;
</content>
	</entry>
</feed>
