Linux Distros Unpatched Vulnerability : CVE-2026-98981
| Reporter | Title | Published | Views | Family All 9 |
|---|---|---|---|---|
| CVE-2026-98981 | 23 Oct 202613:27 | – | circl | |
| CVE-2026-98981 | 23 Oct 202612:19 | – | cve | |
| CVE-2026-98981 namespace: unhash a dentry before detaching the mounts on it | 23 Oct 202612:19 | – | cvelist | |
| CVE-2026-98981 | 23 Oct 202612:19 | – | debiancve | |
| EUVD-2026-108775 | 23 Oct 202612:19 | – | euvd | |
| CVE-2026-98981 | 23 Oct 202613:17 | – | nvd | |
| DEBIAN-CVE-2026-98981 | 23 Oct 202613:17 | – | osv_debian | |
| PT-2026-121958 | 23 Oct 202600:00 | – | ptsecurity | |
| SUSE CVE-2026-98981 | 23 Oct 202623:52 | – | susecve |
| Source | Link |
|---|---|
| security-tracker | www.security-tracker.debian.org/tracker/CVE-2026-98981 |
| cve | www.cve.mitre.org/cgi-bin/cvename.cgi |
#%NASL_MIN_LEVEL 80900
##
# (C) Tenable, Inc.
##
include('compat.inc');
if (description)
{
script_id(371592);
script_version("1.1");
script_set_attribute(attribute:"plugin_modification_date", value:"2026/10/23");
script_cve_id("CVE-2026-98981");
script_name(english:"Linux Distros Unpatched Vulnerability : CVE-2026-98981");
script_set_attribute(attribute:"synopsis", value:
"The Linux/Unix host has one or more packages installed with a vulnerability that the vendor indicates will not be
patched.");
script_set_attribute(attribute:"description", value:
"The Linux/Unix host has one or more packages installed that are impacted by a vulnerability without a vendor supplied
patch available.
- namespace: unhash a dentry before detaching the mounts on it unlink(), rmdir() and rename() remove the
entry from the filesystem, call detach_mounts() on the entry with the inode locked and then call
d_delete() once the inode is unlocked. The thing is that between detach_mounts() and d_delete() the dentry
is still hashed and positive. But after detach_mounts() nothing covers the dentry anymore. A lookup that
finds this dentry in the dcache can uncover what the mounts hid. That's a problem when unlinking files or
directories that are mountpoints in other mount namespaces. Everybody who had the underlying entry covered
can race the detach_mount() call until d_delete() has run. The race window isn't all that small. It
encompasses namespace_unlock() with a full synchronize_rcu_expedited() grace period and the inode_unlock()
of the entry. In my experiments three walkers that kept trying read an overmounted file in 11938 of the
16140 unlinks that removed its mountpoint from a bind mount of the filesystem within a minute. Fun fact,
d_invalidate() has the same ordering problem but gets it right. It unhashes the dentry first and detaches
the mounts afterwards. Let's do the same in __detach_mounts(): - A lookup that hasn't found the dentry yet
misses it in the dcache and waits for the directory lock that the caller holds until the name is gone for
good. - A lockless lookup that found it already fails the mount_lock check while the dentry still counts
as a mountpoint and the d_seq check once it doesn't, and retries. This fixes the lockless path. We still
need to fix the reference count lookup in a follow-up patch. So d_drop() the dentry. The dentry stays
positive and held but can't be found anymore. Then proceed with the detach and unlink. Reproducer: The
reads were counted with the program below, three walkers for 60 s in a VM with 4 CPUs. The race window is
stretched with the debug patch pasted here. fs.detach_race_walk_us sleeps in lookup_fast() once it found a
mountpoint dentry and before its mounts are crossed. fs.detach_race_unlink_us sleeps in vfs_unlink()
between detach_mounts() and d_delete(). // SPDX-License-Identifier: GPL-2.0 /* * unlink_covered: unlink a
file that is a mountpoint in a detached copy of * its mount, against lookups that open it through that
copy. * * A is a tmpfs with the file f1 (content SECRET_F) and the plain file * MARK_A. A' is an
open_tree(OPEN_TREE_CLONE) copy of A with MARK_A bound * on A'/f1, held through an O_PATH fd on its root
once the tree fd is * closed. Walkers open f1 through that fd while the driver unlinks A/f1, * where
nothing is mounted on it. A walker may read MARK_A or get ENOENT. * A read of SECRET_F is a hit: the name
was found after its mount was * gone. The lockless walks use openat2(RESOLVE_CACHED). * * usage:
unlink_covered [-t seconds] [-w walkers] */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include
<errno.h> #include <fcntl.h> #include <pthread.h> #include <stdatomic.h> #include <stdio.h> #include
<stdlib.h> #include <string.h> #include <unistd.h> #include <sys/mount.h> #include <sys/stat.h> #include
<sys/syscall.h> #include <linux/openat2.h> #ifndef __NR_open_tree #define __NR_open_tree 428 #endif
#ifndef __NR_move_mount #define __NR_move_mount 429 #endif #ifndef __NR_openat2 #define __NR_openat2 437
#endif #ifndef OPEN_TREE_CLONE #define OPEN_TREE_CLONE 1 #endif #ifndef OPEN_TREE_CLOEXEC #define
OPEN_TREE_CLOEXEC O_CLOEXEC #endif #ifndef MOVE_MOUNT_F_EMPTY_PATH #define MOVE_MOUNT_F_EMPTY_PATH
0x00000004 #endif #define WORK /tmp/uc #define ADIR WORK /A static int duration = 60, nwalkers = 3;
static atomic_int stop, writer_waiting; static pthread_rwlock_t cur_lock = PTHREAD_RWLOCK_INITIALIZER;
static int cur_fd = -1; /* the root of A', -1 wh ---truncated--- (CVE-2026-98981)
Note that Nessus relies on the presence of the package as reported by the vendor.");
script_set_attribute(attribute:"see_also", value:"https://security-tracker.debian.org/tracker/CVE-2026-98981");
script_set_attribute(attribute:"solution", value:
"There is no known solution at this time.");
script_set_attribute(attribute:"agent", value:"unix");
script_set_cvss_base_vector("CVSS2#AV:N/AC:L/Au:N/C:P/I:P/A:P");
script_set_cvss_temporal_vector("CVSS2#E:U/RL:U/RC:C");
script_set_cvss3_base_vector("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H");
script_set_cvss3_temporal_vector("CVSS:3.0/E:U/RL:U/RC:C");
script_set_attribute(attribute:"cvss_score_source", value:"CVE-2026-98981");
script_set_attribute(attribute:"exploitability_ease", value:"No known exploits are available");
script_set_attribute(attribute:"exploit_available", value:"false");
script_set_attribute(attribute:"vendor_unpatched", value:"true");
script_set_attribute(attribute:"vuln_publication_date", value:"2026/10/23");
script_set_attribute(attribute:"plugin_publication_date", value:"2026/10/23");
script_set_attribute(attribute:"plugin_type", value:"local");
script_set_attribute(attribute:"cpe", value:"cpe:/o:debian:debian_linux:12.0");
script_set_attribute(attribute:"cpe", value:"cpe:/o:debian:debian_linux:13.0");
script_set_attribute(attribute:"cpe", value:"p-cpe:/a:debian:debian_linux:linux");
script_set_attribute(attribute:"generated_plugin", value:"current");
script_end_attributes();
script_category(ACT_GATHER_INFO);
script_family(english:"Misc.");
script_copyright(english:"This script is Copyright (C) 2026 and is owned by Tenable, Inc. or an Affiliate thereof.");
script_dependencies("ssh_get_info2.nasl", "set_linux_os_id.nasl");
script_require_keys("Host/cpu", "Host/local_checks_enabled", "global_settings/vendor_unpatched", "Host/OS/identifier");
script_require_ports("Host/OS/Debian Linux-12", "Host/OS/Debian Linux-13");
exit(0);
}
if (!get_kb_item("global_settings/vendor_unpatched")) exit(0, "Unpatched Vulnerabilities Detection not active.");
if (!get_kb_item("Host/local_checks_enabled")) audit(AUDIT_LOCAL_CHECKS_NOT_ENABLED);
if (empty_or_null(get_one_kb_item("Host/Debian/dpkg-l"))) audit(AUDIT_PACKAGE_LIST_MISSING);
include('linux_unpatched.inc');
var distro_constraints_array = {
"Debian Linux-12": {
"package_manager": "dpkg-l",
"constraints": [
{
"release": "12",
"pkgs": [
{"reference": "btrfs-modules-6.1.0-50-alpha-generic-di"},
{"reference": "cdrom-core-modules-6.1.0-50-alpha-generic-di"},
{"reference": "ext4-modules-6.1.0-50-alpha-generic-di"},
{"reference": "fat-modules-6.1.0-50-alpha-generic-di"},
{"reference": "isofs-modules-6.1.0-50-alpha-generic-di"},
{"reference": "jfs-modules-6.1.0-50-alpha-generic-di"},
{"reference": "kernel-image-6.1.0-50-alpha-generic-di"},
{"reference": "linux-doc"},
{"reference": "linux-doc-6.1"},
{"reference": "linux-headers-6.1.0"},
{"reference": "linux-source"},
{"reference": "linux-source-6.1"},
{"reference": "linux-support-6.1.0"},
{"reference": "loop-modules-6.1.0-50-alpha-generic-di"},
{"reference": "nic-modules-6.1.0-50-alpha-generic-di"},
{"reference": "nic-shared-modules-6.1.0-50-alpha-generic-di"},
{"reference": "nic-wireless-modules-6.1.0-50-alpha-generic-di"},
{"reference": "pata-modules-6.1.0-50-alpha-generic-di"},
{"reference": "ppp-modules-6.1.0-50-alpha-generic-di"},
{"reference": "scsi-core-modules-6.1.0-50-alpha-generic-di"},
{"reference": "scsi-modules-6.1.0-50-alpha-generic-di"},
{"reference": "scsi-nic-modules-6.1.0-50-alpha-generic-di"},
{"reference": "serial-modules-6.1.0-50-alpha-generic-di"},
{"reference": "usb-serial-modules-6.1.0-50-alpha-generic-di"},
{"reference": "xfs-modules-6.1.0-50-alpha-generic-di"}
]
}
]
},
"Debian Linux-13": {
"package_manager": "dpkg-l",
"constraints": [
{
"release": "13",
"pkgs": [
{"reference": "bpftool"},
{"reference": "hyperv-daemons"},
{"reference": "intel-sdsi"},
{"reference": "libcpupower-dev"},
{"reference": "libcpupower1"},
{"reference": "linux-bpf-dev"},
{"reference": "linux-config-6.12"},
{"reference": "linux-cpupower"},
{"reference": "linux-doc"},
{"reference": "linux-doc-6.12"},
{"reference": "linux-headers-4kc-malta"},
{"reference": "linux-headers-5kc-malta"},
{"reference": "linux-headers-6.12.107+deb13-4kc-malta"},
{"reference": "linux-headers-6.12.107+deb13-5kc-malta"},
{"reference": "linux-headers-6.12.107+deb13-alpha-generic"},
{"reference": "linux-headers-6.12.107+deb13-alpha-smp"},
{"reference": "linux-headers-6.12.107+deb13-amd64"},
{"reference": "linux-headers-6.12.107+deb13-arm64"},
{"reference": "linux-headers-6.12.107+deb13-arm64-16k"},
{"reference": "linux-headers-6.12.107+deb13-armmp"},
{"reference": "linux-headers-6.12.107+deb13-armmp-lpae"},
{"reference": "linux-headers-6.12.107+deb13-cloud-amd64"},
{"reference": "linux-headers-6.12.107+deb13-cloud-arm64"},
{"reference": "linux-headers-6.12.107+deb13-common"},
{"reference": "linux-headers-6.12.107+deb13-common-rt"},
{"reference": "linux-headers-6.12.107+deb13-loong64"},
{"reference": "linux-headers-6.12.107+deb13-loongson-3"},
{"reference": "linux-headers-6.12.107+deb13-m68k"},
{"reference": "linux-headers-6.12.107+deb13-mips32r2eb"},
{"reference": "linux-headers-6.12.107+deb13-mips32r2el"},
{"reference": "linux-headers-6.12.107+deb13-mips64r2eb"}
]
}
]
}
};
var distro_constraints_values = linux_unpatched::get_distro_constraints(distro_constraints_arr:distro_constraints_array);
if (empty_or_null(distro_constraints_values)) audit(AUDIT_HOST_NOT, 'affected');
var third_party_support = get_kb_item('Host/OS/extended-third-party');
if (!empty_or_null(third_party_support)) {
var third_party_vendors = distro_constraints_values['third_party'];
if (!empty_or_null(third_party_vendors)) {
var vendor;
foreach vendor (third_party_vendors) {
if (vendor == third_party_support) exit(0, 'A third party management patch is available for this vulnerability from ' + vendor + '.\n');
}
}
}
var report = linux_unpatched::check_unpatched_constraints(distro_constraints_values:distro_constraints_values);
if (!empty_or_null(report))
{
security_report_v4(
port : 0,
severity : SECURITY_WARNING,
extra : report
);
exit(0);
}
else
{
audit(AUDIT_HOST_NOT, 'affected');
}
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation
23 Oct 2026 00:00Current
5.8Medium risk
Vulners AI Score5.8
EPSS0.00209