Skip to content

Commit c0c944b

Browse files
committed
feat(tdx-attest): Add MUSL libc support for TDX attestation
Enable building with x86_64-unknown-linux-musl target by: 1. Vendoring minimal Linux kernel headers that are missing from MUSL: - linux/vm_sockets.h: vsock address family and sockaddr_vm struct - linux/types.h: kernel type aliases (__u8, __u32, __u64, etc.) - linux/ioctl.h: redirect to MUSL's sys/ioctl.h 2. Updating cfg conditions to include MUSL (target_env = "musl") alongside glibc (target_env = "gnu") 3. Modifying build.rs to prioritize vendored headers via include path This allows building statically-linked TDX attestation binaries using MUSL, which is useful for containerized deployments and systems without glibc. Tested: cargo build --target x86_64-unknown-linux-musl -p tdx-attest
1 parent 745b168 commit c0c944b

7 files changed

Lines changed: 276 additions & 6 deletions

File tree

LICENSES/GPL-2.0.txt

Lines changed: 117 additions & 0 deletions
Large diffs are not rendered by default.

tdx-attest-sys/build.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::path::PathBuf;
1010
fn main() {
1111
println!("cargo:rerun-if-changed=csrc/tdx_attest.c");
1212
println!("cargo:rerun-if-changed=csrc/qgs_msg_lib.cpp");
13+
println!("cargo:rerun-if-changed=csrc/linux/vm_sockets.h");
1314
let output_path = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR not set"));
1415
bindgen::Builder::default()
1516
.header("bindings.h")
@@ -21,5 +22,8 @@ fn main() {
2122
cc::Build::new()
2223
.file("csrc/tdx_attest.c")
2324
.file("csrc/qgs_msg_lib.cpp")
25+
// Add csrc to include path first so our vendored linux/vm_sockets.h is found
26+
// before system headers (needed for MUSL builds)
27+
.include("csrc")
2428
.compile("tdx_attest");
2529
}

tdx-attest-sys/csrc/linux/ioctl.h

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// SPDX-FileCopyrightText: Linux kernel contributors
2+
//
3+
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
4+
5+
/*
6+
* Vendored linux/ioctl.h for portable ioctl macros.
7+
*
8+
* This provides the _IO/_IOR/_IOW/_IOWR macros that accept struct types
9+
* and compute ioctl numbers based on sizeof(). These are needed by
10+
* tdx_attest.c and work consistently across glibc and MUSL.
11+
*
12+
* Based on: Linux kernel include/uapi/asm-generic/ioctl.h
13+
*/
14+
15+
#ifndef _LINUX_IOCTL_H
16+
#define _LINUX_IOCTL_H
17+
18+
/* ioctl command encoding: 32 bits total, command in lower 16 bits,
19+
* size of the parameter structure in the lower 14 bits of the
20+
* upper 16 bits.
21+
*/
22+
23+
#define _IOC_NRBITS 8
24+
#define _IOC_TYPEBITS 8
25+
#define _IOC_SIZEBITS 14
26+
#define _IOC_DIRBITS 2
27+
28+
#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)
29+
#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1)
30+
#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1)
31+
#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1)
32+
33+
#define _IOC_NRSHIFT 0
34+
#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
35+
#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
36+
#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS)
37+
38+
/* Direction bits */
39+
#define _IOC_NONE 0U
40+
#define _IOC_WRITE 1U
41+
#define _IOC_READ 2U
42+
43+
#define _IOC(dir,type,nr,size) \
44+
(((dir) << _IOC_DIRSHIFT) | \
45+
((type) << _IOC_TYPESHIFT) | \
46+
((nr) << _IOC_NRSHIFT) | \
47+
((size) << _IOC_SIZESHIFT))
48+
49+
#define _IOC_TYPECHECK(t) (sizeof(t))
50+
51+
/* Used to create numbers.
52+
* NOTE: _IOW means userland is writing and kernel is reading.
53+
* _IOR means userland is reading and kernel is writing.
54+
*/
55+
#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
56+
#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
57+
#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
58+
#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
59+
60+
/* Used to decode ioctl numbers */
61+
#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
62+
#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
63+
#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
64+
#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
65+
66+
#endif /* _LINUX_IOCTL_H */

tdx-attest-sys/csrc/linux/types.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// SPDX-FileCopyrightText: Linux kernel contributors
2+
//
3+
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
4+
5+
/*
6+
* Minimal vendored linux/types.h for MUSL compatibility.
7+
*
8+
* Provides kernel-style type aliases (__u8, __u16, __u32, __u64)
9+
* using standard C types from stdint.h.
10+
*/
11+
12+
#ifndef _LINUX_TYPES_H
13+
#define _LINUX_TYPES_H
14+
15+
#include <stdint.h>
16+
17+
typedef uint8_t __u8;
18+
typedef uint16_t __u16;
19+
typedef uint32_t __u32;
20+
typedef uint64_t __u64;
21+
22+
typedef int8_t __s8;
23+
typedef int16_t __s16;
24+
typedef int32_t __s32;
25+
typedef int64_t __s64;
26+
27+
/* Kernel-style sa_family_t if not already defined */
28+
#ifndef __kernel_sa_family_t
29+
typedef unsigned short __kernel_sa_family_t;
30+
#endif
31+
32+
#endif /* _LINUX_TYPES_H */
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// SPDX-FileCopyrightText: VMware, Inc.
2+
// SPDX-FileCopyrightText: Linux kernel contributors
3+
//
4+
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
5+
6+
/*
7+
* Minimal vendored version of linux/vm_sockets.h for MUSL compatibility.
8+
*
9+
* This header provides the minimal definitions needed by tdx_attest.c
10+
* without pulling in glibc-specific headers that conflict with MUSL.
11+
*
12+
* Based on: Linux kernel include/uapi/linux/vm_sockets.h
13+
* Original copyright: VMware, Inc.
14+
*/
15+
16+
#ifndef _VM_SOCKETS_H
17+
#define _VM_SOCKETS_H
18+
19+
#include <stdint.h>
20+
#include <sys/socket.h>
21+
22+
/* AF_VSOCK = PF_VSOCK = 40 */
23+
#ifndef AF_VSOCK
24+
#define AF_VSOCK 40
25+
#endif
26+
27+
/* Use this as the destination CID in an address when referring to the host
28+
* (any process other than the hypervisor).
29+
*/
30+
#define VMADDR_CID_HOST 2
31+
32+
/* Address structure for vSockets. The address family should be set to
33+
* AF_VSOCK.
34+
*/
35+
struct sockaddr_vm {
36+
sa_family_t svm_family; /* Address family: AF_VSOCK */
37+
unsigned short svm_reserved1; /* Reserved, must be zero */
38+
unsigned int svm_port; /* Port, in host byte order */
39+
unsigned int svm_cid; /* Context ID (CID) */
40+
uint8_t svm_flags; /* Flags */
41+
unsigned char svm_zero[sizeof(struct sockaddr) -
42+
sizeof(sa_family_t) -
43+
sizeof(unsigned short) -
44+
sizeof(unsigned int) -
45+
sizeof(unsigned int) -
46+
sizeof(uint8_t)];
47+
};
48+
49+
#endif /* _VM_SOCKETS_H */

tdx-attest/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ fs-err.workspace = true
2323
serde_json = { workspace = true, features = ["alloc"] }
2424
sha2.workspace = true
2525

26-
[target.'cfg(all(target_os = "linux", target_arch = "x86_64", target_env = "gnu"))'.dependencies]
26+
# Linux x86_64 with glibc or musl
27+
[target.'cfg(all(target_os = "linux", target_arch = "x86_64"))'.dependencies]
2728
tdx-attest-sys.workspace = true
2829

2930
[dev-dependencies]

tdx-attest/src/lib.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@
22
//
33
// SPDX-License-Identifier: Apache-2.0
44

5-
#[cfg(all(target_os = "linux", target_arch = "x86_64", target_env = "gnu"))]
5+
// Linux x86_64 with glibc or musl
6+
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
67
pub use linux::*;
7-
#[cfg(all(target_os = "linux", target_arch = "x86_64", target_env = "gnu"))]
8+
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
89
mod linux;
910

10-
#[cfg(not(all(target_os = "linux", target_arch = "x86_64", target_env = "gnu")))]
11+
// Fallback for non-Linux/non-x86_64 platforms (dummy implementation)
12+
#[cfg(not(all(target_os = "linux", target_arch = "x86_64")))]
1113
pub use dummy::*;
12-
13-
#[cfg(not(all(target_os = "linux", target_arch = "x86_64", target_env = "gnu")))]
14+
#[cfg(not(all(target_os = "linux", target_arch = "x86_64")))]
1415
mod dummy;
1516

1617
pub use cc_eventlog as eventlog;

0 commit comments

Comments
 (0)