From 23bf3cfccb5a6fa9faf85c35ca24ec4c3e29c3fe Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 16 Jun 2021 17:09:40 +0200 Subject: [PATCH] Kit: Adapter: use more reliable utun detection technique Rather than hoping that the AF_SYSTEM fd is of type utun, and then calling "2" on it to get the name -- which could be defined as something else for a different AF_SYSTEM socket type -- instead simply query the AF_SYSTEM control socket ID with getpeername. This has one catch, which is that the ID is dynamically allocated, so we resolve it using the qualified name. Normally we'd make a new AF_SYSTEM socket for this, but since that's not allowed in the sandbox, we reuse the AF_SYSTEM socket that we're checking. At this point in the flow, we know that it's a proper AF_SYSTEM one, based on the first sockaddr member; we just don't know that it's a utun variety. Signed-off-by: Jason A. Donenfeld --- Sources/WireGuardKit/WireGuardAdapter.swift | 27 ++++++++++++++++++--- Sources/WireGuardKitC/WireGuardKitC.h | 15 ++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/Sources/WireGuardKit/WireGuardAdapter.swift b/Sources/WireGuardKit/WireGuardAdapter.swift index b18769e..57e0b58 100644 --- a/Sources/WireGuardKit/WireGuardAdapter.swift +++ b/Sources/WireGuardKit/WireGuardAdapter.swift @@ -57,10 +57,31 @@ public class WireGuardAdapter { /// Tunnel device file descriptor. private var tunnelFileDescriptor: Int32? { - var buf = [CChar](repeating: 0, count: Int(IFNAMSIZ)) + var ctlInfo = ctl_info() + withUnsafeMutablePointer(to: &ctlInfo.ctl_name) { + $0.withMemoryRebound(to: CChar.self, capacity: MemoryLayout.size(ofValue: $0.pointee)) { + _ = strcpy($0, "com.apple.net.utun_control") + } + } for fd: Int32 in 0...1024 { - var len = socklen_t(buf.count) - if getsockopt(fd, SYSPROTO_CONTROL, 2, &buf, &len) == 0 && String(cString: buf).hasPrefix("utun") { + var addr = sockaddr_ctl() + var ret: Int32 = -1 + var len = socklen_t(MemoryLayout.size(ofValue: addr)) + withUnsafeMutablePointer(to: &addr) { + $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { + ret = getpeername(fd, $0, &len) + } + } + if ret != 0 || addr.sc_family != AF_SYSTEM { + continue + } + if ctlInfo.ctl_id == 0 { + ret = ioctl(fd, CTLIOCGINFO, &ctlInfo) + if ret != 0 { + continue + } + } + if addr.sc_id == ctlInfo.ctl_id { return fd } } diff --git a/Sources/WireGuardKitC/WireGuardKitC.h b/Sources/WireGuardKitC/WireGuardKitC.h index d50a4fe..212fc22 100644 --- a/Sources/WireGuardKitC/WireGuardKitC.h +++ b/Sources/WireGuardKitC/WireGuardKitC.h @@ -3,3 +3,18 @@ #include "key.h" #include "x25519.h" + +/* From */ +#define CTLIOCGINFO 0xc0644e03UL +struct ctl_info { + u_int32_t ctl_id; + char ctl_name[96]; +}; +struct sockaddr_ctl { + u_char sc_len; + u_char sc_family; + u_int16_t ss_sysaddr; + u_int32_t sc_id; + u_int32_t sc_unit; + u_int32_t sc_reserved[5]; +};