<feed xmlns='http://www.w3.org/2005/Atom'>
<title>wireguard-openbsd, branch master</title>
<subtitle>WireGuard implementation for the OpenBSD kernel</subtitle>
<id>https://git.zx2c4.com/wireguard-openbsd/atom/?h=master</id>
<link rel='self' href='https://git.zx2c4.com/wireguard-openbsd/atom/?h=master'/>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-openbsd/'/>
<updated>2021-10-26T09:34:13Z</updated>
<entry>
<title>Bump keepalive timers unconditionally on send</title>
<updated>2021-10-26T09:34:13Z</updated>
<author>
<name>Jason A. Donenfeld</name>
<email>Jason@zx2c4.com</email>
</author>
<published>2021-10-26T09:33:43Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-openbsd/commit/?id=06a7d898961e2a7dd60c62529974c155c877a6a9'/>
<id>urn:sha1:06a7d898961e2a7dd60c62529974c155c877a6a9</id>
<content type='text'>
The keepalive timers -- both persistent and mandatory -- are part of the
internal state machine, which needs to be cranked whether or not the
packet was actually sent. A packet might be dropped by the network. Or
the packet might be dropped by the local network stack. The latter case
gives a hint -- which is useful for the data_sent event -- but is
harmful to consider for the keepalive state machine. So, crank those
timers before even calling wg_send.

Incidentally, doing it this way matches exactly what Linux's send.c's
wg_packet_create_data_done and Go's send.go's RoutineSequentialSender do
too.

Suggested-by: Kyle Evans &lt;kevans@freebsd.org&gt;
Reported-by: Ryan Roosa &lt;ryanroosa@gmail.com&gt;
</content>
</entry>
<entry>
<title>Delete all peer allowed IPs at once</title>
<updated>2021-04-13T05:47:31Z</updated>
<author>
<name>Matt Dunwoodie</name>
<email>ncon@noconroy.net</email>
</author>
<published>2021-04-12T23:35:54Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-openbsd/commit/?id=5454705cf72a3461162b614f345f015dfc830414'/>
<id>urn:sha1:5454705cf72a3461162b614f345f015dfc830414</id>
<content type='text'>
This simplifies the deletion process, so we do not require a lookup of
the node before deletion.
</content>
</entry>
<entry>
<title>Merge wg_timers and wg_peer</title>
<updated>2021-04-13T05:47:31Z</updated>
<author>
<name>Matt Dunwoodie</name>
<email>ncon@noconroy.net</email>
</author>
<published>2021-04-04T12:55:44Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-openbsd/commit/?id=95bae487f1f4bae3ae1773b5a00015188be1ba2a'/>
<id>urn:sha1:95bae487f1f4bae3ae1773b5a00015188be1ba2a</id>
<content type='text'>
The primary motivator here is to get rid of CONTAINER_OF, which is quite
an ugly macro.

