Lucene search
+L

Unity Linux 20.1050e Security Update: kernel (UTSA-2026-102019)

🗓️ 21 Aug 2026 00:00:00Reported by TenableType 
nessus
 nessus
🔗 www.tenable.com👁 4 Views

btrfs dirty metadata threshold in Linux kernel causes system hang and coredump on Unity Linux 20.

Related
Refs
Code
#%NASL_MIN_LEVEL 80900
##
# (C) Tenable, Inc.
##

include('compat.inc');

if (description)
{
  script_id(338502);
  script_version("1.1");
  script_set_attribute(attribute:"plugin_modification_date", value:"2026/08/21");

  script_cve_id("CVE-2026-23157");

  script_name(english:"Unity Linux 20.1050e Security Update: kernel (UTSA-2026-102019)");

  script_set_attribute(attribute:"synopsis", value:
"The Unity Linux host is missing one or more security updates.");
  script_set_attribute(attribute:"description", value:
"The Unity Linux 20 host has a package installed that is affected by a vulnerability as referenced in the
UTSA-2026-102019 advisory.

    In the Linux kernel, the following vulnerability has been resolved:

    btrfs: do not strictly require dirty metadata threshold for metadata writepages

    [BUG]
    There is an internal report that over 1000 processes are
    waiting at the io_schedule_timeout() of balance_dirty_pages(), causing
    a system hang and trigger a kernel coredump.

    The kernel is v6.4 kernel based, but the root problem still applies to
    any upstream kernel before v6.18.

    [CAUSE]
    From Jan Kara for his wisdom on the dirty page balance behavior first.

      This cgroup dirty limit was what was actually playing the role here
      because the cgroup had only a small amount of memory and so the dirty
      limit for it was something like 16MB.

      Dirty throttling is responsible for enforcing that nobody can dirty
      (significantly) more dirty memory than there's dirty limit. Thus when
      a task is dirtying pages it periodically enters into balance_dirty_pages()
      and we let it sleep there to slow down the dirtying.

      When the system is over dirty limit already (either globally or within
      a cgroup of the running task), we will not let the task exit from
      balance_dirty_pages() until the number of dirty pages drops below the
      limit.

      So in this particular case, as I already mentioned, there was a cgroup
      with relatively small amount of memory and as a result with dirty limit
      set at 16MB. A task from that cgroup has dirtied about 28MB worth of
      pages in btrfs btree inode and these were practically the only dirty
      pages in that cgroup.

    So that means the only way to reduce the dirty pages of that cgroup is
    to writeback the dirty pages of btrfs btree inode, and only after that
    those processes can exit balance_dirty_pages().

    Now back to the btrfs part, btree_writepages() is responsible for
    writing back dirty btree inode pages.

    The problem here is, there is a btrfs internal threshold that if the
    btree inode's dirty bytes are below the 32M threshold, it will not
    do any writeback.

    This behavior is to batch as much metadata as possible so we won't write
    back those tree blocks and then later re-COW them again for another
    modification.

    This internal 32MiB is higher than the existing dirty page size (28MiB),
    meaning no writeback will happen, causing a deadlock between btrfs and
    cgroup:

    - Btrfs doesn't want to write back btree inode until more dirty pages

    - Cgroup/MM doesn't want more dirty pages for btrfs btree inode
      Thus any process touching that btree inode is put into sleep until
      the number of dirty pages is reduced.

    Thanks Jan Kara a lot for the analysis of the root cause.

    [ENHANCEMENT]
    Since kernel commit b55102826d7d (btrfs: set AS_KERNEL_FILE on the
    btree_inode), btrfs btree inode pages will only be charged to the root
    cgroup which should have a much larger limit than btrfs' 32MiB
    threshold.
    So it should not affect newer kernels.

    But for all current LTS kernels, they are all affected by this problem,
    and backporting the whole AS_KERNEL_FILE may not be a good idea.

    Even for newer kernels I still think it's a good idea to get
    rid of the internal threshold at btree_writepages(), since for most cases
    cgroup/MM has a better view of full system memory usage than btrfs' fixed
    threshold.

    For internal callers using btrfs_btree_balance_dirty() since that
    function is already doing internal threshold check, we don't need to
    bother them.

    But for external callers of btree_writepages(), just respect their
    requests and write back whatever they want, ignoring the internal
    btrfs threshold to avoid such deadlock on btree inode dirty page
    balancing.

Tenable has extracted the preceding description block directly from the Unity Linux security advisory.

Note that Nessus has not tested for this issue but has instead relied only on the application's self-reported version
number.");
  # https://src.uniontech.com/#/security_advisory_detail?utsa_id=UTSA-2026-102019
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?9a604c00");
  # https://git.kernel.org/stable/c/0c3666ec188640c20e254011e7adf4464c32ee58
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?aa18b684");
  # https://git.kernel.org/stable/c/4357e02cafabe01c2d737ceb4c4c6382fc2ee10a
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?ed7fe447");
  # https://git.kernel.org/stable/c/4e159150a9a56d66d247f4b5510bed46fe58aa1c
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?39c7e6e8");
  # https://git.kernel.org/stable/c/629666d20c7dcd740e193ec0631fdff035b1f7d6
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?ec781a97");
  # https://git.kernel.org/stable/c/6a8b6242eaa1dd7a0de2d6de6420d10ffe68db90
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?b33a1f9f");
  # https://git.kernel.org/stable/c/bb9be3f713652e330df00f3724c18c7a5469e7ac
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?35728db5");
  # https://lore.kernel.org/linux-cve-announce/2026021416-CVE-2026-23157-6214@gregkh
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?7abaa623");
  script_set_attribute(attribute:"see_also", value:"https://nvd.nist.gov/vuln/detail/CVE-2026-23157");
  script_set_attribute(attribute:"see_also", value:"https://security-tracker.debian.org/tracker/CVE-2026-23157");
  script_set_attribute(attribute:"solution", value:
"Update the affected kernel package.");
  script_set_cvss_base_vector("CVSS2#AV:L/AC:L/Au:S/C:N/I:N/A:C");
  script_set_cvss_temporal_vector("CVSS2#E:U/RL:OF/RC:C");
  script_set_cvss3_base_vector("CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H");
  script_set_cvss3_temporal_vector("CVSS:3.0/E:U/RL:O/RC:C");
  script_set_attribute(attribute:"cvss_score_source", value:"CVE-2026-23157");

  script_set_attribute(attribute:"exploitability_ease", value:"No known exploits are available");
  script_set_attribute(attribute:"exploit_available", value:"false");

  script_set_attribute(attribute:"vuln_publication_date", value:"2026/02/14");
  script_set_attribute(attribute:"patch_publication_date", value:"2026/08/17");
  script_set_attribute(attribute:"plugin_publication_date", value:"2026/08/21");

  script_set_attribute(attribute:"plugin_type", value:"local");
  script_set_attribute(attribute:"generated_plugin", value:"current");
  script_end_attributes();

  script_category(ACT_GATHER_INFO);
  script_family(english:"Unity Linux Local Security Checks");

  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");
  script_require_keys("Host/local_checks_enabled", "Host/UOS-Server/release", "Host/UOS-Server/rpm-list", "Host/cpu");

  exit(0);
}
include('rpm2.inc');

if (!get_kb_item('Host/local_checks_enabled')) audit(AUDIT_LOCAL_CHECKS_NOT_ENABLED);
var os_product = get_kb_item('installed_os/local/SSH/0/product');
if (isnull(os_product) || 'UOS Server' >!< os_product) audit(AUDIT_OS_NOT, 'UOS Server');
var os_version = get_kb_item('installed_os/local/SSH/0/version');
if (isnull(os_version)) audit(AUDIT_UNKNOWN_APP_VER, 'UOS Server');
if (! preg(pattern:"^(20.1050e)([^0-9]|$)", string:os_version)) audit(AUDIT_OS_NOT, 'UOS Server 20.1050e', 'UOS Server ' + os_version);

if (!get_kb_item('Host/UOS-Server/rpm-list')) audit(AUDIT_PACKAGE_LIST_MISSING);

var cpu = get_kb_item('Host/cpu');
if (isnull(cpu)) audit(AUDIT_UNKNOWN_ARCH);
if ('aarch64' >!< cpu && 'amd64' >!< cpu && 'x86_64' >!< cpu) audit(AUDIT_LOCAL_CHECKS_NOT_IMPLEMENTED, 'UOS Server', cpu);


var constraints = [
  {
    'release': '20',
    'sp': '1050e',
    'pkgs': [
      {'reference':'kernel-4.19.90-2211.5.0.0178.67.uel20', 'sp':'1050e', 'cpu':'aarch64', 'rpm_spec_vers_cmp':TRUE},
      {'reference':'kernel-4.19.90-2211.5.0.0178.67.uel20', 'sp':'1050e', 'cpu':'amd64', 'rpm_spec_vers_cmp':TRUE},
      {'reference':'kernel-4.19.90-2211.5.0.0178.67.uel20', 'sp':'1050e', 'cpu':'x86_64', 'rpm_spec_vers_cmp':TRUE}
    ]
  }
];

var os_release = get_one_kb_item('installed_os/local/SSH/0/release');
var os_sp = get_one_kb_item('Host/*/minor_release');

var flag = 0;
var reference;
var sp;
var _cpu;
var el_string;
var rpm_spec_vers_cmp;
var epoch;
var allowmaj;
var exists_check;
var cves;
foreach var constraint ( constraints ) {
  # Check that the target release is equal to the affected release
  if (!empty_or_null(constraint['release'])){
    if (constraint['release'] != os_release) continue;
  }
  if (!empty_or_null(constraint['sp'])){
    if (constraint['sp'] != os_sp) continue;
  }
  foreach var pkg ( constraint['pkgs'] ) {
    reference = NULL;
    sp = NULL;
    _cpu = NULL;
    el_string = NULL;
    rpm_spec_vers_cmp = NULL;
    epoch = NULL;
    allowmaj = NULL;
    exists_check = NULL;
    cves = NULL;
    if (!empty_or_null(pkg['reference'])) reference = pkg['reference'];
    if (!empty_or_null(pkg['sp'])) sp = pkg['sp'];
    if (!empty_or_null(pkg['cpu'])) _cpu = pkg['cpu'];
    if (!empty_or_null(pkg['el_string'])) el_string = pkg['el_string'];
    if (!empty_or_null(pkg['rpm_spec_vers_cmp'])) rpm_spec_vers_cmp = pkg['rpm_spec_vers_cmp'];
    if (!empty_or_null(pkg['epoch'])) epoch = pkg['epoch'];
    if (!empty_or_null(pkg['allowmaj'])) allowmaj = pkg['allowmaj'];
    if (!empty_or_null(pkg['exists_check'])) exists_check = pkg['exists_check'];
    if (!empty_or_null(pkg['cves'])) cves = pkg['cves'];
    if (reference &&
        ## (no known rpm to check OR known rpm_exists)
        (!exists_check || rpm_exists(rpm:exists_check)) &&
        rpm_check(sp:sp, cpu:_cpu, reference:reference, epoch:epoch, el_string:el_string, rpm_spec_vers_cmp:rpm_spec_vers_cmp, allowmaj:allowmaj, cves:cves)) flag++;
  }
}


if (flag)
{
  security_report_v4(
      port       : 0,
      severity   : SECURITY_WARNING,
      extra      : rpm_report_get()
  );
  exit(0);
}
else
{
  var tested = pkg_tests_get();
  if (tested) audit(AUDIT_PACKAGE_NOT_AFFECTED, tested);
  else audit(AUDIT_PACKAGE_NOT_INSTALLED, 'kernel');
}

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

21 Aug 2026 00:00Current
5.6Medium risk
Vulners AI Score5.6
CVSS 3.15.5
EPSS0.00125
4