Deterministic Builds uses eBPF to intercept syscalls, to build same binaries from same source on Linux. You can start eBPF programs and then just run build tasks while this tool is making your build deterministic transparently.
Intercept syscalls related to time and make their return values fixed. eBPF can only modify syscalls which pass pointers to parameters using BPF helper function bpf_probe_read_user
.
Three syscalls about time are gettimeofday
, clock_gettime
and time
. eBPF intercepts gettimeofday
and clock_gettime
. eBPF can not intercept time
, so preload library is used to return fixed value, which modifies function time
in glibc. To make the
A file is usually read by syscalls including openat
, newstatat
and read
or mmap
. eBPF intercepts these syscalls to modify file name, file timestamps and file contents.
To compile eBPF programs and preload shared objects, you will need clang
, libelf
, zlib
, build-essential
.
On Ubuntu:
apt install clang libelf1 libelf-dev zlib1g-dev build-essential
You can specify the modified timestamp to modify in ./config/time_config.h
.
- Check and turn off vDSO, making it possible for eBPF programs to intercept syscalls about time. You can run
turn_off_vdso.sh
asroot
. It will addvdso=0
flag toGRUB_CMDLINE_LINUX_DEFAULT
in/etc/default/grub
, and it run a reboot to make it take effect. You can also do this manually. - Build and Run Docker as
root
.
docker build -t deterministic_builds .
docker run -it deterministic_builds
- Start eBPF interception in the host OS, run script as
root
.
./start.sh
- Run compile in Docker.
- Stop eBPF interception.
./stop.sh
Some macros in gcc can lead to nondeterminacy in compilation.
Including:
__DATE__
__TIME__
__TIMESTAMP__
__FILE__
There are some timestamps and random fields in binary file vmlinux
, the compiled result of linux kernel.
The eBPF program in this project is developed based on libbpf-bootstap.