Skip to content

Commit 0b52e67

Browse files
committed
Revert "fix: use static-pie linking for Go examples, remove patch_interp.py"
This reverts commit bd1e178.
1 parent bd1e178 commit 0b52e67

4 files changed

Lines changed: 78 additions & 4 deletions

File tree

examples/go-http/Dockerfile

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,22 @@ WORKDIR /src
55
COPY ./main.go /src/main.go
66

77
RUN set -xe; \
8-
CGO_ENABLED=1 \
8+
CGO_ENABLED=0 \
99
GOARCH=amd64 \
1010
go build \
11-
-ldflags='-linkmode external -extldflags "-static-pie" -s -w' \
11+
-buildmode=pie \
12+
-ldflags="-linkmode=internal" \
1213
-o /server main.go \
1314
;
1415

16+
# Strip PT_INTERP from the static PIE binary: Go's internal linker adds
17+
# /lib64/ld-linux-x86-64.so.2 as interpreter for PIE on Linux, but the
18+
# binary is fully self-contained and does not need a dynamic linker.
19+
# Unikraft's elfloader fails when the interpreter is listed but absent.
20+
# Patch the program header: change PT_INTERP (type=3) -> PT_NULL (type=0).
21+
COPY patch_interp.py /patch_interp.py
22+
RUN python3 /patch_interp.py /server
23+
1524
FROM scratch AS rootfs
1625

1726
COPY --from=build /server /bin/server

examples/go-http/patch_interp.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/usr/bin/env python3
2+
"""Strip PT_INTERP from a static PIE binary.
3+
4+
Go's internal linker adds /lib64/ld-linux-x86-64.so.2 as PT_INTERP for PIE
5+
binaries on Linux, but a CGO_ENABLED=0 binary is fully self-contained and
6+
does not need a dynamic linker. Patch PT_INTERP -> PT_NULL so elfloaders
7+
that reject missing interpreters will load the binary directly.
8+
"""
9+
import struct
10+
import sys
11+
12+
path = sys.argv[1]
13+
with open(path, "rb") as f:
14+
data = bytearray(f.read())
15+
16+
e_phoff, = struct.unpack_from("<Q", data, 32)
17+
e_phentsize, = struct.unpack_from("<H", data, 54)
18+
e_phnum, = struct.unpack_from("<H", data, 56)
19+
20+
for i in range(e_phnum):
21+
off = e_phoff + i * e_phentsize
22+
p_type, = struct.unpack_from("<I", data, off)
23+
if p_type == 3: # PT_INTERP
24+
struct.pack_into("<I", data, off, 0) # PT_NULL
25+
print(f"Patched PT_INTERP -> PT_NULL at program header index {i}")
26+
27+
with open(path, "wb") as f:
28+
f.write(data)

examples/go/Dockerfile

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,22 @@ WORKDIR /src
55
COPY ./hello.go /src/hello.go
66

77
RUN set -xe; \
8-
CGO_ENABLED=1 \
8+
CGO_ENABLED=0 \
99
GOARCH=amd64 \
1010
go build \
11-
-ldflags='-linkmode external -extldflags "-static-pie" -s -w' \
11+
-buildmode=pie \
12+
-ldflags="-linkmode=internal" \
1213
-o /hello hello.go \
1314
;
1415

16+
# Strip PT_INTERP from the static PIE binary: Go's internal linker adds
17+
# /lib64/ld-linux-x86-64.so.2 as interpreter for PIE on Linux, but the
18+
# binary is fully self-contained and does not need a dynamic linker.
19+
# Unikraft's elfloader fails when the interpreter is listed but absent.
20+
# Patch the program header: change PT_INTERP (type=3) -> PT_NULL (type=0).
21+
COPY patch_interp.py /patch_interp.py
22+
RUN python3 /patch_interp.py /hello
23+
1524
FROM scratch AS rootfs
1625

1726
COPY --from=build /hello /bin/hello

examples/go/patch_interp.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/usr/bin/env python3
2+
"""Strip PT_INTERP from a static PIE binary.
3+
4+
Go's internal linker adds /lib64/ld-linux-x86-64.so.2 as PT_INTERP for PIE
5+
binaries on Linux, but a CGO_ENABLED=0 binary is fully self-contained and
6+
does not need a dynamic linker. Patch PT_INTERP -> PT_NULL so elfloaders
7+
that reject missing interpreters will load the binary directly.
8+
"""
9+
import struct
10+
import sys
11+
12+
path = sys.argv[1]
13+
with open(path, "rb") as f:
14+
data = bytearray(f.read())
15+
16+
e_phoff, = struct.unpack_from("<Q", data, 32)
17+
e_phentsize, = struct.unpack_from("<H", data, 54)
18+
e_phnum, = struct.unpack_from("<H", data, 56)
19+
20+
for i in range(e_phnum):
21+
off = e_phoff + i * e_phentsize
22+
p_type, = struct.unpack_from("<I", data, off)
23+
if p_type == 3: # PT_INTERP
24+
struct.pack_into("<I", data, off, 0) # PT_NULL
25+
print(f"Patched PT_INTERP -> PT_NULL at program header index {i}")
26+
27+
with open(path, "wb") as f:
28+
f.write(data)

0 commit comments

Comments
 (0)