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; > +}