Issue no privileged ioctl when attaching to a prepared interface

The tun crate runs configure() by default (ensure_root_privileges is true),
which is harmless today because it only acts on fields that were set, and
the attach path sets none. Saying so explicitly documents the intent and
keeps it true if the crate changes.

Also records why packet information stays off: `ip tuntap add ... mode tun`
defaults to no packet information too, so the TUNSETIFF flags match when
attaching and reads and writes stay raw IP packets.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
tsunagi
2026-09-21 12:28:28 +01:00
co-authored by Claude Opus 5
parent 1dd7507bf4
commit 0f8a4eb485
+12 -4
View File
@@ -337,12 +337,20 @@ mod system {
let mut config = tun::Configuration::default(); let mut config = tun::Configuration::default();
config.tun_name(&request.name); config.tun_name(&request.name);
if !existed { if existed {
// Only configure what we are creating ourselves. // Attach only. Reconfiguring an interface somebody
// Reconfiguring somebody else's prepared interface would // prepared for us would need exactly the privileges we
// need privileges we are trying not to require. // are avoiding, so no ioctl beyond TUNSETIFF is issued.
config.platform_config(|platform| {
platform.ensure_root_privileges(false);
});
} else {
// We are creating it, so we configure it.
config.mtu(request.mtu as u16).up(); config.mtu(request.mtu as u16).up();
} }
// Packet information stays off, so reads and writes are raw IP
// packets. `ip tuntap add ... mode tun` also defaults to no
// packet information, so the flags match when attaching.
let device = tun::create_as_async(&config).map_err(|err| { let device = tun::create_as_async(&config).map_err(|err| {
let hint = if existed { let hint = if existed {