mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: 徐晗翔 <xuhx@hust.edu.cn>
To: dakr@kernel.org, rafael@kernel.org
Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org
Subject: driver core: uevent: netns teardown frees uevent_sock while a tagged uevent is still being broadcast (UAF)
Date: Tue, 10 Nov 2026 21:00:29 +0800 (GMT+08:00)	[thread overview]
Message-ID: <21f226b6.22aca.1a1c58bb374.Coremail.xuhx@hust.edu.cn> (raw)
In-Reply-To: <2026102727-data-sequel-ce41@gregkh>

[-- Attachment #1: Type: text/plain, Size: 6706 bytes --]

net->uevent_sock is published as a bare pointer by uevent_net_init()
and freed by uevent_net_exit(), but the tagged broadcast path
dereferences net->uevent_sock->sk without holding uevent_sock_mutex or
taking a socket reference.  uevent_net_exit() drops the mutex before
releasing the socket and never clears net->uevent_sock, so a kobject
whose namespace callback returns an unpinned net pointer can emit a
tagged uevent after the per-net exit has freed the socket; KASAN
reports a slab-use-after-free read in kobject_uevent_net_broadcast()
(inlined into kobject_uevent_env in the report below).

An IB compat device supplies a concrete path.  Its rdma_net is a raw
possible_net_t, and its asynchronous unregister can still be inside
device_del() after the net namespace has run uevent_net_exit().  This
was reported by syzbot (KASAN: slab-use-after-free Read in
disable_device, extid 4393dfdddf166f2de2b0,
https://syzkaller.appspot.com/bug?extid=4393dfdddf166f2de2b0) and I
reproduced it locally on 7.3 with a KASAN kernel; the same reproducer
is clean with a no-rxe control and with the v4 locking change described
below.

The detailed description:

* Test environment / affected version

  Linux 7.3.0 (vanilla mainline tarball), x86_64, QEMU/KVM guest,
  8 vCPU / 4 GB RAM, KASAN generic.  The tested
  lib/kobject_uevent.c is byte-identical to the audited 7.3 tree
  (sha256 bbcf120ea86f42c74dec10e255a8cd0b3034c9f34cd5bb911fd94015729dd076).
  Kernel config included CONFIG_NET_NS=y, CONFIG_INFINIBAND=y,
  CONFIG_INFINIBAND_USER_ACCESS=y, CONFIG_RDMA_RXE=y, CONFIG_DUMMY=y
  and CONFIG_KASAN=y.  The kernel source was not modified to inject
  the race; only the IB/RXE configuration was enabled and a userspace
  reproducer was added.

* Mechanism

  Three sides do not share a lifetime protocol:

    - Publish side: uevent_net_init() allocates ue_sk and stores it
      with net->uevent_sock = ue_sk (lib/kobject_uevent.c:773-803).
      The field is a plain pointer in struct net, with no refcount,
      RCU head, or socket reference (include/net/net_namespace.h:113).

    - Free side: uevent_net_exit() reads the pointer, removes ue_sk
      from the global uevent_sock_list under uevent_sock_mutex only
      when it belongs to the initial user namespace, then unlocks and
      calls netlink_kernel_release(ue_sk->sk) and kfree(ue_sk)
      outside the mutex (lib/kobject_uevent.c:805-817).  It never
      writes net->uevent_sock = NULL.

    - Read side: kobject_uevent_net_broadcast() obtains the target
      net from the kobject namespace callback and passes
      net->uevent_sock->sk directly to
      uevent_net_broadcast_tagged() (lib/kobject_uevent.c:382-421;
      the tagged dereference is at line 415).  This path takes no
      uevent_sock_mutex, no socket reference, and performs no NULL
      check.

  The IB trigger makes the window concrete:

    - ib_class.namespace is net_namespace(), which only does
      read_pnet(&coredev->rdma_net); rdma_init_coredev() stored the
      net with write_pnet() without get_net()
      (drivers/infiniband/core/device.c:536-550, 553-580).

    - remove_one_compat_dev() erases the compat device from the
      xarray under compat_devs_mutex, releases the mutex, and then
      calls ib_free_port_attrs() and device_del()
      (drivers/infiniband/core/device.c:1027-1039).  device_del()
      emits KOBJ_REMOVE at drivers/base/core.c:3983.

    - device_del() has several sleeping or blocking points between
      the xa_erase() and KOBJ_REMOVE (device_lock(), bus_notify(),
      sysfs removal, class callbacks, devres_release_all()), so the
      window is not merely theoretical.

  On netns cleanup, rdma_dev_net_ops is registered with
  register_pernet_device() (drivers/infiniband/core/device.c:3274),
  while uevent_net_ops is registered with register_pernet_subsys()
  (lib/kobject_uevent.c:826).  Because the pernet list is walked in
  reverse on exit, rdma_dev_exit_net() runs before
  uevent_net_exit().  If the async IB path wins the xa_erase() in
  remove_one_compat_dev(), rdma_dev_exit_net() sees an empty xarray
  and proceeds to uevent_net_exit(), which frees ue_sk.  The IB
  worker can then continue through device_del() and read the freed
  ue_sk through net->uevent_sock.

  cleanup_net() calls ops_undo_list() (where uevent_net_exit() frees
  ue_sk) and only later rcu_barrier()/net_complete_free()
  (net/core/net_namespace.c:220-258, 666-729).  struct net itself is
  deferred, so KASAN reports the freed kmalloc-32 ue_sk, not net.


* Reproducer (attached: uevent_uaf_repro.c) and results on 7.3

  The attached file is based on the syzbot C reproducer and adds a
  no-rxe control mode plus a duration argument.  It uses only
  userspace netlink/ioctl calls; no kernel module or source change is
  required.

    # with dummy and rdma_rxe available, as root
    gcc -O2 -pthread uevent_uaf_repro.c -o uevent_uaf_repro
    ./uevent_uaf_repro 60
    ./uevent_uaf_repro no-rxe 30       # negative control

  Results (one QEMU/KVM guest, 8 vCPU):

    - vulnerable 7.3, dummy + rxe, 60 s: 125 iterations, 4 KASAN
      slab-use-after-free reports;
    - vulnerable 7.3, dummy + netns churn without rxe, 30 s:
      191 iterations, 0 KASAN reports;
    - v4-patched kernel, same dummy + rxe trigger, 60 s: 0 reports.

  The first positive report is:

    BUG: KASAN: slab-use-after-free in kobject_uevent_env+0x64b/0x710
    Read of size 8 ...
    Workqueue: ib-unreg-wq ib_unregister_work

     kobject_uevent_env
     device_del
     disable_device
     __ib_unregister_device
     ib_unregister_work

    Allocated by: uevent_net_init
    Freed by:     ops_undo_list -> cleanup_net
    cache:        kmalloc-32

  The race is probabilistic: an earlier 60 s run of the same reproducer
  produced no report, and the successful run had kprobes installed on the path
  (the probe overhead can widen the window).  The v4 run used the same
  kprobe configuration and stayed clean; the no-rxe control also
  stayed clean.  The syzbot report is independent of this local run.


* Suggested direction

  Serialize the tagged broadcast with uevent_net_exit() using the
  existing uevent_sock_mutex, and clear net->uevent_sock before
  dropping the lock:

    - in kobject_uevent_net_broadcast(), take uevent_sock_mutex,
      read ue_sk = net->uevent_sock, and check ue_sk && ue_sk->sk
      before calling uevent_net_broadcast_tagged();
    - in uevent_net_exit(), take the same mutex, set
      net->uevent_sock = NULL while removing ue_sk from the list, then
      release the socket and free ue_sk outside the lock.


  Please keep me in Cc; I am not subscribed to the lists.



Regards,
Hanxiang Xu
xuhx@hust.edu.cn

[-- Attachment #2: uevent_uaf_repro.c --]
[-- Type: text/plain, Size: 13479 bytes --]

// https://syzkaller.appspot.com/bug?id=62db7f0b628381f621ab352d501352f0cb359ba1
// Copyright 2026 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

// IMPORTANT: Do not copy the macros or definitions below directly into your reproducer.
// Instead, add the following line to your reproducer:
// #include "race_toolkit.h"

// --- Race Condition Toolkit ---
// Macros and snippets for CPU pinning, memory barriers, and userfaultfd.

#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <linux/futex.h>
#include <linux/userfaultfd.h>
#include <poll.h>
#include <pthread.h>
#include <sched.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/syscall.h>
#include <time.h>
#include <unistd.h>

// Unbuffered I/O: Ensure logs are written immediately.
#define SETUP_UNBUFFERED_IO() setvbuf(stdout, NULL, _IONBF, 0)

// CPU Pinning: Pin the current thread to a specific CPU core.
#define PIN_TO_CPU(cpu)                                                \
	do {                                                           \
		cpu_set_t mask;                                        \
		CPU_ZERO(&mask);                                       \
		CPU_SET(cpu, &mask);                                   \
		if (sched_setaffinity(0, sizeof(mask), &mask) == -1) { \
			perror("sched_setaffinity");                   \
		}                                                      \
	} while (0)

// Memory Barrier: Ensure memory ordering.
#define MB() __atomic_thread_fence(__ATOMIC_SEQ_CST)

// Spin-wait Barrier: Wait until a memory location has a specific value.
// Best for tight race windows (low latency, no context switches).
#define WAIT_ON(addr, val)                                               \
	do {                                                             \
		while (__atomic_load_n(addr, __ATOMIC_ACQUIRE) != (val)) \
			;                                                \
	} while (0)

// Signal: Set a memory location to a specific value to release a WAIT_ON.
#define SIGNAL(addr, val) __atomic_store_n(addr, val, __ATOMIC_RELEASE)

// --- Timing Primitives ---
// Robust timing loops in VM environments (using CLOCK_MONOTONIC to avoid time(NULL) jumps).

static inline double timer_elapsed_sec(struct timespec* start)
{
	struct timespec now;
	if (clock_gettime(CLOCK_MONOTONIC, &now) == -1) {
		perror("clock_gettime(CLOCK_MONOTONIC) elapsed");
		exit(1);
	}
	return (double)(now.tv_sec - start->tv_sec) + (double)(now.tv_nsec - start->tv_nsec) / 1e9;
}

// Initialize a monotonic timer variable.
#define TIMER_START(t)                                          \
	struct timespec t;                                      \
	if (clock_gettime(CLOCK_MONOTONIC, &t) == -1) {         \
		perror("clock_gettime(CLOCK_MONOTONIC) start"); \
		exit(1);                                        \
	}

// Check if the elapsed time since 't' is less than 'sec' seconds.
#define TIMER_NOT_EXPIRED(t, sec) (timer_elapsed_sec(&(t)) < (double)(sec))

// Futex-based Event: Shared with syzkaller executor.
// Best for general synchronization or longer waits to save CPU.
typedef struct {
	int state;
} event_t;

static void event_init(event_t* ev)
{
	ev->state = 0;
}
static void event_reset(event_t* ev)
{
	ev->state = 0;
}

static void event_set(event_t* ev)
{
	if (__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE)) {
		fprintf(stderr, "event already set\n");
		exit(1);
	}
	__atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE);
	syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1000000);
}