However, any reader should also be aware of the change from d_DISabled
to p_ENabled.
</content>
</entry>
<entry>
<title>Replace timer lock with SMR</title>
<updated>2021-04-13T05:47:31Z</updated>
<author>
<name>Matt Dunwoodie</name>
<email>ncon@noconroy.net</email>
</author>
<published>2021-04-04T12:35:43Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-openbsd/commit/?id=1df85964a33a4ff037aa60915f3d1f24140a2a62'/>
<id>urn:sha1:1df85964a33a4ff037aa60915f3d1f24140a2a62</id>
<content type='text'>
The lock was not used to protect any data structures, it was purely to
ensure race-free setting of t_disabled. That is, that no other thread
was halfway through any wg_timers_run_* function. With smr_* we can
ensure this is still the case by calling smr_barrier() after setting
t_disabled.
</content>
</entry>
<entry>
<title>Run all timeouts in process context</title>
<updated>2021-04-13T05:47:31Z</updated>
<author>
<name>Matt Dunwoodie</name>
<email>ncon@noconroy.net</email>
</author>
<published>2021-04-04T11:49:30Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-openbsd/commit/?id=49d9b81aabce4c7d8491262286a66a55e3698989'/>
<id>urn:sha1:49d9b81aabce4c7d8491262286a66a55e3698989</id>
<content type='text'>
So the reason timeouts were running in interrupt context was because it
was quicker. Running in process context required a `task` to be added,
which we ended up doing anyway. So we might as well rely on timeout API
to do it for us.
</content>
</entry>
<entry>
<title>Use malloc instead of pool_* for infrequent allocations</title>
<updated>2021-04-13T05:47:31Z</updated>
<author>
<name>Matt Dunwoodie</name>
<email>ncon@noconroy.net</email>
</author>
<published>2021-04-04T07:56:55Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-openbsd/commit/?id=463fb4a722d6dd7ad9b30481972210abd0317c97'/>
<id>urn:sha1:463fb4a722d6dd7ad9b30481972210abd0317c97</id>
<content type='text'>
We can get rid of the pool overhead by using the malloc family of
functions. This does lose us the ability to see directly how much each
allocation is using, but it if we really want that, maybe we add new
malloc types? Either way, not something we need at the moment.
</content>
</entry>
<entry>
<title>Use SMR for wg_noise</title>
<updated>2021-04-13T05:47:30Z</updated>
<author>
<name>Matt Dunwoodie</name>
<email>ncon@noconroy.net</email>
</author>
<published>2021-04-02T17:05:08Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-openbsd/commit/?id=acce302ce645ccc1a3f7f46fb2c399c611e623d8'/>
<id>urn:sha1:acce302ce645ccc1a3f7f46fb2c399c611e623d8</id>
<content type='text'>
While the largest change here is to use SMR for wg_noise, this was
motivated by other deficiencies in the module. Primarily, the nonce
operations should be performed in serial (wg_queue_out, wg_deliver_in)
and not parallel (wg_encap, wg_decap). This also brings in a lock-free
encrypt and decrypt path, which is nice.

I suppose other improvements are that local, remote and keypair structs
are opaque, so no more reaching in and fiddling with things.

Unfortunately, these changes make abuse of the API easier (such as
calling noise_keypair_encrypt on a keypair retrieved with
noise_keypair_lookup (instead of noise_keypair_current) as they have
different checks). Additionally, we have to trust that the nonce passed
to noise_keypair_encrypt is non repeating (retrieved with
noise_keypair_nonce_next), and noise_keypair_nonce_check is valid on
received nonces.

One area that could use a little bit more adjustment is the *_free
functions. They are used to call a function once it is safe to free a
parent datastructure (one holding struct noise_{local,remote} *). This
is currently used for lifetimes in the system and allows a consumer of
wg_noise to opaquely manage lifetimes based on the reference counting of
noise, remote and keypair. It is fine for now, but maybe revisit later.
</content>
</entry>
<entry>
<title>Add refcnt_take_if_gt()</title>
<updated>2021-04-13T05:47:30Z</updated>
<author>
<name>Matt Dunwoodie</name>
<email>ncon@noconroy.net</email>
</author>
<published>2021-04-03T13:15:47Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-openbsd/commit/?id=e447e5e6911f4dc85b71b8683614807a4bf342e1'/>
<id>urn:sha1:e447e5e6911f4dc85b71b8683614807a4bf342e1</id>
<content type='text'>
This function (or of similar nature) is required to safely use a refcnt
and smr_entry together. Such functions exist on other platforms as
kref_get_unless_zero (on Linux) and refcount_acquire_if_gt (on FreeBSD).

The following diagram details the following situation with and without
refcnt_take_if_gt in 3 cases, with the first showing the "invalid" use
of refcnt_take.

Situation:

Thread #1 is removing the global referenc (o).
Thread #2 wants to reference an object (r), using a thread pointer (t).

Case:

1) refcnt_take after Thread #1 has released "o"
2) refcnt_take_if_gt before Thread #1 has released "o"
3) refcnt_take_if_gt after Thread #1 has released "o"

Data:

struct obj {
	struct smr_entry smr;
	struct refcnt    refcnt;
} *o, *r, *t1, *t2;

          Thread #1              |               Thread #2
