On Tue, May 26, 2020 at 07:39:01PM +1000, Matt Dunwoodie wrote:
> Hi tech,
> 
> After some feedback and comments, we've addressed the concerns, and
> fixed a few things from our side too. Overall the structure is familiar
> with no major changes, so any prior readings mostly carry over.
> 
> This is a quick summary of the changes. Detailed changes can be found
> on the out-of-tree repo or we can elaborate if more detail is needed.
> 
> * Allow non-root to read WireGuard network configuration of the
>   interface.
>   - This allows users to help debug issues without
>     escalating to root.
> 
> * Removal of wgconf option from ifconfig.
>   - This option was not mature enough for inclusion into base. Upon
>     reflection, this behaviour probably needs further consideration
>     about how to integrate into ifconfig.
> 
> * Fix ioctl interface.
>   - The linked list setup was fragile, complicated, and broken, so
>     we've gone with something much simpler, and user easy to program
>     for, using a boring ioctl pattern that's been tried successfully
>     elsewhere already.
> 
> * Limit the padding of the packet to the MTU.
>   - Fits the protocol spec and prevents unneccessary fragmentation.
> 
> * Align handshake/identity locks and timer semantics with spec and other
>   implementations.
>   - This avoids any subtle edge cases that may occur.
> 
> Here are the changes that shouldn't need any explanation:
> 
> * Updated documentation based on feedback from tech and others.
> * Maintain order of peers when adding/deleting  .
> * Rename noise_alloc to noise_upcall.
> * Remove wg_timers_fn indirection.
> 
> Minor formatting changes may also be present.
> 
> Once someone picks this up, we're more than happy to help integrate
> this and maintain it in-tree.
> 
> Signed
> Matt Dunwoodie

Hi Matt,

just repeating what I commented yesterday for the new diff to make sure
it isn't overlooked.

> +int
> +wg_ioctl_get(struct wg_softc *sc, struct wg_data_io *data)
> +{
> +     struct wg_interface_io  *iface_p, iface_o;
> +     struct wg_peer_io       *peer_p, peer_o;
> +     struct wg_aip_io        *aip_p;
> +
> +     struct wg_peer          *peer;
> +     struct wg_aip           *aip;
> +
> +     size_t                   size, peer_count, aip_count;
> +     int                      ret = 0, is_suser = suser(curproc) == 0;
> +
> +     size = sizeof(struct wg_interface_io);
> +     if (data->wgd_size < size && !is_suser)
> +             goto ret_size;
> +
> +     iface_p = data->wgd_interface;
> +     bzero(&iface_o, sizeof(iface_o));
> +
> +     rw_enter_read(&sc->sc_lock);
> +
> +     if (sc->sc_udp_port != 0) {
> +             iface_o.i_port = ntohs(sc->sc_udp_port);
> +             iface_o.i_flags |= WG_INTERFACE_HAS_PORT;
> +     }
> +
> +     if (sc->sc_udp_rtable != 0) {
> +             iface_o.i_rtable = sc->sc_udp_rtable;
> +             iface_o.i_flags |= WG_INTERFACE_HAS_RTABLE;
> +     }
> +
> +     if (!is_suser)
> +             goto out;
> +
> +     if (noise_local_keys(&sc->sc_local, iface_o.i_public,
> +         iface_o.i_private) == 0) {
> +             iface_o.i_flags |= WG_INTERFACE_HAS_PUBLIC;
> +             iface_o.i_flags |= WG_INTERFACE_HAS_PRIVATE;
> +     }
> +
> +     if (((SIZE_MAX - size) / sizeof(struct wg_peer_io)) < sc->sc_peer_num)
> +             goto error;
> +     size += sizeof(struct wg_peer_io) * sc->sc_peer_num;
> +     if (((SIZE_MAX - size) / sizeof(struct wg_aip_io)) < sc->sc_aip_num)
> +             goto error;

I still think those two should return an error.  'goto error' is misleading as
it doesn't actually set ret != 0.  'error' should probably be renamed
to 'cleanup' to avoid confusion and ret should be set to ERANGE .

> +     size += sizeof(struct wg_aip_io) * sc->sc_aip_num;
> +     if (data->wgd_size < size)
> +             goto error;
> +
> +     peer_count = 0;
> +     peer_p = &iface_p->i_peers[0];
> +     WG_PEERS_FOREACH(peer, sc) {
> +             bzero(&peer_o, sizeof(peer_o));
> +             peer_o.p_flags = WG_PEER_HAS_PUBLIC;
> +             peer_o.p_protocol_version = 1;
> +
> +             if (noise_remote_keys(&peer->p_remote, peer_o.p_public,
> +                 peer_o.p_psk) == 0)
> +                     peer_o.p_flags |= WG_PEER_HAS_PSK;
> +
> +             if (wg_timers_get_persistent_keepalive(&peer->p_timers,
> +                 &peer_o.p_pka) == 0)
> +                     peer_o.p_flags |= WG_PEER_HAS_PKA;
> +
> +             if (wg_peer_get_sockaddr(peer, &peer_o.p_sa) == 0)
> +                     peer_o.p_flags |= WG_PEER_HAS_ENDPOINT;
> +
> +             mtx_enter(&peer->p_counters_mtx);
> +             peer_o.p_txbytes = peer->p_counters_tx;
> +             peer_o.p_rxbytes = peer->p_counters_rx;
> +             mtx_leave(&peer->p_counters_mtx);
> +
> +             wg_timers_get_last_handshake(&peer->p_timers,
> +                 &peer_o.p_last_handshake);
> +
> +             aip_count = 0;
> +             aip_p = &peer_p->p_aips[0];
> +             LIST_FOREACH(aip, &peer->p_aip, a_entry) {
> +                     if ((ret = copyout(&aip->a_data, aip_p, 
> sizeof(*aip_p))) != 0)
> +                             goto error;
> +                     aip_p++;
> +                     aip_count++;
> +             }
> +             peer_o.p_aips_count = aip_count;
> +
> +             if ((ret = copyout(&peer_o, peer_p, sizeof(peer_o))) != 0)
> +                     goto error;
> +
> +             peer_p = (struct wg_peer_io *)aip_p;
> +             peer_count++;
> +     }
> +     iface_o.i_peers_count = peer_count;
> +
> +out:
> +     if ((ret = copyout(&iface_o, iface_p, sizeof(iface_o))) != 0)
> +             goto error;
> +error:
> +     rw_exit_read(&sc->sc_lock);
> +     explicit_bzero(&iface_o, sizeof(iface_o));
> +     explicit_bzero(&peer_o, sizeof(peer_o));
> +ret_size:
> +     data->wgd_size = size;
> +     return ret;
> +}

Reply via email to