static void event_wait(event_t* ev)
{
	while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
		syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0);
}

// userfaultfd setup: Register a memory range for page fault handling.
static int setup_uffd(void* addr, size_t len)
{
	int uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);
	if (uffd == -1)
		return -1;
	struct uffdio_api api = {.api = UFFD_API, .features = 0};
	if (ioctl(uffd, UFFDIO_API, &api) == -1) {
		close(uffd);
		return -1;
	}
	struct uffdio_register reg = {
	    .range = {.start = (uintptr_t)addr, .len = len},
	    .mode = UFFDIO_REGISTER_MODE_MISSING};
	if (ioctl(uffd, UFFDIO_REGISTER, &reg) == -1) {
		close(uffd);
		return -1;
	}
	return uffd;
}

// --- Guidance on Usage ---
// 1. Use WAIT_ON/SIGNAL for tight race conditions to avoid scheduling overhead.
// 2. Use event_t (futexes) for general coordination or when waiting for longer periods.
// 3. Always use PIN_TO_CPU to increase race probability on multi-core systems.
// 4. Use setup_uffd to register a memory range for page fault handling. This allows you to
//    pause a thread accessing that memory until you handle the fault, creating a reliable
//    and controllable race window.
// 5. Call SETUP_UNBUFFERED_IO() at the start of main() to ensure that logs are printed
//    immediately. This is essential for understanding the exact interleaving of events
//    when debugging race conditions.
// 6. For timing-based loops (e.g., running a race for 10 seconds), do NOT use time(NULL)
//    or loops relying on real-time clocks, as VM clocks are highly unreliable and can fail or drift.
//    Instead, use the robust monotonic timing primitives TIMER_START and TIMER_NOT_EXPIRED:
//        TIMER_START(start);
//        while (TIMER_NOT_EXPIRED(start, 10.0)) {
//            // Your race logic here
//        }

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sched.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <signal.h>
#include <errno.h>
#include <time.h>