---------------------------------+------------------------------------
                                 | r = NULL;
 rw_enter_write(&amp;lock);          | smr_read_enter();
                                 |
 t1 = SMR_PTR_GET_LOCKED(&amp;o);    | t2 = SMR_PTR_GET(&amp;o);
 SMR_PTR_SET_LOCKED(&amp;o, NULL);   |
                                 |
 if (refcnt_rele(&amp;t1-&gt;refcnt)    |
   smr_call(&amp;t1-&gt;smr, free, t1); |
                                 | if (t2 != NULL) {
                                 |   refcnt_take(&amp;t2-&gt;refcnt);
                                 |   r = t2;
                                 | }
 rw_exit_write(&amp;lock);           | smr_read_exit();
                               .....
 // called by smr_thread         |
 free(t1);                       |
                               .....
                                 | // use after free
                                 | *r
---------------------------------+------------------------------------
                                 | r = NULL;
 rw_enter_write(&amp;lock);          | smr_read_enter();
                                 |
 t1 = SMR_PTR_GET_LOCKED(&amp;o);    | t2 = SMR_PTR_GET(&amp;o);
 SMR_PTR_SET_LOCKED(&amp;o, NULL);   |
                                 |
 if (refcnt_rele(&amp;t1-&gt;refcnt)    |
   smr_call(&amp;t1-&gt;smr, free, t1); |
                                 | if (t2 != NULL &amp;&amp;
                                 |  refcnt_take_if_gt(&amp;t2-&gt;refcnt, 0))
                                 |   r = t2;
 rw_exit_write(&amp;lock);           | smr_read_exit();
                               .....
 // called by smr_thread         | // we don't have a valid reference
 free(t1);                       | assert(r == NULL);
---------------------------------+------------------------------------
                                 | r = NULL;
 rw_enter_write(&amp;lock);          | smr_read_enter();
                                 |
 t1 = SMR_PTR_GET_LOCKED(&amp;o);    | t2 = SMR_PTR_GET(&amp;o);
 SMR_PTR_SET_LOCKED(&amp;o, NULL);   |
                                 | if (t2 != NULL &amp;&amp;
                                 |  refcnt_take_if_gt(&amp;t2-&gt;refcnt, 0))
                                 |   r = t2;
 if (refcnt_rele(&amp;t1-&gt;refcnt)    |
   smr_call(&amp;t1-&gt;smr, free, t1); |
 rw_exit_write(&amp;lock);           | smr_read_exit();
                               .....
                                 | // we need to put our reference
                                 | if (refcnt_rele(&amp;t2-&gt;refcnt))
                                 |   smr_call(&amp;t2-&gt;smr, free, t2);
                               .....
 // called by smr_thread         |
 free(t1);                       |
---------------------------------+------------------------------------

Currently it uses atomic_add_int_nv to atomically read the refcnt,
but I'm open to suggestions for better ways.

The atomic_cas_uint is used to ensure that refcnt hasn't been modified
since reading `old`.
</content>
</entry>
<entry>
<title>Check iter != NULL</title>
<updated>2021-04-13T05:47:30Z</updated>
<author>
<name>Matt Dunwoodie</name>
<email>ncon@noconroy.net</email>
</author>
<published>2021-03-27T22:19:47Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-openbsd/commit/?id=68de77e987c33ef3f9a8cfa9ce6d85d0798f9784'/>
<id>urn:sha1:68de77e987c33ef3f9a8cfa9ce6d85d0798f9784</id>
<content type='text'>
The problem with checking peer != NULL is that we already dereference
iter to get i_value. This is what was caught in the index == 0 bug
reported on bugs@. Instead, we should assert that iter != NULL.

This is likely to be removed when adjusting wg_noise.c in the not to
distant future.
</content>
</entry>
<entry>
<title>Allow setting keepalive while interface is down</title>
<updated>2021-04-13T05:47:30Z</updated>
<author>
<name>Matt Dunwoodie</name>
<email>ncon@noconroy.net</email>
</author>
<published>2021-03-27T22:18:02Z</published>
<link rel='alternate' type='text/html' href='https://git.zx2c4.com/wireguard-openbsd/commit/?id=5e02e86c4dadfaaa32f38195531cfab113e79c7f'/>
<id>urn:sha1:5e02e86c4dadfaaa32f38195531cfab113e79c7f</id>
<content type='text'>
</content>
</entry>
</feed>
