Lucene search
+L

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

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

Linux kernel TCP GSO xmit error handling causes ACK stall and connection freeze in veth environments.

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

include('compat.inc');

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

  script_cve_id("CVE-2026-43194");

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

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

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

    net: consume xmit errors of GSO frames

    udpgro_frglist.sh and udpgro_bench.sh are the flakiest tests
    currently in NIPA. They fail in the same exact way, TCP GRO
    test stalls occasionally and the test gets killed after 10min.

    These tests use veth to simulate GRO. They attach a trivial
    (return XDP_PASS;) XDP program to the veth to force TSO off
    and NAPI on.

    Digging into the failure mode we can see that the connection
    is completely stuck after a burst of drops. The sender's snd_nxt
    is at sequence number N [1], but the receiver claims to have
    received (rcv_nxt) up to N + 3 * MSS [2]. Last piece of the puzzle
    is that senders rtx queue is not empty (let's say the block in
    the rtx queue is at sequence number N - 4 * MSS [3]).

    In this state, sender sends a retransmission from the rtx queue
    with a single segment, and sequence numbers N-4*MSS:N-3*MSS [3].
    Receiver sees it and responds with an ACK all the way up to
    N + 3 * MSS [2]. But sender will reject this ack as TCP_ACK_UNSENT_DATA
    because it has no recollection of ever sending data that far out [1].
    And we are stuck.

    The root cause is the mess of the xmit return codes. veth returns
    an error when it can't xmit a frame. We end up with a loss event
    like this:

      -------------------------------------------------
      |   GSO super frame 1   |   GSO super frame 2   |
      |-----------------------------------------------|
      | seg | seg | seg | seg | seg | seg | seg | seg |
      |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |
      -------------------------------------------------
         x    ok    ok    <ok>|  ok    ok    ok   <x>
                              \
                               snd_nxt

    x means packet lost by veth, and ok means it went thru.
    Since veth has TSO disabled in this test it sees individual segments.
    Segment 1 is on the retransmit queue and will be resent.

    So why did the sender not advance snd_nxt even tho it clearly did
    send up to seg 8? tcp_write_xmit() interprets the return code
    from the core to mean that data has not been sent at all. Since
    TCP deals with GSO super frames, not individual segment the crux
    of the problem is that loss of a single segment can be interpreted
    as loss of all. TCP only sees the last return code for the last
    segment of the GSO frame (in <> brackets in the diagram above).

    Of course for the problem to occur we need a setup or a device
    without a Qdisc. Otherwise Qdisc layer disconnects the protocol
    layer from the device errors completely.

    We have multiple ways to fix this.

     1) make veth not return an error when it lost a packet.
        While this is what I think we did in the past, the issue keeps
        reappearing and it's annoying to debug. The game of whack
        a mole is not great.

     2) fix the damn return codes
        We only talk about NETDEV_TX_OK and NETDEV_TX_BUSY in the
        documentation, so maybe we should make the return code from
        ndo_start_xmit() a boolean. I like that the most, but perhaps
        some ancient, not-really-networking protocol would suffer.

     3) make TCP ignore the errors
        It is not entirely clear to me what benefit TCP gets from
        interpreting the result of ip_queue_xmit()? Specifically once
        the connection is established and we're pushing data - packet
        loss is just packet loss?

     4) this fix
        Ignore the rc in the Qdisc-less+GSO case, since it's unreliable.
        We already always return OK in the TCQ_F_CAN_BYPASS case.
        In the Qdisc-less case let's be a bit more conservative and only
        mask the GSO errors. This path is taken by non-IP-networks
        like CAN, MCTP etc, so we could regress some ancient thing.
        This is the simplest, but also maybe the hackiest fix?

    Similar fix has been proposed by Eric in the past but never committed
    because original reporter was working with an OOT driver and wasn't
    providing feedback (see Link).

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-100138
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?b1d10f20");
  # https://lore.kernel.org/linux-cve-announce/2026050643-CVE-2026-43194-a00a@gregkh
  script_set_attribute(attribute:"see_also", value:"http://www.nessus.org/u?ffc642cd");
  script_set_attribute(attribute:"see_also", value:"https://nvd.nist.gov/vuln/detail/CVE-2026-43194");
  script_set_attribute(attribute:"solution", value:
"Update the affected kernel package.");
  script_set_cvss_base_vector("CVSS2#AV:N/AC:L/Au:N/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:N/AC:L/PR:N/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-43194");

  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/03/12");
  script_set_attribute(attribute:"patch_publication_date", value:"2026/08/13");
  script_set_attribute(attribute:"plugin_publication_date", value:"2026/08/17");

  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-5.10.0-27.18.uel20', 'sp':'1050e', 'cpu':'aarch64', 'rpm_spec_vers_cmp':TRUE},
      {'reference':'kernel-5.10.0-27.18.uel20', 'sp':'1050e', 'cpu':'amd64', 'rpm_spec_vers_cmp':TRUE},
      {'reference':'kernel-5.10.0-27.18.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_HOLE,
      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

17 Aug 2026 00:00Current
6.7Medium risk
Vulners AI Score6.7
CVSS 3.17.5
EPSS0.00533
3