CVE-2021-30716
A resource exhaustion vulnerability exists in the SMB Server on Apple macOS 11.2. A specially crafted SMB packet can trigger an infinite loop which leads to maximum CPU utilization and denial of service. This vulnerability can be triggered by sending a malicious packet to the vulnerable server.
Apple macOS 11.2
6.5 - CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
CWE-835 - Loop with Unreachable Exit Condition (‘Infinite Loop’)
macOS is a series of proprietary operating systems developed by Apple with macOS 11.2, with Big Sur being the latest.
Server Message Block (SMB) is a network file sharing protocol widely used in Windows network environments and macOS contains a proprietary implementation of both server and client components. SMB is often used in office and enterprise environments for file and printer sharing.
Three distinct versions and multiple dialects of SMB protocol are supported by macOS’ SMB server. This vulnerability is present in SMB2 and newer versions of the protocol, more specifically in the LOCK
request processing.
Lock requests are meant to be used to prevent changes to file contents pending other operations. As specified by SMB protocol , lock request structure contains a file ID which points to a file to be locked, as well as one or more LOCK_ELEMENT
structures which contain file offset at which a lock should be made, lock size and flags. File locking is handled by smb2_dispatch_lock
function which extracts the packet contents, partially validates the locks and proceeds to call ntvfs::lock_range
function in a loop to lock all file ranges specified by LOCK_ELEMENT
entries in the packet. There exists a bug in the way error conditions are handled. Namely , when two LOCK_ELEMENT
structures in a single lock request have an overlapping range , a second lock call can fail , depending on the flags. When lock_range
fails, an error code is returned and looping over LOCK_ELEMENT
structures is halted. Following code is being executed:
100029665 rax_9 = ntvfs::lock_range(r12_1, &var_38, &var_70) [1]
10002966d if (rax_9 u>= 0x40000000)
100029681 if ((platform::log::global_level() & 0x1f) == 0x1f)
1000296ac int64_t* rax_13 = platform::log::logger_for_level(0x1f)
1000296c0 (*(*rax_13 + 0x10))(rax_13, 0x1f, "/AppleInternal/BuildRoot/Library…", 0x56, "smb2_dispatch_lock", "%s: lock_range error, lock_fid: …", "smb2_dispatch_lock", var_70, zmm0.q, zmm0:8.q, rax_9) [2]
100029688 if ((rbx_1 & 4) == 0)
100029688 break [3]
10002968e i = i + 1
100029698 r13_1 = r13_1 + 0x18
100029698 while (i u< zx.q(smb_lock_request.lock_count)) [4]
100029709 if (not(rax_9 u>= 0x40000000 && (rbx_1 & 4) == 0))
100029709 goto label_100029709
10002980b if (i.d == 0)
100029836 rax_5 = smb2_schedule_error(arg1, rax_9)
100029818 else
100029818 while (true) [5]
100029818 int32_t var_68_2 = 2
100029828 ntvfs::lock_range(r12_1, &var_38, &var_70)
10002980b goto label_1000297da
In the above code, when a call to lock_range
at [1] fails, a debug message stating the reason is printed at [2] and break from the loop at [4] is made at [3]. Then, after a few condition checks execution ends up at [5] which causes ntvfs::lock_range
to be called in a loop without any possible exit condition. This constitutes an infinite loop which will keep the client handling thread busy forever. The thread isn’t affected by timeouts and will use all available CPU resources. If a second lock request with the same contents is made , another client handling thread will follow the same path and end up in an infinite loop, too. Depending on number of cores available to the SMB server, additional client handling threads can be allocated, but no matter how many are available, they can be exhausted by running the supplied proof of concept code multiple times. Once all available threads end up stuck in infinite loops, the SMB server becomes unavailable which constitutes a denial of service state. Moreover, the whole operating system is affected as SMB threads use up all available CPU.
2021-03-04 - Vendor Disclosure
2021-05-25 - Vendor Patched
2021-06-02 - Public Release
Discovered by Aleksandar Nikolic of Cisco Talos.