VYPR
High severityOSV Advisory· Published Sep 12, 2025· Updated Apr 15, 2026

CVE-2025-59054

CVE-2025-59054

Description

dstack is a software development kit (SDK) to simplify the deployment of arbitrary containerized apps into trusted execution environments. In versions of dstack prior to 0.5.4, a malicious host may provide a crafted LUKS2 data volume to a dstack CVM for use as the /data mount. The guest will open the volume and write secret data using a volume key known to the attacker, causing disclosure of Wireguard keys and other secret information. The attacker can also pre-load data on the device, which could potentially compromise guest execution. LUKS2 volume metadata is not authenticated and supports null key-encryption algorithms, allowing an attacker to create a volume such that the volume opens (cryptsetup open) without error using any passphrase or token, records all writes in plaintext (or ciphertext with an attacker-known key), and/or contains arbitrary data chosen by the attacker. Version 0.5.4 of dstack contains a patch that addresses LUKS headers.

Affected products

1

Patches

2
fb75a412cb72

Merge pull request #342 from Dstack-TEE/docker-org

https://github.com/dstack-tee/dstackKevin WangSep 24, 2025via osv
4 files changed · +10 10
  • .github/workflows/gateway-release.yml+3 3 modified
    @@ -51,7 +51,7 @@ jobs:
             with:
               context: gateway/dstack-app/builder
               push: true
    -          tags: ${{ vars.DOCKERHUB_USERNAME }}/gateway:${{ env.VERSION }}
    +          tags: ${{ vars.DOCKERHUB_ORG }}/dstack-gateway:${{ env.VERSION }}
               platforms: linux/amd64
               provenance: false
               build-args: |
    @@ -61,7 +61,7 @@ jobs:
           - name: Generate artifact attestation
             uses: actions/attest-build-provenance@v1
             with:
    -          subject-name: "docker.io/${{ vars.DOCKERHUB_USERNAME }}/gateway"
    +          subject-name: "docker.io/${{ vars.DOCKERHUB_ORG }}/dstack-gateway"
               subject-digest: ${{ steps.build-and-push.outputs.digest }}
               push-to-registry: true
     
    @@ -72,7 +72,7 @@ jobs:
               body: |
                 ## Docker Image Information
     
    -            **Image**: `docker.io/${{ vars.DOCKERHUB_USERNAME }}/gateway:${{ env.VERSION }}`
    +            **Image**: `docker.io/${{ vars.DOCKERHUB_ORG }}/dstack-gateway:${{ env.VERSION }}`
     
                 **Digest (SHA256)**: `${{ steps.build-and-push.outputs.digest }}`
     
    
  • .github/workflows/kms-release.yml+3 3 modified
    @@ -54,7 +54,7 @@ jobs:
             with:
               context: kms/dstack-app/builder
               push: true
    -          tags: ${{ vars.DOCKERHUB_USERNAME }}/kms:${{ env.VERSION }}
    +          tags: ${{ vars.DOCKERHUB_ORG }}/dstack-kms:${{ env.VERSION }}
               platforms: linux/amd64
               provenance: false
               build-args: |
    @@ -65,7 +65,7 @@ jobs:
           - name: Generate artifact attestation
             uses: actions/attest-build-provenance@v1
             with:
    -          subject-name: "docker.io/${{ vars.DOCKERHUB_USERNAME }}/kms"
    +          subject-name: "docker.io/${{ vars.DOCKERHUB_ORG }}/dstack-kms"
               subject-digest: ${{ steps.build-and-push.outputs.digest }}
               push-to-registry: true
     
    @@ -92,7 +92,7 @@ jobs:
               body: |
                 ## Docker Image Information
     
    -            **Image**: `docker.io/${{ vars.DOCKERHUB_USERNAME }}/kms:${{ env.VERSION }}`
    +            **Image**: `docker.io/${{ vars.DOCKERHUB_ORG }}/dstack-kms:${{ env.VERSION }}`
     
                 **Digest (SHA256)**: `${{ steps.build-and-push.outputs.digest }}`
     
    
  • .github/workflows/verifier-release.yml+3 3 modified
    @@ -51,7 +51,7 @@ jobs:
               context: verifier
               file: verifier/builder/Dockerfile
               push: true
    -          tags: ${{ vars.DOCKERHUB_USERNAME }}/dstack-verifier:${{ env.VERSION }}
    +          tags: ${{ vars.DOCKERHUB_ORG }}/dstack-verifier:${{ env.VERSION }}
               platforms: linux/amd64
               provenance: false
               build-args: |
    @@ -62,7 +62,7 @@ jobs:
           - name: Generate artifact attestation
             uses: actions/attest-build-provenance@v1
             with:
    -          subject-name: "docker.io/${{ vars.DOCKERHUB_USERNAME }}/dstack-verifier"
    +          subject-name: "docker.io/${{ vars.DOCKERHUB_ORG }}/dstack-verifier"
               subject-digest: ${{ steps.build-and-push.outputs.digest }}
               push-to-registry: true
     
    @@ -73,7 +73,7 @@ jobs:
               body: |
                 ## Docker Image Information
     
    -            **Image**: `docker.io/${{ vars.DOCKERHUB_USERNAME }}/dstack-verifier:${{ env.VERSION }}`
    +            **Image**: `docker.io/${{ vars.DOCKERHUB_ORG }}/dstack-verifier:${{ env.VERSION }}`
     
                 **Digest (SHA256)**: `${{ steps.build-and-push.outputs.digest }}`
     
    
  • verifier/README.md+1 1 modified
    @@ -102,7 +102,7 @@ DSTACK_VERIFIER_PORT=8080 cargo run --bin dstack-verifier
     ```yaml
     services:
       dstack-verifier:
    -    image: kvin/dstack-verifier:latest
    +    image: dstacktee/dstack-verifier:latest
         ports:
           - "8080:8080"
         restart: unless-stopped
    
e36ad5f732d8

Merge branch 'advisory-fix-1'

https://github.com/dstack-tee/dstackKevin WangSep 1, 2025via osv
6 files changed · +622 61
  • Cargo.lock+337 53 modified
    @@ -27,14 +27,26 @@ dependencies = [
      "generic-array",
     ]
     
    +[[package]]
    +name = "aes"
    +version = "0.7.5"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
    +dependencies = [
    + "cfg-if",
    + "cipher 0.3.0",
    + "cpufeatures",
    + "opaque-debug",
    +]
    +
     [[package]]
     name = "aes"
     version = "0.8.4"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
     dependencies = [
      "cfg-if",
    - "cipher",
    + "cipher 0.4.4",
      "cpufeatures",
     ]
     
    @@ -45,8 +57,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1"
     dependencies = [
      "aead",
    - "aes",
    - "cipher",
    + "aes 0.8.4",
    + "cipher 0.4.4",
      "ctr",
      "ghash",
      "subtle",
    @@ -190,7 +202,7 @@ dependencies = [
      "derive_more 2.0.1",
      "either",
      "serde",
    - "sha2",
    + "sha2 0.10.9",
     ]
     
     [[package]]
    @@ -292,7 +304,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "5f70d83b765fdc080dbcd4f4db70d8d23fe4761f2f02ebfa9146b833900634b4"
     dependencies = [
      "alloy-rlp-derive",
    - "arrayvec",
    + "arrayvec 0.7.6",
      "bytes",
     ]
     
    @@ -458,7 +470,7 @@ checksum = "983d99aa81f586cef9dae38443245e585840fcf0fc58b09aee0b1f27aed1d500"
     dependencies = [
      "alloy-primitives",
      "alloy-rlp",
    - "arrayvec",
    + "arrayvec 0.7.6",
      "derive_more 2.0.1",
      "nybbles",
      "serde",
    @@ -673,6 +685,12 @@ version = "0.3.9"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
     
    +[[package]]
    +name = "arrayvec"
    +version = "0.5.2"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
    +
     [[package]]
     name = "arrayvec"
     version = "0.7.6"
    @@ -882,6 +900,12 @@ version = "0.2.0"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
     
    +[[package]]
    +name = "base64"
    +version = "0.13.1"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
    +
     [[package]]
     name = "base64"
     version = "0.22.1"
    @@ -909,6 +933,15 @@ version = "0.1.4"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72"
     
    +[[package]]
    +name = "bincode"
    +version = "1.3.3"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
    +dependencies = [
    + "serde",
    +]
    +
     [[package]]
     name = "bindgen"
     version = "0.69.5"
    @@ -1016,6 +1049,26 @@ dependencies = [
      "digest 0.10.7",
     ]
     
    +[[package]]
    +name = "blake2b_simd"
    +version = "0.5.11"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587"
    +dependencies = [
    + "arrayref",
    + "arrayvec 0.5.2",
    + "constant_time_eq",
    +]
    +
    +[[package]]
    +name = "block-buffer"
    +version = "0.9.0"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
    +dependencies = [
    + "generic-array",
    +]
    +
     [[package]]
     name = "block-buffer"
     version = "0.10.4"
    @@ -1043,7 +1096,7 @@ version = "0.18.1"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "97ccca1260af6a459d75994ad5acc1651bcabcbdbc41467cc9786519ab854c30"
     dependencies = [
    - "base64",
    + "base64 0.22.1",
      "bollard-stubs",
      "bytes",
      "futures-core",
    @@ -1211,7 +1264,7 @@ dependencies = [
      "serde",
      "serde-human-bytes",
      "serde_json",
    - "sha2",
    + "sha2 0.10.9",
     ]
     
     [[package]]
    @@ -1302,6 +1355,15 @@ dependencies = [
      "windows-link",
     ]
     
    +[[package]]
    +name = "cipher"
    +version = "0.3.0"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
    +dependencies = [
    + "generic-array",
    +]
    +
     [[package]]
     name = "cipher"
     version = "0.4.4"
    @@ -1456,6 +1518,12 @@ dependencies = [
      "unicode-xid",
     ]
     
    +[[package]]
    +name = "constant_time_eq"
    +version = "0.1.5"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
    +
     [[package]]
     name = "convert_case"
     version = "0.6.0"
    @@ -1574,6 +1642,31 @@ version = "0.8.21"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
     
    +[[package]]
    +name = "crossterm"
    +version = "0.19.0"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "7c36c10130df424b2f3552fcc2ddcd9b28a27b1e54b358b45874f88d1ca6888c"
    +dependencies = [
    + "bitflags 1.3.2",
    + "crossterm_winapi",
    + "lazy_static",
    + "libc",
    + "mio 0.7.14",
    + "parking_lot 0.11.2",
    + "signal-hook 0.1.17",
    + "winapi",
    +]
    +
    +[[package]]
    +name = "crossterm_winapi"
    +version = "0.7.0"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "0da8964ace4d3e4a044fd027919b2237000b24315a37c916f61809f1ff2140b9"
    +dependencies = [
    + "winapi",
    +]
    +
     [[package]]
     name = "crunchy"
     version = "0.2.4"
    @@ -1603,6 +1696,16 @@ dependencies = [
      "typenum",
     ]
     
    +[[package]]
    +name = "crypto-mac"
    +version = "0.11.0"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e"
    +dependencies = [
    + "generic-array",
    + "subtle",
    +]
    +
     [[package]]
     name = "ct_monitor"
     version = "0.5.3"
    @@ -1628,7 +1731,7 @@ version = "0.9.2"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
     dependencies = [
    - "cipher",
    + "cipher 0.4.4",
     ]
     
     [[package]]
    @@ -1750,7 +1853,7 @@ dependencies = [
      "hashbrown 0.14.5",
      "lock_api",
      "once_cell",
    - "parking_lot_core",
    + "parking_lot_core 0.9.11",
     ]
     
     [[package]]
    @@ -1767,7 +1870,7 @@ checksum = "32ef42eade99e79b9fb9d31532041a0a380a7e849d3486950a40b1afd5bf417c"
     dependencies = [
      "anyhow",
      "asn1_der",
    - "base64",
    + "base64 0.22.1",
      "byteorder",
      "chrono",
      "const-oid",
    @@ -1969,7 +2072,7 @@ version = "0.10.7"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
     dependencies = [
    - "block-buffer",
    + "block-buffer 0.10.4",
      "const-oid",
      "crypto-common",
      "subtle",
    @@ -2083,7 +2186,7 @@ dependencies = [
      "serde",
      "serde-duration",
      "serde_json",
    - "sha2",
    + "sha2 0.10.9",
      "shared_child",
      "smallvec",
      "tokio",
    @@ -2110,7 +2213,7 @@ name = "dstack-guest-agent"
     version = "0.5.3"
     dependencies = [
      "anyhow",
    - "base64",
    + "base64 0.22.1",
      "bollard",
      "cert-client",
      "chrono",
    @@ -2138,7 +2241,7 @@ dependencies = [
      "sd-notify",
      "serde",
      "serde_json",
    - "sha2",
    + "sha2 0.10.9",
      "sha3",
      "strip-ansi-escapes",
      "sysinfo",
    @@ -2191,7 +2294,7 @@ dependencies = [
      "serde-duration",
      "serde-human-bytes",
      "serde_json",
    - "sha2",
    + "sha2 0.10.9",
      "sha3",
      "tempfile",
      "tokio",
    @@ -2230,7 +2333,7 @@ dependencies = [
      "serde",
      "serde-human-bytes",
      "serde_json",
    - "sha2",
    + "sha2 0.10.9",
      "thiserror 2.0.15",
     ]
     
    @@ -2263,7 +2366,7 @@ dependencies = [
      "reqwest",
      "serde",
      "serde_json",
    - "sha2",
    + "sha2 0.10.9",
      "tokio",
      "x509-parser",
     ]
    @@ -2280,7 +2383,7 @@ dependencies = [
      "pkcs8",
      "serde",
      "serde_json",
    - "sha2",
    + "sha2 0.10.9",
      "tokio",
     ]
     
    @@ -2315,17 +2418,19 @@ dependencies = [
      "host-api",
      "k256",
      "libc",
    + "luks2",
      "parity-scale-codec",
      "ra-rpc",
      "ra-tls",
      "rand 0.8.5",
      "regex",
      "schnorrkel",
    + "scopeguard",
      "serde",
      "serde-human-bytes",
      "serde_json",
      "serde_yaml2",
    - "sha2",
    + "sha2 0.10.9",
      "sha3",
      "sodiumbox",
      "tdx-attest",
    @@ -2342,7 +2447,7 @@ name = "dstack-vmm"
     version = "0.5.3"
     dependencies = [
      "anyhow",
    - "base64",
    + "base64 0.22.1",
      "bon",
      "clap",
      "dirs",
    @@ -2369,7 +2474,7 @@ dependencies = [
      "serde",
      "serde-human-bytes",
      "serde_json",
    - "sha2",
    + "sha2 0.10.9",
      "shared_child",
      "strip-ansi-escapes",
      "supervisor-client",
    @@ -2548,7 +2653,7 @@ version = "0.3.1"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418"
     dependencies = [
    - "arrayvec",
    + "arrayvec 0.7.6",
      "auto_impl",
      "bytes",
     ]
    @@ -2559,7 +2664,7 @@ version = "0.4.0"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4"
     dependencies = [
    - "arrayvec",
    + "arrayvec 0.7.6",
      "auto_impl",
      "bytes",
     ]
    @@ -3045,7 +3150,7 @@ version = "0.2.1"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd"
     dependencies = [
    - "arrayvec",
    + "arrayvec 0.7.6",
     ]
     
     [[package]]
    @@ -3127,7 +3232,7 @@ dependencies = [
      "ipconfig",
      "lru-cache",
      "once_cell",
    - "parking_lot",
    + "parking_lot 0.12.4",
      "rand 0.8.5",
      "resolv-conf",
      "smallvec",
    @@ -3148,7 +3253,7 @@ dependencies = [
      "ipconfig",
      "moka",
      "once_cell",
    - "parking_lot",
    + "parking_lot 0.12.4",
      "rand 0.9.2",
      "resolv-conf",
      "smallvec",
    @@ -3163,7 +3268,17 @@ version = "0.12.4"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
     dependencies = [
    - "hmac",
    + "hmac 0.12.1",
    +]
    +
    +[[package]]
    +name = "hmac"
    +version = "0.11.0"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
    +dependencies = [
    + "crypto-mac",
    + "digest 0.9.0",
     ]
     
     [[package]]
    @@ -3353,7 +3468,7 @@ version = "0.1.16"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e"
     dependencies = [
    - "base64",
    + "base64 0.22.1",
      "bytes",
      "futures-channel",
      "futures-core",
    @@ -3611,14 +3726,23 @@ dependencies = [
      "similar",
     ]
     
    +[[package]]
    +name = "instant"
    +version = "0.1.13"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
    +dependencies = [
    + "cfg-if",
    +]
    +
     [[package]]
     name = "instant-acme"
     version = "0.7.2"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "37221e690dcc5d0ea7c1f70decda6ae3495e72e8af06bca15e982193ffdf4fc4"
     dependencies = [
      "async-trait",
    - "base64",
    + "base64 0.22.1",
      "bytes",
      "http",
      "http-body",
    @@ -3662,7 +3786,7 @@ dependencies = [
      "clap",
      "fs-err",
      "hex_fmt",
    - "sha2",
    + "sha2 0.10.9",
      "sha3",
     ]
     
    @@ -3807,7 +3931,7 @@ dependencies = [
      "elliptic-curve",
      "once_cell",
      "serdect",
    - "sha2",
    + "sha2 0.10.9",
      "signature",
     ]
     
    @@ -4005,6 +4129,28 @@ dependencies = [
      "insta",
     ]
     
    +[[package]]
    +name = "luks2"
    +version = "0.5.0"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "2044d8bd5489b199890c3dbf38d4c8f50f3a5a38833986808b14e2367fe267fa"
    +dependencies = [
    + "aes 0.7.5",
    + "base64 0.13.1",
    + "bincode",
    + "crossterm",
    + "hmac 0.11.0",
    + "pbkdf2",
    + "rust-argon2",
    + "secrecy",
    + "serde",
    + "serde-big-array",
    + "serde_json",
    + "sha2 0.9.9",
    + "thiserror 1.0.69",
    + "xts-mode",
    +]
    +
     [[package]]
     name = "macro-string"
     version = "0.1.4"
    @@ -4095,6 +4241,19 @@ dependencies = [
      "adler2",
     ]
     
    +[[package]]
    +name = "mio"
    +version = "0.7.14"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
    +dependencies = [
    + "libc",
    + "log",
    + "miow",
    + "ntapi 0.3.7",
    + "winapi",
    +]
    +
     [[package]]
     name = "mio"
     version = "1.0.4"
    @@ -4107,6 +4266,15 @@ dependencies = [
      "windows-sys 0.59.0",
     ]
     
    +[[package]]
    +name = "miow"
    +version = "0.3.7"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
    +dependencies = [
    + "winapi",
    +]
    +
     [[package]]
     name = "moka"
     version = "0.12.10"
    @@ -4117,7 +4285,7 @@ dependencies = [
      "crossbeam-epoch",
      "crossbeam-utils",
      "loom 0.7.2",
    - "parking_lot",
    + "parking_lot 0.12.4",
      "portable-atomic",
      "rustc_version 0.4.1",
      "smallvec",
    @@ -4251,7 +4419,7 @@ dependencies = [
      "kqueue",
      "libc",
      "log",
    - "mio",
    + "mio 1.0.4",
      "notify-types",
      "walkdir",
      "windows-sys 0.60.2",
    @@ -4263,6 +4431,15 @@ version = "2.0.0"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d"
     
    +[[package]]
    +name = "ntapi"
    +version = "0.3.7"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
    +dependencies = [
    + "winapi",
    +]
    +
     [[package]]
     name = "ntapi"
     version = "0.4.1"
    @@ -4481,7 +4658,7 @@ dependencies = [
      "ecdsa",
      "elliptic-curve",
      "primeorder",
    - "sha2",
    + "sha2 0.10.9",
     ]
     
     [[package]]
    @@ -4512,7 +4689,7 @@ version = "3.7.5"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa"
     dependencies = [
    - "arrayvec",
    + "arrayvec 0.7.6",
      "bitvec",
      "byte-slice-cast",
      "const_format",
    @@ -4534,14 +4711,39 @@ dependencies = [
      "syn 2.0.106",
     ]
     
    +[[package]]
    +name = "parking_lot"
    +version = "0.11.2"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
    +dependencies = [
    + "instant",
    + "lock_api",
    + "parking_lot_core 0.8.6",
    +]
    +
     [[package]]
     name = "parking_lot"
     version = "0.12.4"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
     dependencies = [
      "lock_api",
    - "parking_lot_core",
    + "parking_lot_core 0.9.11",
    +]
    +
    +[[package]]
    +name = "parking_lot_core"
    +version = "0.8.6"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
    +dependencies = [
    + "cfg-if",
    + "instant",
    + "libc",
    + "redox_syscall 0.2.16",
    + "smallvec",
    + "winapi",
     ]
     
     [[package]]
    @@ -4552,7 +4754,7 @@ checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
     dependencies = [
      "cfg-if",
      "libc",
    - "redox_syscall",
    + "redox_syscall 0.5.17",
      "smallvec",
      "windows-targets 0.52.6",
     ]
    @@ -4581,6 +4783,15 @@ dependencies = [
      "once_cell",
     ]
     
    +[[package]]
    +name = "pbkdf2"
    +version = "0.8.0"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa"
    +dependencies = [
    + "crypto-mac",
    +]
    +
     [[package]]
     name = "pear"
     version = "0.2.9"
    @@ -4610,7 +4821,7 @@ version = "3.0.5"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3"
     dependencies = [
    - "base64",
    + "base64 0.22.1",
      "serde",
     ]
     
    @@ -5193,7 +5404,7 @@ dependencies = [
      "serde",
      "serde-human-bytes",
      "serde_json",
    - "sha2",
    + "sha2 0.10.9",
      "sha3",
      "tdx-attest",
      "tracing",
    @@ -5333,6 +5544,15 @@ dependencies = [
      "yasna",
     ]
     
    +[[package]]
    +name = "redox_syscall"
    +version = "0.2.16"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
    +dependencies = [
    + "bitflags 1.3.2",
    +]
    +
     [[package]]
     name = "redox_syscall"
     version = "0.5.17"
    @@ -5429,7 +5649,7 @@ version = "0.12.23"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb"
     dependencies = [
    - "base64",
    + "base64 0.22.1",
      "bytes",
      "encoding_rs",
      "futures-channel",
    @@ -5479,7 +5699,7 @@ version = "0.4.0"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
     dependencies = [
    - "hmac",
    + "hmac 0.12.1",
      "subtle",
     ]
     
    @@ -5569,7 +5789,7 @@ dependencies = [
      "memchr",
      "multer",
      "num_cpus",
    - "parking_lot",
    + "parking_lot 0.12.4",
      "pin-project-lite",
      "rand 0.8.5",
      "ref-cast",
    @@ -5689,6 +5909,18 @@ version = "1.2.1"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18"
     
    +[[package]]
    +name = "rust-argon2"
    +version = "0.8.3"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb"
    +dependencies = [
    + "base64 0.13.1",
    + "blake2b_simd",
    + "constant_time_eq",
    + "crossbeam-utils",
    +]
    +
     [[package]]
     name = "rustc-demangle"
     version = "0.1.26"
    @@ -6014,7 +6246,7 @@ version = "0.10.2"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213"
     dependencies = [
    - "cipher",
    + "cipher 0.4.4",
     ]
     
     [[package]]
    @@ -6092,13 +6324,13 @@ checksum = "6e9fcb6c2e176e86ec703e22560d99d65a5ee9056ae45a08e13e84ebf796296f"
     dependencies = [
      "aead",
      "arrayref",
    - "arrayvec",
    + "arrayvec 0.7.6",
      "curve25519-dalek",
      "getrandom_or_panic",
      "merlin",
      "rand_core 0.6.4",
      "serde_bytes",
    - "sha2",
    + "sha2 0.10.9",
      "subtle",
      "zeroize",
     ]
    @@ -6160,6 +6392,15 @@ dependencies = [
      "cc",
     ]
     
    +[[package]]
    +name = "secrecy"
    +version = "0.8.0"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e"
    +dependencies = [
    + "zeroize",
    +]
    +
     [[package]]
     name = "security-framework"
     version = "3.3.0"
    @@ -6216,6 +6457,15 @@ dependencies = [
      "serde_derive",
     ]
     
    +[[package]]
    +name = "serde-big-array"
    +version = "0.3.3"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "cd31f59f6fe2b0c055371bb2f16d7f0aa7d8881676c04a55b1596d1a17cd10a4"
    +dependencies = [
    + "serde",
    +]
    +
     [[package]]
     name = "serde-duration"
     version = "0.5.3"
    @@ -6315,7 +6565,7 @@ version = "3.14.0"
     source = "registry+https://github.com/rust-lang/crates.io-index"
     checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5"
     dependencies = [
    - "base64",
    + "base64 0.22.1",
      "chrono",
      "hex",
      "indexmap 1.9.3",
    @@ -6362,6 +6612,19 @@ dependencies = [
      "serde",
     ]
     
    +[[package]]
    +name = "sha2"
    +version = "0.9.9"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
    +dependencies = [
    + "block-buffer 0.9.0",
    + "cfg-if",
    + "cpufeatures",
    + "digest 0.9.0",
    + "opaque-debug",
    +]
    +
     [[package]]
     name = "sha2"
     version = "0.10.9"
    @@ -6427,7 +6690,18 @@ checksum = "47106eded3c154e70176fc83df9737335c94ce22f821c32d17ed1db1f83badb1"
     dependencies = [
      "libc",
      "os_pipe",
    - "signal-hook",
    + "signal-hook 0.3.18",
    +]
    +
    +[[package]]
    +name = "signal-hook"
    +version = "0.1.17"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "7e31d442c16f047a671b5a71e2161d6e68814012b7f5379d269ebd915fac2729"
    +dependencies = [
    + "libc",
    + "mio 0.7.14",
    + "signal-hook-registry",
     ]
     
     [[package]]
    @@ -6711,7 +6985,7 @@ checksum = "3c3ffa3e4ff2b324a57f7aeb3c349656c7b127c3c189520251a648102a92496e"
     dependencies = [
      "libc",
      "memchr",
    - "ntapi",
    + "ntapi 0.4.1",
      "objc2-core-foundation",
      "objc2-io-kit",
      "windows 0.61.3",
    @@ -6774,7 +7048,7 @@ dependencies = [
      "serde",
      "serde-human-bytes",
      "serde_json",
    - "sha2",
    + "sha2 0.10.9",
      "tdx-attest-sys",
      "thiserror 2.0.15",
     ]
    @@ -6964,8 +7238,8 @@ dependencies = [
      "bytes",
      "io-uring",
      "libc",
    - "mio",
    - "parking_lot",
    + "mio 1.0.4",
    + "parking_lot 0.12.4",
      "pin-project-lite",
      "signal-hook-registry",
      "slab",
    @@ -7170,7 +7444,7 @@ dependencies = [
      "matchers",
      "nu-ansi-term",
      "once_cell",
    - "parking_lot",
    + "parking_lot 0.12.4",
      "regex",
      "sharded-slab",
      "smallvec",
    @@ -8017,6 +8291,16 @@ dependencies = [
      "zeroize",
     ]
     
    +[[package]]
    +name = "xts-mode"
    +version = "0.4.1"
    +source = "registry+https://github.com/rust-lang/crates.io-index"
    +checksum = "75a099a2f21d48275314733f85bc43b6c6213b66394233aaea573fc7a520dcd9"
    +dependencies = [
    + "byteorder",
    + "cipher 0.3.0",
    +]
    +
     [[package]]
     name = "yaml-rust2"
     version = "0.8.1"
    
  • Cargo.toml+3 0 modified
    @@ -211,3 +211,6 @@ which = "7.0.2"
     smallvec = "1.14.0"
     cmd_lib = "1.9.5"
     serde_yaml2 = "0.1.2"
    +
    +luks2 = "0.5.0"
    +scopeguard = "1.2.0"
    
  • dstack-util/Cargo.toml+2 0 modified
    @@ -49,6 +49,8 @@ serde_yaml2.workspace = true
     bollard.workspace = true
     sodiumbox.workspace = true
     libc.workspace = true
    +luks2.workspace = true
    +scopeguard.workspace = true
     
     [dev-dependencies]
     rand.workspace = true
    
  • dstack-util/src/system_setup.rs+280 8 modified
    @@ -18,9 +18,14 @@ use dstack_types::{
         KeyProvider, KeyProviderInfo,
     };
     use fs_err as fs;
    +use luks2::{
    +    LuksAf, LuksConfig, LuksDigest, LuksHeader, LuksJson, LuksKdf, LuksKeyslot, LuksSegment,
    +    LuksSegmentSize,
    +};
     use ra_rpc::client::{CertInfo, RaClient, RaClientConfig};
     use ra_tls::cert::generate_ra_cert;
     use rand::Rng as _;
    +use scopeguard::defer;
     use serde::{Deserialize, Serialize};
     use tdx_attest::extend_rtmr3;
     use tracing::{info, warn};
    @@ -449,10 +454,7 @@ impl<'a> Stage0<'a> {
                     .notify_q("boot.progress", "mounting data disk")
                     .await;
                 info!("Mounting encrypted data disk");
    -            let root_hd = &self.args.device;
    -            let disk_crypt_key = disk_crypt_key.trim();
    -            cmd!(echo -n $disk_crypt_key | cryptsetup luksOpen --type luks2 -d- $root_hd $name)
    -                .or(Err(anyhow!("Failed to open encrypted data disk")))?;
    +            self.open_encrypted_volume(disk_crypt_key, name)?;
                 cmd! {
                     zpool import dstack;
                     zpool status dstack;
    @@ -468,15 +470,55 @@ impl<'a> Stage0<'a> {
     
         fn luks_setup(&self, disk_crypt_key: &str, name: &str) -> Result<()> {
             let root_hd = &self.args.device;
    +        let sector_offset = PAYLOAD_OFFSET / 512;
             cmd! {
                 info "Formatting encrypted disk";
                 echo -n $disk_crypt_key |
    -                cryptsetup luksFormat --type luks2 --cipher aes-xts-plain64 --pbkdf pbkdf2 -d- $root_hd $name;
    +                cryptsetup luksFormat
    +                    --type luks2
    +                    --offset $sector_offset
    +                    --cipher aes-xts-plain64
    +                    --pbkdf pbkdf2
    +                    -d-
    +                    $root_hd
    +                    $name;
    +        }
    +        .or(Err(anyhow!("Failed to setup luks volume")))?;
    +        self.open_encrypted_volume(disk_crypt_key, name)
    +    }
    +
    +    fn open_encrypted_volume(&self, disk_crypt_key: &str, name: &str) -> Result<()> {
    +        let root_hd = &self.args.device;
    +        let disk_crypt_key = disk_crypt_key.trim();
    +        // Create a private tmpfs mount to ensure the header stays in-memory.
    +        let tmp_hdr_dir = "/tmp/dstack-luks-header";
    +        let in_mem_hdr = format!("{tmp_hdr_dir}/luks-header");
    +        defer! {
    +            // Ensure cleanup of header file and tmpfs mount.
    +            cmd! {
    +                info "Cleaning up in-memory LUKS header";
    +                rm -f $in_mem_hdr;
    +                umount $tmp_hdr_dir;
    +                rmdir $tmp_hdr_dir;
    +            }.ok();
    +        }
    +        cmd! {
    +            info "Mounting tmpfs for in-memory LUKS header";
    +            mkdir -p $tmp_hdr_dir;
    +            mount -t tmpfs -o size=64M,mode=0700,nosuid,nodev,noexec tmpfs $tmp_hdr_dir;
    +            info "Loading the LUKS2 header";
    +            cryptsetup luksHeaderBackup --header-backup-file=$in_mem_hdr $root_hd;
    +        }
    +        .context("Failed to load LUKS2 header")?;
     
    +        let hdr_file = fs::File::open(&in_mem_hdr).context("Failed to open LUKS2 header")?;
    +        validate_luks2_headers(hdr_file).context("Failed to validate LUKS2 header")?;
    +
    +        cmd! {
                 info "Opening the device";
    -            echo -n $disk_crypt_key |
    -                cryptsetup luksOpen --type luks2 -d- $root_hd $name;
    -        }.or(Err(anyhow!("Failed to setup luks volume")))?;
    +            echo -n $disk_crypt_key | cryptsetup luksOpen --type luks2 --header $in_mem_hdr -d- $root_hd $name;
    +        }
    +        .or(Err(anyhow!("Failed to open encrypted data disk")))?;
             Ok(())
         }
     
    @@ -914,3 +956,233 @@ impl Stage1<'_> {
             Ok(())
         }
     }
    +
    +macro_rules! const_pad {
    +    ($s:expr, $len:expr) => {
    +        const {
    +            assert!($s.len() <= $len, "The s is too long");
    +            let mut padded: [u8; $len] = [0; $len];
    +            let mut i = 0;
    +            while i < $s.len() {
    +                padded[i] = $s[i];
    +                i += 1;
    +            }
    +            padded
    +        }
    +    };
    +}
    +
    +const PAYLOAD_OFFSET: u64 = 16777216;
    +
    +fn validate_luks2_headers(mut reader: impl std::io::Read) -> Result<()> {
    +    validate_single_luks2_header(&mut reader, 0)?;
    +    validate_single_luks2_header(&mut reader, 1)?;
    +    Ok(())
    +}
    +
    +fn validate_single_luks2_header(mut reader: impl std::io::Read, hdr_ind: u64) -> Result<()> {
    +    let mut hdr_data = vec![0u8; 4096];
    +    reader
    +        .read_exact(&mut hdr_data)
    +        .context("Failed to read LUKS header")?;
    +    let header =
    +        LuksHeader::read_from(&mut &hdr_data[..]).context("Failed to decode LUKS header")?;
    +    let LuksHeader {
    +        magic,
    +        version,
    +        hdr_size,
    +        seqid: _,
    +        label,
    +        csum_alg,
    +        salt: _,
    +        uuid: _,
    +        subsystem,
    +        hdr_offset,
    +        csum: _,
    +        ..
    +    } = header;
    +
    +    let expected_magic = match hdr_ind {
    +        0 => [76, 85, 75, 83, 186, 190],
    +        1 => [83, 75, 85, 76, 186, 190],
    +        _ => bail!("Invalid LUKS header index: {hdr_ind}"),
    +    };
    +    if magic != expected_magic {
    +        bail!("Invalid LUKS magic: {magic:?}");
    +    }
    +    if version != 2 {
    +        bail!("Invalid LUKS version: {version}");
    +    }
    +    if label != [0; 48] {
    +        bail!("Invalid LUKS label: {:?}", label);
    +    }
    +    if csum_alg != const_pad!(b"sha256", 32) {
    +        bail!("Invalid LUKS checksum algorithm");
    +    }
    +    if subsystem != [0; 48] {
    +        bail!("Invalid LUKS subsystem");
    +    }
    +    if hdr_offset != hdr_ind * hdr_size {
    +        bail!("Invalid LUKS header offset: {hdr_offset}");
    +    }
    +    if !(4096..=1024 * 1024 * 16).contains(&hdr_size) {
    +        bail!("Invalid LUKS header size: {hdr_size}");
    +    }
    +
    +    // Check JSON
    +    let json_size = hdr_size - 4096;
    +    let mut jsn_data = vec![0u8; json_size as usize];
    +    reader
    +        .read_exact(&mut jsn_data)
    +        .context("Failed to read LUKS JSON")?;
    +    let json_end = jsn_data
    +        .iter()
    +        .position(|&b| b == 0)
    +        .unwrap_or(jsn_data.len());
    +    jsn_data.truncate(json_end);
    +
    +    let json = LuksJson::read_from(&mut &jsn_data[..]).context("Failed to decode LUKS JSON")?;
    +    let LuksJson {
    +        keyslots,
    +        tokens,
    +        segments,
    +        digests,
    +        config:
    +            LuksConfig {
    +                json_size: _,
    +                keyslots_size: _,
    +                flags,
    +                requirements,
    +            },
    +    } = json;
    +
    +    if keyslots.len() != 1 {
    +        bail!("Invalid LUKS keyslots");
    +    }
    +    if !tokens.is_empty() {
    +        bail!("Invalid LUKS tokens");
    +    }
    +    if segments.len() != 1 {
    +        bail!("Invalid LUKS segments");
    +    }
    +    if digests.len() != 1 {
    +        bail!("Invalid LUKS digests");
    +    }
    +    if flags.is_some() {
    +        bail!("Invalid LUKS flags");
    +    }
    +    if requirements.is_some() {
    +        bail!("Invalid LUKS requirements");
    +    }
    +
    +    {
    +        let first_keyslot = keyslots.get(&0).context("no LUKS keyslot")?;
    +        let LuksKeyslot::luks2 {
    +            key_size,
    +            area,
    +            kdf,
    +            af,
    +            priority,
    +        } = first_keyslot;
    +        if area.encryption() != "aes-xts-plain64" {
    +            bail!("Invalid LUKS keyslot encryption: {}", area.encryption());
    +        }
    +        if *key_size != 64 {
    +            bail!("Invalid LUKS keyslot key size: {key_size}");
    +        }
    +        if area.key_size() != 64 {
    +            bail!("Invalid LUKS keyslot key size: {}", area.key_size());
    +        }
    +        {
    +            let LuksKdf::pbkdf2 {
    +                hash,
    +                iterations: _,
    +                salt: _,
    +            } = kdf
    +            else {
    +                bail!("Invalid LUKS keyslot KDF");
    +            };
    +            if hash != "sha256" {
    +                bail!("Invalid LUKS keyslot hash: {hash}");
    +            }
    +        }
    +        {
    +            let LuksAf::luks1 { hash, stripes } = af;
    +            if hash != "sha256" {
    +                bail!("Invalid LUKS keyslot hash: {hash}");
    +            }
    +            if *stripes != 4000 {
    +                bail!("Invalid LUKS keyslot stripes: {stripes}");
    +            }
    +        }
    +        if priority.is_some() {
    +            bail!("Invalid LUKS keyslot priority");
    +        }
    +    }
    +
    +    {
    +        let first_segment = segments.get(&0).context("no LUKS segment")?;
    +        let LuksSegment::crypt {
    +            offset,
    +            size,
    +            iv_tweak,
    +            encryption,
    +            sector_size,
    +            integrity,
    +            flags,
    +        } = first_segment;
    +        if *offset != PAYLOAD_OFFSET {
    +            bail!("Invalid LUKS segment offset");
    +        }
    +        if *size != LuksSegmentSize::dynamic {
    +            bail!("Invalid LUKS segment size");
    +        }
    +        if *iv_tweak != 0 {
    +            bail!("Invalid LUKS segment IV tweak");
    +        }
    +        if encryption != "aes-xts-plain64" {
    +            bail!("Invalid LUKS segment encryption");
    +        }
    +        if *sector_size != 512 {
    +            bail!("Invalid LUKS segment sector size");
    +        }
    +        if integrity.is_some() {
    +            bail!("Invalid LUKS segment integrity");
    +        }
    +        if flags.is_some() {
    +            bail!("Invalid LUKS segment flags");
    +        }
    +    }
    +    {
    +        let first_digest = digests.get(&0).context("no LUKS digest")?;
    +        let LuksDigest::pbkdf2 {
    +            keyslots,
    +            segments,
    +            hash,
    +            digest: _,
    +            iterations: _,
    +            salt: _,
    +        } = first_digest;
    +        if hash != "sha256" {
    +            bail!("Invalid LUKS digest hash: {hash}");
    +        }
    +        if keyslots != &[0] {
    +            bail!("Invalid LUKS digest keyslots: {keyslots:?}");
    +        }
    +        if segments != &[0] {
    +            bail!("Invalid LUKS digest segments: {segments:?}");
    +        }
    +    }
    +    Ok(())
    +}
    +
    +#[test]
    +fn test_validate_luks2_header() {
    +    let header_data = include_bytes!("../tests/fixtures/luks_header_good").to_vec();
    +    validate_luks2_headers(&mut &header_data[..]).expect("Failed to validate LUKS2 header");
    +    let header_data = include_bytes!("../tests/fixtures/luks_header_cipher_null").to_vec();
    +    let error = validate_luks2_headers(&mut &header_data[..]).unwrap_err();
    +    assert!(error
    +        .to_string()
    +        .contains("Invalid LUKS keyslot encryption"));
    +}
    
  • dstack-util/tests/fixtures/luks_header_cipher_null+0 0 added
  • dstack-util/tests/fixtures/luks_header_good+0 0 added

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.