Lucene search
K

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

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

Kernel security update fixes mm/slub TID updates on slab deactivation to prevent object loss.

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

include('compat.inc');

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

  script_cve_id("CVE-2022-49700");

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

  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-987258 advisory.

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

    mm/slub: add missing TID updates on slab deactivation

    The fastpath in slab_alloc_node() assumes that c->slab is stable as long as
    the TID stays the same. However, two places in __slab_alloc() currently
    don't update the TID when deactivating the CPU slab.

    If multiple operations race the right way, this could lead to an object
    getting lost; or, in an even more unlikely situation, it could even lead to
    an object being freed onto the wrong slab's freelist, messing up the
    `inuse` counter and eventually causing a page to be freed to the page
    allocator while it still contains slab objects.

    (I haven't actually tested these cases though, this is just based on
    looking at the code. Writing testcases for this stuff seems like it'd be
    a pain...)

    The race leading to state inconsistency is (all operations on the same CPU
    and kmem_cache):

     - task A: begin do_slab_free():
        - read TID
        - read pcpu freelist (==NULL)
        - check `slab == c->slab` (true)
     - [PREEMPT A->B]
     - task B: begin slab_alloc_node():
        - fastpath fails (`c->freelist` is NULL)
        - enter __slab_alloc()
        - slub_get_cpu_ptr() (disables preemption)
        - enter ___slab_alloc()
        - take local_lock_irqsave()
        - read c->freelist as NULL
        - get_freelist() returns NULL
        - write `c->slab = NULL`
        - drop local_unlock_irqrestore()
        - goto new_slab
        - slub_percpu_partial() is NULL
        - get_partial() returns NULL
        - slub_put_cpu_ptr() (enables preemption)
     - [PREEMPT B->A]
     - task A: finish do_slab_free():
        - this_cpu_cmpxchg_double() succeeds()
        - [CORRUPT STATE: c->slab==NULL, c->freelist!=NULL]

    From there, the object on c->freelist will get lost if task B is allowed to
    continue from here: It will proceed to the retry_load_slab label,
    set c->slab, then jump to load_freelist, which clobbers c->freelist.

    But if we instead continue as follows, we get worse corruption:

     - task A: run __slab_free() on object from other struct slab:
        - CPU_PARTIAL_FREE case (slab was on no list, is now on pcpu partial)
     - task A: run slab_alloc_node() with NUMA node constraint:
        - fastpath fails (c->slab is NULL)
        - call __slab_alloc()
        - slub_get_cpu_ptr() (disables preemption)
        - enter ___slab_alloc()
        - c->slab is NULL: goto new_slab
        - slub_percpu_partial() is non-NULL
        - set c->slab to slub_percpu_partial(c)
        - [CORRUPT STATE: c->slab points to slab-1, c->freelist has objects
          from slab-2]
        - goto redo
        - node_match() fails
        - goto deactivate_slab
        - existing c->freelist is passed into deactivate_slab()
        - inuse count of slab-1 is decremented to account for object from
          slab-2

    At this point, the inuse count of slab-1 is 1 lower than it should be.
    This means that if we free all allocated objects in slab-1 except for one,
    SLUB will think that slab-1 is completely unused, and may free its page,
    leading to use-after-free.

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-987258
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?1dee1e35");
  # https://lore.kernel.org/linux-cve-announce/2025022629-CVE-2022-49700-2b3e@gregkh
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?7434652c");
  script_set_attribute(attribute:"see_also", value:"https://nvd.nist.gov/vuln/detail/CVE-2022-49700");
  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:H/I:H/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-2022-49700");

  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:"2022/07/21");
  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
5.7Medium risk
Vulners AI Score5.7
CVSS 3.17.8
EPSS0.00283
SSVC
4