#define NETLINK_RDMA 20
#define RDMA_NL_NLDEV 5
#define RDMA_NLDEV_CMD_NEWLINK 3
#define RDMA_NLDEV_ATTR_DEV_NAME 2
#define RDMA_NLDEV_ATTR_NDEV_NAME 51
#define RDMA_NLDEV_ATTR_LINK_TYPE 65

static int create_dummy_interface(const char *name) {
    int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if (fd < 0) return -1;

    struct {
        struct nlmsghdr nlh;
        struct ifinfomsg ifm;
        char buf[1024];
    } req = {0};

    req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
    req.nlh.nlmsg_type = RTM_NEWLINK;
    req.nlh.nlmsg_seq = 1;

    req.ifm.ifi_family = AF_UNSPEC;

    struct rtattr *rta;

    rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.nlh.nlmsg_len));
    rta->rta_type = IFLA_IFNAME;
    rta->rta_len = RTA_LENGTH(strlen(name) + 1);
    strcpy(RTA_DATA(rta), name);
    req.nlh.nlmsg_len = NLMSG_ALIGN(req.nlh.nlmsg_len) + RTA_ALIGN(rta->rta_len);

    struct rtattr *linkinfo = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.nlh.nlmsg_len));
    linkinfo->rta_type = IFLA_LINKINFO;
    linkinfo->rta_len = RTA_LENGTH(0);

    rta = (struct rtattr *)(((char *)linkinfo) + RTA_ALIGN(linkinfo->rta_len));
    rta->rta_type = IFLA_INFO_KIND;
    rta->rta_len = RTA_LENGTH(strlen("dummy") + 1);
    strcpy(RTA_DATA(rta), "dummy");
    
    linkinfo->rta_len += RTA_ALIGN(rta->rta_len);
    req.nlh.nlmsg_len = NLMSG_ALIGN(req.nlh.nlmsg_len) + RTA_ALIGN(linkinfo->rta_len);

    struct sockaddr_nl sa = { .nl_family = AF_NETLINK };
    sendto(fd, &req, req.nlh.nlmsg_len, 0, (struct sockaddr *)&sa, sizeof(sa));
    
    struct {
        struct nlmsghdr nlh;
        struct nlmsgerr err;
    } resp;
    recv(fd, &resp, sizeof(resp), 0);
    close(fd);
    return resp.err.error;
}

