Docker 29.4.2 breaks SteamCMD in AMP containers with CreateBoundSocket error + FIX

OS Name/Version:

Debian 12.13

Product Name/Version:

AMP version: 2.7.2.2 - 20260429.1
Docker Engine version: 29.4.2
Docker API version: 1.54
containerd: v2.2.3
runc: 1.3.5

Problem Description:

After Docker updated to 29.4.2, SteamCMD inside AMP Docker containers started failing with:

CreateBoundSocket: failed to create socket, error [no name available] (38)

This caused AMP game server updates/installs to fail. In my case this affected a Windrose instance running inside an AMP-created Docker container.

Example container:

AMP_Windrose01   cubecoders/ampbase:wine-stable

Docker was using the built-in seccomp profile before the workaround:

Security Options:
 apparmor
 seccomp
  Profile: builtin

Steps to reproduce:

Step 1

Use AMP on Debian 12 with Docker Engine 29.4.2.

Step 2

Create or update a game server instance that uses SteamCMD inside an AMP Docker container.

Step 3

Run Update on the instance.

Step 4

SteamCMD fails with:

CreateBoundSocket: failed to create socket, error [no name available] (38)

Actions taken to resolve so far:

I found that Docker 29.4.2 appears to block the syscall path SteamCMD needs inside the AMP container. I worked around it by using a custom Docker seccomp profile based on Docker/Moby’s default profile, with two targeted changes:

Allow AF_ALG socket family 38
Allow 32-bit x86 socketcall

This is not seccomp=unconfined. Seccomp remains enabled:

Seccomp:        2
Seccomp_filters:        1

Security note:

This workaround intentionally makes Docker’s seccomp profile less restrictive than the current built-in profile. AF_ALG was blocked by Docker as a mitigation for CVE-2026-31431 / “Copy Fail”, a Linux kernel local privilege-escalation issue involving the algif_aead / AF_ALG crypto API.

So this should not be described as having “no security issues.”

My understanding is:

Vulnerable host kernel + AF_ALG allowed = risky
Patched host kernel + AF_ALG allowed = much less concerning
Vulnerable host kernel + AF_ALG blocked = mitigated by Docker's seccomp profile

This should be treated as a temporary workaround until Docker/CubeCoders provides an official fix.

————————————————————————————————————————

The workaround steps I used are below.

Docker 29.4.2 SteamCMD / AMP CreateBoundSocket Fix

Disclaimer: I am not responsible if this breaks your server, Docker setup, AMP install, containers, game saves, network config, or anything else. This is just what fixed the issue on my Debian 12 AMP host. Read the commands first, make backups, and use at your own risk.

Problem

After updating Docker to 29.4.2, SteamCMD inside CubeCoders AMP Docker containers started failing with errors like:

CreateBoundSocket: failed to create socket, error [no name available] (38)

In AMP, this caused SteamCMD updates/installs to fail. Example affected flow:

Loading Steam API...CreateBoundSocket: failed to create socket, error [no name available] (38)
OK
force_install_dir "4129620"
Connecting anonymously to Steam Public...Retrying...
CreateBoundSocket: failed to create socket, error [no name available] (38)
Retrying...

Scope

This workaround is for a Docker/seccomp issue affecting SteamCMD inside AMP Docker containers.

The relevant issue is:

Docker 29.4.2 + seccomp + SteamCMD inside AMP containers

This guide assumes a normal AMP Docker setup using CubeCoders’ Wine stable base image, for example:

cubecoders/ampbase:wine-stable

Security note

This workaround intentionally makes Docker’s seccomp profile less restrictive than the current built-in profile.

The important change is that it re-allows:

AF_ALG socket family 38
32-bit x86 socketcall

Docker blocked AF_ALG as a mitigation for CVE-2026-31431 / “Copy Fail”, a Linux kernel local privilege-escalation issue involving the algif_aead / AF_ALG crypto API.

So I do not describe this workaround as having “no security issues.”

A more accurate way to think about it is:

Vulnerable host kernel + AF_ALG allowed = risky
Patched host kernel + AF_ALG allowed = much less concerning
Vulnerable host kernel + AF_ALG blocked = mitigated by Docker's seccomp profile

If your host kernel has been patched for CVE-2026-31431 and you have rebooted into the patched kernel, the specific known exploit risk should be greatly reduced. However, this custom profile still gives containers broader syscall access than Docker’s hardened built-in profile.

Use this as a temporary workaround, especially on trusted/self-hosted game servers. Avoid running random untrusted containers while this workaround is active. Once Docker/CubeCoders provides an official fix, remove the custom profile and return to Docker’s built-in seccomp profile.

Check the currently running kernel with:

uname -r

On Debian, also check what kernel package is installed/candidate with:

apt policy linux-image-amd64

Remember: installing a patched kernel package is not enough by itself. You need to reboot into the patched kernel.

Host / Environment

This was tested on:

