Lucene search
K

Unity Linux 20.1070e Security Update: kernel (UTSA-2025-987124)

🗓️ 07 Oct 2025 00:00:00Reported by TenableType 
nessus
 nessus
🔗 www.tenable.com👁 7 Views

Unity Linux kernel fix for memcontrol slab freeing memory cgroup reference to prevent kmem pinning.

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

include('compat.inc');

if (description)
{
  script_id(269078);
  script_version("1.2");
  script_set_attribute(attribute:"plugin_modification_date", value:"2025/10/15");

  script_cve_id("CVE-2021-47011");

  script_name(english:"Unity Linux 20.1070e Security Update: kernel (UTSA-2025-987124)");

  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-2025-987124 advisory.

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

    mm: memcontrol: slab: fix obtain a reference to a freeing memcg

    Patch series Use obj_cgroup APIs to charge kmem pages, v5.

    Since Roman's series The new cgroup slab memory controller applied.
    All slab objects are charged with the new APIs of obj_cgroup.  The new
    APIs introduce a struct obj_cgroup to charge slab objects.  It prevents
    long-living objects from pinning the original memory cgroup in the
    memory.  But there are still some corner objects (e.g.  allocations
    larger than order-1 page on SLUB) which are not charged with the new
    APIs.  Those objects (include the pages which are allocated from buddy
    allocator directly) are charged as kmem pages which still hold a
    reference to the memory cgroup.

    E.g.  We know that the kernel stack is charged as kmem pages because the
    size of the kernel stack can be greater than 2 pages (e.g.  16KB on
    x86_64 or arm64).  If we create a thread (suppose the thread stack is
    charged to memory cgroup A) and then move it from memory cgroup A to
    memory cgroup B.  Because the kernel stack of the thread hold a
    reference to the memory cgroup A.  The thread can pin the memory cgroup
    A in the memory even if we remove the cgroup A.  If we want to see this
    scenario by using the following script.  We can see that the system has
    added 500 dying cgroups (This is not a real world issue, just a script
    to show that the large kmallocs are charged as kmem pages which can pin
    the memory cgroup in the memory).

            #!/bin/bash

            cat /proc/cgroups | grep memory

            cd /sys/fs/cgroup/memory
            echo 1 > memory.move_charge_at_immigrate

            for i in range{1..500}
            do
                    mkdir kmem_test
                    echo $$ > kmem_test/cgroup.procs
                    sleep 3600 &
                    echo $$ > cgroup.procs
                    echo `cat kmem_test/cgroup.procs` > cgroup.procs
                    rmdir kmem_test
            done

            cat /proc/cgroups | grep memory

    This patchset aims to make those kmem pages to drop the reference to
    memory cgroup by using the APIs of obj_cgroup.  Finally, we can see that
    the number of the dying cgroups will not increase if we run the above test
    script.

    This patch (of 7):

    The rcu_read_lock/unlock only can guarantee that the memcg will not be
    freed, but it cannot guarantee the success of css_get (which is in the
    refill_stock when cached memcg changed) to memcg.

      rcu_read_lock()
      memcg = obj_cgroup_memcg(old)
      __memcg_kmem_uncharge(memcg)
          refill_stock(memcg)
              if (stock->cached != memcg)
                  // css_get can change the ref counter from 0 back to 1.
                  css_get(&memcg->css)
      rcu_read_unlock()

    This fix is very like the commit:

      eefbfa7fd678 (mm: memcg/slab: fix use after free in obj_cgroup_charge)

    Fix this by holding a reference to the memcg which is passed to the
    __memcg_kmem_uncharge() before calling __memcg_kmem_uncharge().

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-2025-987124
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?e5cdf61d");
  # https://lore.kernel.org/linux-cve-announce/2024022831-CVE-2021-47011-5b75@gregkh
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?89a12d43");
  script_set_attribute(attribute:"see_also", value:"https://nvd.nist.gov/vuln/detail/CVE-2021-47011");
  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-2021-47011");

  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:"2021/11/09");
  script_set_attribute(attribute:"patch_publication_date", value:"2025/09/23");
  script_set_attribute(attribute:"plugin_publication_date", value:"2025/10/07");

  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) 2025 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.1070e([^0-9]|$)", string:os_version)) audit(AUDIT_OS_NOT, 'UOS Server 20.1070e', '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': '1070e',
    'pkgs': [
      {'reference':'kernel-5.10.0-74.16', 'sp':'1070e', 'cpu':'aarch64', 'rpm_spec_vers_cmp':TRUE},
      {'reference':'kernel-5.10.0-74.16', 'sp':'1070e', 'cpu':'amd64', 'rpm_spec_vers_cmp':TRUE},
      {'reference':'kernel-5.10.0-74.16', 'sp':'1070e', '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

15 Oct 2025 00:00Current
6.8Medium risk
Vulners AI Score6.8
CVSS 3.15.5
EPSS0.00239
SSVC
7