static int delete_interface(const char *name) {
    int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if (fd < 0) return -1;

    struct {
        struct nlmsghdr nlh;
        struct ifinfomsg ifm;
        char buf[1024];
    } req = {0};

    req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
    req.nlh.nlmsg_type = RTM_DELLINK;
    req.nlh.nlmsg_seq = 1;

    req.ifm.ifi_family = AF_UNSPEC;

    struct rtattr *rta;

    rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.nlh.nlmsg_len));
    rta->rta_type = IFLA_IFNAME;
    rta->rta_len = RTA_LENGTH(strlen(name) + 1);
    strcpy(RTA_DATA(rta), name);
    req.nlh.nlmsg_len = NLMSG_ALIGN(req.nlh.nlmsg_len) + RTA_ALIGN(rta->rta_len);

    struct sockaddr_nl sa = { .nl_family = AF_NETLINK };
    sendto(fd, &req, req.nlh.nlmsg_len, 0, (struct sockaddr *)&sa, sizeof(sa));
    
    struct {
        struct nlmsghdr nlh;
        struct nlmsgerr err;
    } resp;
    recv(fd, &resp, sizeof(resp), 0);
    close(fd);
    return resp.err.error;
}

static void bring_up_interface(const char *name) {
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd < 0) return;
    struct ifreq ifr;
    strcpy(ifr.ifr_name, name);
    if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0) {
        ifr.ifr_flags |= IFF_UP;
        ioctl(fd, SIOCSIFFLAGS, &ifr);
    }
    close(fd);
}

