CVE-2017-8779 - libtirpc, libntirpc: Memory leak when failing to parse XDR strings or bytearrays ("rpcbomb")

Solution In Progress - Updated -

Environment

  • Red Hat Enterprise Linux 6
  • Red Hat Enterprise Linux 7
  • Red Hat Gluster Storage 3
  • Red Hat Ceph Storage 2 [ libntirpc tech preview ]

Issue

Issues in the interaction between rpcbind, which provides a directory service for SunRPC-based services such as NFS, and the low-level programming interfaces for SunRPC provided by libtirpc, libntirpc, and glibc, could lead to memory being allocated and never freed. This could occur when malformed messages are sent to rpcbind, and would be visible as an increase in the process' VmSize as reported in /proc/$pid/status or by top.

Impact

Red Hat Product Security has rated this issue Important.

This flaw could be used to execute a remote Denial of Service (DoS) attack. In the default system configuration, with the sysctl variable vm.overcommit_memory set to either 0 or 1, an attack would take a not-insignificant amount of time to exhaust the system's memory. If vm.overcommit_memory is set to a value of 2, the time required to exhaust system memory is sufficiently reduced. It was further noticed that, a 32-bit system would have its memory exhausted faster than a 64-bit system.

Detailed Description

SunRPC is an RPC (remote procedure call) mechanism originally designed by Sun Microsystems in the 1980s. Messages are encoded using XDR (external data representation: RFC4506, a binary format for serialising structured messages to disk or to send across the network).

XDR messages of particular types (such as "string", "bytes") include a 32-bit size field. When libtirpc parses this field, it will malloc() a corresponding amount of memory and then attempt to parse the rest of the message. If the message was truncated, parsing would return an error without freeing the allocated region. Client code such as rpcbind is supposed to call a routine to free the reserved memory in this case - as it would after using the results of a successful parse - but in certain error cases it failed to do so. Potentially, up to 4GiB per message could be allocated.

Since the allocated regions were never actually used, the kernel would not allocate physical memory for these pages. Persistent attacks sending hundreds of thousands of packets could cause the allocator's page tables eventually to grow, causing the system to swap and rpcbind to be terminated by the OOM (out-of-memory) Killer.

Depending on the setting of sysctl vm.overcommit_memory, the process could map more virtual memory than was physically available on the system with very little impact. If vm.overcommit_memory=2 was set, other processes could potentially be impacted as the affected service rapidly consumed large amounts of available memory, causing the OOM Killer to be invoked. Details about Configuring System Memory can be found within the Red Hat Enterprise Linux Performance Tuning Guide.

Resolution

Mitigations are described below. Patches to all affected components will be made available in future updates.

Mitigation

  1. Close port 111 on machines which are on a public or untrusted network. 111 (tcp/udp) should be closed
  2. A system having port 111 open should have firewall rules (iptables or firewalld) to accept connections from trusted machines only
  3. Use vm.overcommit_memory=0 or 1 only

Note: The above mitigations are present by default on default installations of Red Hat Enterprise Linux Server. These settings can be changed by a system administrator during or post installation time. The packages system-config-firewall and firewalld deny remote access to rpcbind by default. vm.overcommit_memory is normally set to 0. Additionally, we suggest that a simple cron job can be setup which monitors VmSize of rpcbind and can trigger alerts.

If your environment has a particular need to set vm.overcommit_memory=2, we strongly recommend setting per-process resource limits using systemd directives such as LimitAS, or ulimit hard limits.

Errata

This issue was resolved with the release of the following Security Errata.
NOTE: This Security Errata introduced a regression within the rpcbind package for a subset of our customers and resolved in subsequent Bugfix Errata which is listed below.

Root Cause

On one hand, libtirpc's interface was too fragile in this case. Since it didn't actually use the allocated region, it should have released it immediately (or never allocated it in the first place). This would allow the exceptional case in rpcbind to remain simple without risking a leak. On the other hand, client code -- especially in long-lived daemons -- should always be careful to deallocate resources under any circumstances, as any failure to do so may be an opportunity to attackers.

Patches for libtirpc, libntirpc, glibc and rpcinfo were all proposed in the security community and to upstream maintainers, with some of that activity occurring on Red Hat's Bugzilla. In cases like this, improving all of the involved software makes systems more robust into the future. Red Hat Product Security also undertook an analysis of other programs using XDR and the SunRPC interfaces in case the bug manifested elsewhere - particularly in important services such as krb5 and nfs-ganesha. On examining the relevant code, we did not find any obvious instances of similar errors in other packages and are confident this particular flaw is confined to rpcbind.

More information about this issue can be found on our CVE page: CVE-2017-8779

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.