Debian 12
Docker Engine 29.4.2
CubeCoders AMP
AMP game instance using cubecoders/ampbase:wine-stable
Kernel: 6.1.0-44-amd64

Before the fix, Docker showed the default built-in seccomp profile:

docker info | grep -A5 "Security Options"

Output:

Security Options:
 apparmor
 seccomp
  Profile: builtin

What fixed it

The workaround was to use a custom Docker seccomp profile based on Docker/Moby’s default profile, but with two targeted changes:

  1. Allow AF_ALG sockets.
  2. Allow the old 32-bit socketcall syscall path.

This keeps seccomp enabled. It is not the same as running containers with:

seccomp=unconfined

After the fix, Docker showed:

Security Options:
 apparmor
 seccomp
  Profile: /etc/docker/seccomp/default-plus-afalg.json
 cgroupns

Docker also prints this warning:

WARNING: daemon is not using the default seccomp profile

That warning is expected because a custom profile is being used.

Step 1 — Back up existing Docker daemon config

sudo mkdir -p /root/docker-seccomp-backup

sudo cp -a /etc/docker/daemon.json \
  /root/docker-seccomp-backup/daemon.json.backup.$(date +%F-%H%M%S) \
  2>/dev/null || true

Step 2 — Create seccomp profile directory

sudo mkdir -p /etc/docker/seccomp

Step 3 — Download Docker/Moby default seccomp profile

sudo curl -fsSL \
  https://raw.githubusercontent.com/moby/profiles/main/seccomp/default.json \
  -o /etc/docker/seccomp/default-plus-afalg.json

Verify it downloaded:

ls -lh /etc/docker/seccomp/default-plus-afalg.json

Step 4 — Add AF_ALG socket allow rule

AF_ALG is socket family number 38.

sudo python3 - <<'PY'
import json
from pathlib import Path

path = Path("/etc/docker/seccomp/default-plus-afalg.json")

with path.open("r") as f:
    profile = json.load(f)

rule = {
    "names": ["socket"],
    "action": "SCMP_ACT_ALLOW",
    "args": [
        {
            "index": 0,
            "value": 38,
            "op": "SCMP_CMP_EQ"
        }
    ]
}

syscalls = profile["syscalls"]

already = False
for entry in syscalls:
    if entry.get("names") == ["socket"] and entry.get("action") == "SCMP_ACT_ALLOW":
        for arg in entry.get("args", []):
            if arg.get("index") == 0 and arg.get("value") == 38 and arg.get("op") == "SCMP_CMP_EQ":
                already = True

if not already:
    insert_at = 0
    for i, entry in enumerate(syscalls):
        if entry.get("names") == ["socket"]:
            insert_at = i
            break
    syscalls.insert(insert_at, rule)

with path.open("w") as f:
    json.dump(profile, f, indent=2)

print("Done. AF_ALG socket allow rule is present.")
PY

Validate JSON:

python3 -m json.tool /etc/docker/seccomp/default-plus-afalg.json >/dev/null && echo "JSON OK"

Expected:

JSON OK

Step 5 — Allow old 32-bit socketcall

This was the missing part in my case.

SteamCMD was still failing even after AF_ALG tested OK inside the container. The reason appears to be that some older/32-bit SteamCMD code paths can still hit socketcall, and Docker’s seccomp profile was returning errno 38.

Back up the profile first:

sudo cp -a /etc/docker/seccomp/default-plus-afalg.json \
  /root/docker-seccomp-backup/default-plus-afalg.before-socketcall.$(date +%F-%H%M%S).json

Patch the socketcall rule:

sudo python3 - <<'PY'
import json
from pathlib import Path

path = Path("/etc/docker/seccomp/default-plus-afalg.json")

with path.open("r") as f:
    profile = json.load(f)

changed = False

for entry in profile["syscalls"]:
    if entry.get("names") == ["socketcall"]:
        entry["action"] = "SCMP_ACT_ALLOW"
        entry.pop("errnoRet", None)
        entry["includes"] = {"arches": ["x86"]}
        changed = True

if not changed:
    profile["syscalls"].insert(0, {
        "names": ["socketcall"],
        "action": "SCMP_ACT_ALLOW",
        "includes": {"arches": ["x86"]}
    })

with path.open("w") as f:
    json.dump(profile, f, indent=2)

print("Done. socketcall is now allowed for 32-bit x86 processes.")
PY

Validate JSON again:

python3 -m json.tool /etc/docker/seccomp/default-plus-afalg.json >/dev/null && echo "JSON OK"

Step 6 — Configure Docker to use the custom profile

This edits /etc/docker/daemon.json without wiping other existing settings.

sudo python3 - <<'PY'
import json
from pathlib import Path

path = Path("/etc/docker/daemon.json")

if path.exists() and path.stat().st_size > 0:
    with path.open("r") as f:
        data = json.load(f)
else:
    data = {}

data["seccomp-profile"] = "/etc/docker/seccomp/default-plus-afalg.json"

with path.open("w") as f:
    json.dump(data, f, indent=2)