static int send_rdma_newlink(const char *ibdev_name, const char *link_type, const char *ndev_name) {
    int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_RDMA);
    if (fd < 0) return -1;

    struct {
        struct nlmsghdr nlh;
        char buf[1024];
    } req = {0};

    req.nlh.nlmsg_len = NLMSG_LENGTH(0);
    req.nlh.nlmsg_type = (RDMA_NL_NLDEV << 10) | RDMA_NLDEV_CMD_NEWLINK;
    req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
    req.nlh.nlmsg_seq = 1;

    struct rtattr *rta;

    rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.nlh.nlmsg_len));
    rta->rta_type = RDMA_NLDEV_ATTR_DEV_NAME;
    rta->rta_len = RTA_LENGTH(strlen(ibdev_name) + 1);
    strcpy(RTA_DATA(rta), ibdev_name);
    req.nlh.nlmsg_len = NLMSG_ALIGN(req.nlh.nlmsg_len) + RTA_ALIGN(rta->rta_len);

    rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.nlh.nlmsg_len));
    rta->rta_type = RDMA_NLDEV_ATTR_LINK_TYPE;
    rta->rta_len = RTA_LENGTH(strlen(link_type) + 1);
    strcpy(RTA_DATA(rta), link_type);
    req.nlh.nlmsg_len = NLMSG_ALIGN(req.nlh.nlmsg_len) + RTA_ALIGN(rta->rta_len);

    rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.nlh.nlmsg_len));
    rta->rta_type = RDMA_NLDEV_ATTR_NDEV_NAME;
    rta->rta_len = RTA_LENGTH(strlen(ndev_name) + 1);
    strcpy(RTA_DATA(rta), ndev_name);
    req.nlh.nlmsg_len = NLMSG_ALIGN(req.nlh.nlmsg_len) + RTA_ALIGN(rta->rta_len);

    struct sockaddr_nl sa = { .nl_family = AF_NETLINK };
    sendto(fd, &req, req.nlh.nlmsg_len, 0, (struct sockaddr *)&sa, sizeof(sa));
    
    struct {
        struct nlmsghdr nlh;
        struct nlmsgerr err;
    } resp;
    recv(fd, &resp, sizeof(resp), 0);
    close(fd);
    return resp.err.error;
}

