Commit Graph

165 Commits

Author SHA1 Message Date
Jason A. Donenfeld 20584d1c32 support: account for protosw change
e7d02be19 ("protosw: refactor protosw and domain static declaration and
load") changed the way this function should be invoked.

Link: e7d02be19d
Reported-by: Michael Pro <michael.adm@gmail.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2022-09-04 19:19:55 +02:00
Jason A. Donenfeld 3cc22b29d6 version: bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2022-06-15 16:11:06 +02:00
Joseph Mingrone 11468c59f8 compat: update version to handle sbcreatecontrol() changes
The sockbuf changes to merge two versions of sbcreatecontrol() into one
occurred in b46667c63eb7 in the FreeBSD src repository.  The value of
__FreeBSD_version at the time of that commit was 1400059, so check
for systems with a version stamp less than 1400059.

Ideally __FreeBSD_version would have been bumped in b46667c63eb7,
however it was set to 1400059 53 commits prior in 3a9a9c0ca44e and not
bumped to 1400060 until 374 commits later in 85d7875d4291.  Thus, this
is not a perfect solution because CURRENT systems built from 53 possible
commits that require the adjustment will still fail to build the
wireguard kernel module.  This is better than checking for systems with
__FreeBSD_version < 1400057.  In that case, there are 767 different
commits a CURRENT system may be built from where the module will fail to
build.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2022-06-14 21:58:03 +02:00
Jason A. Donenfeld 5ba28362fe crypto: inline blake2s convenience function
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2022-06-14 11:35:01 +02:00
Jason A. Donenfeld 5c58322798 wg_noise: import hmac from crypto
This is weird and no library should implement it. Bring it into wg_noise
instead.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2022-06-14 11:33:26 +02:00
Jason A. Donenfeld a7d386f91e version: bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2022-06-14 11:19:42 +02:00
Jason A. Donenfeld e519e8e44d compat: fix version stamp
Reported-by: Michael Butler <imb@protected-networks.net>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2022-06-14 01:26:13 +02:00
Jason A. Donenfeld 416c5dcf27 crypto: harmonize with compat and clean up
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2022-06-14 01:24:38 +02:00
John Baldwin 613c964ee9 crypto: use curve25519 API from the kernel when available
Signed-off-by: John Baldwin <jhb@FreeBSD.org>
2022-06-14 00:55:29 +02:00
John Baldwin f59e60e369 crypto: use <crypto/chacha20_poly1305.h> when present
Signed-off-by: John Baldwin <jhb@FreeBSD.org>
2022-06-14 00:55:15 +02:00
John Baldwin a6354a1436 crypto: use OCF to encrypt/decrypt packets when supported
This requires the the recent changes in FreeBSD to support the
Chacha20-Poly1305 AEAD cipher with support for an 8 byte nonce (vs the
12 byte nonce used by TLS and IPsec).

Signed-off-by: John Baldwin <jhb@FreeBSD.org>
2022-06-14 00:54:55 +02:00
John Baldwin b7441e3154 if_wg: wg_peer_alloc and wg_aip_add: Use M_WAITOK with malloc
Signed-off-by: John Baldwin <jhb@FreeBSD.org>
2022-06-14 00:54:37 +02:00
Jason A. Donenfeld ccf37db6e6 build: include compat.h for all files
54b2075 ("build: only include compat.h for if_wg.c and fix build with an
obj directory") scoped compat.h to if_wg.c, which broke building on
12.3.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2022-06-10 23:37:49 +02:00
Jason A. Donenfeld d0c75d8e7d version: bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2022-06-10 19:21:17 +02:00
Jason A. Donenfeld c66627f1ea if_wg: account for added argument to sbcreatecontrol
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2022-06-10 19:16:09 +02:00
John Baldwin 352883bb38 crypto: return an error code from mbuf crypt routines
This permits returning different error codes for different conditions.

Signed-off-by: John Baldwin <jhb@FreeBSD.org>
2022-06-10 19:04:15 +02:00
John Baldwin 7658a19cb6 if_wg: wg_module_init: clean up more if the self tests fail
Signed-off-by: John Baldwin <jhb@FreeBSD.org>
2022-06-10 18:58:50 +02:00
John Baldwin ddc22dade9 if_wg: avoid scheduling excessive tasks for encryption/decryption
Previously the wg_encrypt/decrypt_dispatch routines would wakeup all
of the non-scheduled tasks.  This resulted in waking up several tasks
which did no useful work but did add overhead in terms of extra
context switches, etc.  In a single-threaded iperf3 TCP test on an
8-CPU system, only ~13% of the scheduled tasks did any work.

Instead, adopt a similar scheme to that used in the Linux wireguard
driver in which each call only wakes up a single task and uses
per-queue CPU iterators to round-robin among CPUs when choosing a task
to schedule.  This improved throughput in the iperf3 TCP test by more
than double and ~65% of scheduled tasks did useful work.

Signed-off-by: John Baldwin <jhb@FreeBSD.org>
2022-06-10 18:58:50 +02:00
John Baldwin dad3e685f5 if_wg: wg_mbuf_reset: don't free send tags
Send tags are only added on mbufs sent to an interface which
supports if_snd_tag_alloc.  Just assert that they are never
present instead.

Signed-off-by: John Baldwin <jhb@FreeBSD.org>
2022-06-10 18:57:51 +02:00
John Baldwin 60ac45234c wg_cookie: ratelimit_init: use callout_init_mtx
callout_init_rw() happens to compile ok because both are macros that
dereference the passed in lock's "lock_object" member to pass to the
real function.

Signed-off-by: John Baldwin <jhb@FreeBSD.org>
2022-06-10 18:57:33 +02:00
John Baldwin 7196782c5d if_wg: wg_clone_create: Use M_WAITOK with malloc
Signed-off-by: John Baldwin <jhb@FreeBSD.org>
2022-06-10 18:57:22 +02:00
John Baldwin 8c2797b04a if_wg: wgc_get/set: use M_WAITOK with malloc()
This reduces the edge cases which need handling, and M_WAITOK is safe
to use in this context.

While here, narrow the scope of the sc_lock to the code that interacts
with the softc, but not copyin/copyout, malloc, and nvlist_pack calls
before and after interacting with the softc.

Signed-off-by: John Baldwin <jhb@FreeBSD.org>
2022-06-10 18:57:16 +02:00
John Baldwin 1d5dd08074 if_wg: wg_queue_delist_staged: use more standard STAILQ_CONCAT
No functional change.

Signed-off-by: John Baldwin <jhb@FreeBSD.org>
2022-06-10 18:57:08 +02:00
John Baldwin a31339b25e if_wg: wg_queue_len: remove locking
Locking a mutex just to read a single word doesn't close any races.

Signed-off-by: John Baldwin <jhb@FreeBSD.org>
2022-06-10 18:57:00 +02:00
John Baldwin 54b2075e29 build: only include compat.h for if_wg.c and fix build with an obj directory
In particular, this permits building the module as part of a kernel
build via the LOCAL_MODULES facility.

Signed-off-by: John Baldwin <jhb@FreeBSD.org>
2022-06-10 18:56:32 +02:00
Jason A. Donenfeld b5cb87eebb if_wg: account for input function returning a boolean
Since 742e7210 ("udp: allow udp_tun_func_t() to indicate it did not eat
the packet"), wg_input must return a boolean. We force a cast for old
kernels. It'd be nicer to work around this in compat.h, but we can't
because FreeBSD's headers have dependencies we can't resolve from there.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2022-06-10 18:41:27 +02:00
Jason A. Donenfeld 5043212a73 if_wg: do not use continue statement on \!VIMAGE
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2022-06-10 17:42:51 +02:00
Jason A. Donenfeld 8ed513557b version: bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-11-05 15:40:17 +01:00
Jason A. Donenfeld 0c4dfbf209 if_wg: protect in6_mask2len with INET6
In the process, just don't do v6 allowedips if there's no INET6 support.

Reported-by: Yi <yu@boenyc.us>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-10-29 16:20:16 +02:00
Jason A. Donenfeld 93bd2b17d6 if_wg: bump keepalive timers unconditionally on send
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 <kevans@freebsd.org>
Reported-by: Ryan Roosa <ryanroosa@gmail.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-10-26 11:22:32 +02:00
Jason A. Donenfeld 64a507ad6b compat: taskqueue draining was backported to stable/13
Since 407b687dfef ("Make sure all tasklets are drained before unloading
the LinuxKPI. Else use-after-free may happen."), stable/13 now has the
taskqueue API that we need.

Reported-by: Herbert J. Skuhra <herbert@gojira.at>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-06-07 11:51:17 +02:00
Jason A. Donenfeld bf27d10262 version: bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-06-06 15:35:25 +02:00
Jason A. Donenfeld 7855bfe930 if_wg: do not crash if deiniting before vnet is up
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-06-06 15:33:17 +02:00
Jason A. Donenfeld 0955fa72f5 global: replace rwlock with mtx if never rlocked
There were multiple places where a rwlock was used despite never
rlocking, so just change these into mtxs. This was done with the aid of
Coccinelle's spatch, using this input:

    #spatch -j 4 --recursive-includes --include-headers-for-types --include-headers --in-place --macro-file <seebelow.h>

    virtual after_start

    @initialize:ocaml@
    @@

    let has_write_table = Hashtbl.create 101
    let has_read_table = Hashtbl.create 101

    let ok i m =
      let entry = (i,m) in
      Hashtbl.mem has_write_table entry && not(Hashtbl.mem has_read_table entry)

    @hasw depends on !after_start@
    identifier i,m;
    struct i x;
    @@

    (
    rw_wlock(&x.m)
    |
    rw_wunlock(&x.m)
    )

    @script:ocaml@
    i << hasw.i;
    m << hasw.m;
    @@
    Hashtbl.replace has_write_table (i,m) ()

    @hasr depends on !after_start@
    identifier i,m;
    struct i x;
    @@

    (
    rw_rlock(&x.m)
    |
    rw_runlock(&x.m)
    )

    @script:ocaml@
    i << hasr.i;
    m << hasr.m;
    @@
    Hashtbl.replace has_read_table (i,m) ()

    @finalize:ocaml depends on !after_start@
    wt << merge.has_write_table;
    rt << merge.has_read_table;
    @@

    let redo ts dst =
      List.iter (Hashtbl.iter (fun k _ -> Hashtbl.add dst k ())) ts in
    redo wt has_write_table;
    redo rt has_read_table;

    let it = new iteration() in
    it#add_virtual_rule After_start;
    it#register()

    (* ----------------------------------------------------------- *)

    @depends on after_start@
    identifier i;
    identifier m : script:ocaml(i) { ok i m };
    @@

    struct i {
      ...
    - struct rwlock m;
    + struct mtx m;
      ...
    }

    @depends on after_start disable fld_to_ptr@
    identifier m;
    identifier i : script:ocaml(m) { ok i m };
    struct i x;
    @@

    - rw_wlock
    + mtx_lock
       (&x.m)

    @depends on after_start disable fld_to_ptr@
    identifier m;
    identifier i : script:ocaml(m) { ok i m };
    struct i x;
    @@

    - rw_wunlock
    + mtx_unlock
       (&x.m)

    @depends on after_start disable fld_to_ptr@
    identifier m;
    expression e;
    identifier i : script:ocaml(m) { ok i m };
    struct i x;
    @@

    - rw_init(&x.m, e);
    + mtx_init(&x.m, e, NULL, MTX_DEF);

    @depends on after_start disable fld_to_ptr@
    identifier m;
    identifier i : script:ocaml(m) { ok i m };
    struct i x;
    @@

    - rw_destroy
    + mtx_destroy
       (&x.m)

    @depends on after_start disable fld_to_ptr, ptr_to_array@
    identifier m;
    identifier i : script:ocaml(m) { ok i m };
    struct i *x;
    @@

    - rw_wlock
    + mtx_lock
       (&x->m)

    @depends on after_start disable fld_to_ptr, ptr_to_array@
    identifier m;
    identifier i : script:ocaml(m) { ok i m };
    struct i *x;
    @@

    - rw_wunlock
    + mtx_unlock
       (&x->m)

    @depends on after_start disable fld_to_ptr, ptr_to_array@
    identifier m;
    expression e;
    identifier i : script:ocaml(m) { ok i m };
    struct i *x;
    @@

    - rw_init(&x->m, e);
    + mtx_init(&x->m, e, NULL, MTX_DEF);

    @depends on after_start disable fld_to_ptr, ptr_to_array@
    identifier m;
    identifier i : script:ocaml(m) { ok i m };
    struct i *x;
    @@

    - rw_destroy
    + mtx_destroy
       (&x->m)

A few macros needed to be provided manually for the parser to work:

    #define LIST_HEAD(x,y) int
    #define TAILQ_HEAD(x,y) int
    #define STAILQ_HEAD(x,y) int
    #define CK_LIST_HEAD(x,y) int
    #define CK_LIST_ENTRY(x) int
    #define LIST_ENTRY(x) int
    #define TAILQ_ENTRY(x) int
    #define STAILQ_ENTRY(x) int

Co-authored-by: Julia Lawall <julia.lawall@inria.fr>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-06-05 23:29:57 +02:00
Jason A. Donenfeld 5158e2c0f4 global: destroy rwlocks and mtxs
Before, most uses of rwlock and mtx never called the destroy method,
which might cause problems for witness.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-06-05 23:29:34 +02:00
Jason A. Donenfeld b4a0f872e6 compat: account for lack of CSUM_SND_TAG on ≤12.2
This was added to 12.1 in a security fix, but wasn't really wired up
properly, so this effectively disables it from packet resetting, which
is a bummer, but it's more preferable than hacking this in bad ways.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-06-01 15:27:11 +02:00
Jason A. Donenfeld 2265d72ca1 if_wg: add braces for 12.1 compiler warning
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-06-01 15:27:11 +02:00
Jason A. Donenfeld a554cedba4 if_wg: pass back result of selftests and enable in CI
Hopefully bad tests will cause the module to not insert, so the CI picks
this up. It looks like a failure to insert the module at the moment
actually causes another crash, though:

    Kernel page fault with the following non-sleepable locks held:
    exclusive sleep mutex if_cloners lock (if_cloners lock) r = 0 (0xffffffff81d9a9b8) locked @ /usr/src/sys/net/if_clone.c:447
    stack backtrace:
    #0 0xffffffff80c66181 at witness_debugger+0x71
    #1 0xffffffff80c6729d at witness_warn+0x40d
    #2 0xffffffff8109499e at trap_pfault+0x7e
    #3 0xffffffff81093fab at trap+0x2ab
    #4 0xffffffff810687f8 at calltrap+0x8
    #5 0xffffffff82925610 at wg_module_event_handler+0x120
    #6 0xffffffff80bd53c3 at module_register_init+0xd3
    #7 0xffffffff80bc5c61 at linker_load_module+0xc01
    #8 0xffffffff80bc73b9 at kern_kldload+0xe9
    #9 0xffffffff80bc74db at sys_kldload+0x5b
    #10 0xffffffff810952f7 at amd64_syscall+0x147
    #11 0xffffffff8106911e at fast_syscall_common+0xf8

    Fatal trap 12: page fault while in kernel mode
    cpuid = 9; apic id = 09
    fault virtual address   = 0x70
    fault code              = supervisor read data, page not present
    instruction pointer     = 0x20:0xffffffff80d18e37
    stack pointer           = 0x28:0xfffffe0115fb35a0
    frame pointer           = 0x28:0xfffffe0115fb35c0
    code segment            = base 0x0, limit 0xfffff, type 0x1b
                            = DPL 0, pres 1, long 1, def32 0, gran 1
    processor eflags        = interrupt enabled, resume, IOPL = 0
    current process         = 1587 (kldload)
    trap number             = 12
    panic: page fault
    cpuid = 9
    time = 1621380034
    KDB: stack backtrace:
    #0 0xffffffff80c44695 at kdb_backtrace+0x65
    #1 0xffffffff80bf9d01 at vpanic+0x181
    #2 0xffffffff80bf9ad3 at panic+0x43
    #3 0xffffffff81094917 at trap_fatal+0x387
    #4 0xffffffff810949b7 at trap_pfault+0x97
    #5 0xffffffff81093fab at trap+0x2ab
    #6 0xffffffff810687f8 at calltrap+0x8
    #7 0xffffffff82925610 at wg_module_event_handler+0x120
    #8 0xffffffff80bd53c3 at module_register_init+0xd3
    #9 0xffffffff80bc5c61 at linker_load_module+0xc01
    #10 0xffffffff80bc73b9 at kern_kldload+0xe9
    #11 0xffffffff80bc74db at sys_kldload+0x5b
    #12 0xffffffff810952f7 at amd64_syscall+0x147
    #13 0xffffffff8106911e at fast_syscall_common+0xf8

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-05-19 01:23:09 +02:00
Jason A. Donenfeld 0f6950b07f version: bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-05-06 11:19:05 +02:00
Jason A. Donenfeld 47f0fccb86 if_wg: destroy interfaces before uma zone
Fixes:

    #12 0xffffffff80f20105 in uma_zalloc_arg (zone=<optimized out>,
        udata=<optimized out>, udata@entry=0x0, flags=flags@entry=257)
        at /usr/src/sys/vm/uma_core.c:3420
    #13 0xffffffff82922844 in uma_zalloc (zone=<unavailable>, flags=257)
        at /usr/src/sys/vm/uma.h:358
    #14 wg_packet_alloc (m=0xfffff801154bfa00) at if_wg.c:1769
    #15 wg_send_keepalive (peer=0xfffff800075dd000,
        peer@entry=<error reading variable: value is not available>)
        at if_wg.c:1291

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-05-03 19:55:50 +02:00
Jason A. Donenfeld 561f3a8f93 wg_noise: set handshake to dead before removing keypair
Otherwise CK_LIST_REMOVE might be called twice on the same element.
Running the following trigger will reproduce the bug that Manojav
reported:

    #!/usr/local/bin/bash
    NUM_PEER=50
    peer_args=( )
    for ((i=0; i<NUM_PEER; i++)); do
      port="$RANDOM"
      private="$(wg genkey)"
      ifconfig "wg$i" create
      wg set "wg$i" listen-port "$port" private-key <(echo "$private")
      peer_args+=( peer "$(wg pubkey <<<"$private")" endpoint "127.0.0.1:$port" persistent-keepalive 1 )
    done
    for ((i=0; i<NUM_PEER; i++)); do
      wg set "wg$i" "${peer_args[@]}"
      ifconfig "wg$i" up
    done
    wg
    while true; do
      for ((i=0; i<NUM_PEER; i++)); do
        ifconfig "wg$i" down
        ifconfig "wg$i" up
      done
    done

Reported-by: Manojav Sridhar <manojav@manojav.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-05-03 19:54:39 +02:00
Jason A. Donenfeld 280bee380d if_wg: put event notifiers in main loop
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-05-03 16:03:02 +02:00
Jason A. Donenfeld 1a515a5df1 version: bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-05-03 09:57:39 +02:00
Jason A. Donenfeld c61c06a812 wg_noise: cleanup counter algorithm
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-05-03 09:06:19 +02:00
Jason A. Donenfeld de25b2aa73 wg_cookie: zero before init in selftest for witness
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-05-02 20:52:11 +02:00
Jason A. Donenfeld a41a7eb994 if_wg: don't double increment error counter
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-05-02 20:24:24 +02:00
Jason A. Donenfeld 24c418a7ad if_wg: ensure packet is not shared before writing
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-05-02 20:17:18 +02:00
Jason A. Donenfeld 9095d03409 if_wg: don't memcpy data for no reason
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-05-02 19:51:21 +02:00
Jason A. Donenfeld 350e95248f if_wg: pad packets properly
This takes into account mismatched MTUs. Borrows the
"calculate_skb_padding" function from Linux.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-05-02 13:39:55 +02:00
Jason A. Donenfeld cad7ead734 if_wg: return to m temporary variable style
The rest of the code uses this, so go with it for now. Maybe later ncon
will want to clean up everything to be this way, but for now keep it
consistent.

This partially reverts commit a1fdf6646b,
but doesn't reintroduce the bug that it had fixed.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-04-30 10:28:39 +02:00