mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* WARNING in do_notify_parent (kernel/signal.c:2174)
@ 2026-05-07 13:24 y2k
  2026-05-09 10:37 ` Oleg Nesterov
  0 siblings, 1 reply; 5+ messages in thread
From: y2k @ 2026-05-07 13:24 UTC (permalink / raw)
  To: oleg; +Cc: brauner, linux-kernel, syzkaller

Hello,

I am reporting a kernel bug found with syzkaller fuzzer.


KERNEL VERSION
--------------
7.1.0-rc2-00099-gadc1e5c6203c
arch: x86_64
preemption: PREEMPT(lazy)


REPRODUCER (syzkaller program)
------------------------------
# {Threaded:false Repeat:false Procs:1 Sandbox: SandboxArg:0 Sysctl:true HandleSegv:true}
syz_clone(0x200080, &(0x7f00000003c0)="9562597ade4c359303b4585229dfcf8a12e5a172b6bfeb0d6d973e21df1c19605d9eb45142bd770cb6310057f646adcbde17681e392e8c11af0836a4ffff47c8c083fd4da4af3fdaa71e8a42df556d90bfb7e2511aac2628e271cddf224733c2881a422684cd3c7033fd24e00b205efdd94ece24e22040e80a310fb8cfaafecb00e067c5c2dfc13181c8773d3a37aa7635b8da5dbf2c9b25a7192f3861c442929542a4a564920eb870a06b383e781fe0d54d05275c7e2cd2f901c72c8270308a5db0adbed89176bac1122b21cb2e2d202569ae8d5a97cbce75aff3444207cb68bfcf", 0xe2, 0x0, 0x0, 0x0)


KERNEL CONFIG (relevant options)
---------------------------------
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
CONFIG_KASAN_SHADOW_OFFSET=0xdffffc0000000000
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF4=y
CONFIG_DEBUG_BUGVERBOSE=y


CRASH REPORT
------------
------------[ cut here ]------------
WARNING: kernel/signal.c:2174 at do_notify_parent+0xfef/0x11c0 kernel/signal.c:2174
CPU: 1 UID: 0 PID: 1245 Comm: syz.3.17 Not tainted 7.1.0-rc2-00099-gadc1e5c6203c #1 PREEMPT(lazy)
Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996)
RIP: 0010:do_notify_parent+0xfef/0x11c0 kernel/signal.c:2174
Code: 06 00 00 e8 23 b8 ff ff e9 81 f8 ff ff 41 bf 01 00 00 00 e9 76 f8 ff ff 4c 8d bb d0 08 00 00 e9 e7 f1 ff ff e8 82 88 39 00 90 <0f> 0b 90 45 31 ff e9 95 f8 ff ff e8 71 88 39 00 90 0f 0b 90 e9 d8
RSP: 0018:ffff8880057ffd38 EFLAGS: 00010093
RAX: 0000000000000000 RBX: ffff88800c158000 RCX: ffffffff8287ce7e
RDX: ffff88800c158000 RSI: 0000000000000040 RDI: 0000000000000007
RBP: ffff88800c015e50 R08: 0000000000000001 R09: ffffed1000afffb7
R10: 0000000000000080 R11: ffff88800c158000 R12: 1ffff11000afffaa
R13: dffffc0000000000 R14: 0000000000000080 R15: 0000000000000001
FS:  000055556c108500(0000) GS:ffff8881121b5000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007ff9749c2480 CR3: 00000000afea6000 CR4: 00000000000006f0
Call Trace:
 <TASK>
 exit_notify kernel/exit.c:757 [inline]
 do_exit+0x1a84/0x2960 kernel/exit.c:987
 __do_sys_exit kernel/exit.c:1084 [inline]
 __se_sys_exit kernel/exit.c:1082 [inline]
 __x64_sys_exit+0x42/0x50 kernel/exit.c:1082
 x64_sys_call+0x1880/0x1880 arch/x86/include/generated/asm/syscalls_64.h:61
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0x115/0x6a0 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
 </TASK>


REPRODUCTION NOTES
------------------
The bug was reproduced consistently. Syzkaller minimized the reproducer
to a single syz_clone() call. The WARNING fires in do_notify_parent()
during process exit when notifying the parent, called from exit_notify()
via do_exit() -> sys_exit().

Reproducing took 38 minutes across 87 programs. The crash is confirmed
not corrupted and reproducible.

This bug was found with syzkaller. The full .config is available on request.

Thanks,
y2k
y2k@desarrollaria.com

^ permalink raw reply	[flat|nested] 5+ messages in thread
* Re: WARNING in do_notify_parent (kernel/signal.c:2174)
@ 2026-05-07 16:00 y2k
  0 siblings, 0 replies; 5+ messages in thread
From: y2k @ 2026-05-07 16:00 UTC (permalink / raw)
  To: oleg; +Cc: brauner, linux-kernel, syzkaller

I noticed that commit 0f8e38eeb995 adds WARN_ON_ONCE for invalid signals
in do_notify_parent(). The syzkaller reproducer triggers this via
syz_clone() with CLONE_THREAD flags.

Could this be related to the ptrace path in exit.c:749 where
exit_signal=-1 (set for CLONE_THREAD processes) could reach
do_notify_parent() without a valid_signal() check?

Thanks,
y2k
y2k@desarrollaria.com

^ permalink raw reply	[flat|nested] 5+ messages in thread
* Re: WARNING in do_notify_parent (kernel/signal.c:2174)
@ 2026-05-07 15:45 y2k
  0 siblings, 0 replies; 5+ messages in thread
From: y2k @ 2026-05-07 15:45 UTC (permalink / raw)
  To: oleg; +Cc: brauner, linux-kernel, syzkaller

Follow-up: I found that commit 0f8e38eeb995 by Oleg Nesterov
("do_notify_parent: sanitize the valid_signal() checks") appears to be
related to this WARNING.

The syzkaller reproducer confirms the WARN_ON_ONCE fires in real
conditions via syz_clone() with specific arguments.

Kernel tested: 7.1.0-rc2-00099-gadc1e5c6203c

Thanks,
y2k
y2k@desarrollaria.com

^ permalink raw reply	[flat|nested] 5+ messages in thread
* WARNING in do_notify_parent (kernel/signal.c:2174)
@ 2026-04-24 23:27 Jie Zhu
  0 siblings, 0 replies; 5+ messages in thread
From: Jie Zhu @ 2026-04-24 23:27 UTC (permalink / raw)
  To: linux-kernel

Hello,

I'm reporting a kernel WARNING in do_notify_parent() (kernel/signal.c:2174)
that is reliably triggered by a specific combination of clone flags. Found
with syzkaller.

Tested on the latest upstream tree:
  commit: 27d128c1cff6 ("Merge tag 'trace-ring-buffer-v7.1-3'")
  config: defconfig + KASAN (outline) + KCOV

The WARNING triggers on every run, not a race.

Call Trace:

  WARNING: kernel/signal.c:2174 at do_notify_parent+0xbe3/0xc10
  CPU: 1 UID: 0 PID: 350 Comm: do_notify_paren Not tainted
7.0.0-g27d128c1cff6 #3 PREEMPT(lazy)
  Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, 1996)
  RIP: 0010:do_notify_parent+0xbe3/0xc10
  Call Trace:
   <TASK>
   do_exit+0x124b/0x18b0
   __x64_sys_exit+0x30/0x30
   x64_sys_call+0x1880/0x1880
   do_syscall_64+0x10c/0x640
   entry_SYSCALL_64_after_hwframe+0x77/0x7f
   </TASK>

The WARNING at kernel/signal.c:2174 is one of the three WARN_ON_ONCE checks
at the top of do_notify_parent():

  WARN_ON_ONCE(!valid_signal(sig));            /* line 2174 */
  WARN_ON_ONCE(task_is_stopped_or_traced(tsk));/* line 2178 */
  WARN_ON_ONCE(!tsk->ptrace &&                 /* line 2180 */
               !thread_group_empty(tsk));

The reproducing clone flags are:
  CLONE_NEWTIME | CLONE_CHILD_SETTID | CLONE_VFORK | CLONE_FILES
  (0x1004480, note CLONE_VM is stripped by the syz_clone helper)

In exit_notify() (kernel/exit.c:755), the non-ptraced thread_group_leader
path calls do_notify_parent() guarded by thread_group_empty(). However, the
specific flag combination appears to reach do_notify_parent() in a state that
violates one of its preconditions.

Syzkaller reproducer (syz program):

  syz_clone(0x1004580, 0x0, 0x0, 0x0, 0x0, 0x0)

C reproducer below. It sets up a sandbox with PID/net/mount namespaces, then
does a single clone() call with the above flags. Triggers on every run.

Best,
Jie

---
// autogenerated by syzkaller (https://github.com/google/syzkaller)

#define _GNU_SOURCE

#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <sched.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include <linux/capability.h>

static bool write_file(const char* file, const char* what, ...)
{
    char buf[1024];
    va_list args;
    va_start(args, what);
    vsnprintf(buf, sizeof(buf), what, args);
    va_end(args);
    buf[sizeof(buf) - 1] = 0;
    int len = strlen(buf);
    int fd = open(file, O_WRONLY | O_CLOEXEC);
    if (fd == -1)
        return false;
    if (write(fd, buf, len) != len) {
        int err = errno;
        close(fd);
        errno = err;
        return false;
    }
    close(fd);
    return true;
}

static void setup_gadgetfs();
static void setup_binderfs();
static void setup_fusectl();
static void sandbox_common_mount_tmpfs(void)
{
    write_file("/proc/sys/fs/mount-max", "100000");
    if (mkdir("./syz-tmp", 0777))
    exit(1);
    if (mount("", "./syz-tmp", "tmpfs", 0, NULL))
    exit(1);
    if (mkdir("./syz-tmp/newroot", 0777))
    exit(1);
    if (mkdir("./syz-tmp/newroot/dev", 0700))
    exit(1);
    unsigned bind_mount_flags = MS_BIND | MS_REC | MS_PRIVATE;
    if (mount("/dev", "./syz-tmp/newroot/dev", NULL, bind_mount_flags, NULL))
    exit(1);
    if (mkdir("./syz-tmp/newroot/proc", 0700))
    exit(1);
    if (mount("syz-proc", "./syz-tmp/newroot/proc", "proc", 0, NULL))
    exit(1);
    if (mkdir("./syz-tmp/newroot/selinux", 0700))
    exit(1);
    const char* selinux_path = "./syz-tmp/newroot/selinux";
    if (mount("/selinux", selinux_path, NULL, bind_mount_flags, NULL)) {
        if (errno != ENOENT)
    exit(1);
        if (mount("/sys/fs/selinux", selinux_path, NULL,
bind_mount_flags, NULL) && errno != ENOENT)
    exit(1);
    }
    if (mkdir("./syz-tmp/newroot/sys", 0700))
    exit(1);
    if (mount("/sys", "./syz-tmp/newroot/sys", 0, bind_mount_flags, NULL))
    exit(1);
    if (mount("/sys/kernel/debug",
"./syz-tmp/newroot/sys/kernel/debug", NULL, bind_mount_flags, NULL) &&
errno != ENOENT)
    exit(1);
    if (mount("/sys/fs/smackfs", "./syz-tmp/newroot/sys/fs/smackfs",
NULL, bind_mount_flags, NULL) && errno != ENOENT)
    exit(1);
    if (mount("/proc/sys/fs/binfmt_misc",
"./syz-tmp/newroot/proc/sys/fs/binfmt_misc", NULL, bind_mount_flags,
NULL) && errno != ENOENT)
    exit(1);
    if (mkdir("./syz-tmp/newroot/syz-inputs", 0700))
    exit(1);
    if (mount("/syz-inputs", "./syz-tmp/newroot/syz-inputs", NULL,
bind_mount_flags | MS_RDONLY, NULL) && errno != ENOENT)
    exit(1);
    if (mkdir("./syz-tmp/pivot", 0777))
    exit(1);
    if (syscall(SYS_pivot_root, "./syz-tmp", "./syz-tmp/pivot")) {
        if (chdir("./syz-tmp"))
    exit(1);
    } else {
        if (chdir("/"))
    exit(1);
        if (umount2("./pivot", MNT_DETACH))
    exit(1);
    }
    if (chroot("./newroot"))
    exit(1);
    if (chdir("/"))
    exit(1);
    setup_gadgetfs();
    setup_binderfs();
    setup_fusectl();
}

static void setup_gadgetfs()
{
    if (mkdir("/dev/gadgetfs", 0777)) {
    }
    if (mount("gadgetfs", "/dev/gadgetfs", "gadgetfs", 0, NULL)) {
    }
}

static void setup_fusectl()
{
    if (mount(0, "/sys/fs/fuse/connections", "fusectl", 0, 0)) {
    }
}

static void setup_binderfs()
{
    if (mkdir("/dev/binderfs", 0777)) {
    }
    if (mount("binder", "/dev/binderfs", "binder", 0, NULL)) {
    }
    if (symlink("/dev/binderfs", "./binderfs")) {
    }
}

static void loop();

static void sandbox_common()
{
    prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
    if (getppid() == 1)
    exit(1);
    struct rlimit rlim;
    rlim.rlim_cur = rlim.rlim_max = (200 << 20);
    setrlimit(RLIMIT_AS, &rlim);
    rlim.rlim_cur = rlim.rlim_max = 32 << 20;
    setrlimit(RLIMIT_MEMLOCK, &rlim);
    rlim.rlim_cur = rlim.rlim_max = 136 << 20;
    setrlimit(RLIMIT_FSIZE, &rlim);
    rlim.rlim_cur = rlim.rlim_max = 1 << 20;
    setrlimit(RLIMIT_STACK, &rlim);
    rlim.rlim_cur = rlim.rlim_max = 128 << 20;
    setrlimit(RLIMIT_CORE, &rlim);
    rlim.rlim_cur = rlim.rlim_max = 256;
    setrlimit(RLIMIT_NOFILE, &rlim);
    if (unshare(CLONE_NEWNS)) {
    }
    if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)) {
    }
    if (unshare(CLONE_NEWIPC)) {
    }
    if (unshare(0x02000000)) {
    }
    if (unshare(CLONE_NEWUTS)) {
    }
    if (unshare(CLONE_SYSVSEM)) {
    }
    typedef struct {
        const char* name;
        const char* value;
    } sysctl_t;
    static const sysctl_t sysctls[] = {
        {"/proc/sys/kernel/shmmax", "16777216"},
        {"/proc/sys/kernel/shmall", "536870912"},
        {"/proc/sys/kernel/shmmni", "1024"},
        {"/proc/sys/kernel/msgmax", "8192"},
        {"/proc/sys/kernel/msgmni", "1024"},
        {"/proc/sys/kernel/msgmnb", "1024"},
        {"/proc/sys/kernel/sem", "1024 1048576 500 1024"},
    };
    unsigned i;
    for (i = 0; i < sizeof(sysctls) / sizeof(sysctls[0]); i++)
        write_file(sysctls[i].name, sysctls[i].value);
}

static int wait_for_loop(int pid)
{
    if (pid < 0)
    exit(1);
    int status = 0;
    while (waitpid(-1, &status, __WALL) != pid) {
    }
    return WEXITSTATUS(status);
}

static void drop_caps(void)
{
    struct __user_cap_header_struct cap_hdr = {};
    struct __user_cap_data_struct cap_data[2] = {};
    cap_hdr.version = _LINUX_CAPABILITY_VERSION_3;
    cap_hdr.pid = getpid();
    if (syscall(SYS_capget, &cap_hdr, &cap_data))
    exit(1);
    const int drop = (1 << CAP_SYS_PTRACE) | (1 << CAP_SYS_NICE);
    cap_data[0].effective &= ~drop;
    cap_data[0].permitted &= ~drop;
    cap_data[0].inheritable &= ~drop;
    if (syscall(SYS_capset, &cap_hdr, &cap_data))
    exit(1);
}

static int do_sandbox_none(void)
{
    if (unshare(CLONE_NEWPID)) {
    }
    int pid = fork();
    if (pid != 0)
        return wait_for_loop(pid);
    sandbox_common();
    drop_caps();
    if (unshare(CLONE_NEWNET)) {
    }
    write_file("/proc/sys/net/ipv4/ping_group_range", "0 65535");
    sandbox_common_mount_tmpfs();
    loop();
    exit(1);
}

#define USLEEP_FORKED_CHILD (3 * 50 *1000)

static long handle_clone_ret(long ret)
{
    if (ret != 0) {
        return ret;
    }
    usleep(USLEEP_FORKED_CHILD);
    syscall(__NR_exit, 0);
    while (1) {
    }
}

static long syz_clone(volatile long flags, volatile long stack,
              volatile long stack_len, volatile long ptid,
              volatile long ctid, volatile long tls)
{
    long sp = (stack + stack_len) & ~15;
    long ret = (long)syscall(__NR_clone, flags & ~CLONE_VM, sp, ptid,
ctid, tls);
    return handle_clone_ret(ret);
}

void loop(void)
{
    if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {}
    syz_clone(0x1004580, 0, 0, 0, 0, 0);
}

int main(void)
{
    syscall(__NR_mmap, 0x1ffffffff000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul);
    syscall(__NR_mmap, 0x200000000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul);
    syscall(__NR_mmap, 0x200001000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul);
    do_sandbox_none();
    return 0;
}
---

To reproduce:
  $ gcc -static -o repro repro.c -lpthread
  # run inside a VM or container with the affected kernel
  $ ./repro

Thanks.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-05-09 10:37 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-07 13:24 WARNING in do_notify_parent (kernel/signal.c:2174) y2k
2026-05-09 10:37 ` Oleg Nesterov
  -- strict thread matches above, loose matches on Subject: below --
2026-05-07 16:00 y2k
2026-05-07 15:45 y2k
2026-04-24 23:27 Jie Zhu

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®