int main(int argc, char **argv) {
    /* no-rxe: negative control; keep the same dummy/netns churn without IB.
     * Optional numeric arg: run duration in seconds (default 10).
     */
    int use_rxe = 1;
    double secs = 10.0;
    for (int ai = 1; ai < argc; ai++) {
        if (strcmp(argv[ai], "no-rxe") == 0) {
            use_rxe = 0;
        } else {
            double v = atof(argv[ai]);
            if (v > 0)
                secs = v;
        }
    }
    SETUP_UNBUFFERED_IO();
    TIMER_START(start);
    srand(time(NULL) ^ getpid());
    printf("[*] uevent_uaf_repro: use_rxe=%d secs=%.0f pid=%d\n", use_rxe, secs, getpid());
    
    int iter = 0;
    while (TIMER_NOT_EXPIRED(start, secs)) {
        char dummy_name[32];
        char rxe_name[32];
        sprintf(dummy_name, "d%d_%d", getpid(), iter);
        sprintf(rxe_name, "r%d_%d", getpid(), iter);
        
        int res = create_dummy_interface(dummy_name);
        if (res < 0 && res != -EEXIST) {
            printf("[-] Failed to create dummy interface: %d\n", res);
            exit(1);
        }
        
        bring_up_interface(dummy_name);
        
        if (use_rxe) {
            res = send_rdma_newlink(rxe_name, "rxe", dummy_name);
            if (res < 0) {
                printf("[-] Failed to create RXE device: %d\n", res);
            }
        }
        
        int p[2];
        if (pipe(p) < 0) {
            exit(1);
        }
        
        pid_t pid = fork();
        if (pid == 0) {
            close(p[0]);
            if (unshare(CLONE_NEWNET) < 0) {
                printf("[-] unshare(CLONE_NEWNET) failed: %d\n", errno);
                exit(1);
            }
            // Signal parent that we are in new netns
            if (write(p[1], "1", 1) != 1) {}
            
            // Wait for parent to signal us to exit
            char c;
            if (read(p[1], &c, 1) != 1) {}
            
            // Exit, triggering cleanup_net
            exit(0);
        }
        
        close(p[1]);
        char c;
        // Wait for child to unshare
        if (read(p[0], &c, 1) != 1) {}
        close(p[0]);
        
        // Signal child to exit
        kill(pid, SIGKILL);
        
        // Random delay between 0 and 50ms to hit the race window
        // cleanup_net blocks on synchronize_rcu() which takes some time
        usleep(rand() % 50000);
        
        // Immediately delete the dummy interface to trigger ib_unregister_work
        delete_interface(dummy_name);
        
        waitpid(pid, NULL, 0);
        
        // Wait a bit for workqueues to finish
        usleep(50000);
        
        iter++;
    }
    
    printf("[+] Reproducer finished after %d iterations.\n", iter);
    return 0;
}

      parent reply	other threads:[~2026-11-10 13:00 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-27 12:35 usb: devio: usbdev_release() has no barrier against an in-flight async_completed() callback (use-after-free window on struct usb_dev_state)gregkh@linuxfoundation.org 徐晗翔
2026-10-27 14:12 ` Greg KH
2026-11-03 11:21   ` mm/slub: has_pcs_used() reads remote per-CPU sheaf state from flush_all_cpus_locked() without synchronization (data race; KCSAN blind spot: slub.o is uninstrumented) 徐晗翔
2026-11-04  9:41     ` Qing Wang
2026-11-04 10:07       ` Qing Wang
2026-11-03 11:30   ` futex/hrtimer: hrtimer_sleeper::task is read unsynchronized in 16 places on v7.3 -- the accessor series that fixes this is not in 7.3; please make sure it reaches the affected trees (backport nudge + stock-kernel KCSAN evidence) 徐晗翔
2026-11-03 11:48   ` cgroup: fork vs cgroup.procs write race in favordynmods mode -- v7.3 is affected; please make sure bf6fbf46b5ff reaches the stable trees (repro incl. uninstrumented natural hit) 徐晗翔
2026-11-03 14:51     ` Sasha Levin
2026-11-03 11:57   ` net: rtnetlink: rtnl_link_unregister() vs in-flight RTM_GETLINK dump readers -- v7.3 lacks the synchronize_rcu() fix (Fixes: 6b57ff21a310 family); A/B reproduction on stock 7.3 徐晗翔
2026-11-03 15:49     ` Eric Dumazet
2026-11-04 15:03     ` Sasha Levin
2026-11-03 12:07   ` wifi: wilc1000: SDIO/SPI remove destroys the srcu_struct before wiphy_unregister() -- late cfg80211 callbacks write through dangling srcu state (unfixed upstream; controlled + natural Oops) 徐晗翔
2026-11-03 12:10   ` gpio: gpiolib: final put of the gpio_device happens inside the SRCU read critical section on the setup-failure path -- deterministic use-after-free read at guard release (unfixed upstream) 徐晗翔
2026-11-05  8:52     ` Linus Walleij
2026-11-04 12:54   ` soc: qcom: pmic_glink_altmode: fix use-after-free on unbind (no cancel_work_sync for port work and enable_work) 徐晗翔
2026-11-04 13:04     ` Greg KH
2026-11-04 12:57   ` usb: typec: anx7411: unregister partner/altmodes before stopping the IRQ work -- use-after-free, double unregister, orphan partner on remove 徐晗翔
2026-11-04 13:28     ` Greg KH
2026-11-04 12:58   ` usb: typec: ucsi: deadlock on cros_ec unbind -- connector lock held across cancel_delayed_work_sync vs the mode-selection work's unbounded trylock polling 徐晗翔
2026-11-04 13:00   ` usb: typec: stusb160x/rt1719/hd3ss3220: IRQ thread vs remove -- double unregister / use-after-free on the partner and port 徐晗翔
2026-11-04 13:01   ` usb: typec: ucsi: displayport: data race on dp->header/ vdo_data/vdo_size -- work reads them unlocked while writers hold con->lock (VDM mismatch) 徐晗翔
2026-11-04 13:02   ` usb: typec: class: three lifetime/locking gaps around the mux/switch handles and mode_selection (drvdata UAF after provider unbind; no concurrent protocol for set/put; unlocked state_update vs delete) 徐晗翔
2026-11-10 12:56   ` driver core: uevent: netns teardown frees uevent_sock while a tagged uevent is still being broadcast (UAF) 徐晗翔
2026-11-10 13:00   ` 徐晗翔 [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=21f226b6.22aca.1a1c58bb374.Coremail.xuhx@hust.edu.cn \
    --to=xuhx@hust.edu.cn \
    --cc=dakr@kernel.org \
    --cc=driver-core@lists.linux.dev \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rafael@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®