print(json.dumps(data, indent=2))
PY

Validate Docker daemon config JSON:

python3 -m json.tool /etc/docker/daemon.json

Expected to contain:

{
  "seccomp-profile": "/etc/docker/seccomp/default-plus-afalg.json"
}

If your daemon config already had other settings, those should still be present too.

Step 7 — Restart Docker

Stop AMP/game instances first if possible.

sudo systemctl restart docker

Check Docker came back:

sudo systemctl status docker --no-pager

Confirm the custom seccomp profile is loaded:

docker info | grep -A5 "Security Options"

Expected:

Security Options:
 apparmor
 seccomp
  Profile: /etc/docker/seccomp/default-plus-afalg.json
 cgroupns

Again, this warning is expected:

WARNING: daemon is not using the default seccomp profile

Step 8 — Recreate the affected AMP game container

This part mattered.

Existing AMP containers may not pick up the changed Docker seccomp profile until the container wrapper is recreated.

List containers:

docker ps -a --format 'table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Status}}'

Example:

CONTAINER ID   NAMES            IMAGE                              STATUS
aff398977831   AMP_Windrose01   cubecoders/ampbase:wine-stable     Up 12 seconds

Stop the affected instance in AMP first.

Then remove only the Docker container wrapper:

docker rm AMP_Windrose01

Replace AMP_Windrose01 with your actual AMP container name.

Do not delete the AMP instance itself.

Start the instance again from AMP. AMP should recreate the container using the new Docker daemon seccomp profile.

Step 9 — Verify seccomp and AF_ALG inside the AMP container

Check seccomp is still enabled:

docker exec AMP_Windrose01 grep Seccomp /proc/self/status

Expected:

Seccomp:        2
Seccomp_filters:        1

Check AF_ALG socket creation:

docker exec -i AMP_Windrose01 python3 - <<'PY'
import socket
try:
    s = socket.socket(38, socket.SOCK_SEQPACKET, 0)
    print("AF_ALG socket OK")
    s.close()
except Exception as e:
    print("AF_ALG socket FAILED:", repr(e))
PY

Expected:

AF_ALG socket OK

Check Docker is using the custom profile:

docker info | grep -A5 "Security Options"

Expected:

Security Options:
 apparmor
 seccomp
  Profile: /etc/docker/seccomp/default-plus-afalg.json
 cgroupns

Result after fix

After applying the profile and recreating the AMP container, SteamCMD worked again. The important part is that the old CreateBoundSocket error disappeared and SteamCMD could connect to Steam Public.

Successful AMP update log:

Loading Steam API...OK
force_install_dir "4129620"
Connecting anonymously to Steam Public...OK
Waiting for client config...OK
Waiting for user info...OK
@sSteamCmdForcePlatformType windows
"@sSteamCmdForcePlatformType" = "windows"
app_update 4129620 validate
 Update state (0x5) verifying install, progress: 48.09 (1462470440 / 3041100240)
 Update state (0x5) verifying install, progress: 96.87 (2945959199 / 3041100240)
 Update state (0x0) unknown, progress: 0.00 (0 / 0)
Success! App '4129620' fully installed.
quit
Unloading Steam API...OK

It also successfully installed Steam app 1007:

app_update 1007 validate
Success! App '1007' fully installed.

Rollback / Undo

If Docker releases a fixed version and you want to go back to Docker’s built-in seccomp profile, remove the custom profile entry from /etc/docker/daemon.json.

sudo python3 - <<'PY'
import json
from pathlib import Path

path = Path("/etc/docker/daemon.json")

if not path.exists():
    raise SystemExit("No /etc/docker/daemon.json exists.")

with path.open("r") as f:
    data = json.load(f)

data.pop("seccomp-profile", None)

with path.open("w") as f:
    json.dump(data, f, indent=2)

print(json.dumps(data, indent=2))
PY

Validate JSON:

python3 -m json.tool /etc/docker/daemon.json

Restart Docker:

sudo systemctl restart docker

Confirm Docker is back to the built-in profile:

docker info | grep -A5 "Security Options"

Expected:

Security Options:
 apparmor
 seccomp
  Profile: builtin

You may also need to recreate any AMP containers again after reverting so they pick up the built-in profile.

Notes

  • This is safer than seccomp=unconfined because seccomp remains enabled.
  • The custom profile is based on Docker/Moby’s default profile.
  • The two important changes were:
    • Allow AF_ALG socket family 38.
    • Allow socketcall for 32-bit x86 processes.
  • This fixed SteamCMD inside a cubecoders/ampbase:wine-stable AMP container for me.
  • Existing containers may need to be recreated after changing Docker’s daemon-level seccomp profile.
  • If the host kernel is patched for CVE-2026-31431 and the system has rebooted into that patched kernel, the known AF_ALG exploit risk should be greatly reduced.
  • Even on a patched kernel, this should still be treated as a temporary workaround until Docker/CubeCoders provides an official fix.
1 Like